diff --git a/.circleci/config.yml b/.circleci/config.yml index 34ebad5f8..c7bd1bd91 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,200 +1,455 @@ -# CircleCI v2 Config -version: 2 +# CircleCI v2.1 Config +version: 2.1 -defaults_working_directory: &defaults_working_directory - working_directory: /home/circleci/project +## +# orbs +# +# Orbs used in this pipeline +## +orbs: + slack: circleci/slack@3.4.2 + pr-tools: mojaloop/pr-tools@0.1.8 -defaults_docker_node: &defaults_docker_node - docker: - - image: node:10.15-alpine -defaults_Dependencies: &defaults_Dependencies - name: Install default dependencies - command: | - apk --no-cache add git - apk --no-cache add ca-certificates - apk --no-cache add curl - apk --no-cache add openssh-client - apk add --no-cache -t build-dependencies make gcc g++ python libtool autoconf automake - npm config set unsafe-perm true - npm install -g gitbook-cli - -defaults_Environment: &defaults_environment - name: Set default environment - command: | - echo "Nothing to do here right now...move along!" - -defaults_slack_announcement: &defaults_slack_announcement - name: Slack announcement for tag releases - command: | - curl -X POST \ - $SLACK_WEBHOOK_ANNOUNCEMENT \ - -H 'Content-type: application/json' \ - -H 'cache-control: no-cache' \ - -d "{ - \"text\": \"*${CIRCLE_PROJECT_REPONAME}* - Release \`${CIRCLE_TAG}\`: https://github.com/mojaloop/${CIRCLE_PROJECT_REPONAME}/releases/tag/${CIRCLE_TAG}\" - }" - -defaults_git_identity_setup: &defaults_git_identity_setup - name: Setup Git Identity - command: | - echo "Setting BASH_ENV..." - source $BASH_ENV +## +# defaults +# +# YAML defaults templates, in alphabetical order +## +defaults_Dependencies: &defaults_Dependencies | + apk --no-cache add git \ + ca-certificates \ + curl \ + openssh-client \ + make gcc g++ python3 libtool autoconf automake \ + python3 \ + py3-pip + pip3 install --upgrade pip + pip3 install awscli - git config --global user.email "$GIT_CI_USER" - git config --global user.password "$GIT_CI_PASSWORD" - git config --global user.name "$GIT_CI_EMAIL" - git remote add $GITHUB_PROJECT_USERNAME https://$GIT_CI_USER:$GITHUB_TOKEN@github.com/$GITHUB_PROJECT_USERNAME/$GITHUB_PROJECT_REPONAME.git -defaults_publish_to_gh_pages: &defaults_publish_to_gh_pages - name: Publish documentation +defaults_configure_nvm: &defaults_configure_nvm + name: Configure NVM command: | - echo "Setting BASH_ENV..." - source $BASH_ENV - - echo "Fetching info from remote $GITHUB_PROJECT_USERNAME" - git fetch -q $GITHUB_PROJECT_USERNAME &> git.log + touch $HOME/.profile + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash + export NVM_DIR="$HOME/.nvm" + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + echo "Installing Node version: $(cat .nvmrc)" + nvm install $(cat .nvmrc) + nvm alias default $(cat .nvmrc) + nvm use $(cat .nvmrc) - echo "Checking out $GITBOOK_TARGET_BRANCH" - git checkout -b $GITBOOK_TARGET_BRANCH $GITHUB_PROJECT_USERNAME/$GITBOOK_TARGET_BRANCH &> git.log +## +# Executors +# +# CircleCI Executors +## +executors: + default-docker: + working_directory: &WORKING_DIR /home/circleci/project + resource_class: large + docker: + - image: node:16.15.0-alpine # Ref: https://hub.docker.com/_/node?tab=tags&page=1&name=alpine - echo "Pulling latest code from $GITBOOK_TARGET_BRANCH branch..." - git pull -q $GITHUB_PROJECT_USERNAME $GITBOOK_TARGET_BRANCH --rebase &> git.log - - echo "Copying contents of _book to root..." - cp -R _book/* . - - echo "Staging general changes..." - git add . - - echo "Staging generated UML..." - git add -f assets/images/uml/*.* - - echo "Commiting changes..." - git commit -a -m "Updating release to $GITHUB_TAG" - - echo "Publishing $GITHUB_TAG release to $GITBOOK_TARGET_BRANCH on github..." - git push -q $GITHUB_PROJECT_USERNAME $GITBOOK_TARGET_BRANCH &> git.log + legacy-docker: + working_directory: *WORKING_DIR + docker: + - image: node:10.15.2-alpine + default-machine: + working_directory: *WORKING_DIR + machine: + image: ubuntu-2004:current # Ref: https://circleci.com/developer/machine/image/ubuntu-2004 + +## +# Jobs +# +# A map of CircleCI jobs +## jobs: - setup: - <<: *defaults_working_directory - <<: *defaults_docker_node + build: + executor: default-docker steps: - checkout - run: - <<: *defaults_Dependencies + name: Install general dependencies + command: *defaults_Dependencies - run: - <<: *defaults_environment + <<: *defaults_configure_nvm - run: - name: Access npm folder as root - command: cd $(npm root -g)/npm + name: install node dependencies + command: npm ci - run: - name: Update NPM install - command: npm install + name: build + command: npm run build + + build-legacy: + executor: legacy-docker + steps: + - checkout + - run: + name: Install general dependencies + command: *defaults_Dependencies - run: - name: Delete build dependencies - command: apk del build-dependencies + name: install node dependencies + command: | + cd ./legacy + npm ci + - run: + name: build + command: cd ./legacy && npm run gitbook:build - save_cache: - key: dependency-cache-{{ .Revision }} + name: Save legacy build cache + key: build-legacy-cache-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }} paths: - - node_modules + - /home/circleci/project/legacy/_book - build: - <<: *defaults_working_directory - <<: *defaults_docker_node + test-puml: + executor: default-machine steps: - checkout - run: - <<: *defaults_Dependencies + <<: *defaults_configure_nvm - run: - <<: *defaults_environment + no_output_timeout: 30m + name: Update NPM install + command: npm ci - run: - name: Installing build dependencies + name: Check if plantuml has been updated correctly command: | - echo 'Installing build dependencies via APK' - apk add --no-cache -t gitbook-build-dependencies openjdk8-jre graphviz ttf-droid ttf-droid-nonlatin + set +o pipefail + npm run build:plantuml:all + FILE_COUNT=$(git diff --cached --name-only | grep .svg | wc -l) + if [ ${FILE_COUNT} -ne "0" ]; then + echo 'Plantuml files are out of sync. Please run npm run build:plantuml:all and try again.'; + exit 1; + else + echo 'Plantuml files are up to date'; + fi - echo 'Setting env vars' - echo 'export PLANTUML_VERSION=$PLANTUML_VERSION' >> $BASH_ENV - echo 'export LANG=$PLANTUML_LANG' >> $BASH_ENV + infra: + executor: default-docker + steps: + - checkout + - run: + name: Install general dependencies + command: *defaults_Dependencies + - run: + name: Install terraform + command: | + cd /usr/local/bin + curl https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip -o terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \ + unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \ + rm terraform_${TERRAFORM_VERSION}_linux_amd64.zip + environment: + TERRAFORM_VERSION: 1.11.4 + - run: + name: Update infrastructure + command: | + cd ./infra/src + terraform init \ + -backend-config="bucket=docs.mojaloop.io-state" \ + -backend-config="region=eu-west-2" \ + -backend-config="dynamodb_table=docs.mojaloop.io-lock" + terraform refresh + terraform apply --auto-approve - echo 'Downloading plantuml jar' - curl -L https://sourceforge.net/projects/plantuml/files/plantuml.${PLANTUML_VERSION}.jar/download -o plantuml.jar + s3_upload: + executor: default-docker + steps: + - checkout + - run: + name: Install general dependencies + command: *defaults_Dependencies - restore_cache: keys: - - dependency-cache-{{ .Revision }} + - build-legacy-cache-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }} - run: - name: Build Gitbooks + name: test aws cli + permissions command: | - npm run gitbook:build - - save_cache: - key: build-cache-{{ .Revision }} - paths: - - _book + aws --version + aws s3 ls s3://docs.mojaloop.io-root + - run: + name: run build and deploy script + command: ./scripts/_deploy_preview_s3.sh + environment: + BUCKET_NAME: docs.mojaloop.io-root + DOMAIN: docs.mojaloop.io - deploy: - <<: *defaults_working_directory - <<: *defaults_docker_node + deploy_pr_preview: + executor: default-docker steps: - checkout - run: - <<: *defaults_Dependencies + name: Install general dependencies + command: *defaults_Dependencies + - restore_cache: + keys: + - build-legacy-cache-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }} + - run: + name: Configure GitHub CLI + command: | + apk add --no-cache github-cli - run: - <<: *defaults_environment + name: Check PR Preview Limits + command: | + set -x # Enable debug output + echo "Starting PR Preview Limits check..." + + # Debug CIRCLE_PULL_REQUEST value + echo "CIRCLE_PULL_REQUEST value: $CIRCLE_PULL_REQUEST" + + # Extract PR number from CIRCLE_PULL_REQUEST using POSIX-compliant syntax + PR_NUMBER=$(echo "$CIRCLE_PULL_REQUEST" | sed -E 's/.*\/pull\/([0-9]+)$/\1/') + + # If extraction failed, try branch name + if [ -z "$PR_NUMBER" ]; then + PR_NUMBER=$(echo "$CIRCLE_BRANCH" | sed -E 's/^pull\/([0-9]+)$/\1/') + fi + + if [ -z "$PR_NUMBER" ]; then + echo "Error: Could not extract PR number from CIRCLE_PULL_REQUEST or branch name" + exit 1 + fi + + echo "Extracted PR Number: $PR_NUMBER" + + PREVIEW_LIMIT=${PREVIEW_LIMIT:-10} # Default to 10 if not set + echo "Preview Limit: $PREVIEW_LIMIT" + + # Check if this PR already has a preview + echo "Checking if PR #${PR_NUMBER} already has a preview..." + if aws s3 ls "s3://docs.mojaloop.io-root/pr/${PR_NUMBER}/" 2>/dev/null; then + echo "PR #${PR_NUMBER} already has a preview, allowing update" + exit 0 + fi + + # Get count of existing previews + echo "Counting existing previews..." + # Debug: Show what we're seeing in S3 + echo "S3 listing for pr/ directory:" + aws s3 ls s3://docs.mojaloop.io-root/pr/ 2>/dev/null || echo "No pr/ directory found" + + # Check if pr/ directory exists before counting + if aws s3 ls s3://docs.mojaloop.io-root/pr/ 2>/dev/null; then + # List all directories in the pr folder and count them + PREVIEW_COUNT=$(aws s3 ls s3://docs.mojaloop.io-root/pr/ 2>/dev/null | grep -c '^[[:space:]]*PRE [0-9]' 2>/dev/null || echo "0") + else + PREVIEW_COUNT="0" + fi + # Ensure PREVIEW_COUNT is a clean number (remove any whitespace/newlines) + PREVIEW_COUNT=$(echo "$PREVIEW_COUNT" | tr -d '\n\r ') + echo "Current preview count: $PREVIEW_COUNT" + + if [ "$PREVIEW_COUNT" -ge "$PREVIEW_LIMIT" ]; then + echo "Maximum number of previews ($PREVIEW_LIMIT) reached" + gh pr comment "$PR_NUMBER" --body "⚠️ Preview deployment skipped: Maximum number of previews ($PREVIEW_LIMIT) reached. Please wait for other PRs to be merged or closed." + exit 1 + fi + + echo "Preview count ($PREVIEW_COUNT) is under limit ($PREVIEW_LIMIT), proceeding with deployment" - run: - name: setup environment vars + name: Deploy PR Preview command: | - echo 'export GITBOOK_TARGET_BRANCH=$GITBOOK_TARGET_BRANCH' >> $BASH_ENV - echo 'export GITHUB_TOKEN=$GITHUB_TOKEN' >> $BASH_ENV - echo 'export GITHUB_PROJECT_USERNAME=$CIRCLE_PROJECT_USERNAME' >> $BASH_ENV - echo 'export GITHUB_PROJECT_REPONAME=$CIRCLE_PROJECT_REPONAME' >> $BASH_ENV - echo 'export GITHUB_TAG=$CIRCLE_TAG' >> $BASH_ENV - echo 'export GIT_CI_USER=$GIT_CI_USER' >> $BASH_ENV - echo 'export GIT_CI_EMAIL=$GIT_CI_EMAIL' >> $BASH_ENV + # Extract PR number from CIRCLE_PULL_REQUEST + export PR_NUMBER=$(echo "$CIRCLE_PULL_REQUEST" | sed -E 's/.*\/pull\/([0-9]+)$/\1/') + if [ -z "$PR_NUMBER" ]; then + echo "Error: Could not extract PR number from CIRCLE_PULL_REQUEST" + exit 1 + fi + ./scripts/_deploy_preview_s3.sh + environment: + BUCKET_NAME: docs.mojaloop.io-root + DOMAIN: docs.mojaloop.io + IS_PR: "true" + - run: + name: Comment PR with Preview URL + command: | + PR_NUMBER=${CIRCLE_PULL_REQUEST##*/} + if [ -n "$PR_NUMBER" ]; then + gh pr comment "$PR_NUMBER" --body "Preview deployment is available at: https://docs.mojaloop.io/pr/${PR_NUMBER}/" + fi + + cleanup_pr_preview: + executor: default-docker + steps: + - checkout + - run: + name: Install general dependencies + command: *defaults_Dependencies + - run: + name: Configure GitHub CLI and jq + command: | + apk add --no-cache github-cli jq + - run: + name: Cleanup PR Previews + command: | + set -x # Enable debug output + echo "Starting PR preview cleanup..." + + # Get all open PRs (including draft) + echo "Fetching open PRs..." + OPEN_PRS=$(gh pr list --state open --json number) + if ! echo "$OPEN_PRS" | jq empty 2>/dev/null; then + echo "Error: Invalid JSON response from GitHub CLI for open PRs" + echo "Response was: $OPEN_PRS" + exit 1 + fi + + # Create a list of open PR numbers for exclusion + OPEN_PR_NUMBERS=$(echo "$OPEN_PRS" | jq -r '.[].number') + echo "Open PR numbers: $OPEN_PR_NUMBERS" + + # Get all PR preview directories from S3 + echo "Fetching PR preview directories from S3..." + + # Check if the pr/ directory exists in S3 + if ! aws s3 ls s3://docs.mojaloop.io-root/pr/ 2>/dev/null; then + echo "No pr/ directory found in S3, no cleanup needed" + exit 0 + fi + + S3_PREVIEWS=$(aws s3 ls s3://docs.mojaloop.io-root/pr/ 2>/dev/null | grep '^[[:space:]]*PRE [0-9]' | awk '{print $2}' | sed 's/\///') + + if [ -z "$S3_PREVIEWS" ]; then + echo "No PR previews found in S3" + exit 0 + fi + + echo "Found PR preview directories: $S3_PREVIEWS" + + # Clean up previews for PRs that are not in the open list + echo "$S3_PREVIEWS" | while IFS= read -r pr_number; do + # Skip if PR number is empty + if [ -z "$pr_number" ]; then + echo "Skipping empty PR number" + continue + fi + + # Check if this PR is still open + if echo "$OPEN_PR_NUMBERS" | grep -q "^${pr_number}$"; then + echo "PR #$pr_number is still open, skipping cleanup" + continue + fi + + echo "PR #$pr_number is not open, cleaning up preview..." + if aws s3 rm s3://docs.mojaloop.io-root/pr/${pr_number} --recursive; then + echo "Cleanup completed for PR #$pr_number" + else + echo "Warning: Failed to cleanup PR #$pr_number" + fi + done + + echo "PR preview cleanup completed" + + # When a new tag is pushed, create a new version of docs + # and push it to master to be uploaded + bump_version: + executor: default-docker + steps: + - checkout + - run: + name: Install general dependencies + command: *defaults_Dependencies + - run: + <<: *defaults_configure_nvm + - run: + name: Configure git + command: | + git config user.email ${GIT_CI_EMAIL} + git config user.name ${GIT_CI_USER} + git checkout master - restore_cache: keys: - - build-cache-{{ .Revision }} + - build-legacy-cache-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }} - run: - <<: *defaults_git_identity_setup + name: create a new version in website/versioned_docs + command: | + npm ci + ./node_modules/.bin/vuepress version docs $CIRCLE_TAG - run: - <<: *defaults_publish_to_gh_pages + name: Configure ssh + command: | + mkdir -p ~/.ssh + ssh-keyscan -p 443 ssh.github.com >> ~/.ssh/known_hosts + ssh-keyscan github.com >> ~/.ssh/known_hosts - run: - <<: *defaults_slack_announcement + name: Commit and push the release + command: | + git add . + git commit -anm "chore(ci): release $CIRCLE_TAG" + git push -u origin master +## +# Workflows +# +# CircleCI Workflow config +## workflows: version: 2 build_and_test: + when: + not: + equal: [ scheduled_pipeline, << pipeline.trigger_source >> ] jobs: - - setup: + - build: context: org-global filters: tags: only: /.*/ - branches: - ignore: - - /feature.*/ - - /bugfix.*/ - - gh-pages - - build: + + - build-legacy: + context: org-global + filters: + tags: + only: /.*/ + + - test-puml: context: org-global - requires: - - setup filters: tags: only: /.*/ + + - infra: + context: org-global + requires: + - build + - build-legacy + - test-puml + + - s3_upload: + context: org-global + requires: + - infra + filters: branches: - ignore: - - /feature.*/ - - /bugfix.*/ - - gh-pages - - deploy: + only: + - master + + - bump_version: context: org-global requires: - build + - build-legacy filters: - tags: - only: /v[0-9]+(\.[0-9]+)*/ branches: ignore: - /.*/ + tags: + only: /v[0-9]+(\.[0-9]+)*(\-snapshot)?(\-hotfix(\.[0-9]+))?/ + + - deploy_pr_preview: + context: org-global + requires: + - infra + filters: + branches: + ignore: /master|main/ + + scheduled_cleanup: + when: + equal: [ scheduled_pipeline, << pipeline.trigger_source >> ] + jobs: + - cleanup_pr_preview: + context: org-global diff --git a/.gitignore b/.gitignore index 5f1920278..5bca1818b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,23 @@ -# --------------- # -# IntelliJ # -# --------------- # -.idea/ -**/*.iml - -# VSCode directory -.vscode - -# Node +build +.terraform +pids +logs node_modules - -# Gitbook -_book - -# Gitbook UML -**/uml - -# MacOs +npm-debug.log +coverage/ +run +dist .DS_Store +.nyc_output +.basement +config.local.js +basement_dist -*.log +# https://devspace.sh/ +devspace* +.devspace/**.* -*.jar +# Add ignores +*IGNORE* +*ignore* +!.npmignore diff --git a/.husky/post-commit b/.husky/post-commit new file mode 100755 index 000000000..3c7606197 --- /dev/null +++ b/.husky/post-commit @@ -0,0 +1,6 @@ +#!/usr/bin/env sh +# . "$(dirname -- "$0")/_/husky.sh" + +echo "Running post-commit hooks..." + +git update-index --again diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 000000000..26069c529 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,8 @@ +# #!/usr/bin/env sh +# . "$(dirname -- "$0")/_/husky.sh" + +echo "Running pre-commit hooks..." + +npm run dep:check + +npm run build:plantuml:diff diff --git a/.ncurc.yaml b/.ncurc.yaml new file mode 100644 index 000000000..3cbc122a5 --- /dev/null +++ b/.ncurc.yaml @@ -0,0 +1,3 @@ +## Add a TODO comment indicating the reason for each rejected dependency upgrade added to this list, and what should be done to resolve it (i.e. handle it through a story, etc). +reject: [ +] diff --git a/.nvmrc b/.nvmrc index 70324da03..dc5620acb 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v10.15.1 +22.15.0 \ No newline at end of file diff --git a/CODEOWNERS b/CODEOWNERS index a66aed9b9..b1e397e9c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -6,7 +6,7 @@ ## @global-owner1 and @global-owner2 will be requested for ## review when someone opens a pull request. #* @global-owner1 @global-owner2 -* @millerabel @mdebarros @kjw000 @elnyry @NicoDuvenage +* @bushjames @elnyry-sam-k @kjw000 @millerabel @PaulMakinMojaloop @simeonoriko @vijayg10 @shashi165 @JulieG19 ## Order is important; the last matching pattern takes the most ## precedence. When someone opens a pull request that only diff --git a/LICENSE.md b/LICENSE.md index 91650b194..432308c9a 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,10 +1,10 @@ # LICENSE -Copyright © 2017 Bill & Melinda Gates Foundation +Copyright © 2021 Mojaloop Foundation -The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 -(the "License") and you may not use these files except in compliance with the [License](http://www.apache.org/licenses/LICENSE-2.0). You may obtain a copy of the License at +The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 +(the "License") and you may not use these files except in compliance with the [License](http://www.apache.org/licenses/LICENSE-2.0). -[http://www.apache.org/licenses/LICENSE-2.0]() +You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the [License](http://www.apache.org/licenses/LICENSE-2.0). diff --git a/README.md b/README.md index a7a7247cb..e9b5364fc 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,145 @@ -# Mojaloop Overview -[![Git Commit](https://img.shields.io/github/last-commit/mojaloop/documentation.svg?style=flat)](https://github.com/mojaloop/documentation/commits/master) -[![Git Releases](https://img.shields.io/github/release/mojaloop/documentation.svg?style=flat)](https://github.com/mojaloop/documentation/releases) -[![CircleCI](https://circleci.com/gh/mojaloop/documentation.svg?style=svg)](https://circleci.com/gh/mojaloop/documentation) +# Mojaloop Documentation -Mojaloop is open source software for creating digital payments platforms that connect all customers, merchants, banks, and other financial providers in a country's economy. Rather than a financial product or application in itself, Mojaloop establishes a blueprint for technology that bridges all the financial products and applications in any given market. +> This is the official documentation for the Mojaloop project. -The basic idea behind Mojaloop is that we need to connect multiple Digital Financial Services Providers \(DFSPs\) together into a competitive and interoperable network in order to maximize opportunities for poor people to get access to financial services with low or no fees. We don't want a single monopoly power in control of all payments in a country, or a system that shuts out new players. It also doesn't help if there are too many isolated subnetworks. +__Published at: [docs.mojaloop.io](https://docs.mojaloop.io)__ -![Mojaloop Solution](./mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-simple.svg) -Our model addresses these issues in several key ways: +## Building and testing locally -* A set of central services provides a hub through which money can flow from one DFSP to another. This is similar to how money moves through a central bank or clearing house in developed countries. Besides a central ledger, central services can provide identity lookup, fraud management, and enforce scheme rules. -* A standard set of interfaces a DFSP can implement to connect to the system, and example code that shows how to use the system. A DFSP that wants to connect up can adapt our example code or implement the standard interfaces into their own software. The goal is for it to be as straightforward as possible for a DFSP to connect to the interoperable network. -* Complete working open-source implementations of both sides of the interfaces - an example DFSP that can send and receive payments and the client that an existing DFSP could host to connect to the network. +```bash -The intention for the Mojaloop project is for financial institutions and commercial providers to use the open-source software to help build digital, interoperable payments platforms that drive financial inclusion on a national scale. Specifically, the platforms will enable seamless, low-cost transactions between individual users, merchants, banks, providers, and even government offices - helping connect poor customers with everyone else in the digital economy. +# install npm dependencies +npm ci + +# run the local server +npm run dev +``` + +## Building the project +Run `npm run build` to build the project to render the static vuepress site for a deployment. + + +## Rebuild all Puml -> svg + +For consistent rending of sequence diagrams, we build the .puml sources to .svgs using the following script. + +This script requires docker to be installed and running, since it uses a docker container to run the plantuml server. + +```bash +# render all plantuml sources to svg files deterministically +./scripts/_build_plantuml.sh + +# render just one file at a time, e.g. `figure1.plantuml` +PUML_MATCH="figure1.plantuml" +./scripts/_build_plantuml.sh +``` + +This also ensures that the sequence diagrams are easily readable inline in markdown documents. + +This script also runs as a git commit hook, so any changes added to puml sources are automatically +rendered to svg without you having to do anything! + +If you want to skip the commit hook, you can always run `git commit -n` +## Versioning + +We use `vuepress-plugin-versioning` to help us keep older versions of our docs for posterity. By default, when you browse +the docs, you see the _latest published version_. Pending changes in the main/master branch are viewable under the versioning +tab in the top navigation bar. + +See [https://titanium-docs-devkit.netlify.app/guide/versioning.html](https://titanium-docs-devkit.netlify.app/guide/versioning.html) for more information on the plugin. + +We are working to automate this process, but for now, you can make a new version of the docs with the following: + +```bash +./node_modules/.bin/vuepress version docs +``` + +> Known issue: sidebar not appearing in older versions +> Go to `./website/versioned_docs//sidebar.config.json` +> And remove the `/next` at the start of each entry + +### Deploying Manually + +You can also deploy them manually, by running: +```bash +./scripts/_deploy_preview_s3.sh +``` + +Note that you need to have the `aws` cli, AWS access, and `aws-mfa` set up on your machine for this to work. + +## PR Preview System + +The documentation site includes an automated PR preview system that creates a live preview of documentation changes for each pull request. Here's how it works: + +### Key Components + +1. **CircleCI Configuration** (`.circleci/config.yml`): + - `deploy_pr_preview` job: Handles PR preview deployment + - `cleanup_pr_preview` job: Cleans up old PR previews + - Enforces a limit on the number of concurrent previews + +2. **Deployment Script** (`scripts/_deploy_preview_s3.sh`): + - Builds the documentation site with PR preview environment variables + - Uploads to S3 under the `/pr/{PR_NUMBER}/` path + - Sets appropriate permissions and headers + +3. **CloudFront Configuration** (`infra/src/cloudfront.tf`): + - Serves PR previews from the S3 bucket + - Handles directory indexes via CloudFront function + - Manages caching and routing + +4. **CloudFront Function** (`infra/src/redirect/index.js`): + - Handles directory index requests (e.g., `/pr/123/` → `/pr/123/index.html`) + - Manages legacy URL redirects + +5. **Preview Banner** (`docs/.vuepress/theme/components/PreviewBanner.vue`): + - Displays a prominent banner at the top of PR preview pages + - Shows PR number and links to the GitHub PR + - Automatically adjusts navbar height to accommodate the banner + +### How to Use + +1. Create a pull request against the main branch +2. CircleCI will automatically: + - Build the documentation with PR preview mode enabled + - Deploy to a preview URL: `https://docs.mojaloop.io/pr/{PR_NUMBER}` + - Comment on the PR with the preview URL +3. Preview will be automatically cleaned up when the PR is closed + +### Preview Limits + +- Maximum of 10 concurrent previews +- Previews are automatically cleaned up after PR closure +- Existing previews are updated when new commits are pushed + +### Testing Locally + +To test the PR preview system locally: + +```bash +# Run with PR preview mode enabled +VUEPRESS_IS_PR=true VUEPRESS_PR_NUMBER=123 npm run dev +``` + +This will: +- Show the PR preview banner +- Adjust the navbar height automatically +- Display the PR number and link to GitHub + +### Troubleshooting + +If a preview isn't working: +1. Check the CircleCI build logs for deployment issues +2. Verify the PR number is correctly extracted +3. Ensure the CloudFront function is properly handling directory indexes +4. Check S3 for the presence of files at `/pr/{PR_NUMBER}/` +5. Verify environment variables are set correctly in the build process + +## Contributing to the project +Please refer to the [Contributing Guide](./contributing-guide.md) for details on how to contribute to Mojaloop Docs 2.0. + +## License + +Apache License. Version 2.0 +See [`./license`](./LICENSE.md) for more information. diff --git a/SUMMARY.md b/SUMMARY.md deleted file mode 100644 index 70f4ecb62..000000000 --- a/SUMMARY.md +++ /dev/null @@ -1,142 +0,0 @@ -# Table of contents - -* [Mojaloop Overview](README.md) -* [Mojaloop Background](mojaloop-background/README.md) - * [Core Scenarios](mojaloop-background/core-scenarios.md) - * [Level One Principles](mojaloop-background/level-one-principles.md) -* [Onboarding](onboarding.md) -* [Deployment Guide](deployment-guide/README.md) - * [Releases](deployment-guide/releases.md) - * [Local Setup Linux](deployment-guide/local-setup-linux.md) - * [Local Setup Mac](deployment-guide/local-setup-mac.md) - * [Local Setup Windows](deployment-guide/local-setup-windows.md) - * [Troubleshooting](deployment-guide/deployment-troubleshooting.md) -* [Contributors Guide](contributors-guide/README.md) - * [Standards](contributors-guide/standards/README.md) - * [Versioning](contributors-guide/standards/versioning.md) - * [Creating new Features](contributors-guide/standards/creating-new-features.md) - * [ML OSS Bug Triage](contributors-guide/standards/triaging-ml-oss-bugs.md) - * [Tools and Technologies](contributors-guide/tools-and-technologies/README.md) - * [Pragmatic REST](contributors-guide/tools-and-technologies/pragmatic-rest.md) - * [Code Quality Metrics](contributors-guide/tools-and-technologies/code-quality-metrics.md) - * [Automated Testing](contributors-guide/tools-and-technologies/automated-testing.md) - * [Documentation](contributors-guide/documentation/README.md) - * [API Documentation](contributors-guide/documentation/api-documentation.md) - * [Documentation Style Guide](contributors-guide/documentation/documentation-style-guide.md) -* [Mojaloop Technical Overview](mojaloop-technical-overview/README.md) - * [Mojaloop Hub](mojaloop-technical-overview/overview/README.md) - * [Current Architecture - PI8](mojaloop-technical-overview/overview/components-PI8.md) - * [Legacy Architecture - PI7](mojaloop-technical-overview/overview/components-PI7.md) - * [Legacy Architecture - PI6](mojaloop-technical-overview/overview/components-PI6.md) - * [Legacy Architecture - PI5](mojaloop-technical-overview/overview/components-PI5.md) - * [Legacy Architecture - PI3](mojaloop-technical-overview/overview/components-PI3.md) - * [Account-Lookup Service](mojaloop-technical-overview/account-lookup-service/README.md) - * [GET Participants](mojaloop-technical-overview/account-lookup-service/als-get-participants.md) - * [POST Participants](mojaloop-technical-overview/account-lookup-service/als-post-participants.md) - * [POST Participants (batch)](mojaloop-technical-overview/account-lookup-service/als-post-participants-batch.md) - * [DEL Participants](mojaloop-technical-overview/account-lookup-service/als-del-participants.md) - * [GET Parties](mojaloop-technical-overview/account-lookup-service/als-get-parties.md) - * [Quoting Service](mojaloop-technical-overview/quoting-service/README.md) - * [Central-Ledger Services](mojaloop-technical-overview/central-ledger/README.md) - * [Admin Operations](mojaloop-technical-overview/central-ledger/admin-operations/README.md) - * [POST Participant Limit](mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md) - * [GET Participant Limit Details](mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md) - * [GET All Participant Limits](mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md) - * [POST Participant limits](mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-post-participant-limits.md) - * [GET Transfer Status](mojaloop-technical-overview/central-ledger/admin-operations/1.1.5-get-transfer-status.md) - * [POST Participant Callback](mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md) - * [GET Participant Callback](mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md) - * [GET Participant Position](mojaloop-technical-overview/central-ledger/admin-operations/4.1.0-get-participant-position-details.md) - * [GET All Participants Positions](mojaloop-technical-overview/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md) - * [Transfer Operations](mojaloop-technical-overview/central-ledger/transfers/README.md) - * [Prepare Handler](mojaloop-technical-overview/central-ledger/transfers/1.1.0-prepare-transfer-request.md) - * [Prepare Handler Consume (a)](mojaloop-technical-overview/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md) - * [Prepare Handler Consume (b)](mojaloop-technical-overview/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md) - * [Prepare Position Handler](mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.md) - * [Prepare Position Handler](mojaloop-technical-overview/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md) - * [Position Handler Consume (a)](mojaloop-technical-overview/central-ledger/transfers/1.1.2.a-position-handler-consume.md) - * [Position Handler Consume (b)](mojaloop-technical-overview/central-ledger/transfers/1.1.2.b-position-handler-consume.md) - * [Fulfil Handler](mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request.md) - * [Fulfil Handler Consume](mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume.md) - * [Fulfil Position Handler](mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.md) - * [Fulfil Position Handler](mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md) - * [Fulfil Reject Transfer](mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md) - * [Fulfil Reject Transfer (a)](mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md) - * [Fulfil Handler (Reject-Abort)](mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler.md) - * [Notifications]() - * [Notification to Participant (a)](mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md) - * [Notification to Participant (b)](mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md) - * [Reject/Abort]() - * [Abort Position Handler](mojaloop-technical-overview/central-ledger/transfers/1.3.3-abort-position-handler-consume.md) - * [Timeout]() - * [Transfer Timeout](mojaloop-technical-overview/central-ledger/transfers/2.3.0-transfer-timeout.md) - * [Timeout Handler Consume](mojaloop-technical-overview/central-ledger/transfers/2.3.1-timeout-handler-consume.md) - * [Bulk Transfer Operations](mojaloop-technical-overview/central-bulk-transfers/README.md) - * [Bulk Prepare Overview](mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md) - * [Bulk Prepare Handler](mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md) - * [Prepare Handler](mojaloop-technical-overview/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md) - * [Position Handler Overview](mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md) - * [Prepare Position Handler Consume](mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md) - * [Fulfil Position Handler Consume](mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md) - * [Fulfil Abort Position Handler Consume](mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md) - * [Bulk Fulfil Handler Overview](mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md) - * [Bulk Fulfil Handler Consume](mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md) - * [Fulfil Handler - Commit](mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md) - * [Fulfil Handler - Reject/Abort](mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md) - * [Bulk Processing Handler](mojaloop-technical-overview/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md) - * [Notifications]() - * [Notification to Participant (a)](mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md) - * [Notification to Participant (b)](mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md) - * [Timeout Overview](mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md) - * [Timeout Handler Consume](mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md) - * [Central-Settlements Service](mojaloop-technical-overview/central-settlements/README.md) - * [Settlement Process](mojaloop-technical-overview/central-settlements/settlement-process/README.md) - * [Settlement Windows By Params](mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-windows-by-params.md) - * [Request Settlement Window](mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-window-by-id.md) - * [Close Settlement Window](mojaloop-technical-overview/central-settlements/settlement-process/post-close-settlement-window.md) - * [Create Settlement](mojaloop-technical-overview/central-settlements/settlement-process/post-create-settlement.md) - * [Request Settlement](mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-id.md) - * [Settlement Transfer Acknowledgement](mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-transfer-ack.md) - * [Settlement Abort](mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-abort.md) - * [Request Settlement By SPA](mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-spa.md) - * [Request Settlements By Params](mojaloop-technical-overview/central-settlements/settlement-process/get-settlements-by-params.md) - * [Funds In/Out](mojaloop-technical-overview/central-settlements/funds-in-out/README.md) - * [Reconciliation Transfer Prepare](mojaloop-technical-overview/central-settlements/funds-in-out/reconciliation-transfer-prepare.md) - * [Transfer State and Position Change](mojaloop-technical-overview/central-settlements/funds-in-out/transfer-state-and-position-change.md) - * [Funds In](mojaloop-technical-overview/central-settlements/funds-in-out/funds-in-prepare-reserve-commit.md) - * [Funds Out - Prepare & Reserve](mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-prepare-reserve.md) - * [Funds Out - Commit](mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-commit.md) - * [Funds Out - Abort](mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-abort.md) - * [OSS Settlement FSD](mojaloop-technical-overview/central-settlements/oss-settlement-fsd.md) - * [Central-Event-Processor Services](mojaloop-technical-overview/central-event-processor/README.md) - * [Event Handler (Placeholder)](mojaloop-technical-overview/central-event-processor/9.1.0-event-handler-placeholder.md) - * [Notification Handler For Rejections](mojaloop-technical-overview/central-event-processor/5.1.1-notification-handler-for-rejections.md) - * [Signature Validation](mojaloop-technical-overview/central-event-processor/signature-validation.md) - * [Event Framework](mojaloop-technical-overview/event-framework/README.md) - * [Event Stream Processor](mojaloop-technical-overview/event-stream-processor/README.md) - * [Fraud Services](mojaloop-technical-overview/fraud-services/README.md) - * [Ecosystem Fraud Documentation](mojaloop-technical-overview/fraud-services/related-documents/documentation.md) - * [SDK Scheme Adapter](mojaloop-technical-overview/sdk-scheme-adapter/README.md) - * [Usage](mojaloop-technical-overview/sdk-scheme-adapter/usage/README.md) - * [Scheme Adapter to Scheme Adapter](mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/README.md) - * [Scheme Adapter to Local ML Cluster](mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/README.md) - * [Scheme Adapter to WSO2 API Gateway](mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/README.md) -* [API Specifications](api/README.md) - * [Mojaloop](api/mojaloop-api-specification.md) - * [Central Ledger API](api/central-ledger-api-specification.md) - * [Central Settlements](api/central-settlements-api-specification.md) - * [ALS Oracle](api/als-oracle-api-specification.md) -* [Repo Details](repositories/README.md) - * [Helm](repositories/helm.md) - * [Project](repositories/project.md) -* [Mojaloop Roadmap](mojaloop-roadmap.md) -* [Mojaloop Publications](mojaloop-publications.md) -* [Discussion Documents](discussions/readme.md) - * [ISO integration Overivew](discussions/ISO_Integration.md) - * [Moajoop Decimal Type; Based on XML Schema Decimal Type](discussions/decimal.md) - * [Workbench Workstream](discussions/workbench.md) - * [Cross Border Meeting Notes Day 1](discussions/cross_border_day_1.md) - * [Cross Border Meeting Notes Day 2](discussions/cross_border_day_2.md) -* [Frequently Asked Questions](contributors-guide/frequently-asked-questions.md) -* [Glossary of Terms](glossary.md) - diff --git a/api/assets/interface-contracts/oracle-service-swagger-v1.yaml b/api/assets/interface-contracts/oracle-service-swagger-v1.yaml deleted file mode 100644 index ec3c98087..000000000 --- a/api/assets/interface-contracts/oracle-service-swagger-v1.yaml +++ /dev/null @@ -1,952 +0,0 @@ -swagger: '2.0' -info: - version: '1.2' - title: Interface for interaction between Mojaloop's Account Lookup Service(ALS) and an Oracle Registry Service - description: Based on Mojaloop [API Definition](https://github.com/mojaloop/mojaloop-specification/blob/master/API%20Definition%20v1.0.pdf) updated on 2018-03-13 Version 1.0. More information can be found are [mojaloop.io](http://mojaloop.io/) - contact: {} -basePath: / -schemes: [] -consumes: - - application/json -produces: - - application/json -paths: - /participants/{Type}/{ID}: - get: - description: The HTTP request GET /participants/{Type}/{ID} is used to find out in which FSP the requested Party, defined by {Type} and {ID} is located (for example, GET /participants/MSISDN/123456789). This HTTP request should support a query string to filter FSP information regarding a specific currency only (This similarly applies to the SubId). To query a specific currency only, the HTTP request GET /participants/{Type}/{ID}?currency=XYZ should be used, where XYZ is the requested currency. Note - Both the currency and the SubId can be used mutually inclusive or exclusive - summary: Look up participant information - tags: - - participants - operationId: ParticipantsByTypeAndIDGet - deprecated: false - produces: - - application/json - parameters: - - name: accept - in: header - required: true - type: string - description: The Accept header field indicates the version of the API the client would like the server to use. - - name: Type - in: path - required: true - type: string - description: The type of lookup being requested, this can be MSISDN, bankAccount etc. - - name: ID - in: path - required: true - type: string - description: The ID related to the Type, if MSISDN then this is the mobile number being requested - - name: Currency - in: query - required: false - type: string - description: The Currency code applicable to the ID being requested - - name: SubId - in: query - required: false - type: string - description: The SubId related to the ID, or the Type - - name: content-type - in: header - required: true - type: string - description: The Content-Type header indicates the specific version of the API used to send the payload body. - - name: date - in: header - required: true - type: string - description: The Date header field indicates the date when the request was sent. - - name: fspiop-source - in: header - required: true - type: string - description: The FSPIOP-Source header field is a non-HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing and signature verification (see header field FSPIOP-Signature). - - name: x-forwarded-for - in: header - required: false - type: string - description: The X-Forwarded-For header field is an unofficially accepted standard used for informational purposes of the originating client IP address, as a request might pass multiple proxies, firewalls, and so on. Multiple X-Forwarded-For values as in the example shown here should be expected and supported by implementers of the API. Note - An alternative to X-Forwarded-For is defined in RFC 7239. However, to this point RFC 7239 is less-used and supported than X-Forwarded-For. - - name: fspiop-destination - in: header - required: false - type: string - description: The FSPIOP-Destination header field is a non-HTTP standard field used by the API for HTTP header based routing of requests and responses to the destination. The field should be set by the original sender of the request (if known), so that any entities between the client and the server do not need to parse the payload for routing purposes. - - name: fspiop-encryption - in: header - required: false - type: string - description: The FSPIOP-Encryption header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request. - - name: fspiop-signature - in: header - required: false - type: string - description: The FSPIOP-Signature header field is a non-HTTP standard field used by the API for applying an end-to-end request signature. - - name: fspiop-uri - in: header - required: false - type: string - description: The FSPIOP-URI header field is a non-HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information see API Signature document. - - name: fspiop-http-method - in: header - required: false - type: string - description: The FSPIOP-HTTP-Method header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information see API Signature document. - responses: - 200: - description: OK - schema: - $ref: '#/definitions/ParticipantsTypeIDGetResponse' - headers: - Content-Length: - type: string - 400: - description: Bad Request - The application cannot process the request; for example, due to malformed syntax or the payload exceeded size restrictions. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 401: - description: Unauthorized - The request requires authentication in order to be processed. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 403: - description: Forbidden - The request was denied and will be denied in the future. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 404: - description: Not Found - The resource specified in the URI was not found. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 405: - description: Method Not Allowed - An unsupported HTTP method for the request was used. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 406: - description: Not acceptable - The server is not capable of generating content according to the Accept headers sent in the request. Used in the API to indicate that the server does not support the version that the client is requesting. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 501: - description: Not Implemented - The server does not support the requested service. The client should not retry. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 503: - description: Service Unavailable - The server is currently unavailable to accept any new service requests. This should be a temporary state, and the client should retry within a reasonable time frame. - schema: - $ref: '#/definitions/ErrorInformationResponse' - put: - description: The PUT /participants/{Type}/{ID} is used to update information in the server regarding the provided identity, defined by {Type} and {ID} (for example, PUT /participants/MSISDN/123456789). - summary: Return participant information - tags: - - participants - operationId: ParticipantsByTypeAndIDPut - deprecated: false - produces: - - application/json - parameters: - - name: Type - in: path - required: true - type: string - description: The type of lookup being requested, this can be MSISDN, bankAccount etc. - - name: ID - in: path - required: true - type: string - description: The ID related to the Type, if MSISDN then this is the mobile number being requested - - name: content-type - in: header - required: true - type: string - description: The Content-Type header indicates the specific version of the API used to send the payload body. - - name: date - in: header - required: true - type: string - description: The Date header field indicates the date when the request was sent. - - name: fspiop-source - in: header - required: true - type: string - description: The FSPIOP-Source header field is a non-HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing and signature verification (see header field FSPIOP-Signature). - - name: body - in: body - required: true - description: '' - schema: - $ref: '#/definitions/ParticipantsTypeIDPutRequest' - - name: accept - in: header - required: false - type: string - description: The Accept header field indicates the version of the API the client would like the server to use. - - name: x-forwarded-for - in: header - required: false - type: string - description: The X-Forwarded-For header field is an unofficially accepted standard used for informational purposes of the originating client IP address, as a request might pass multiple proxies, firewalls, and so on. Multiple X-Forwarded-For values as in the example shown here should be expected and supported by implementers of the API. Note - An alternative to X-Forwarded-For is defined in RFC 7239. However, to this point RFC 7239 is less-used and supported than X-Forwarded-For. - - name: fspiop-destination - in: header - required: false - type: string - description: The FSPIOP-Destination header field is a non-HTTP standard field used by the API for HTTP header based routing of requests and responses to the destination. The field should be set by the original sender of the request (if known), so that any entities between the client and the server do not need to parse the payload for routing purposes. - - name: fspiop-encryption - in: header - required: false - type: string - description: The FSPIOP-Encryption header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request. - - name: fspiop-signature - in: header - required: false - type: string - description: The FSPIOP-Signature header field is a non-HTTP standard field used by the API for applying an end-to-end request signature. - - name: fspiop-uri - in: header - required: false - type: string - description: The FSPIOP-URI header field is a non-HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information see API Signature document. - - name: fspiop-http-method - in: header - required: false - type: string - description: The FSPIOP-HTTP-Method header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information see API Signature document. - - name: content-length - in: header - required: false - type: integer - format: int32 - exclusiveMaximum: false - exclusiveMinimum: false - description: The Content-Length header field indicates the anticipated size of the payload body. Only sent if there is a body. Note - The API supports a maximum size of 5242880 bytes (5 Megabytes) - responses: - 204: - description: No Content - headers: {} - 400: - description: Bad Request - The application cannot process the request; for example, due to malformed syntax or the payload exceeded size restrictions. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 401: - description: Unauthorized - The request requires authentication in order to be processed. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 403: - description: Forbidden - The request was denied and will be denied in the future. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 404: - description: Not Found - The resource specified in the URI was not found. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 405: - description: Method Not Allowed - An unsupported HTTP method for the request was used. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 406: - description: Not acceptable - The server is not capable of generating content according to the Accept headers sent in the request. Used in the API to indicate that the server does not support the version that the client is requesting. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 501: - description: Not Implemented - The server does not support the requested service. The client should not retry. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 503: - description: Service Unavailable - The server is currently unavailable to accept any new service requests. This should be a temporary state, and the client should retry within a reasonable time frame. - schema: - $ref: '#/definitions/ErrorInformationResponse' - post: - description: The HTTP request POST /participants/{Type}/{ID} is used to create information in the server regarding the provided identity, defined by {Type} and {ID} (for example, POST /participants/MSISDN/123456789). - summary: Create participant information - tags: - - participants - operationId: ParticipantsByTypeAndIDPost - deprecated: false - produces: - - application/json - parameters: - - name: accept - in: header - required: true - type: string - description: The Accept header field indicates the version of the API the client would like the server to use. - - name: Type - in: path - required: true - type: string - description: The type of lookup being requested, this can be MSISDN, bankAccount etc. - - name: ID - in: path - required: true - type: string - description: The ID related to the Type, if MSISDN then this is the mobile number being requested - - name: content-type - in: header - required: true - type: string - description: The Content-Type header indicates the specific version of the API used to send the payload body. - - name: date - in: header - required: true - type: string - description: The Date header field indicates the date when the request was sent. - - name: fspiop-source - in: header - required: true - type: string - description: The FSPIOP-Source header field is a non-HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing and signature verification (see header field FSPIOP-Signature). - - name: body - in: body - required: true - description: '' - schema: - $ref: '#/definitions/ParticipantsTypeIDPutRequest' - - name: x-forwarded-for - in: header - required: false - type: string - description: The X-Forwarded-For header field is an unofficially accepted standard used for informational purposes of the originating client IP address, as a request might pass multiple proxies, firewalls, and so on. Multiple X-Forwarded-For values as in the example shown here should be expected and supported by implementers of the API. Note - An alternative to X-Forwarded-For is defined in RFC 7239. However, to this point RFC 7239 is less-used and supported than X-Forwarded-For. - - name: fspiop-destination - in: header - required: false - type: string - description: The FSPIOP-Destination header field is a non-HTTP standard field used by the API for HTTP header based routing of requests and responses to the destination. The field should be set by the original sender of the request (if known), so that any entities between the client and the server do not need to parse the payload for routing purposes. - - name: fspiop-encryption - in: header - required: false - type: string - description: The FSPIOP-Encryption header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request. - - name: fspiop-signature - in: header - required: false - type: string - description: The FSPIOP-Signature header field is a non-HTTP standard field used by the API for applying an end-to-end request signature. - - name: fspiop-uri - in: header - required: false - type: string - description: The FSPIOP-URI header field is a non-HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information see API Signature document. - - name: fspiop-http-method - in: header - required: false - type: string - description: The FSPIOP-HTTP-Method header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information see API Signature document. - - name: content-length - in: header - required: false - type: integer - format: int32 - exclusiveMaximum: false - exclusiveMinimum: false - description: The Content-Length header field indicates the anticipated size of the payload body. Only sent if there is a body. Note - The API supports a maximum size of 5242880 bytes (5 Megabytes) - responses: - 201: - description: Created - headers: {} - 400: - description: Bad Request - The application cannot process the request; for example, due to malformed syntax or the payload exceeded size restrictions. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 401: - description: Unauthorized - The request requires authentication in order to be processed. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 403: - description: Forbidden - The request was denied and will be denied in the future. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 404: - description: Not Found - The resource specified in the URI was not found. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 405: - description: Method Not Allowed - An unsupported HTTP method for the request was used. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 406: - description: Not acceptable - The server is not capable of generating content according to the Accept headers sent in the request. Used in the API to indicate that the server does not support the version that the client is requesting. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 501: - description: Not Implemented - The server does not support the requested service. The client should not retry. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 503: - description: Service Unavailable - The server is currently unavailable to accept any new service requests. This should be a temporary state, and the client should retry within a reasonable time frame. - schema: - $ref: '#/definitions/ErrorInformationResponse' - delete: - description: The HTTP request DELETE /participants/{Type}/{ID} is used to delete information in the server regarding the provided identity, defined by {Type} and {ID}) (for example, DELETE /participants/MSISDN/123456789). This HTTP request should support a query string to delete FSP information regarding a specific currency only (This similarly applies to the SubId). To delete a specific currency only, the HTTP request DELETE /participants/{Type}/{ID}?currency=XYZ should be used, where XYZ is the requested currency. Note - Both the currency and the SubId can be used mutually inclusive or exclusive - summary: Delete participant information - tags: - - participants - operationId: ParticipantsByTypeAndIDDelete - deprecated: false - produces: - - application/json - parameters: - - name: accept - in: header - required: true - type: string - description: The Accept header field indicates the version of the API the client would like the server to use. - - name: Type - in: path - required: true - type: string - description: The type of lookup being requested, this can be MSISDN, bankAccount etc. - - name: ID - in: path - required: true - type: string - description: The ID related to the Type, if MSISDN then this is the mobile number being requested - - name: Currency - in: query - required: false - type: string - description: The Currency code applicable to the ID being requested - - name: SubId - in: query - required: false - type: string - description: The SubId related to the ID, or the Type - - name: content-type - in: header - required: true - type: string - description: The Content-Type header indicates the specific version of the API used to send the payload body. - - name: date - in: header - required: true - type: string - description: The Date header field indicates the date when the request was sent. - - name: fspiop-source - in: header - required: true - type: string - description: The FSPIOP-Source header field is a non-HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing and signature verification (see header field FSPIOP-Signature). - - name: x-forwarded-for - in: header - required: false - type: string - description: The X-Forwarded-For header field is an unofficially accepted standard used for informational purposes of the originating client IP address, as a request might pass multiple proxies, firewalls, and so on. Multiple X-Forwarded-For values as in the example shown here should be expected and supported by implementers of the API. Note - An alternative to X-Forwarded-For is defined in RFC 7239. However, to this point RFC 7239 is less-used and supported than X-Forwarded-For. - - name: fspiop-destination - in: header - required: false - type: string - description: The FSPIOP-Destination header field is a non-HTTP standard field used by the API for HTTP header based routing of requests and responses to the destination. The field should be set by the original sender of the request (if known), so that any entities between the client and the server do not need to parse the payload for routing purposes. - - name: fspiop-encryption - in: header - required: false - type: string - description: The FSPIOP-Encryption header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request. - - name: fspiop-signature - in: header - required: false - type: string - description: The FSPIOP-Signature header field is a non-HTTP standard field used by the API for applying an end-to-end request signature. - - name: fspiop-uri - in: header - required: false - type: string - description: The FSPIOP-URI header field is a non-HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information see API Signature document. - - name: fspiop-http-method - in: header - required: false - type: string - description: The FSPIOP-HTTP-Method header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information see API Signature document. - responses: - 204: - description: No Content - headers: {} - 400: - description: Bad Request - The application cannot process the request; for example, due to malformed syntax or the payload exceeded size restrictions. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 401: - description: Unauthorized - The request requires authentication in order to be processed. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 403: - description: Forbidden - The request was denied and will be denied in the future. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 404: - description: Not Found - The resource specified in the URI was not found. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 405: - description: Method Not Allowed - An unsupported HTTP method for the request was used. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 406: - description: Not acceptable - The server is not capable of generating content according to the Accept headers sent in the request. Used in the API to indicate that the server does not support the version that the client is requesting. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 501: - description: Not Implemented - The server does not support the requested service. The client should not retry. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 503: - description: Service Unavailable - The server is currently unavailable to accept any new service requests. This should be a temporary state, and the client should retry within a reasonable time frame. - schema: - $ref: '#/definitions/ErrorInformationResponse' - /participants: - post: - description: The HTTP request POST /participants is used to create information in the server regarding the provided list of identities. This request should be used for bulk creation of FSP information for more than one Party. The optional currency parameter should indicate that each provided Party supports the currency - summary: Batch create participant information #fail these as a batch or accept it as a batch - tags: - - participants - operationId: ParticipantsPost - deprecated: false - produces: - - application/json - parameters: - - name: accept - in: header - required: true - type: string - description: The Accept header field indicates the version of the API the client would like the server to use. - - name: content-type - in: header - required: true - type: string - description: The Content-Type header indicates the specific version of the API used to send the payload body. - - name: date - in: header - required: true - type: string - description: The Date header field indicates the date when the request was sent. - - name: fspiop-source - in: header - required: true - type: string - description: The FSPIOP-Source header field is a non-HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing and signature verification (see header field FSPIOP-Signature). - - name: body - in: body - required: true - description: '' - schema: - $ref: '#/definitions/ParticipantsPostRequest' - - name: content-length - in: header - required: false - type: integer - format: int32 - exclusiveMaximum: false - exclusiveMinimum: false - description: The Content-Length header field indicates the anticipated size of the payload body. Only sent if there is a body. Note - The API supports a maximum size of 5242880 bytes (5 Megabytes) - - name: x-forwarded-for - in: header - required: false - type: string - description: The X-Forwarded-For header field is an unofficially accepted standard used for informational purposes of the originating client IP address, as a request might pass multiple proxies, firewalls, and so on. Multiple X-Forwarded-For values as in the example shown here should be expected and supported by implementers of the API. Note - An alternative to X-Forwarded-For is defined in RFC 7239. However, to this point RFC 7239 is less-used and supported than X-Forwarded-For. - - name: fspiop-destination - in: header - required: false - type: string - description: The FSPIOP-Destination header field is a non-HTTP standard field used by the API for HTTP header based routing of requests and responses to the destination. The field should be set by the original sender of the request (if known), so that any entities between the client and the server do not need to parse the payload for routing purposes. - - name: fspiop-encryption - in: header - required: false - type: string - description: The FSPIOP-Encryption header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request. - - name: fspiop-signature - in: header - required: false - type: string - description: The FSPIOP-Signature header field is a non-HTTP standard field used by the API for applying an end-to-end request signature. - - name: fspiop-uri - in: header - required: false - type: string - description: The FSPIOP-URI header field is a non-HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information see API Signature document. - - name: fspiop-http-method - in: header - required: false - type: string - description: The FSPIOP-HTTP-Method header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information see API Signature document. - responses: - 201: - description: Created - headers: {} - schema: - $ref: '#/definitions/ParticipantsIDPutResponse' - 400: - description: Bad Request - The application cannot process the request; for example, due to malformed syntax or the payload exceeded size restrictions. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 401: - description: Unauthorized - The request requires authentication in order to be processed. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 403: - description: Forbidden - The request was denied and will be denied in the future. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 404: - description: Not Found - The resource specified in the URI was not found. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 405: - description: Method Not Allowed - An unsupported HTTP method for the request was used. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 406: - description: Not acceptable - The server is not capable of generating content according to the Accept headers sent in the request. Used in the API to indicate that the server does not support the version that the client is requesting. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 501: - description: Not Implemented - The server does not support the requested service. The client should not retry. - schema: - $ref: '#/definitions/ErrorInformationResponse' - 503: - description: Service Unavailable - The server is currently unavailable to accept any new service requests. This should be a temporary state, and the client should retry within a reasonable time frame. - schema: - $ref: '#/definitions/ErrorInformationResponse' -definitions: - CurrencyEnum: - title: CurrencyEnum - description: The currency codes defined in ISO 4217 as three-letter alphabetic codes are used as the standard naming representation for currencies. - example: AED - type: string - enum: - - AED - - AFN - - ALL - - AMD - - ANG - - AOA - - ARS - - AUD - - AWG - - AZN - - BAM - - BBD - - BDT - - BGN - - BHD - - BIF - - BMD - - BND - - BOB - - BRL - - BSD - - BTN - - BWP - - BYN - - BZD - - CAD - - CDF - - CHF - - CLP - - CNY - - COP - - CRC - - CUC - - CUP - - CVE - - CZK - - DJF - - DKK - - DOP - - DZD - - EGP - - ERN - - ETB - - EUR - - FJD - - FKP - - GBP - - GEL - - GGP - - GHS - - GIP - - GMD - - GNF - - GTQ - - GYD - - HKD - - HNL - - HRK - - HTG - - HUF - - IDR - - ILS - - IMP - - INR - - IQD - - IRR - - ISK - - JEP - - JMD - - JOD - - JPY - - KES - - KGS - - KHR - - KMF - - KPW - - KRW - - KWD - - KYD - - KZT - - LAK - - LBP - - LKR - - LRD - - LSL - - LYD - - MAD - - MDL - - MGA - - MKD - - MMK - - MNT - - MOP - - MRO - - MUR - - MVR - - MWK - - MXN - - MYR - - MZN - - NAD - - NGN - - NIO - - NOK - - NPR - - NZD - - OMR - - PAB - - PEN - - PGK - - PHP - - PKR - - PLN - - PYG - - QAR - - RON - - RSD - - RUB - - RWF - - SAR - - SBD - - SCR - - SDG - - SEK - - SGD - - SHP - - SLL - - SOS - - SPL - - SRD - - STD - - SVC - - SYP - - SZL - - THB - - TJS - - TMT - - TND - - TOP - - TRY - - TTD - - TVD - - TWD - - TZS - - UAH - - UGX - - USD - - UYU - - UZS - - VEF - - VND - - VUV - - WST - - XAF - - XCD - - XDR - - XOF - - XPF - - YER - - ZAR - - ZMW - - ZWD - PartyIdTypeEnum: - title: PartyIdTypeEnum - description: Below are the allowed values for the enumeration - MSISDN An MSISDN (Mobile Station International Subscriber Directory Number, that is, the phone number) is used as reference to a participant. The MSISDN identifier should be in international format according to the ITU-T E.164 standard. Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix. - EMAIL An email is used as reference to a participant. The format of the email should be according to the informational RFC 3696. - PERSONAL_ID A personal identifier is used as reference to a participant. Examples of personal identification are passport number, birth certificate number, and national registration number. The identifier number is added in the PartyIdentifier element. The personal identifier type is added in the PartySubIdOrType element. - BUSINESS A specific Business (for example, an organization or a company) is used as reference to a participant. The BUSINESS identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the PartySubIdOrType element should be used. - DEVICE A specific device (for example, a POS or ATM) ID connected to a specific business or organization is used as reference to a Party. For referencing a specific device under a specific business or organization, use the PartySubIdOrType element. - ACCOUNT_ID A bank account number or FSP account ID should be used as reference to a participant. The ACCOUNT_ID identifier can be in any format, as formats can greatly differ depending on country and FSP. - IBAN A bank account number or FSP account ID is used as reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without whitespace. - ALIAS An alias is used as reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias is a username in the FSP system. The ALIAS identifier can be in any format. It is also possible to use the PartySubIdOrType element for identifying an account under an Alias defined by the PartyIdentifier. - example: MSISDN - type: string - enum: - - MSISDN - - EMAIL - - PERSONAL_ID - - BUSINESS - - DEVICE - - ACCOUNT_ID - - IBAN - - ALIAS - ErrorInformation: - title: ErrorInformation - description: Data model for the complex type ErrorInformation. - type: object - properties: - errorCode: - description: Specific error number. - type: string - errorDescription: - description: Error description string. - type: string - extensionList: - $ref: '#/definitions/ExtensionList' - required: - - errorCode - - errorDescription - ErrorInformationResponse: - title: ErrorInformationResponse - description: Data model for the complex type object that contains an optional element ErrorInformation used along with 4xx and 5xx responses. - type: object - properties: - errorInformation: - $ref: '#/definitions/ErrorInformation' - Extension: - title: Extension - description: Data model for the complex type Extension - type: object - properties: - key: - description: Extension key. - type: string - value: - description: Extension value. - type: string - required: - - key - - value - ExtensionList: - title: ExtensionList - description: Data model for the complex type ExtensionList - type: object - properties: - extension: - description: Number of Extension elements - type: array - items: - $ref: '#/definitions/Extension' - minItems: 1 - maxItems: 16 - required: - - extension - ParticipantsTypeIDGetResponse: - title: ParticipantsTypeIDGetResponse - description: OK - type: object - properties: - partyList: - description: List of PartyTypeIdInfo elements that were either created or failed to be created. - type: array - items: - $ref: '#/definitions/PartyTypeIdInfo' - minItems: 1 - maxItems: 10000 - ParticipantsTypeIDPutRequest: - title: ParticipantsTypeIDPutRequest - description: PUT /participants/{Type}/{ID} object - type: object - properties: - fspId: - description: FSP Identifier that the Party belongs to. - type: string - currency: - description: Indicate that the provided Currency was set to be supported by each successfully added PartyIdInfo. - type: string - partySubIdOrType: - description: A sub-identifier or sub-type for the Party. - type: string - required: - - fspId - - currency - ParticipantsPostRequest: - title: ParticipantsPostRequest - description: POST /participants object - type: object - properties: - requestId: - description: The ID of the request, decided by the client. Used for identification of the callback from the server. - type: string - partyList: - description: List of PartyIdInfo elements that the client would like to update or create FSP information about. - type: array - items: - $ref: '#/definitions/PartyIdInfo' - minItems: 1 - maxItems: 10000 - required: - - requestId - - partyList - PartyIdInfo: - title: PartyIdInfo - description: Data model for the complex type PartyIdInfo. - type: object - properties: - partyIdType: - description: Type of the identifier. - type: string - partyIdentifier: - description: An identifier for the Party. - type: string - partySubIdOrType: - description: A sub-identifier or sub-type for the Party. - type: string - fspId: - description: FSP ID - type: string - currency: - description: Indicate that the provided Currency was set to be supported by each successfully added PartyIdInfo. - type: string - required: - - partyIdType - - partyIdentifier - ParticipantsIDPutResponse: - title: ParticipantsIDPutResponse - type: object - description: PUT /participants/{ID} object - properties: - partyList: - type: array - items: - $ref: '#/definitions/PartyResult' - minItems: 1 - maxItems: 10000 - description: List of PartyResult elements that were either created or failed to be created. - required: - - partyList - PartyResult: - title: PartyResult - type: object - description: Data model for the complex type PartyResult. - properties: - partyId: - $ref: '#/definitions/PartyIdInfo' - errorInformation: - $ref: '#/definitions/ErrorInformation' - required: - - partyId - PartyTypeIdInfo: - title: PartyTypeIdInfo - description: Data model for the complex type PartyIdInfo. - type: object - properties: - fspId: - description: FSP ID - type: string - currency: - description: Indicate that the provided Currency was set to be supported by each successfully added PartyIdInfo. - type: string - partySubIdOrType: - description: A sub-identifier or sub-type for the Party. - type: string - required: - - fspId - - currency -tags: - - name: participants - description: '' \ No newline at end of file diff --git a/api/mojaloop-api-specification.md b/api/mojaloop-api-specification.md deleted file mode 100644 index 02bb0694d..000000000 --- a/api/mojaloop-api-specification.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -showToc: false ---- -https://raw.githubusercontent.com/mojaloop/mojaloop-specification/master/Supporting%20Files/fspiop-rest-v1.0-OpenAPI-implementation.yaml \ No newline at end of file diff --git a/contributing-guide.md b/contributing-guide.md new file mode 100644 index 000000000..6c739d397 --- /dev/null +++ b/contributing-guide.md @@ -0,0 +1,62 @@ +# Mojaloop Docs 2.0 Contributing Guide + +> This README contains guide on contributing to Mojaloop Docs 2.0 - a Vuepress-powered site for Mojaloop documentation. + + +## Getting started +The first step in contributing to the Mojaloop documentation repository is to go through the Contributors guide and the + + +## Setting up locally +Refer to the [README](./README.md#building-and-testing-locally) for guide on how to setup the documentation site locally. + + +## Adding Content +New content added to the documentation should follow the guidelines defined here in additi + +## Creating new pages +TBD + +## Migrating existing pages +While much of the migration is done manually for now, a script will soon be provided to allow you move content from an existing directory to the new documentation site. + + +## Handling Images +TBDD + + +## Documentation Conventions +These are some of the defined conventions that guide contributing to the + +### Folder and Directory Structure +- All top-level documentation pages should be created as folders in the `vuepress/docs` directory. e.g. a `Community` top-level page is created in `vuepress/docs/community/` +- All + +## Assets +- Assets including images for a specific pages should be added to the `/assets/` directory for that page/ +- The naming convention for images (new or existing) added to the `/assets` documentation name should be `-
- + +### Page/Section Headers +As much as is possible, the following should be adhered to when creating headers for pages and sections: + +- Page headers should use sentence case. +- Page headers and section headers should not contain numbers. The previous Mojaloop documentation used numbers as part of page and section headers which resulted in brittle links that were easily broken when content was changed. + + +## Creating a Pull Request +Once you have created content that you are ready, the following steps should be followed to create a new PR: +- Run the `./verify-links` script to ensure that there are no broken links on your page. See [Verifying Page Links](#verifying-page-links) section for more details. +- Check for any typographical errors +- Create a pull request using `master` as the base branch + + + +## Verifying Page Links +Before opening a PR, ensure that all the links on the new page are correct and accessible. While this process is manual for now, a `./verify-links` script will soon be added to the repository that can be run to verify all the links of the page. + + +## Versioning + +TBD + + diff --git a/contributors-guide/README.md b/contributors-guide/README.md deleted file mode 100644 index 8e0ef21cf..000000000 --- a/contributors-guide/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# Contributors Guide - -## How do I contribute? - -* Review the [Mojaloop Deployment](../deployment-guide/) Guide and the [Onboarding Guide](https://github.com/mojaloop/mojaloop/blob/master/onboarding.md) -* Browse through the [Repository Overview](../repositories/) to understand how the Mojaloop code is managed across multiple Github Repositories -* Get familiar with our [Standards](standards/) on contributing to this project -* Go through the [New Contributor Checklist](./new-contributor-checklist.md), and browse through the project board and work on your [good first issue](https://github.com/mojaloop/project/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) -* Review the [Roadmap](../mojaloop-roadmap.md) and contribute to future opportunities - -## What work is needed? - -Work is tracked as issues in the [mojaloop/project](https://github.com/mojaloop/project) repository GitHub. You'll see issues there that are open and marked as bugs, stories, or epics. An epic is larger work that contains multiple stories. Start with any stories that are marked with "[good first issue](https://github.com/mojaloop/project/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)". In addition, anything that is in the backlog and not assigned to someone are things we could use help with. Stories that have owners are in someone's backlog already, though you can always ask about them in the issue or on Slack. - -There's a [roadmap](../mojaloop-roadmap.md) that shows larger work that people could do or are working on. It has some main initiatives and epics and the order, but lacks dates as this work is community driven. Work is broken down from there into issues in GitHub. - -In general, we are looking for example implementations and bug fixes, and project enhancements. - -### Where do I get help? - -Join the [Mojaloop Slack Discussions](https://mojaloop-slack.herokuapp.com/) to connect with other developers. - -Also checkout the [FAQ](https://github.com/mojaloop/documentation/blob/master/contributors-guide/frequently-asked-questions.md) - -### What is the current release? - -See the [Mojaloop Slack Announcements](https://mojaloop.slack.com/messages/CG3MAJZ5J) to find out information on the latest release. - -### What's here and what's not? - -This is free code provided under an [Apache 2.0 license](https://github.com/mojaloop/mojaloop/blob/master/LICENSE.md). - -The code is released with an Apache 2.0 license but the Specification documents under the 'mojaloop-specification' documents are published with CC BY-ND 4.0 License - -We don't provide production servers to run it on. That's up to you. You are free \(and encouraged!\) to clone these repositories, participate in the community of developers, and contribute back to the code. - -We are not trying to replace any mobile wallet or financial providers. We provide code to link together new and existing financial providers using a common scheme. There are central services for identifying a customer's provider, quoting, fulfillment, deferred net settlement, and shared fraud management. Each provider can take advantage of these services to send and receive money with others on the system and there's no cost to them to onboard new providers. We provide code for a simple example mobile money provider to show how integration can be done, but our example DFSP is not meant to be a production mobile money provider. - -## Where do I send bugs, questions, and feedback? - -For bugs, see [Reporting bugs](https://github.com/mojaloop/mojaloop/blob/master/contribute/Reporting-Bugs.md). - -### Related Projects - -The [Interledger Protocol Suite](https://interledger.org/) \(ILP\) is an open and secure standard that enables DFSPs to settle payments with minimal _counter-party risk_ \(the risk you incur when someone else is holding your money\). With ILP, you can transact across different systems with no chance that someone in the middle disappears with your money. Mojaloop uses the Interledger Protocol Suite for the clearing layer. - -## Types of Contributors - -There are three types of contributors that we are targeting for this phase of the Mojaloop project. - -### Developers or General Contributors - -These individuals are those that want to start contributing to the Mojaloop community. This could be a developer or quality assurance person that wants to write new code or fix a bug. This could also be a business, compliance or risk specialist that wants to help provide rules, write documentation or participate in requirements gathering. - -### Hub Operators - -Typically these or organizations or individuals or government agencies that are interested in setting up their own Mojaloop Switch to become part of the ecosystem. - -### Implementation Teams - -Implementation teams can assist banks, government offices, mobile operators or credit unions in deploying Mojaloop. - diff --git a/contributors-guide/new-contributor-checklist.md b/contributors-guide/new-contributor-checklist.md deleted file mode 100644 index a2ea91725..000000000 --- a/contributors-guide/new-contributor-checklist.md +++ /dev/null @@ -1,63 +0,0 @@ -# New Contributor Checklist - -This guide summarizes the steps needed to get up and running as a contributor to Mojaloop. They needn't be completed all in one sitting, but by the end of the checklist, you should have learned a good deal about Mojaloop, and be prepared to contribute to the community. - - -## 1. Tools & Documentation - -- Make sure you have a GitHub account already, or sign up for an account [here](https://github.com/join) - -- Join the slack community at the [self-invite link](https://mojaloop-slack.herokuapp.com/), and join the following channels: - - `#announcements` - Announcements for new Releases and QA Status - - `#design-authority` - Questions + Discussion around Mojaloop Design - - `#general` - General discussion about Mojaloop - - `#help-mojaloop` - Ask for help with installing or running Mojaloop - - `#ml-oss-bug-triage` - Discussion and triage for new bugs and issues - -- Say hi! Feel free to give a short introduction of yourself to the community on the `#general` channel. - -- Review the [Git workflow guide](https://mojaloop.io/documentation/contributors-guide/standards/creating-new-features.html) and ensure you are familiar with git. - - Further reading: [Introduction to Github workflow](https://www.atlassian.com/git/tutorials/comparing-workflows) - -- Familiarize yourself with our standard coding style: https://standardjs.com/ - -- Browse through the [Mojaloop Documentation](https://mojaloop.io/documentation/) and get a basic understanding of how the technology works. - -- Go through the [Developer Tools Guide](https://github.com/mojaloop/mojaloop/blob/master/onboarding.md) to get the necessary developer tools up and running on your local environment. - -- (Optional) Get the Central-Ledger up and running on local machines: - - https://github.com/mojaloop/central-ledger/blob/master/Onboarding.md - - https://github.com/mojaloop/ml-api-adapter/blob/master/Onboarding.md - -- (Optional:) Run an entire switch yourself with Kubernetes https://mojaloop.io/documentation/deployment-guide/ _(note: if running locally, your Kubernetes cluster will need 8gb or more of RAM)_ - -## 2. Finding an Issue - -- Review the [good-first-issue](https://github.com/mojaloop/project/labels/good%20first%20issue) list on [`mojaloop/project`](https://github.com/mojaloop/project), to find a good issue to start working on. Alternatively, reach out to the community on Slack at `#general` to ask for help to find an issue. - -- Leave a comment on the issue asking for it to be assigned to you -- this helps make sure we don't duplicate work. As always, reach out to us on Slack if you have any questions or concerns. - -- Fork the relevant repos for the issue, clone and create a new branch for the issue - - Refer to our [git user guide](https://mojaloop.io/documentation/contributors-guide/standards/creating-new-features.html) if you get lost - - -## 3. Opening your First PR - -> _Complete this part of the guide once you have been added to the Mojaloop GitHub organization. If you don't have access, reach out to us on the `#general` or `#help-mojaloop` - -- Sign up for [Zenhub](https://www.zenhub.com/), and connect it to the Mojaloop Organisation, Search for the _'project'_ workspace -- Install the [Zenhub Browser extension](https://www.zenhub.com/extension) for Chrome or Firefox, and browse the (Mojaloop Project Kanban board](https://github.com/mojaloop/project#zenhub) - -- When your branch is ready for review, open a new pull request from your repository back into the mojaloop project. - >_Note: if the CI/CD pipelines don't run, this may be because your Github account isn't added to the Mojaloop repo_ -- Ensure the following: - - A good description of the feature/bugfix you implemented - - The PR is _assigned_ to yourself - - You have assigned two or more _reviewers_. GitHub often has suggested reviewers, but if you don't know who to assign, feel free to ask whoever created the issue. - -- (Optional) Post a link to your PR on the `#ml-oss-devs` channel in Slack so everyone can share in the fun - - -## FAQs: - -> None as of yet. If you have problems getting through this list, or need more help, reach out to us on Slack! \ No newline at end of file diff --git a/contributors-guide/standards/README.md b/contributors-guide/standards/README.md deleted file mode 100644 index a8e6059d2..000000000 --- a/contributors-guide/standards/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Standards - -## Standards - -### Standards for adopting an Open Source contribution into Mojaloop - -This document provides guidelines regarding the adoption of a contribution to the Mojaloop Open Source repositories. - -#### Prerequisites - -1. The contribution should be in-line with the LevelOne Principles -2. Basic guidelines regarding status of the contribution \(Code-base / Standards / Designs / Specifications\) -3. Basic documentation to get started - -#### Guidelines regarding adoption - -1. Create a private repo on the Mojaloop GitHub organization -2. Have a sub-team of the DA take a look to make sure its portable \(to OSS\) - aligns with L1P principles, etc, and ensure design is in line with standards -3. Check Licensing -4. Assess Performance impact -5. Create action items \(stories\) to update naming, remove/sanitize any items that are not generic -6. Configuration for 'modes of operation' -7. Enable CI/CD pipeline - -### Versioning - -Review the information on [versioning](versioning.md) for Mojaloop. - -### Creating new Features - -Process for creating new [features and branches](creating-new-features.md) in Mojaloop. - -### Pull Request Process - -It's a good idea to ask about major changes on [Slack](https://mojaloop.slack.com). Submit pull requests which include both the change and the reason for the change. Pull requests will be denied if they violate the [Level One Principles](https://leveloneproject.org/wp-content/uploads/2016/03/L1P_Level-One-Principles-and-Perspective.pdf) - -### Code of conduct - -We use a [standard developer code of conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html) - -### Licensing - -See [License](https://github.com/mojaloop/mojaloop/blob/master/contribute/License.md) policy diff --git a/contributors-guide/standards/creating-new-features.md b/contributors-guide/standards/creating-new-features.md deleted file mode 100644 index 21e009b0a..000000000 --- a/contributors-guide/standards/creating-new-features.md +++ /dev/null @@ -1,46 +0,0 @@ -# Creating new Features - -### Fork - -Fork the Mojaloop repository into your own personal space. Ensure that you keep the `master` branch in sync. - -Refer to the following documentation for more information: [https://help.github.com/articles/fork-a-repo/](https://help.github.com/articles/fork-a-repo/) - -1. Clone repo using Git Fork button \(refer to the above documentation for more information\) -2. Clone your forked repo: `git clone https://github.com//.git` -3. Synchronise your forked repo with Mojaloop - - Add a new upstream repo for Mojaloop `$ git remote add mojaloop https://github.com/mojaloop/.git` - - You should now see that you have two remotes: - - ```bash - git remote -v - origin https://github.com//.git (fetch) - origin https://github.com//.git (push) - mojaloop https://github.com/mojaloop/.git (fetch) - mojaloop https://github.com/mojaloop/.git (push) - ``` - -4. To sync to your current branch: `git pull mojaloop ` This will merge any changes from Mojaloop's repo into your forked repo. -5. Push the changes back to your remote fork: `git push origin ` - -### Creating a Branch - -Create a new branch from the `master` branch with the following format: `/` where `issue#` can be attained from the Github issue, and the `issueDescription` is the issue description formatted in CamelCase. - -1. Create and checkout the branch: `git checkout -b /` -2. Push the branch to your remote: `git push origin /` - -Where `` can be one of the following: - -| branchType | Description | -| :--- | :--- | -| feature | Any new or maintenance features that are in active development. | -| hotfix | A hotfix branch is for any urgent fixes. | -| release | A release branch containing a snapshot of a release. | -| backup | A temporary backup branch. Used normally during repo maintenance. | - -### Merge into Mojaloop Repo - -Once the feature is completed create a PR from your Feature Branch into the `master` branch on the Mojaloop repository \(not your personal repo\) for approval, and check validations \(e.g. unit tests, code coverage, etc executed via CircieCI\). diff --git a/contributors-guide/standards/versioning.md b/contributors-guide/standards/versioning.md deleted file mode 100644 index 350f77758..000000000 --- a/contributors-guide/standards/versioning.md +++ /dev/null @@ -1,53 +0,0 @@ -# Versioning - -## Versioning of releases made for core Switch services - -This document provides guidelines regarding the versioning strategy used for the releases of Mojaloop Open Source repositories corresponding to the Switch services. - -### Versioning Strategy - -1. The current versioning system is inspired by the [Semantic Versioning](https://semver.org/) numbering system for releases. -2. However, this is customized to depict the timelines of the Mojaloop project, based on the Program Increment \(PI\) and Sprint numbers -3. For example, the release number v5.1.0 implies that this release was the first one made during a Sprint 5.1, where Sprint5.1 is the first Sprint in PI-5. So for a version vX.Y.Z, X.Y is the Sprint number where X is the PI number and Z represents the number of release for this specific repository. Example v4.4.4 implies that the current release is the fourth of four releases made in Sprint 4.4 \(of PI-4\) - -### Current Version - -The currrent version information for Mojaloop can be found [here](../../deployment-guide/releases.md). - -### Sprint schedule for PI9 - -Below is the Sprint schedule for Program Increment 9 which ends with the PI 10 on-site event at the of January 2020 in Tanzania. Please use this as guidance during the versioning and release processes. - -|Phase/Milestone|Start|End|Weeks|Notes| -|---|---|---|---|---| -|**Phase-3 PI6 On-site**|4/16/2019|4/18/2019|3 days| Johannesburg| -|**Phase-3 PI7 On-site**|6/25/2019|6/27/2019|3 days| Arusha| -|**Phase-3 PI8 On-site**|9/10/2019|9/12/2019|3 days| Abidjan| -|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| -|**Sprint 9.1**|2/3/2020|2/16/2020|2 weeks| | -|**Sprint 9.2**|2/17/2020|3/1/2020|2 weeks| | -|**Sprint 9.3**|3/2/2020|3/15/2020|2 weeks| | -|**Sprint 9.4**|3/16/2020|3/29/2020|2 weeks| | -|**Sprint 9.5**|3/30/2020|4/12/2020|2 weeks| | -|**Sprint 9.6**|3/13/2020|4/19/2020|1 week | | -|**Phase-4 PI 10 On-site**|4/21/2020|4/23/2020|3 days| Tanzania | - -### Previous Sprint Schedules: - -#### PI8 -|Phase/Milestone|Start|End|Weeks|Notes| -|---|---|---|---|---| -|**Sprint 8.1**|9/16/2019|9/29/2019|2 weeks| | -|**Sprint 8.2**|9/30/2019|10/13/2019|2 weeks| | -|**Sprint 8.3**|10/14/2019|10/27/2019|2 weeks| | -|**Sprint 8.4**|10/28/2019|11/10/2019|2 weeks| | -|**Sprint 8.5**|11/11/2019|11/24/2019|2 weeks| | -|**Sprint 8.6**|11/25/2019|12/8/2019|2 weeks| | -|**Sprint 8.7**|12/9/2019|1/5/2020|4 weeks| Christmas Break| -|**Sprint 8.8**|1/6/2020|1/26/2020|3 weeks| 1 week prep| -|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| - -### Notes - -1. A new release for **helm** repo is made whenver a configuration change is needed for any of the core Switch services based on the changes made \(features, bug-fixes\). -2. However, if there is no release made to helm necessitated by a configuration change, then a release is done every Sprint anyway, to bring it up to date with the latest releases on the core Switch services. diff --git a/contributors-guide/tools-and-technologies/automated-testing.md b/contributors-guide/tools-and-technologies/automated-testing.md deleted file mode 100644 index cc6c42ca9..000000000 --- a/contributors-guide/tools-and-technologies/automated-testing.md +++ /dev/null @@ -1,138 +0,0 @@ -# QA and Regression Testing in Mojaloop -An overview of the testing framework set up in Mojaloop - -Contents: -1. [Regression requirements](#regression-topics) -2. [Developer Testing](#developer-testing) -3. [Postman and Newman Testing](#postman-and-newman-testing) -4. [Executing regression test](#executing-regression-test) -5. [Process flow of a typical Scheduled Test](#process-flow-of-a-typical-scheduled-test) -6. [Newman Commands](#newman-commands) - -## Regression Topics - In order for a deployed system to be robust, one of the last checkpoints is to determine if the environment it is deployed in, is in a healthy state and all exposed functionality works exactly the way as intended. - - Prior to that though, there are quite a number of disciplines one must put in place to ensure maximum control. - - To illustrate how the Mojaloop project reaches this goal, we are going to show you the various checkpoints put in place. - -### Developer Testing - Looking at each component and module, inside the code base, you will find a folder named "*test*" which contain three types of tests. - + Firstly, the *coverage test* which alerts one if there are unreachable or redundant code - + Unit Tests, which determines if the intended functionality works as expected - + Integration Tests, which does not test end-to-end functionality, but the immediate neighbouring interaction - + Automated code-standard checks implemented by means of packages that form part of the code base - - These tests are executed by running the command line instructions, by the developer, during the coding process. Also, the tests are automatically executed every time a *check-in* is done and a Github Pull-Request issued for the code to be integrated into the project. - - The procedure described above, falls outside the realm of Quality Assurance (QA) and Regression testing, which this document addresses. - - Once a developer has written new functionality or extended existing functionality, by having to go through the above rigorous tests, one can assume the functionality in question is executing as intended. How does one then ensure that this new portion of code does not negatively affect the project or product as a whole? - - When the code has passed all of the above and is deployed as part of the CI/CD processes implemented by our workflow, the new component(s) are accepted onto the various hosts, cloud-based or on-premise implementations. These hosts ranges from development platforms through to production environments. - -### Postman and Newman Testing - Parallel to the deployment process is the upkeep and maintenance of the [Postman](https://github.com/mojaloop/postman.git "Postman") Collection testing Framework. When a new release is done, as part of the workflow, Release Notes are published listing all of the new and/or enhanced functionality implemented as part of the release. These notes are used by the QA team to extend and enhance the existing Postman Collections where tests are written behind the request/response scripts to test both positive as well as negative scenarios agains the intended behaviour. These tests are then run in the following manner: - + Manually to determine if the tests cover all aspects and angles of the functionality, positive to assert intended behaviour and negative tests to determine if the correct alternate flows work as intended when something unexpected goes wrong - + Scheduled - as part of the Regression regime, to do exactly the same as the manual intent, but fully automated (with the *Newman Package*) with reports and logs produced to highlight any unintended behaviour and to also warn where known behaviour changed from a previous run. - -In order to facilitate the automated and scheduled testing of a Postman Collection, there are various methods one can follow and the one implemented for Mojaloop use is explained further down in this document. - -There is a complete repository containing all of the scripts, setup procedures and anything required in order to set up an automated [QA and Regression Testing Framework](https://github.com/mojaloop/ml-qa-regression-testing.git "QA and Regression Testing Framework"). This framework allows one to target any Postman Collection, specifying your intended Environment to execute against, as well as a comma-separated list of intended email recipients to receive the generated report. This framework is in daily use by Mojaloop and exists on an EC2 instance on AWS, hosting the required components like Node, Docker, Email Server and Newman, as well as various Bash Scripts and Templates for use by the framework to automatically run the intended collections every day. Using this guide will allow anyone to set up their own Framework. - -#### Postman Collections - -There are a number of Postman collections in use throughout the different processes: -+ [OSS-New-Deployment-FSP-Setup](https://github.com/mojaloop/postman/blob/master/OSS-New-Deployment-FSP-Setup.postman_collection.json) : This collection needs to be executed once after a new deployment, normally by the Release Manager, to seed the Database with the required enumerations and static data, as well as test FSPs with their accounts and position data in order to be able to execute any manual or automation tests by other collections. - + Notes: Ensure that there is a delay of `200ms` if executed through Postman UI Test Runner. This will ensure that tests have enough time to validate requests against the simulator. -+ [OSS-API-Tests](https://github.com/mojaloop/postman/blob/master/OSS-API-Tests.postman_collection.json) : This suite of tests will issue a request/response against each and every exposed API, testing APIs such as the Mojaloop core APIs, bulk quotes, admin-APIs, Settlement APIs, Metrics APIs, Fund-in and out APIs etc. These tests are done to test the message headers, body, responses received and not to test the end-to-end flow of a transfer for example - + Notes: Ensure that there is a delay of `1500ms` if executed through Postman UI Test Runner. This will ensure that tests have enough time to validate requests against the simulator. -+ [OSS-Feature-Tests](https://github.com/mojaloop/postman/blob/master/OSS-Feature-Tests.postman_collection.json) : Scenario based testing are performed with this collection, such as Settlements processes, Block Transfers, Negative testing scenarios and so on - + Notes: Ensure that there is a delay of `1500ms` if executed through Postman UI Test Runner. This will ensure that tests have enough time to validate requests against the simulator. -+ [Golden_Path](https://github.com/mojaloop/postman/blob/master/Golden_Path.postman_collection.json) : This test collection is the one used by the scheduled regression testing framework to test end-to-end scenarios, resembling real-world use-cases where the response from one API call is used to populate the request of a subsequent call. We make use of an intelligent simulator playing the role of an FSP on the recipient side of the scenario, responding to various request from a Payer FSP as an example - + Notes: Ensure that there is a delay of `1500ms` if executed through Postman UI Test Runner. This will ensure that tests have enough time to validate requests against the simulator. - -#### Environment Configuration - -You will need to customize the following environment config file to match your deployment environment: -+ [Local Environment Config](https://github.com/mojaloop/postman/blob/master/environments/Mojaloop-Local.postman_environment.json) - -_Tips:_ -- _The host configurations will be the most likely changes required to match your environment. e.g. `HOST_CENTRAL_LEDGER: http://central-ledger.local`_ -- _Refer to the ingress hosts that have been configured in your `values.yaml` as part of your Helm deployment._ - -### Executing regression test -For the Mojaloop QA and Regression Testing Framework specifically, Postman regression test can be executed by going into the EC2 instance via SSH, for which you need the PEM file, and then by running a script(s). - -Following the requirements and instructions as set out in the detail in [QA and Regression Testing Framework](https://github.com/mojaloop/ml-qa-regression-testing.git "QA and Regression Testing Framework"), everyone will be able to create their own Framework and gain access to their instance to execute tests against any Postman Collection targeting any Environment they have control over. - -##### Steps to execute the script via Postman UI -+ Import the desired collection into your Postman UI. You can either download the collection from the repo or alternatively use the `RAW` link and import it directly via the **import link** option. -+ Import the environment config into your Postman UI via the Environmental Config setup. Note that you will need to download the environmental config to your machine and customize it to your environment. -+ Ensure that you have pre-loaded all prerequisite test data before executing transactions (party, quotes, transfers) as per the example collection [OSS-New-Deployment-FSP-Setup](https://github.com/mojaloop/postman/blob/master/OSS-New-Deployment-FSP-Setup.postman_collection.json): - + Hub Accounts - + FSP onboarding - + Add any test data to Simulator (if applicable) - + Oracle onboarding -+ The `p2p_money_transfer` test cases from the [Golden_Path](https://github.com/mojaloop/postman/blob/master/Golden_Path.postman_collection.json) collection are a good place to start. - -##### Steps to execute the bash script to run the Newman / Postman test via CLI -+ To run a test via this method, you will have to be in posession of the PEM-file of the server on which the Mojaloop QA and Regression Framework was deployed on an EC2 instance on Amazon Cloud. - -+ SSH into the specific EC2 instance and when running the script, it will in turn run the commands via an instantiated Docker container. - -+ You will notice that by using this approach where both the URLs for the Postman-Collection and Environment File are required as input parameters (together with a comma-delimited email recipient list for the report) you have total freedom of executing any Postman Collection you choose. - -+ Also, by having an Environment File, the specific Mojaloop services targeted can be on any server. This means you can execute any Postman test against any Mojaloop installation on any server of your choice. - -+ The EC2 instance we execute these tests from are merely containing all the tools and processes in order to execute your required test and does not host any Mojaloop Services as such. - -``` -./testMojaloop.sh -``` - -## Process flow of a typical Scheduled Test - -{% uml src="contributors-guide/tools-and-technologies/assets/diagrams/automated-testing/QARegressionTestingMojaloop-Complete.plantuml" %} -{% enduml %} - -## Newman Commands -The following section is a reference, obtained from the Newman Package site itself, highlighting the different commands that may be used in order to have access to the Postman environment by specifying some commands via the CLI. -``` -Example: -+ newman run -e -n 1 -- - -Usage: run [options] - - URL or path to a Postman Collection. - - Options: - - -e, --environment Specify a URL or Path to a Postman Environment. - -g, --globals Specify a URL or Path to a file containing Postman Globals. - --folder Specify folder to run from a collection. Can be specified multiple times to run multiple folders (default: ) - -r, --reporters [reporters] Specify the reporters to use for this run. (default: cli) - -n, --iteration-count Define the number of iterations to run. - -d, --iteration-data Specify a data file to use for iterations (either json or csv). - --export-environment Exports the environment to a file after completing the run. - --export-globals Specify an output file to dump Globals before exiting. - --export-collection Specify an output file to save the executed collection - --postman-api-key API Key used to load the resources from the Postman API. - --delay-request [n] Specify the extent of delay between requests (milliseconds) (default: 0) - --bail [modifiers] Specify whether or not to gracefully stop a collection run on encountering an errorand whether to end the run with an error based on the optional modifier. - -x , --suppress-exit-code Specify whether or not to override the default exit code for the current run. - --silent Prevents newman from showing output to CLI. - --disable-unicode Forces unicode compliant symbols to be replaced by their plain text equivalents - --global-var Allows the specification of global variables via the command line, in a key=value format (default: ) - --color Enable/Disable colored output. (auto|on|off) (default: auto) - --timeout [n] Specify a timeout for collection run (in milliseconds) (default: 0) - --timeout-request [n] Specify a timeout for requests (in milliseconds). (default: 0) - --timeout-script [n] Specify a timeout for script (in milliseconds). (default: 0) - --ignore-redirects If present, Newman will not follow HTTP Redirects. - -k, --insecure Disables SSL validations. - --ssl-client-cert Specify the path to the Client SSL certificate. Supports .cert and .pfx files. - --ssl-client-key Specify the path to the Client SSL key (not needed for .pfx files) - --ssl-client-passphrase Specify the Client SSL passphrase (optional, needed for passphrase protected keys). - -h, --help output usage information -``` - diff --git a/contributors-guide/tools-and-technologies/license-scanning.md b/contributors-guide/tools-and-technologies/license-scanning.md deleted file mode 100644 index 7cf041946..000000000 --- a/contributors-guide/tools-and-technologies/license-scanning.md +++ /dev/null @@ -1,21 +0,0 @@ -# License Scanning - -## Motivation - -As an open source project, Mojaloop must remain free of so called ['viral' licenses](https://en.wikipedia.org/wiki/Viral_license) in any dependencies which are incompatible with the license of the project. - -In order to scan the licenses across all mojaloop subprojects, we made a tool called [`license-scanner`](https://github.com/vessels-tech/license-scanner). Using this tool we can, en masse: - -- run `fossa-cli` across the entire codebase and upload the reports to the Fossa Website (requires a Fossa API Key) -- run `npm-license-checker` across the codebase and export a `.xlsx` file for manually verifying the licenses - - -## Using `license-scanner` - ->Note: `license-scanner` is currently in Vessel Tech's company github repo, but may be brought into the core mojaloop project in the future. - -You can find `license-scanner` [here](https://github.com/vessels-tech/license-scanner). Follow the instructions in the readme to get up and running. - -## CI/CD Pipeline - -We are currently in the process of integrating license scans into the CI/CD Pipeline \ No newline at end of file diff --git a/deployment-guide/README.md b/deployment-guide/README.md deleted file mode 100644 index 05e559973..000000000 --- a/deployment-guide/README.md +++ /dev/null @@ -1,257 +0,0 @@ -# Mojaloop Deployment - -The document is intended for an audience with a stable technical knowledge that would like to setup an environment for development, testing and contributing to the Mojaloop project. - -## Deployment and Setup - -- [Pre-requisites](#1-pre-requisites) -- [Kubernetes](#3-kubernetes) - - [Kubernetes Dashboard](#31-kubernetes-dashboard) -- [Helm](#4-helm) - - [Helm configuration](#41-helm-configuration) -- [Postman](#6-postman) - - [Installing Postman](#61-installing-postman) - - [Setup Postman](#62-setup-postman) - -### 1. Pre-requisites - -A list of the pre-requisite tool set required for the deployment of Mojaloop; -- **Kubernetes** An open-source system for automating deployment, scaling, and management of containerized applications. Find out more about [Kubernetes](https://kubernetes.io), - - kubectl - Kubernetes CLI for Kubernetes Management is required. Find out more about [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/), - - [Install-kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/), - - microk8s - MicroK8s installs a barebones upstream Kubernetes for a single node deployment generally used for local development. We recommend this installation on Linux (ubuntu) OS. Find out more about [microk8s](https://microk8s.io/) and [microk8s documents](https://microk8s.io/docs/), - - [Install-microk8s](https://microk8s.io/docs/), - - kubectx - Not required but useful. Find out more about [kubectx](https://github.com/ahmetb/kubectx), - - kubetail - Not required but useful. Bash script that enables you to aggregate (tail/follow) logs from multiple pods into one stream. Find out more about [kubetail](https://github.com/johanhaleby/kubetail), -- **Docker** Provides containerized environment to host the application. Find out more about [Docker](https://docker.com), -- **Helm** A package manager for Kubernetes. Find out more about [Helm](https://helm.sh), -- **Postman** Postman is a Google Chrome application for the interacting with HTTP API's. It presents you with a friendly GUI for the construction requests and reading responces. https://www.getpostman.com/apps. Find out more about [Postman](https://postman.com). - -For **local guides** on how to setup the pre-requisites on your laptop or desktop, refer to the appropriate link document below; -- [Local Setup for Mac](local-setup-mac.md) -- [Local Setup for Linux](local-setup-linux.md) -- [Local Setup for Windows](local-setup-windows.md) - -### 2. Deployment Recommendations - -This provides environment resource recommendations with a view of the infrastructure architecture. - -**Resources Requirements:** - -* Control Plane (i.e. Master Node) - - [https://kubernetes.io/docs/setup/cluster-large/#size-of-master-and-master-components](https://kubernetes.io/docs/setup/cluster-large/#size-of-master-and-master-components) - - * 3x Master Nodes for future node scaling and HA (High Availability) - -* ETCd Plane: - - [https://etcd.io/docs/v3.3.12/op-guide/hardware](https://etcd.io/docs/v3.3.12/op-guide/hardware) - - * 3x ETCd nodes for HA (High Availability) - -* Compute Plane (i.e. Worker Node): - - TBC once load testing has been concluded. However the current general recommended size: - - * 3x Worker nodes, each being: - * 4x vCPUs, 16GB of RAM, and 40gb storage - - **Note** that this would also depend on your underlying infrastructure, and it does NOT include requirements for persistent volumes/storage. - -![Mojaloop Deployment Recommendations - Infrastructure Architecture](./assets/diagrams/deployment/KubeInfrastructureArch.svg) - -### 3. Kubernetes - -This section will guide the reader through the deployment process to setup Kubernetes. - -If you are new to Kubernetes it is strongly recommended to familiarize yourself with Kubernetes. [Kubernetes Concepts](https://kubernetes.io/docs/concepts/overview/) is a good place to start and will provide an overview. - -The following are Kubernetes concepts used within the project. An understanding of these concepts is imperative before attempting the deployment; - -* Deployment -* Pod -* ReplicaSets -* Service -* Ingress -* StatefulSet -* DaemonSet -* Ingress Controller -* ConfigMap -* Secret - -Insure **kubectl** is installed. A complete set of installation instruction are available [here](https://kubernetes.io/docs/tasks/tools/install-kubectl/). - -#### 3.1. Kubernetes Dashboard: - -1. Kubernetes Dashboard roles, services & deployment. - - Install for Dashboard using Helm (not needed if **MicroK8s** is installed): [kubernetes-dashboard](https://github.com/helm/charts/tree/master/stable/kubernetes-dashboard) - - **IMPORTANT:** Always verify the current [kubernetes-dashboard](https://github.com/kubernetes/dashboard) yaml file is still correct as used in the below command. - ```bash - kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml - ``` - - If you have installed MicroK8s, **enable the MicroK8s** dashboard; - ```bash - microk8s.enable dashboard - ``` - **Remember** to prefix all **kubectl** commands with **microk8s** if you opted not to create an alias. - -2. Verify Kubernetes Dashboard. _Windows replace `grep` with `findstr`_; - ```bash - kubectl get pod --namespace=kube-system |grep dashboard - ``` - -3. Start proxy for local UI in new terminal; - ```bash - kubectl proxy ui - ``` - -4. Open URI in default browser: - - ``` - http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ - ``` - - Select **Token**. Generate a token to use there by: _Windows replace `grep` with `findstr`_ - - ```bash - kubectl -n kube-system get secrets | grep dashboard-token - ``` - - The token to use is shown on the last line of the output of that command; - - ```bash - kubectl -n kube-system describe secrets/kubernetes-dashboard-token-btbwf - ``` - - The **{kubernetes-dashboard-token-btbwf}** is retrieved from the output in the previous step. For more information on generating the token, follow the **Authentication** link in the window. - -![kubernetes-dashboard](./assets/diagrams/deployment/kubernetesDashboard.png) - -### 4. Helm - -Please review [Mojaloop Helm Chart](../repositories/helm.md) to understand the relationships between the deployed Mojaloop helm charts. - -#### 4.1. Helm configuration - -1. Config Helm CLI and install Helm Tiller on K8s cluster: - ```bash - helm init - ``` - _Note: if `helm init` fails with `connection refused error`, refer to [troubleshooting](./deployment-troubleshooting.md#helm_init_connection_refused)_ - -2. Validate Helm Tiller is up and running. _Windows replace `grep` with `findstr`_: - ```bash - kubectl -n kube-system get po | grep tiller - ``` - -3. Add mojaloop repo to your Helm config (optional). _Linux use with sudo_: - ```bash - helm repo add mojaloop http://mojaloop.io/helm/repo/ - ``` - If the repo already exists, substitute 'add' with 'apply' in the above command. - -4. Add the additional dependency Helm repositories. This is needed to resolve Helm Chart dependencies required by Mojaloop charts. Linux use with sudo; - ```bash - helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator - helm repo add kiwigrid https://kiwigrid.github.io - helm repo add elastic https://helm.elastic.co - ``` - -5. Update helm repositories. _Linux use with sudo_: - ```bash - helm repo update - ``` - -6. Install nginx-ingress for load balancing & external access. _Linux use with sudo_: - ```bash - helm --namespace kube-public install stable/nginx-ingress - ``` - -### 5. Mojaloop - -#### 5.1. Mojaloop Helm Deployment - -1. Install Mojaloop. _Linux use with sudo_: - - Default installation: - ```bash - helm --namespace demo --name moja install mojaloop/mojaloop - ``` - - Version specific installation: - ```bash - helm --namespace demo --name moja install mojaloop/mojaloop -version {version} - ``` - - List of available versions: - ```bash - helm search -l mojaloop/mojaloop - ``` - - Custom configured installation: - ```bash - helm --namespace demo --name moja install mojaloop/mojaloop -f {custom-values.yaml} - ``` - _Note: Download and customize the [values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml). Also ensure that you are using the value.yaml from the correct version which can be found via [Helm Releases](https://github.com/mojaloop/helm/releases)._ - -#### 5.2. Verifying Mojaloop Deployment - -1. Update your /ect/hosts for local deployment: - - _Note: This is only applicable for local deployments, and is not needed if custom DNS or ingress rules are configured in a customized [values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml)_. - - ```bash - vi /etc/hosts - ``` - _Windows the file can be updated in notepad - need to open with Administrative privileges. File location `C:\Windows\System32\drivers\etc\hosts`_. - - Include the following lines (_or alternatively combine them_) to the host config. - - The below required config is applicable to Helm release >= versions 6.2.2 for Mojaloop API Services; - ```text - 127.0.0.1 central-ledger.local central-settlement.local ml-api-adapter.local account-lookup-service.local account-lookup-service-admin.local quoting-service.local moja-simulator.local central-ledger central-settlement ml-api-adapter account-lookup-service account-lookup-service-admin quoting-service simulator host.docker.internal - ``` - - The below optional config is applicable to Helm release >= versions 6.2.2 for Internal components, please include the following in the host configuration. - ```text - 127.0.0.1 forensic-logging-sidecar.local central-kms.local central-event-processor.local email-notifier.local - ``` - - For Helm legacy releases prior to versions 6.2.2, please include the following in the host configuration. - ```text - 127.0.0.1 interop-switch.local central-end-user-registry.local central-directory.local central-hub.local - ``` - -2. Test system health in your browser after installation. This will only work if you have an active helm chart deployment running. - - _Note: The examples below are only applicable to a local deployment. The entries should match the DNS values or ingress rules as configured in the [values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml) or otherwise matching any custom ingress rules configured_. - - **ml-api-adapter** health test: - ``` - http://ml-api-adapter.local/health - ``` - - **central-ledger** health test: - ``` - http://central-ledger.local/health - ``` - -### 6. Postman - -Postman is used to send requests and receive responses. - -#### 6.1. Installing Postman - -Please, follow these instructions: [Get Postman](https://www.getpostman.com/postman) and install the Postman application. - -#### 6.2. Setup Postman - -Grab the latest collections & environment files from [Mojaloop Postman Github repo](https://github.com/mojaloop/postman): [https://github.com/mojaloop/postman](https://github.com/mojaloop/postman) - -After an initial setup or new deployment, the [OSS New Deployment FSP Setup section](../contributors-guide/tools-and-technologies/automated-testing.md) needs to be completed. This will seed the Database with the required enumerations and static data to enable the sucessful execution of any manual or automation tests by the other collections. - -Refer to the [QA and Regression Testing in Mojaloop](../contributors-guide/tools-and-technologies/automated-testing.md) documentation for more complete information to complement your testing requirements. diff --git a/deployment-guide/assets/diagrams/deployment/KubeInfrastructureArch.svg b/deployment-guide/assets/diagrams/deployment/KubeInfrastructureArch.svg deleted file mode 100644 index b6dc2bb11..000000000 --- a/deployment-guide/assets/diagrams/deployment/KubeInfrastructureArch.svg +++ /dev/null @@ -1,2 +0,0 @@ - -
3x Master
Nodes

[Not supported by viewer]
3x ETCd
Nodes

[Not supported by viewer]
Alt: DSN Round Robin Fail-over
Alt: DSN Round Robin Fail-over
Layer 4 Load Balancer
<font style="font-size: 14px">Layer 4 Load Balancer</font>
Firewall
Firewall
DMZ
[Not supported by viewer]
External
Consumer

[Not supported by viewer]
3x Worker
Nodes

[Not supported by viewer]
KEY
[Not supported by viewer]
Ingress Controller deployed as a DaemonSet
[Not supported by viewer]
\ No newline at end of file diff --git a/deployment-guide/deployment-troubleshooting.md b/deployment-guide/deployment-troubleshooting.md deleted file mode 100644 index a84d11156..000000000 --- a/deployment-guide/deployment-troubleshooting.md +++ /dev/null @@ -1,182 +0,0 @@ -# Deployment Troubleshooting - -## Local deployment with MicroK8s - suggestions: - -- use **v1.15 of MicroK8s** (higher version not yet supported) (details in "Installation of mojaloop helm charts fail with validation failed" section) -- try `microk8s.inspect` for hints (for example connectivity problems when ip forwarding is not enabled, more about it in "MicroK8s - Connectivity Issues section") -- enable following microk8s add-ons (check with `sudo microk8s.status`): - - storage - - ingress - - dns - - istio - - dashboard - -## 1. Known issues - -### 1.1. Mojaloop Helm Charts does not support Kubernetes v1.16 or greater - -#### Description - -When installing mojaloop helm charts, the following error occurs: - - ``` - Error: validation failed: [unable to recognize "": no matches for kind "Deployment" in version "apps/v1beta2", unable to recognize "": no matches for kind "Deployment" in version "extensions/v1beta1", unable to recognize "": no matches for kind "StatefulSet" in version "apps/v1beta2", unable to recognize "": no matches for kind "StatefulSet" in version "apps/v1beta1"] - ``` - -#### Reason - -In version 1.16 of Kubernetes breaking change has been introduced (more about it [in "Deprecations and Removals" of Kubernetes release notes](https://kubernetes.io/docs/setup/release/notes/#deprecations-and-removals). The Kubernetes API versions `apps/v1beta1` and `apps/v1beta2`are no longer supported and and have been replaced by `apps/v1`. - -Currently Mojaloop helm charts (as of v8.4.x) refer to deprecated ids, therefore it's not possible to install current Mojaloop charts on Kubernetes version above 1.15 without manually changing charts. - -Refer to the following issue for more info: [mojaloop/helm#219](https://github.com/mojaloop/helm/issues/219) - -#### Fixes - -Ensure that you are deploying the Mojaloop Helm charts on v1.15 of Kubernetes (or microk8s when working locally). - -#### Additional details for `microk8s` fix - -To check version of `microk8s`: - ```bash - snap info microk8s - ``` -_Note: Look at the end of the output for a row starting with "installed"_ - -To install most recent supported version: - ```bash - snap refresh microk8s --channel=1.15/stable --classic - ``` - - -## 2. Deployment issues - -### 2.1. MicroK8s - helm init connection refused - -#### Description - -The helm init: - - ```bash - helm init - ``` - -fails with error when installing locally on `microk8s`: - - ``` - Error: error installing: Post http://localhost:8080/apis/apps/v1/namespaces/kube-system/deployments: dial tcp 127.0.0.1:8080: connect: connection refused - ``` - -#### Reason - -This may be a missing `~/.kube/config` file, where helm looks for connection details. - -#### Fix - option #1 - -One of the solutions is to generate that file by issuing: - - ```bash - microk8s.kubectl config view --raw > $HOME/.kube/config - ``` - -#### Fix - option #2 - -Another option is to export the config to a new file: - - ```bash - microk8s.kubectl config view --raw > $HOME/.kube/local.config - ``` - -And then export the following env var: - - ```bash - export KUBECONFIG=$HOME/.kube/local.config - ``` - -### 2.2. `ERR_NAME_NOT_RESOLVED` Error - -#### Description - -The following error is displayed when attempting to access an end-point (e.g. central-ledger.local) via the Kubernetes Service directly in a browser: `ERR_NAME_NOT_RESOLVED` - -#### Fixes - - * Verify that that Mojaloop was deployed by checking that the helm chart(s) was installed by executing: - - ```bash - helm list - ``` - - If the helm charts are not listed, see the [Helm Chart Installation](README.md#4-helm) section to install a chart. - - * Ensure that all the Mojaloop Pods/Containers have started up correctly and are available through the Kubernetes dashboard. - - * Note that the Mojaloop deployment via Helm can take a few minutes to initially startup depending on the system's available resources and specification. It is recommended that you wait at least 10m for all Pods/Containers to self heal before troubleshooting. - -### 2.3. MicroK8s - Connectivity Issues - -#### Description - -My pods can’t reach the internet or each other (but my MicroK8s host machine can). - -An example of this is that the Central-Ledger logs indicate that there is an error with the Broker transport as per the following example: -``` -2019-11-05T12:28:10.470Z - info: Server running at: -2019-11-05T12:28:10.474Z - info: Handler Setup - Registering {"type":"prepare","enabled":true}! -2019-11-05T12:28:10.476Z - info: CreateHandler::connect - creating Consumer for topics: [topic-transfer-prepare] -2019-11-05T12:28:10.515Z - info: CreateHandler::connect - successfully connected to topics: [topic-transfer-prepare] -2019-11-05T12:30:20.960Z - error: Consumer::onError()[topics='topic-transfer-prepare'] - Error: Local: Broker transport failure) -``` - -#### Fixes - -Make sure packets to/from the pod network interface can be forwarded to/from the default interface on the host via the iptables tool. Such changes can be made persistent by installing the iptables-persistent package: - -```bash -sudo iptables -P FORWARD ACCEPT -sudo apt-get install iptables-persistent -``` - -or, if using ufw: - - -```bash -sudo ufw default allow routed -``` -The MicroK8s inspect command can be used to check the firewall configuration: - -```bash -microk8s.inspect -``` - - -## 3. Ingress issues - -### 3.1. Ingress rules are not resolving for Nginx Ingress v0.22 or later - -#### Description - -Ingress rules are unable to resolve to the correct path based on the annotations specified in the values.yaml configuration files when using Nginx Ingress controllers v0.22 or later. - -This is due to the changes introduced in Nginx Ingress controllers that are v0.22 or later as per the following link: https://kubernetes.github.io/ingress-nginx/examples/rewrite/#rewrite-target. - -#### Fixes - - * Make the following change to all Ingress annotations (from --> to) in each of the values.yaml files: - - `nginx.ingress.kubernetes.io/rewrite-target: '/'` --> `nginx.ingress.kubernetes.io/rewrite-target: '/$1'` - - -### 3.2. Ingress rules are not resolving for Nginx Ingress earlier than v0.22 - -#### Description - -Ingress rules are unable to resolve to the correct path based on the annotations specified in the values.yaml configuration files when using Nginx Ingress controllers that are older than v0.22. - -This is due to the changes introduced in Nginx Ingress controllers that are v0.22 or later as per the following link: https://kubernetes.github.io/ingress-nginx/examples/rewrite/#rewrite-target. - -#### Fixes - - * Make the following change to all Ingress annotations (from --> to) in each of the values.yaml files: - - `nginx.ingress.kubernetes.io/rewrite-target: '/$1'` --> `nginx.ingress.kubernetes.io/rewrite-target: '/'` diff --git a/deployment-guide/local-setup-linux.md b/deployment-guide/local-setup-linux.md deleted file mode 100644 index cc10fd4bf..000000000 --- a/deployment-guide/local-setup-linux.md +++ /dev/null @@ -1,111 +0,0 @@ -# Mojaloop Setup for Linux (Ubuntu) - -Local setup on a Laptop or Desktop to run the Mojaloop project. - -## Setup Introduction - -This document will provide guidelines to a technical capable resources to setup, deploy and configure the Mojaloop applications on a local environment, utilizing Docker, Kubernetes and HELM charts. - -At this point the reader/implementer should be familiar with [Mojaloop's deployment guide](./README.md). Imported information is contained in that document and as such a prerequisite to this document. - -* [Environment recommendations](#1-environment-recommendations) - * [Kubernetes](#2-kubernetes) - * [MicroK8S](#21-microk8s) - * [Docker](#12-docker) -* [Useful Tips](#2-useful-tips) - -## 1. Environment recommendations - -This environment setup was validated on: - * 64-bit version of Ubuntu Bionic 18.04(LTS). - * This guide is based on Ubuntu 18.04.2 (bionic) on a x86_64 desktop with 8 CPU's and 16GB RAM. - -## 2. Kubernetes - -Kubernetes installation for a local environment. - -#### 2.1. MicroK8S - -We recommend install directly from the snap store. - -Don't have the snap command? [Install snapd first](https://snapcraft.io/docs/core/install). - -1. Installing MicroK8s from snap. - ```bash - snap install microk8s --classic - ``` - -2. Verify MicroK8s is installed and available. - ```bash - microk8s.status - ``` - -3. During installation you can use the --wait-ready flag to wait for the kubernetes services to initialise. - ```bash - microk8s.status --wait -ready - ``` - -4. To avoid colliding with a **kubectl** already installed and to avoid overwriting any existing Kubernetes configuration file, MicroK8s adds a **microk8s.kubectl** command, configured to exclusively access the new **MicroK8s** install. - ```bash - microk8s.kubectl get services - ``` - -5. This step is only necessary if you require **microk8s.kubectl** to function as a standard **kubectl** command. This **DOES NOT** mean that you can then use **kubectl** to access **OTHER** k8s clusters. - - An example of why you would use this: You have a bash script or 3rd party tool that expects **kubectl** to be available. E.g. If you want to use Helm, it will not work against **microk8s.kubectl**, thus one **MUST** setup the alias for Helm to function correctly. - ```bash - snap alias microk8s.kubectl kubectl - ``` - - Reverting it at any time; - ```bash - snap unalias kubectl - ``` - - We will stick with the standard command of prefixing with **microk8s.** for this guide. - -6. If you already have **kubectl** installed and would like to use it to access the **MicroK8s** deployment. - ```bash - microk8s.kubectl config view --raw > $HOME/.kube/config - ``` - -7. View the current context. - ```bash - microk8s.kubectl config get-contexts - ``` - -9. Make sure the current context is **microk8s**. If not, set it as the current context. - ```bash - microk8s.kubectl config use-context microk8s - ``` - -### 1.2. Docker - -Docker is deployed as part of the MicroK8s installation. The docker daemon used by MicroK8s is listening on unix:///var/snap/microk8s/current/docker.sock. You can access it with the **microk8s.docker** command. - -1. If you require **microk8s.docker** to function as a standard **docker** command, you set an alias. - ```bash - sudo snap alias microk8s.docker docker - ``` - - Undo the alias; - ```bash - sudo snap unalias docker - ``` - -2. We will apply the native microK8s commands by prefix commands **microk8s.** - ```bash - microk8s.docker ps - ``` - -3. Continue setup and configuration from the Kubernetes Dashboard section in the [Mojaloop's deployment guide](./README.md#31-kubernetes-dashboard) document. - -## 2. Useful Tips - -1. Resolve problems with VSCode and kafka on ubuntu 18.04. To make the code work with VSCode debugger, added the following into the launch.json - ```json - "env": { - "LD_LIBRARY_PATH": "${workspaceFolder}/node_modules/node-rdkafka/build/deps", - "WITH_SASL": 0 - } - ``` diff --git a/deployment-guide/local-setup-mac.md b/deployment-guide/local-setup-mac.md deleted file mode 100644 index 2db7f5cbc..000000000 --- a/deployment-guide/local-setup-mac.md +++ /dev/null @@ -1,89 +0,0 @@ -# Mojaloop local environment setup for Mac - -Local setup on a Laptop or Desktop to run the Mojaloop project. - -## Setup Introduction - -This document will provide guidelines to a technical capable resources to setup, deploy and configure the Mojaloop applications on a local environment, utilizing Docker, Kubernetes and HELM charts. - -At this point the reader/implementer should be familiar with [Mojaloop's deployment guide](./README.md). Imported information is contained in that document and as such a prerequisite to this document. - -* [Local Deployment](local-setup-mac.md#local-deployment) - * [Kubernetes](local-setup-mac.md#1-kubernetes) - * [Kubernetes Installation with Docker](local-setup-mac.md#11-kubernetes-installation-with-docker) - * [Kubernetes environment setup](local-setup-mac.md#12-kubernetes-environment-setup) - - -## 1. Kubernetes - -This section will guide the reader through the deployment process to setup Kubernetes within Docker. - -If you are new to Kubernetes it is strongly recommended to familiarize yourself with Kubernetes. [Kubernetes Concepts](https://kubernetes.io/docs/concepts/overview/) is a good place to start and will provide an overview. - -The following are Kubernetes concepts used within the project. An understanding of these concepts is imperative before attempting the deployment; - -* Deployment -* Pod -* ReplicaSets -* Service -* Ingress -* StatefulSet -* DaemonSet -* Ingress Controller -* ConfigMap -* Secret - -### 1.1. Kubernetes Installation with Docker - -* **kubectl** Complete set of installation instruction are available [here](https://kubernetes.io/docs/tasks/tools/install-kubectl/) - - ```bash - brew install kubernetes-cli - ``` - To verify if the installation was successful, check the version; - - ```bash - kubectl version - ``` - -To install Kubernetes with Docker, follow the steps below; - -* Click on the Docker icon on the status barr - * Select **Preferences** - * Go to **Advanced** - * Increase the CPU allocation to at least 4 - * Increase the Memory allocation to at least 8.0 GiB - -![Kubernetes Install with Docker 1](./assets/diagrams/deployment/KubernetesInstallWithDocker-1.png) - -* Go to **Kubernetes** - * Select **Enable Kubernetes** tick box - * Make sure **Kubernetes** is selected - * Click **Apply** - * Click **Install** on the confirmation tab. - * The option is available to wait for completion or run as a background task. - -![Kubernetes Install with Docker 2](./assets/diagrams/deployment/KubernetesInstallWithDocker-2.png) - -### 1.2. Kubernetes environment setup: - -1. List the current Kubernetes context; - ```bash - kubectl config get-contexts - ``` - - **or** - ```bash - kubectx - ``` -2. Change your Contexts; - ```bash - kubectl config use-context docker-for-desktop - ``` - - **or** - ```bash - kubectx docker-for-desktop - ``` - -3. Continue setup and configuration from the Kubernetes Dashboard section in the [Mojaloop's deployment guide](./README.md#31-kubernetes-dashboard) document. \ No newline at end of file diff --git a/deployment-guide/local-setup-windows.md b/deployment-guide/local-setup-windows.md deleted file mode 100644 index bd6be3736..000000000 --- a/deployment-guide/local-setup-windows.md +++ /dev/null @@ -1,122 +0,0 @@ -# Mojaloop local environment setup for Windows - -Local setup on a Laptop or Desktop to run the Mojaloop project. - -## Setup Introduction - -This document will provide guidelines to a technical capable resources to setup, deploy and configure the Mojaloop applications on a local environment, utilizing Docker, Kubernetes and HELM charts. - -At this point the reader/implementer should be familiar with [Mojaloop's deployment guide](./README.md). Imported information is contained in that document and as such a prerequisite to this document. - -* [Kubernetes](#1-kubernetes) - * [Kubernetes Installation with Docker](#11-kubernetes-installation-with-docker) - * [Kubernetes environment setup](#12-kubernetes-environment-setup) - - -## 1. Kubernetes - -This section will guide the reader through the deployment process to setup Kubernetes within Docker. - -If you are new to Kubernetes it is strongly recommended to familiarize yourself with Kubernetes. [Kubernetes Concepts](https://kubernetes.io/docs/concepts/overview/) is a good place to start and will provide an overview. - -The following are Kubernetes concepts used within the project. An understanding of these concepts is imperative before attempting the deployment; - -* Deployment -* Pod -* ReplicaSets -* Service -* Ingress -* StatefulSet -* DaemonSet -* Ingress Controller -* ConfigMap -* Secret - -### 1.1 Kubernetes Installation with Docker - -* **kubectl** is part of the installation package when installing Docker Desktop for Windows. - - Please note the minimum system and operation requirements; - * Docker Desktop for Windows require Microsoft Hyper-V to run. Hyper-V will be enable as part of the installation process, - * Windows 10 64bit: Pro, Enterprise, Education (1607 Anneversary Update, Build 14393 or later), - * CPU SLAT-capable feature, - * At least 4GB of RAM. (At least 16GB will be required to run the Mojaloop project). - -1. Installing Docker for Windows: - - You will require Docker Desktop for Windows 18.02 Edge (win50) and higher, or 18.06 Stable (win 70) and higher. Kubernetes on Docker Desktop for Windows is available on these versions and higher. They are downloadable from: - ``` - https://docs.docker.com/docker-for-windows/install/ - ``` - - Once download is completed, the downloaded file can normally be found in your Download folder. Installation is as per normal installations for windows. A restart will be required after this step. - -2. Enable visualization: - - Docker Desktop for Windows requires Microsoft Hyper-V to run. The Docker Desktop installer enables Hyper-V for you. - - If Hyper-V is not enabled, A pop-up messages will request if you would like to turn this on. Read the messages and select 'Ok' if appropriate. - - You need to insure that **VT-X/AMD-v** is enabled from `cmd.exe`: - ```bash - systeminfo - ``` - - If not, from `cmd.exe` run as Administrator and execute: - ```bash - bcdedit /set hypervisorlaunchtype auto - ``` - - A reboot would be required again for the updates to take effect. - -3. Start Docker Desktop for Windows: - - Docker does not start automatically after installation. To start it, select **Docker Desktop** and click on it (or hit Enter). - - When the _whale_ in the status bar stays steady, **Docker Desktop** is up-and-running, and accessible from any terminal window. Note - if the _whale_ is not on the status bar, it will be in the **hidden icon** notifications area, click the up arrow on the taskbar to show it. - - ![Docker is Running](./assets/diagrams/deployment/DockerIsRunning.png) - -### 1.2 Kubernetes environment setup - -1. Setting up the Kubernetes runtime environment within Docker Desktop: - - * Open the Docker Desktop for Windows menu by right-clicking the Docker icon. - * Select **Settings** to open the settings dialog. - * Under the **General** tab you can configure when to start and update Docker. - - * Go to **Advanced** tab - * Increase the CPU allocation to at least 4 - * Increase the Memory allocation to at least 8.0 GiB - - (If your system resource allow, more can be allocated as indicated below.) - - ![Docker Advance Settings](./assets/diagrams/deployment/DockerAdvanceSettings.png) - - Kubernetes on Docker Desktop for Windows is available in 18.02 Edge (win50) and higher, and in 18.06 Stable (win 70) and higher. - - * go to **Kubernetes** tab - * Select **Enable Kubernetes** - * Select **Show system container (advanced)** - - ![Enable Kubernetes](./assets/diagrams/deployment/EnableKubernetes.png) - -2. Set the context to be used. - - As mentioned, the Kubernetes client command, `kubectl` is included and configured to connect to the local Kubernetes server. If you have `kubectl` already installed, be sure to change context to point to **docker-for-desktop**; - - Through `cmd.exe`: - ```bash - kubectl config get-contexts - kubectl config use-context docker-for-desktop - ``` - - Or through the Docker Desktop for Windows menu: - - * right-clicking the Docker icon - * Select **Kubernetes** - * Select **docker-for-desktop** - - ![Docker For Desktop](./assets/diagrams/deployment/DockerForDesktop.png) - -3. Continue setup and configuration from the Kubernetes Dashboard section in the [Mojaloop's deployment guide](./README.md#31-kubernetes-dashboard) document. diff --git a/deployment-guide/releases.md b/deployment-guide/releases.md deleted file mode 100644 index 76d7022e5..000000000 --- a/deployment-guide/releases.md +++ /dev/null @@ -1,39 +0,0 @@ -# Mojaloop Releases - -Below you will find more information on the current and historical releases for Mojaloop. - -Refer to [Versioning Documentation](../contributors-guide/standards/versioning.md) for more information on the release strategy and standards. - -## Current Releases -* Helm: [![Git Releases](https://img.shields.io/github/release/mojaloop/helm.svg?style=flat)](https://github.com/mojaloop/helm/releases) -* Central-Ledger: [![Git Releases](https://img.shields.io/github/release/mojaloop/central-ledger.svg?style=flat)](https://github.com/mojaloop/central-ledger/releases) -* Ml-API-Adapter: [![Git Releases](https://img.shields.io/github/release/mojaloop/ml-api-adapter.svg?style=flat)](https://github.com/mojaloop/ml-api-adapter/releases) -* Central-Settlement: [![Git Releases](https://img.shields.io/github/release/mojaloop/central-settlement.svg?style=flat)](https://github.com/mojaloop/central-settlement/releases) -* Central-Event-Processor: [![Git Releases](https://img.shields.io/github/release/mojaloop/central-event-processor.svg?style=flat)](https://github.com/mojaloop/central-event-processor/releases) -* Email-Notifier: [![Git Releases](https://img.shields.io/github/release/mojaloop/email-notifier.svg?style=flat)](https://github.com/mojaloop/email-notifier/releases) -* Account-Lookup-Service: [![Git Releases](https://img.shields.io/github/release/mojaloop/account-lookup-service.svg?style=flat)](https://github.com/mojaloop/account-lookup-service/releases) -* Quoting-Service: [![Git Releases](https://img.shields.io/github/release/mojaloop/quoting-service.svg?style=flat)](https://github.com/mojaloop/quoting-service/releases) - - -## Helm Charts Packaged Releases - -Refer to [Mojaloop Helm Repository](../repositories/helm.md) documentation to find out more information about Helm. Below are some of the Helm releases made and timelines. Please note that this is not an exhaustive list. For an exhaustive list, please visit the [Helm releases page](https://github.com/mojaloop/helm/releases). - -| Version | Release Date | Tested | Notes | -| --- | :---: | :---: | --- | -| [8.7.0](https://github.com/mojaloop/helm/releases/tag/v8.7.0) | 2019/12/12 | ✓ | Sprint release | -| [8.4.0](https://github.com/mojaloop/helm/releases/tag/v8.4.0) | 2019/11/12 | ✓ | Sprint release | -| [8.1.0](https://github.com/mojaloop/helm/releases/tag/v8.1.0) | 2019/10/08 | ✓ | Sprint release | -| [7.4.3](https://github.com/mojaloop/helm/releases/tag/v7.4.3) | 2019/08/30 | ✓ | Sprint release | -| [7.4.1](https://github.com/mojaloop/helm/releases/tag/v7.4.1) | 2019/08/23 | ✓ | Sprint release | -| [6.3.1](https://github.com/mojaloop/helm/releases/tag/v6.3.1) | 2019/05/31 | ✓ | Sprint release | -| [5.5.0](https://github.com/mojaloop/helm/releases/tag/v5.5.0) | 2019/04/02 | - | Sprint release | -| [5.4.2](https://github.com/mojaloop/helm/releases/tag/v5.4.2) | 2019/03/29 | ✓ | Sprint release | -| [5.4.1](https://github.com/mojaloop/helm/releases/tag/v5.4.1) | 2019/03/21 | ✓ | Sprint release | -| [5.4.0](https://github.com/mojaloop/helm/releases/tag/v5.4.0) | 2019/03/19 | ✓ | Sprint release | -| [5.2.0](https://github.com/mojaloop/helm/releases/tag/v5.2.0) | 2019/02/20 | ✓ | Sprint release | -| [5.1.3](https://github.com/mojaloop/helm/releases/tag/v5.1.3) | 2019/02/14 | ✓ | Sprint release | -| [5.1.2](https://github.com/mojaloop/helm/releases/tag/v5.1.2) | 2019/02/11 | ✓ | Sprint release | -| [5.1.1](https://github.com/mojaloop/helm/releases/tag/v5.1.1) | 2019/02/08 | ✓ | Sprint release | -| [5.1.0](https://github.com/mojaloop/helm/releases/tag/v5.1.0) | 2019/02/06 | ✓ | Sprint release | -| [4.4.1](https://github.com/mojaloop/helm/releases/tag/v4.4.1) | 2019/01/31 | ✓ | Released at PI4 Convening in Jan 2019 | diff --git a/discussions/Scope-for-Versioning-Proposal.md b/discussions/Scope-for-Versioning-Proposal.md deleted file mode 100644 index caf4a70a4..000000000 --- a/discussions/Scope-for-Versioning-Proposal.md +++ /dev/null @@ -1,91 +0,0 @@ -# Scope for Versioning, A Proposal - -## Overview: - -This is a versioning proposal for Mojaloop that intends to address the Scope of the discussion as part of an initial iteration and then build on it. - -The goal is to come up with a proposal that keeps the versioning Scheme simple to use and clear regarding compatibility issues. However, it also needs to include all the details needed for a Mojaloop Mojaloop eco-system. - - -#### Proposal -A Mojaloop Version _**x.y**_ can be defined that can encompass the versions of all the three APIs included (detailed below). - -In the version _**x.y**_, ‘x’ indicates the Major version and ‘y’ a minor version, similar to the Mojaloop FSPIOP API versioning standards. - -To keep things simple, there is a need to bundle all the components included in the Mojaloop eco-system indicating what all items are included there. - -In effect we may say Mojaloop version _**x.y**_ includes -1. Mojaloop FSPIOP API - -1.1 Maintained by CCB - -1.2 Uses x.y format - -1.3 Currently version v1.0, v1.1 and v2.0 are in the pipeline - -2. Settlement API - -2.1 Maintained by Settlements stream, core-team - -2.2 To use x.y format - -2.3 Currently version v1.1 and v2.0 is in the pipeline - -3. Admin / Operations API - -3.1 Maintained by the core-team - -3.2 To use x.y format - -3.3 Can use version v1.0 - -4. Helm - -4.1 Maintained by Core-team - -4.2 Uses x.y.z format - -4.3 PI, Sprint based versioning. - -4.4 Bundles compatible versions of individual services together - -5. Internal Schemas - -5.1 DB Schema x.y - -5.2 Internal messaging Schema (Kafka) x.y - -**For example**: -Mojaloop **1.0** includes -1. APIs - -1.1 FSPIOP API v1.0 - -1.2 Settlements API v1.1 - -1.3 Admin API v1.0 - -2. Internal schemas - -2.1 DB Schema v1.0 - -2.2 Internal messaging version v1.0 - -3. Helm v9.1.0 - -3.1 Individual services' versions - -3.2 Monitoring components versions - -#### Advantages: -1. The advantage of this strategy is primarily simplicity. A given version say - Mojaloop v1.0 can just be used in discussions which then refers to specific versions of the three APIs - FSPIOP, Settlements, Admin APIs, along with the Helm version that is a bundle of the individual services which are compatible with each other and can be deployed together. Along with these, the Schema versions for the DB and Internal messaging to communicate whether any changes have been made to these or not since the previously released version. - -2. The other advantage, obviously, is that it caters for everyone who may be interested in differing levels of details, whether high level or detailed. Because of the nature of how the major and minor versions, it should be easy for Users and adopters to understand compatibility issues as well. - -#### Compatibility: -As described in the section 3.3 of the API Definition v1.0 - https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#33-api-versioning , whether or not a version is backwards compatible, is indicated by the Major version. All versions with the same major version must be compatible while those having different major versions, will most likely not be compatible. - -#### Helm version: -1. Uses x.y.z format -2. Consists of individual service versions -3. Abstracts individual services and makes it manageable diff --git a/discussions/readme.md b/discussions/readme.md deleted file mode 100644 index eac37f946..000000000 --- a/discussions/readme.md +++ /dev/null @@ -1,21 +0,0 @@ -# Discussion Documents - -## PI 9 - -- [Versioning Draft Proposal](./versioning_draft_proposal.md) -- [Code Improvement Project](./code_improvement.md) - -## PI 8 - -- [Cross Border Meeting Notes Day 1](./cross_border_day_1.md) - -- [Cross Border Meeting Notes Day 2](./cross_border_day_2.md) - -- [ISO integration Overivew](./ISO_Integration.md) - -- [Mojaoop Decimal Type; Based on XML Schema Decimal Type](./decimal.md) - -## PI 7 - -- [Workbench Workstream](./workbench.md) - diff --git a/discussions/versioning_draft_proposal.md b/discussions/versioning_draft_proposal.md deleted file mode 100644 index b03436fff..000000000 --- a/discussions/versioning_draft_proposal.md +++ /dev/null @@ -1,190 +0,0 @@ -# Versioning Draft Proposal - ->_Note:_ This document is a living draft of a proposal for versioning within Mojaloop. Once the proposal is ready, it will be submitted to the CCB for approval. - -__Goal:__ -- Propose a standard a new 'Mojaloop Version', which embodies: - 1. API Versions: FSPIOP API, Hub Operations / Admin API, Settlement API - 2. Internal Schema Versions: Database Schema and Internal Messaging Versions - 3. Helm: Individual Service Versions, Monitoring Component Versions - -This is covered in more detail in [Versioning Proposal Scope](./Scope-for-Versioning-Proposal.md) - - -## Definitions: - -- _service_: Mojaloop follows a microservices oriented approach, where a large application is broken down into smaller _micro services_. In this instance, Service refers to a containerized application running as part of a Mojaloop deployment. At the moment, this takes the form of a Docker container running inside of a Kubernetes cluster. e.g. `mojaloop/central-ledger` is the _central-ledger_ service -- _service version_: The version of the given service. This currently doesn't follow semantic versioning, but may in the future e.g. `mojaloop/central-ledger:v10.0.1`. The current approach is described in more detail in the [standards/Versioning doc](https://github.com/mojaloop/documentation/blob/master/contributors-guide/standards/versioning.md). -- _helm_: Helm is an application package manager that runs on top of Kubernetes. It may also be refered to as the "deployment". A single helm deployment runs many different services, and MAY run multiple versions of the same service simultaneously. We also refer to the deployment as it's repo, `mojaloop/helm` interchangably. -- _helm version_: A helm version is the version of the packaged helm charts, e.g.`mojaloop/helm:v1.1.0` -- _interface_: An interface is the protocol by which a Mojaloop switch interacts with the outside world. This includes interactions with Participants (DFSPs) who transfer funds through the switch, hub operators running a Mojaloop switch, and admins performing administrative functions. -- _api_: Application Programming Interface - in most cases referring to the `FSPIOP-API` a.k.a. Open API for FSP Interoperability defined [here](https://github.com/mojaloop/mojaloop-specification). -- _api version_: The Version of the `FSPIOP-API`, e.g. `FSPIOP-API v1`. For the purposes of this document, it refers to the contract between a Mojaloop Switch and Participants (DFSPs) who implement the FSPIOP-API - - -## 1. [1197](https://github.com/mojaloop/project/issues/1197) Versioning Best Practices: - -> As a switch implementer, I want to research the best practices for managing and implementing versioning, so that we have a clear understanding of well tried approaches. - -### General: - -- Most best practices follow semantic versioning for APIs, this will be covered more in [#1198](https://github.com/mojaloop/project/issues/1198) - -#### Backwards Compatibility: - -> Hub operators will likely need to support multiple versions of the API at the same time, in order to cater for different participants as they can't all be expected to upgrade at the same time. - -- "The Robustness principle, states that you should be “liberal in what you accept and conservative in what you send”. In terms of APIs this implies a certain tolerance in consuming services." [3] - -- Backwards Compatibility vs Backwards Incompatiblity [4]: - - Generally, additions are considered backwards compatible - - Removing or changing names is backwards incompatible - - It's more something to assess on a case-by-case basis, but [Google's API Design Doc](https://cloud.google.com/apis/design/compatibility) helps lay out the cases. - - -### Versioning our APIs - -The [Mojaloop Spec](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#33-api-versioning) already outlines many of the decisions made around versioning APIs. - -In terms of common best practices, there are many approaches for requesting different versions, including adding in a version in the url, but let's not worry about this because the spec already lays this out for us, using the HTML vendor extension: [3.3.4.1 Http Accept Header](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#3341-http-accept-header) - -As for version negotiation, the spec also states that in the event of an unsupported version being requested by a client, a HTTP status 406 can be returned, along with an error message which describes the supported versions. [3.3.4.3 Non-Acceptable Version Requested by Client](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#3343-non-acceptable-version-requested-by-client) - -Another best practice around versioning is specifying to what level clients may request specific apis. - - In a development environment, many APIs will allow specificy up to the BUGFIX version, i.e. vX.X.X - - In production however, this is limited to Major versions only, e.g. v1, v2 - - e.g. The Google API Platform supports only major versions, not minor and patch versions - - Given the new features that may become available with v1.1 of the Mojaloop API, we might want to allow participants to specify MAJOR and MINOR versions, i.e. vX.X. This practice should be avoided however, since minor versions should be backwards compatible - -Participants talking on on the same MAJOR version of the API should be able to interact. Participants on different MAJOR versions are not able to interact. For example, a participant on API v1.1 can send transfers to another participant on v1.0, but not to a different participant on v2.0. - - -### Managing Switch Versions - -> This is a big open question at the moment. Once we have a better idea of the scope of this versioning proposal, from [#1198](https://github.com/mojaloop/project/issues/1198) - -_2 high level approaches:_ -1. __For any given API version, we run one version the service set at a time, which can support multiple versions of the api.__ - -e.g.: -- `mojaloop/helm` release v1.0.0 MAY run `mojaloop/central-ledger:v10.0.0`, which supports `FSPIOP-API v1` only -- A future release of the helm charts: `mojaloop/helm` release v1.1.0 runs `mojaloop/central-ledger:v10.1.0`, which supports `FSPIOP-API v1` and `FSPIOP-API v1.1` - -This approach: -- pushes the version negotiation to the application layer (instead of the transport layer, such as nginx routing based on the `Accept` header) -- may assume database migrations have been run in an intermediate helm relase, e.g. `mojaloop/helm:v1.0.1`, to prepare for the next minor release - - -2. __API versions are closely linked to service versions, such that to support _n_ versions of the API, _n_ service versions must also be running.__ - -e.g.: -- `mojaloop/helm:v1.0.0` runs only 1 version of the central-ledger: `mojaloop/central-ledger:v10.0.0`, and supports `FSPIOP-API v1` only. -- A new deployment of `mojaloop/helm:v1.1.0` is made to support a new MINOR api version. This helm version runs 2 versions of the central-ledger service: `mojaloop/central-ledger:v10.0.0` and `mojaloop/central-ledger:v10.1.0`, alongside one another. -- routing between the different APIs is done at the transport layer, e.g. with an nginx router sending an Accept header of: `application/vnd.interoperability.participants+json;version=1` to `mojaloop/central-ledger:v10.0.0`, and an Accept header of: `application/vnd.interoperability.participants+json;version=1.1` to `mojaloop/central-ledger:v10.1.0` accordingly - - -### Version Management Across Mojaloop Services - -This section deals with how Mojaloop services interact within a given deployment. Here, we attempt to propose questions such as "should an instance of central-ledger:v10.0.1 be able to talk to ml-api-adapter:v10.1.0? How about ml-api-adapter:v11.0.0?"? or "how do we make sure both central-ledger:v10.0.1 and central-ledger:v10.1.0 talk to the database at the same time?" - -There are two places where this happens: -1. Where services interact with saved state - MySQL Percona Databases -2. Where services interact with each other - Apache Kakfa and (some) internal APIs - -This implies we need to version: -- the database schema -- messages within Apache kafka - - need to make sure the right services can appropriately read the right messages. E.g. Can `mojaloop/ml-api-adapter:v10.1.0` publish messages to kafka that `mojaloop/central-ledger:v10.0.1` can understand? - - Q: If we decide to make breaking changes to the message format, how can we ensure that messages in the kafka streams don't get picked up by the wong services? - -### Versioning the Database - -[5] demonstrates zero-downtime deployment approaches with Kubernetes - -Key observations: -- in order to support rollbacks, the services must be both forward and backwards compatible. - - consecutive app versions must be schema compatible -- 'Never deploy any breaking schema changes', separate into multiple deployments instead - -For example, start with a `PERSON` table: -``` -PK ID - NAME - ADDRESS_LINE_1 - ADDRESS_LINE_2 - ZIPCODE - COUNTRY -``` - -And we want to break this down (normalize) into 2 tables, `PERSON` and `ADDRESS`: -``` -#person -PK ID - NAME - -#address -PK ID -FK PERSON_ID - ADDRESS_LINE_1 - ADDRESS_LINE_2 - ZIPCODE - COUNTRY -``` - -If this change were made in one migration, 2 different versions of our application won't be able compatible. Instead, the schema changes must be broken down: - -1. Create `ADDRESS` table - - App use the `PERSON` table data as previously - - Trigger a copy of data to the `ADDRESS` table -2. The `ADDRESS` now becomes the 'source of truth' - - App now uses the `ADDRESS` table data - - Trigger a copy of new added to address to the `PERSON` table -3. Stop copying data -4. Remove extra columns from `PERSON` table - - -This means for any one change of the database schema, multiple application versions will need to be created, and multiple deployments must be made in succession for this change to be made. - -- [5] also notes how simple Kubernetes makes deploying such a change - - rolling upgrade deployments - - Tip: make sure your health endpoint waits for the migrations to finish! - -- Q: so how do we make big changes that touch both the database schema and the API? - - this seems really hard, and would need a lot of coordination - - If we don't design it correctly, it could mean that a single schema change could require all DFSPs to be on board - - This is why I think the API version and Service version should be unrelated. We should be able to deploy a new version of a service (which runs a migration), and supports an old API version - -## Versioning in Kafka Messages - -Currently, we use the lime protocol for our kafka message formats: https://limeprotocol.org/ - -Also refer to the [mojaloop/central-services-stream readme](https://github.com/mojaloop/central-services-stream/blob/master/src/kafka/protocol/readme.md) for more information about the message format. - -The lime protocol provides for a `type`, field, which supports MIME type declarations. So we could potentially handle messages in a manner similar to the API above (e.g. `application/vnd.specific+json`). Versioning messages in this manner means that consumers reading these messages would need to be backwards and fowards compatible (consecutive message versions must be schema compatible). - - -- Q. does it make sense to put the `version` in the Kafka topic? - - One example, ml-api-adapter publishes messages to the `prepare` topic - - If we add versioning to this, `ml-api-adapter:v10.0.0` publishes messages to a `prepare_v10.0` topic, and a new instance of the `ml-api-adapter:v10.1.0` will publish to the `prepare_v10.1` topic. - - subscribers can subscribe to whichever prepare topic they want, or both, depending on their own tolerance to such messages - - This may have some serious performance side effects - - -- Another potential option would be to allow for a message _'adapter'_ in the deployment. Say the `ml-api-adapter:v10.1.0` is producing messages to a `prepare_v10.1` topic, and there is no corresponding `central-ledger` in the deployment to read such messages, we could have an _adapter_, which subcscribes to `prepare_v10.1`, reformats them to be backwards compatible, and publishes them to `prepare_v10.0` in the old format. - -Such an approach would allow for incremental schema changes to the messaging format as services are gradually upgraded. - -All in all, I didn't see too much about this subject, so we'll likely need to return later down the line. - -[6] suggests some approaches, such as using a schema registry for kafka messages, such as [Apache Arvo](https://docs.confluent.io/current/schema-registry/index.html) -- This adds a certain level of 'strictness' to the messages we produce, and will help enforce versioning -- Adds a separate 'schema registry' component, which ensures messages conform to a given schema. This doesn't really help enforce versioning, and leaves the work up to us still, but does give more guarantees about the message formats. - -## References - -- [1] LTS versioning within [nodejs](https://nodejs.org/en/about/releases/). This is a great example of an LTS strategy, and how to clearly communicate such a strategy. -- [2] [Semantic Versioning Reference](https://semver.org/) -- [3] https://www.ben-morris.com/rest-apis-dont-need-a-versioning-strategy-they-need-a-change-strategy/ -- [4] https://cloud.google.com/apis/design/compatibility -- [5] [Nicolas Frankel - Zero-downtime deployment with Kubernetes, Spring Boot and Flyway](https://www.youtube.com/watch?v=RvCnrBZ0DPY) -- [6] [Stackoverflow - Kafka Topic Message Versioning](https://stackoverflow.com/questions/52387013/kafka-topic-message-versioning) \ No newline at end of file diff --git a/docs/.vuepress/components/Foo/Bar.vue b/docs/.vuepress/components/Foo/Bar.vue new file mode 100644 index 000000000..7ee8286a2 --- /dev/null +++ b/docs/.vuepress/components/Foo/Bar.vue @@ -0,0 +1,15 @@ + + + diff --git a/docs/.vuepress/components/demo-component.vue b/docs/.vuepress/components/demo-component.vue new file mode 100644 index 000000000..7d49de79d --- /dev/null +++ b/docs/.vuepress/components/demo-component.vue @@ -0,0 +1,15 @@ + + + diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js new file mode 100644 index 000000000..b02c07a01 --- /dev/null +++ b/docs/.vuepress/config.js @@ -0,0 +1,1178 @@ +const { description } = require('../../package') + +// Determine if we're in PR preview mode +const isPrPreview = process.env.VUEPRESS_IS_PR === 'true' + +// Set base URL for PR previews +const base = isPrPreview ? `/pr/${process.env.VUEPRESS_PR_NUMBER}/` : '/' + +module.exports = { + /** + * Ref:https://v1.vuepress.vuejs.org/config/#title + */ + title: 'Mojaloop Documentation', + /** + * Ref:https://v1.vuepress.vuejs.org/config/#description + */ + description: description, + + /** + * Base URL for the site + * + * ref:https://v1.vuepress.vuejs.org/config/#base + */ + base, + + /** + * Extra tags to be injected to the page HTML `` + * + * ref:https://v1.vuepress.vuejs.org/config/#head + */ + head: [ + ['meta', { name: 'theme-color', content: '#00a3ff' }], + ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }], + ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }] + ], + + theme: 'titanium', + + /** + * Theme configuration, here is the default theme configuration for VuePress. + * + * ref:https://v1.vuepress.vuejs.org/theme/default-theme-config.html + */ + themeConfig: { + repo: 'https://github.com/mojaloop/documentation/', + docsBranch: 'master', + editLinks: true, + docsDir: 'docs', + editLinkText: 'Edit this page on GitHub', + smoothScroll: true, + logo: '/mojaloop_logo_med.png', + sidebarDepth: 2, + lastUpdated: true, + footerCopyright: 'Apache 2.0 Licensed | Copyright © 2020 - 2024 Mojaloop Foundation', + // PR Preview configuration + isPrPreview: isPrPreview, + prNumber: process.env.VUEPRESS_PR_NUMBER || '', + nav: [ + { + text: 'Adoption', + link: '/adoption/', + }, + { + text: 'Community', + link: '/community/' + }, + { + text: 'Technical', + link: '/technical/' + }, + { + text: 'Product', + link: '/product/' + }, + + { + text: 'Training Program', + link: 'https://mojaloop.io/mojaloop-training-program/' + } + ], + // Ref: https://vuepress.vuejs.org/theme/default-theme-config.html#sidebar + sidebar: { + '/adoption/': [ + { + title: 'Scheme Guide', + collapsable: false, + sidebarDepth: 2, + children: [ + ['Scheme/platform-operating-guideline', 'Platform Operating Guideline Template'], + ['Scheme/scheme-business-rules', 'Scheme Business Rules Template'], + ['Scheme/scheme-key-choices', 'Scheme Key Choices'], + ['Scheme/scheme-participation-agreement', 'Scheme Participation Agreement Template'], + ['Scheme/scheme-uniform-glossary', 'Uniform Glossary Template'], + ] + }, + { + title: 'Hub Operations Guide', + // path: './HubOperations/TechOps/tech-ops-introduction', + collapsable: false, // optional, defaults to true + sidebarDepth: 1, // optional, defaults to 1 + children: [ + { + title: 'Technical Operations Guide', + collapsable: true, + // path: 'HubOperations/TechOps/tech-ops-introduction', + sidebarDepth: 2, + children: [ + 'HubOperations/TechOps/tech-ops-introduction', + 'HubOperations/TechOps/incident-management', + 'HubOperations/TechOps/problem-management', + 'HubOperations/TechOps/change-management', + 'HubOperations/TechOps/release-management', + 'HubOperations/TechOps/defect-triage', + 'HubOperations/TechOps/key-terms-kpis', + 'HubOperations/TechOps/incident-management-escalation-matrix', + 'HubOperations/TechOps/service-level-agreements' + ] + }, + { + title: 'Settlement Management Guide', + collapsable: true, + // path: './HubOperations/Settlement/settlement-management-introduction', + sidebarDepth: 2, + children: [ + 'HubOperations/Settlement/settlement-management-introduction', + 'HubOperations/Settlement/settlement-basic-concepts', + 'HubOperations/Settlement/ledgers-in-the-hub', + ] + }, + { + title: 'Guide to Finance Portal v2', + collapsable: true, + // path: './HubOperations/Onboarding/busops-portal-introduction', + sidebarDepth: 2, + children: [ + 'HubOperations/Portalv2/busops-portal-introduction', + 'HubOperations/Portalv2/settlement-business-process', + 'HubOperations/Portalv2/accessing-the-portal', + 'HubOperations/Portalv2/managing-windows', + 'HubOperations/Portalv2/settling', + 'HubOperations/Portalv2/checking-settlement-details', + 'HubOperations/Portalv2/monitoring-dfsp-financial-details', + 'HubOperations/Portalv2/enabling-disabling-transactions', + 'HubOperations/Portalv2/recording-funds-in-out', + 'HubOperations/Portalv2/updating-ndc', + 'HubOperations/Portalv2/searching-for-transfer-data' + ] + }, + { + title: 'Roled-Based Access Control', + collapsable: true, + // path: './HubOperations/RBAC/Role-based-access-control', + sidebarDepth: 2, + children: [ + 'HubOperations/RBAC/Role-based-access-control' + ] + }, + { + title: 'Onboarding Guide for the Hub Operator', + collapsable: true, + // path: './HubOperations/Onboarding/onboarding-introduction', + sidebarDepth: 2, + children: [ + 'HubOperations/Onboarding/onboarding-introduction', + 'HubOperations/Onboarding/business-onboarding', + 'HubOperations/Onboarding/technical-onboarding', + ] + } + ] + } + ], + '/community/': [ + { + title: 'Community', + collapsable: false, + sidebarDepth: 2, + children: [ + ['contributing/contributors-guide', 'Welcome to the community'], + ['mojaloop-roadmap', 'Product Roadmap'], + ['mojaloop-publications', 'Mojaloop Publications'] + ] + }, + { + title: 'Contributing', + collapsable: false, + sidebarDepth: 2, + children: [ + ['contributing/contributors-guide', 'Contributors\' Guide'], + ['contributing/product-engineering-process','Product Engineering Process'], + ['contributing/design-review', 'Technical Design & Code Review'], + ['contributing/consequential-change-process', 'Consequential Change Process'], + ['contributing/critical-change-process', 'Critical Change Process'], + ['contributing/new-contributor-checklist', 'New Contributor Checklist'], + ['contributing/code-of-conduct', 'Code of Conduct'], + ['contributing/signing-the-cla', 'Signing the CLA'], + ['contributing/cvd', 'Disclosing Security Vulnerabilities'], + ] + }, + { + title: 'Standards', + collapsable: false, + sidebarDepth: 2, + children: [ + ['standards/guide', 'Our Standards'], + ['standards/invariants', 'Mojaloop Invariants'], + ['standards/versioning', 'Versioning'], + ['standards/creating-new-features', 'Creating New Features'], + ['standards/triaging-bugs', 'Triaging Bugs'], + ] + }, + { + title: 'Tools and Technologies', + collapsable: false, + sidebarDepth: 2, + children: [ + ['tools/tools-and-technologies', 'Tools'], + ['tools/pragmatic-rest', 'Pragmatic Rest'], + ['tools/code-quality-metrics', 'Code Quality Metrics'], + ['tools/automated-testing', 'Automated Testing'], + ['tools/cybersecurity', 'Cybersecurity'], + ] + }, + { + title: 'Documentation', + collapsable: false, + children: [ + ['documentation/standards', 'Standards'], + ['documentation/api-documentation', 'API Documentation'], + ['documentation/style-guide', 'Style Guide'], + ] + }, + { + title: 'Archive', + collapsable: false, + sidebarDepth: 4, + children: [ + { + title: 'Notes Archive', + collapsable: true, + path: 'archive/notes/', + children: [ + ['archive/notes/ccb-notes', 'CCB Notes'], + ['archive/notes/da-notes', 'Meeting Notes'], + ['archive/notes/scrum-of-scrum-notes', 'Scrum Notes'] + ] + }, + { + title: 'Discussion Docs Archive', + collapsable: true, + path: 'archive/discussion-docs/', + children: [ + { + title: 'PI 10', + collapsable: true, + children: [ + ['archive/discussion-docs/performance-project', 'Performance Project'], + ['archive/discussion-docs/code-improvement', 'Code Improvement Project'], + ['archive/discussion-docs/cross-border', 'Cross Border Project'], + ['archive/discussion-docs/psip-project', 'PSIP Project'] + ] + }, + { + title: 'PI 9', + collapsable: true, + children: [ + ['archive/discussion-docs/versioning-draft-proposal', 'Versioning Draft Proposal'], + ] + }, + { + title: 'PI 8', + collapsable: true, + children: [ + ['archive/discussion-docs/cross-border-day-1', 'CB Day 1 Meeting Notes'], + ['archive/discussion-docs/cross-border-day-2', 'CB Day 2 Meeting Notes'], + ['archive/discussion-docs/iso-integration', 'ISO Integration Overview'], + ['archive/discussion-docs/mojaloop-decimal', 'Mojaloop Decimal Type'] + ] + }, + { + title: 'PI 7', + collapsable: true, + children: [ + ['archive/discussion-docs/workbench', 'Workbench Workstream'], + ] + } + ] + }, + ] + } + ], + '/technical/': [ + { + title: 'Mojaloop Technical Overview', + collapsable: false, + sidebarDepth: 1, + children: [ + { + title: "Deployment Guide", + // path: 'technical/deployment-guide/readme', + collapsible: true, + sidebarDepth: 2, + children: [ + ['technical/deployment-guide/', 'Deploying Mojaloop'], + 'technical/deployment-guide/deployment-troubleshooting', + 'technical/deployment-guide/upgrade-strategy-guide', + 'technical/deployment-guide/mojaloop-repository-update-guide' + ] + }, + { + title: "Mojaloop Hub", + collapsable: true, + sidebarDepth: 2, + children: [ + ['technical/overview/','Mojaloop Component Overview'], + 'technical/overview/components-PI14', + 'technical/overview/components-PI12', + 'technical/overview/components-PI11', + 'technical/overview/components-PI8', + 'technical/overview/components-PI7', + 'technical/overview/components-PI6', + 'technical/overview/components-PI5', + 'technical/overview/components-PI3' + ] + }, + { + title: "Mojaloop Releases", + path: "technical/releases" + }, + { + title: "Account Lookup Service", + collapsable: true, + sidebarDepth: 2, + children: [ + ['technical/account-lookup-service/', 'Overview'], + 'technical/account-lookup-service/als-get-participants', + 'technical/account-lookup-service/als-post-participants', + 'technical/account-lookup-service/als-post-participants-batch', + 'technical/account-lookup-service/als-del-participants', + 'technical/account-lookup-service/als-get-parties', + ] + }, + { + title: "Quoting Service", + collapsable: true, + sidebarDepth: 2, + children: [ + ['technical/quoting-service/','Overview'], + 'technical/quoting-service/qs-get-quotes', + 'technical/quoting-service/qs-post-quotes', + 'technical/quoting-service/qs-get-bulk-quotes', + 'technical/quoting-service/qs-post-bulk-quotes' + ] + }, + { + title: "Central Ledger", + collapsable: true, + sidebarDepth: 2, + children: [ + { + title: "Overview", + path: "technical/central-ledger/" + }, + { + title: "Admin Operations", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-ledger/admin-operations/", + }, + { + title: "POST Participant Limit", + path: "technical/central-ledger/admin-operations/1.0.0-post-participant-position-limit" + }, + { + title: "GET Participant Limit Details", + path: "technical/central-ledger/admin-operations/1.1.0-get-participant-limit-details" + }, + { + title: "GET All Participant Limits", + path: "technical/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants" + }, + { + title: "POST Participant limits", + path: "technical/central-ledger/admin-operations/1.1.0-post-participant-limits" + }, + { + title: "GET Transfer Status", + path: "technical/central-ledger/admin-operations/1.1.5-get-transfer-status" + }, + { + title: "POST Participant Callback", + path: "technical/central-ledger/admin-operations/3.1.0-post-participant-callback-details" + }, + { + title: "GET Participant Callback", + path: "technical/central-ledger/admin-operations/3.1.0-get-participant-callback-details" + }, + { + title: "GET Participant Position", + path: "technical/central-ledger/admin-operations/4.1.0-get-participant-position-details" + }, + { + title: "GET All Participants Positions", + path: "technical/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants" + } + ] + }, + { + title: "Transfers Operations", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-ledger/transfers/" + }, + { + title: "Prepare Handler", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-ledger/transfers/1.1.0-prepare-transfer-request" + }, + { + title: "Prepare Handler Consume", + path: "technical/central-ledger/transfers/1.1.1.a-prepare-handler-consume" + } + ] + }, + { + title: "Prepare Position Handler", + path: "technical/central-ledger/transfers/1.3.0-position-handler-consume" + }, + { + title: "Prepare Position Handler v1.1", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-ledger/transfers/1.3.0-position-handler-consume-v1.1" + }, + { + title: "Prepare Position Handler", + path: "technical/central-ledger/transfers/1.3.1-prepare-position-handler-consume" + }, + { + title: "Position Handler Consume", + path: "technical/central-ledger/transfers/1.1.2.a-position-handler-consume" + } + ] + }, + { + title: "Fulfil Handler", + path: "technical/central-ledger/transfers/2.1.0-fulfil-transfer-request" + }, + { + title: "Fulfil Handler v1.1", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1" + }, + { + title: "Fulfil Handler Consume", + path: "technical/central-ledger/transfers/2.1.1-fulfil-handler-consume" + }, + { + title: "Fulfil Handler Consume v1.1", + path: "technical/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1" + } + ] + }, + { + title: "Fulfil Position Handler", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-ledger/transfers/1.3.0-position-handler-consume" + }, + { + title: "Fulfil Position Handler", + path: "technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume" + }, + { + title: "Fulfil Position Handler v1.1", + path: "technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1" + } + ] + }, + { + title: "Fulfil Reject Transfer", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer" + }, + { + title: "Fulfil Reject Transfer (a)", + path: "technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer" + }, + { + title: "Fulfil Handler (Reject-Abort)", + path: "technical/central-ledger/transfers/2.2.1-fulfil-reject-handler" + } + ] + }, + { + title: "Fulfil Reject Transfer v1.1", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1" + }, + { + title: "Fulfil Reject Transfer (a) v1.1", + path: "technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1" + }, + { + title: "Fulfil Handler (Reject-Abort) v1.1", + path: "technical/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1" + } + ] + }, + { + title: "Notifications", + collapsable: true, + children: [ + { + title: "Notification to Participant (a)", + path: "technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant" + }, + { + title: "Notification to Participant (a) - v1.1", + path: "technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1" + }, + { + title: "Notification to Participant (b)", + path: "technical/central-ledger/transfers/1.1.4.b-send-notification-to-participant" + } + ] + }, + { + title: "Reject/Abort", + collapsable: true, + children: [ + { + title: "Abort Position Handler", + path: "technical/central-ledger/transfers/1.3.3-abort-position-handler-consume" + } + ] + }, + { + title: "Timeout", + collapsable: true, + children: [ + { + title: "Transfer Timeout", + path: "technical/central-ledger/transfers/2.3.0-transfer-timeout" + }, + { + title: "Timeout Handler Consume", + path: "technical/central-ledger/transfers/2.3.1-timeout-handler-consume" + } + ] + }, + ] + }, + { + title: "FX Transfer Operations", + collapsable: true, + children: [ + { + title: "Overview", + path: "central-fx-transfers/transfers/" + }, + { + title: "FX Prepare Handler", + collapsable: true, + children: [ + { + title: "Overview", + path: "central-fx-transfers/transfers/1.1.0-fx-prepare-transfer-request" + }, + { + title: "FX Prepare Handler Consume", + path: "central-fx-transfers/transfers/1.1.1.a-fx-prepare-handler-consume" + } + ] + }, + { + title: "FX Position Handler", + path: "central-fx-transfers/transfers/1.1.2.a-fx-position-handler-consume" + }, + { + title: "FX Fulfil Handler", + path: "central-fx-transfers/transfers/2.1.0-fx-fulfil-transfer-request" + }, + { + title: "Notifications process", + path: "central-fx-transfers/transfers/1.1.4.a-send-notification-to-participant-v2.0" + }, + { + title: "Reject/Abort", + path: "central-fx-transfers/transfers/2.2.0-fx-fulfil-reject-transfer" + } + ] + }, + { + title: "Bulk Transfers Operations", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-bulk-transfers/" + }, + { + title: "Bulk Prepare", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview" + }, + { + title: "Bulk Prepare Handler", + path: "technical/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume" + } + ] + }, + { + title: "Prepare Handler", + collapsable: true, + path: "technical/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk" + }, + { + title: "Position Handler", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview" + }, + { + title: "Prepare Position Handler Consume", + path: "technical/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume" + }, + { + title: "Fulfil Position Handler Consume", + path: "technical/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume" + }, + { + title: "Fulfil Abort Position Handler Consume", + path: "technical/central-bulk-transfers/transfers/2.3.2-position-consume-abort" + } + ] + }, + { + title: "Bulk Fulfil Handler", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview" + }, + { + title: "Bulk Fulfil Handler Consume", + path: "technical/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume" + }, + { + title: "Fulfil Handler - Commit", + path: "technical/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk" + }, + { + title: "Fulfil Handler - Reject/Abort", + path: "technical/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk" + } + ] + }, + { + title: "Bulk Processing Handler", + path: "technical/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler" + }, + { + title: "Notifications", + collapsable: true, + children: [ + { + title: "Notification to Participant (a)", + path: "technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant" + }, + { + title: "Notification to Participant (b)", + path: "technical/central-ledger/transfers/1.1.4.b-send-notification-to-participant" + } + ] + }, + { + title: "Timeout", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk" + }, + { + title: "Timeout Handler Consume", + path: "technical/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume" + } + ] + }, + { + title: "Bulk Abort Overview", + path: "technical/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk" + }, + { + title: "Get Bulk Transfer Overview", + path: "technical/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk" + } + ] + } + ] + }, + { + // TODO: Placeholder and temporary link for this section until it can be migrated from legacy docs. + title: 'Central Settlement Services', + path: 'https://docs.mojaloop.io/legacy/mojaloop-technical-overview/central-settlements/' + }, + { + title: "Transaction Requests Service", + collapsable: true, + sidebarDepth: 2, + children: [ + { + title: "Overview", + path: "technical/transaction-requests-service/" + }, + { + title: "GET Transaction Requests", + path: "technical/transaction-requests-service/transaction-requests-get" + }, + { + title: "POST Transaction Requests", + path: "technical/transaction-requests-service/transaction-requests-post" + }, + { + title: "Authorizations", + path: "technical/transaction-requests-service/authorizations" + } + ] + }, + { + title: "Central Event Processor Service", + collapsable: true, + sidebarDepth: 2, + children: [ + { + title: "Overview", + path: "technical/central-event-processor/" + }, + { + title: "Event Handler (Placeholder)", + path: "technical/central-event-processor/event-handler-placeholder" + }, + { + title: "Notification Handler for Rejections", + path: "technical/central-event-processor/notification-handler-for-rejections" + }, + { + title: "Signature Validation", + path: "technical/central-event-processor/signature-validation" + } + ] + }, + { + title: "Event Framework", + collapsable: true, + sidebarDepth: 2, + children: [ + { + title: "Overview", + path: "technical/event-framework/" + }, + { + title: "Event Stream Processor", + path: "technical/event-stream-processor/" + } + ] + }, + { + title: "Security & vulnerability management", + collapsable: true, + sidebarDepth: 2, + children: [ + { + title: "Security Overview", + path: "technical/security/security-overview" + }, + { + title: "Dependency vulnerability management", + path: "technical/security/dependency-vulnerability-management" + } + ] + }, + { + title: "SDK Scheme Adapter", + collapsable: true, + sidebarDepth: 2, + children: [ + { + title: "Overview", + path: "technical/sdk-scheme-adapter/" + }, + { + title: "Integration Flow Patterns", + path: "technical/sdk-scheme-adapter/IntegrationFlowPatterns" + }, + { + title: "Request To Pay - support", + path: "technical/sdk-scheme-adapter/RequestToPay" + }, + { + title: "Bulk Integration Flow Patterns", + path: "technical/sdk-scheme-adapter/IntegrationBulkFlowPatterns" + }, + { + title: "Usage tests", + path: "technical/sdk-scheme-adapter/usage/" + }, + { + title: "Support for Bulk Transfers", + collapsable: true, + sidebarDepth: 2, + children: [ + { + title: "Overview", + path: "technical/sdk-scheme-adapter/BulkEnhancements/" + }, + { + title: "API", + path: "technical/sdk-scheme-adapter/BulkEnhancements/SDKBulk-API-Design" + }, { + title: "DDD & Event Sourcing Design", + path: "technical/sdk-scheme-adapter/BulkEnhancements/SDKBulk-EventSourcing-Design" + }, { + title: "Tests", + path: "technical/sdk-scheme-adapter/BulkEnhancements/SDKBulk-Tests" + } + ] + } + ] + }, + { + title: "ML Testing Toolkit", + collapsable: true, + children: [ + { + title: "Overview", + path: "technical/ml-testing-toolkit/" + } + ] + } + ] + }, + { + title: 'Reference architecture', + // path: './HubOperations/TechOps/tech-ops-introduction', + collapsable: true, // optional, defaults to true + sidebarDepth: 1, // optional, defaults to 1 + children: [ + { + title: 'Bounded Contexts', + // path: 'reference-architecture/boundedContexts/', // optional, link of the title, which should be an absolute path and must exist + //collapsable: false, + initialOpenGroupIndex: -1, + children: [ + { + title: 'Common Terms & Conventions', + path: 'reference-architecture/boundedContexts/commonTermsConventions/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Account Lookup & Discovery', + path: 'reference-architecture/boundedContexts/accountLookupAndDiscovery/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Accounts & Balances', + path: 'reference-architecture/boundedContexts/accountsAndBalances/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Quoting/Agreements', + path: 'reference-architecture/boundedContexts/quotingAgreement/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Auditing', + path: 'reference-architecture/boundedContexts/auditing/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'FSP Interop API', + path: 'reference-architecture/boundedContexts/fspInteropApi/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Logging', + path: 'reference-architecture/boundedContexts/logging/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Notifications And Alerts', + path: 'reference-architecture/boundedContexts/notificationsAndAlerts/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Participant Lifecycle Management', + path: 'reference-architecture/boundedContexts/participantLifecycleManagement/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + //{ + // title: 'Platform Monitoring', + // path: '/boundedContexts/platformMonitoring/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + //}, + { + title: 'Reporting', + path: 'reference-architecture/boundedContexts/reporting/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Scheduling', + path: 'reference-architecture/boundedContexts/scheduling/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Security', + path: 'reference-architecture/boundedContexts/security/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Settlements', + path: 'reference-architecture/boundedContexts/settlements/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Third Party API', + path: 'reference-architecture/boundedContexts/thirdPartyApi/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Transfers', + path: 'reference-architecture/boundedContexts/transfers/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + ], + }, + { + title: 'Common Interface List', + path: 'reference-architecture/boundedContexts/commonInterfaces/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + + + { + title: 'How to Implement', + path: 'reference-architecture/howToImplement/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Glossary', + path: 'reference-architecture/glossary/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + }, + { + title: 'Further Reading', + path: 'reference-architecture/furtherReading/', // optional, link of the title, which should be an absolute path and must exist + // children: [ /* ... */ ], + } + ] + }, + { + title: 'Mojaloop APIs', + collapsable: false, // optional, defaults to true + sidebarDepth: 1, // optional, defaults to 1 + children: [ + { + title: 'FSPIOP API', + collapsable: true, + sidebarDepth: 4, + children: [ + { + title: 'Overview', + path: 'api/fspiop/', + }, + { + title: 'API Definitions', + collapsable: false, + children: [ + { + title: 'v1.1 (Current)', + path: 'api/fspiop/v1.1/api-definition' + }, + { + title: 'Older versions', + children: [ + ['api/fspiop/v1.0/api-definition', 'v1.0'], + ] + } + ] + }, + { + title: 'Logical Data Model', + path: 'api/fspiop/logical-data-model', + collapsable: true + }, + { + title: 'Generic Transaction Patterns', + path: 'api/fspiop/generic-transaction-patterns', + collapsable: true + }, + { + title: 'Use Cases', + path: 'api/fspiop/use-cases' + }, + { + title: 'JSON Binding Rules', + path: 'api/fspiop/json-binding-rules' + }, + { + title: 'Scheme Rules', + path: 'api/fspiop/scheme-rules', + }, + { + title: 'PKI Best Practices', + path: 'api/fspiop/pki-best-practices', + }, + { + title: 'Signature (v1.1)', + path: 'api/fspiop/v1.1/signature', + }, + { + title: 'Encryption (v1.1)', + path: 'api/fspiop/v1.1/encryption', + }, + { + title: 'Glossary', + path: 'api/fspiop/glossary', + }, + ] + }, + { + title: 'Administration API', + collapsable: true, + sidebarDepth: 2, + children: [ + { + title: 'Overview', + path: 'api/administration/' + }, + { + title: 'Central Ledger API', + path: 'api/administration/central-ledger-api', + }, + ] + }, + { + title: 'Settlement API', + collapsable: true, + sidebarDepth: 2, + children: [ + ['api/settlement/', 'Overview'], + ] + }, + { + title: 'Thirdparty API', + collapsable: true, + sidebarDepth: 2, + children: [ + { + title: 'Overview', + path: 'api/thirdparty/', + }, + { + title: 'Transaction Patterns', + collapsable: true, + children: [ + { + title: 'Transaction Patterns Linking', + path: 'api/thirdparty/transaction-patterns-linking' + }, + { + title: 'Transaction Patterns Transfer', + path: 'api/thirdparty/transaction-patterns-transfer' + } + ] + }, + { + title: 'Data Models', + path: 'api/thirdparty/data-models', + collapsable: true + }, + ] + }, + { + title: 'Misc', + collapsable: true, + children: [ + ['api/fspiop/glossary', 'Glossary'], + ['api/license', 'License'], + ], + } + ] + }, + { + title: 'Mojaloop Hub Operations', + collapsable: true, // optional, defaults to true + sidebarDepth: 1, // optional, defaults to 1 + children: [ + { + title: 'Bounded Contexts', + // path: 'reference-architecture/boundedContexts/', // optional, link of the title, which should be an absolute path and must exist + //collapsable: false, + initialOpenGroupIndex: -1, + children: [ + '', + 'business-operations-framework/SecurityBC', + 'business-operations-framework/Microfrontend-JAMStack', + 'business-operations-framework/ReportingBC', + 'business-operations-framework/ReportDeveloperGuide', + { + title: "Settlement Ops Implementation", + path: 'business-operations-framework/SettlementBC' + } + ] + } + ] + } + ], + '/product/': [ + { + title: 'Mojaloop Features', + collapsable: false, + sidebarDepth: 2, + children: [ + ['features/ml-feature-list', 'About Mojaloop'], + ['features/use-cases', 'Use Cases'], + ['features/transaction', 'Transactions'], + ['features/risk', 'Risk Management'], + ['features/connectivity', 'Connectivity Support'], + ['features/product', 'Portals and Operational Features'], + ['features/tariffs', 'Fees and Tariffs'], + ['features/performance', 'Performance'], + ['features/deployment', 'Deploying Mojaloop'], + ['features/security', 'Mojaloop Security'], + ['features/engineering', 'Engineering Principles'], + ['features/invariants', 'Invariants'] + ] + } + ] + } + }, + + /** + * Apply plugins,ref:https://v1.vuepress.vuejs.org/zh/plugin/ + */ + plugins: [ + '@vuepress/plugin-back-to-top', + '@vuepress/plugin-medium-zoom', + 'versioning' + ] +}; + diff --git a/docs/.vuepress/enhanceApp.js b/docs/.vuepress/enhanceApp.js new file mode 100644 index 000000000..8452a8689 --- /dev/null +++ b/docs/.vuepress/enhanceApp.js @@ -0,0 +1,14 @@ +/** + * Client app enhancement file. + * + * https://v1.vuepress.vuejs.org/guide/basic-config.html#app-level-enhancements + */ + +export default ({ + Vue, // the version of Vue being used in the VuePress app + options, // the options for the root Vue instance + router, // the router instance for the app + siteData // site metadata +}) => { + // ...apply enhancements for the site. +} diff --git a/docs/.vuepress/public/BizOps-Framework-BizOps-Framework.png b/docs/.vuepress/public/BizOps-Framework-BizOps-Framework.png new file mode 100644 index 000000000..a3a0a1290 Binary files /dev/null and b/docs/.vuepress/public/BizOps-Framework-BizOps-Framework.png differ diff --git a/docs/.vuepress/public/BizOps-Framework-IaC-3.xx-&-Mojaloop-13.xx.png b/docs/.vuepress/public/BizOps-Framework-IaC-3.xx-&-Mojaloop-13.xx.png new file mode 100644 index 000000000..dd0df8f1e Binary files /dev/null and b/docs/.vuepress/public/BizOps-Framework-IaC-3.xx-&-Mojaloop-13.xx.png differ diff --git a/docs/.vuepress/public/BizOps-Framework-IaC-4.xx-&-Mojaloop-13.xx.png b/docs/.vuepress/public/BizOps-Framework-IaC-4.xx-&-Mojaloop-13.xx.png new file mode 100644 index 000000000..31b84b3bd Binary files /dev/null and b/docs/.vuepress/public/BizOps-Framework-IaC-4.xx-&-Mojaloop-13.xx.png differ diff --git a/docs/.vuepress/public/BizOps-Framework-Micro-frontend-deploy.png b/docs/.vuepress/public/BizOps-Framework-Micro-frontend-deploy.png new file mode 100644 index 000000000..5e1436e18 Binary files /dev/null and b/docs/.vuepress/public/BizOps-Framework-Micro-frontend-deploy.png differ diff --git a/docs/.vuepress/public/BizOps-Framework-Security-BC.png b/docs/.vuepress/public/BizOps-Framework-Security-BC.png new file mode 100644 index 000000000..e1795ba89 Binary files /dev/null and b/docs/.vuepress/public/BizOps-Framework-Security-BC.png differ diff --git a/docs/.vuepress/public/BizOps-Framework-Settlements.png b/docs/.vuepress/public/BizOps-Framework-Settlements.png new file mode 100644 index 000000000..460eb6637 Binary files /dev/null and b/docs/.vuepress/public/BizOps-Framework-Settlements.png differ diff --git a/docs/.vuepress/public/BusinessFlowView.png b/docs/.vuepress/public/BusinessFlowView.png new file mode 100644 index 000000000..95f1af385 Binary files /dev/null and b/docs/.vuepress/public/BusinessFlowView.png differ diff --git a/docs/.vuepress/public/PM4ML_system_architecture.png b/docs/.vuepress/public/PM4ML_system_architecture.png new file mode 100644 index 000000000..340db13a2 Binary files /dev/null and b/docs/.vuepress/public/PM4ML_system_architecture.png differ diff --git a/docs/.vuepress/public/Reporting-&-Auditing-Overview.png b/docs/.vuepress/public/Reporting-&-Auditing-Overview.png new file mode 100644 index 000000000..d55f8e71b Binary files /dev/null and b/docs/.vuepress/public/Reporting-&-Auditing-Overview.png differ diff --git a/docs/.vuepress/public/RestReportingArchitecture.drawio.png b/docs/.vuepress/public/RestReportingArchitecture.drawio.png new file mode 100644 index 000000000..4c3766373 Binary files /dev/null and b/docs/.vuepress/public/RestReportingArchitecture.drawio.png differ diff --git a/docs/.vuepress/public/TLS_connection.svg b/docs/.vuepress/public/TLS_connection.svg new file mode 100644 index 000000000..d4afa9830 --- /dev/null +++ b/docs/.vuepress/public/TLS_connection.svg @@ -0,0 +1,47 @@ +ClientClientServerServerTLS session initServer certificate exchange1Request server certificate2Server certificateServer certificatesigned by server's CA3Validate certificateClient certificate exchange4Request client certificate5Client certificateClient certificate issued by clientand signed by server's CA6Validate certificateTLS session initiated \ No newline at end of file diff --git a/docs/.vuepress/public/action_add_withdraw.png b/docs/.vuepress/public/action_add_withdraw.png new file mode 100644 index 000000000..fbe9126c6 Binary files /dev/null and b/docs/.vuepress/public/action_add_withdraw.png differ diff --git a/docs/.vuepress/public/action_change_net_debit_cap.png b/docs/.vuepress/public/action_change_net_debit_cap.png new file mode 100644 index 000000000..37478eebe Binary files /dev/null and b/docs/.vuepress/public/action_change_net_debit_cap.png differ diff --git a/docs/.vuepress/public/action_update_ndc.png b/docs/.vuepress/public/action_update_ndc.png new file mode 100644 index 000000000..55c3feea6 Binary files /dev/null and b/docs/.vuepress/public/action_update_ndc.png differ diff --git a/docs/.vuepress/public/add_withdraw_funds.png b/docs/.vuepress/public/add_withdraw_funds.png new file mode 100644 index 000000000..62f0dfebc Binary files /dev/null and b/docs/.vuepress/public/add_withdraw_funds.png differ diff --git a/docs/.vuepress/public/change_mgmt_flow.png b/docs/.vuepress/public/change_mgmt_flow.png new file mode 100644 index 000000000..4a6883c13 Binary files /dev/null and b/docs/.vuepress/public/change_mgmt_flow.png differ diff --git a/docs/.vuepress/public/check_settlement_details.png b/docs/.vuepress/public/check_settlement_details.png new file mode 100644 index 000000000..6917cd179 Binary files /dev/null and b/docs/.vuepress/public/check_settlement_details.png differ diff --git a/docs/.vuepress/public/client.png b/docs/.vuepress/public/client.png new file mode 100644 index 000000000..b296c0350 Binary files /dev/null and b/docs/.vuepress/public/client.png differ diff --git a/docs/.vuepress/public/clientgraphql.png b/docs/.vuepress/public/clientgraphql.png new file mode 100644 index 000000000..84a201287 Binary files /dev/null and b/docs/.vuepress/public/clientgraphql.png differ diff --git a/docs/.vuepress/public/close.png b/docs/.vuepress/public/close.png new file mode 100644 index 000000000..c87338a2d Binary files /dev/null and b/docs/.vuepress/public/close.png differ diff --git a/docs/.vuepress/public/confirm_action_add_withdraw_funds.png b/docs/.vuepress/public/confirm_action_add_withdraw_funds.png new file mode 100644 index 000000000..3140e66bb Binary files /dev/null and b/docs/.vuepress/public/confirm_action_add_withdraw_funds.png differ diff --git a/docs/.vuepress/public/confirm_action_update_ndc.png b/docs/.vuepress/public/confirm_action_update_ndc.png new file mode 100644 index 000000000..983a5330b Binary files /dev/null and b/docs/.vuepress/public/confirm_action_update_ndc.png differ diff --git a/docs/.vuepress/public/defect_triage.png b/docs/.vuepress/public/defect_triage.png new file mode 100644 index 000000000..5940d6be2 Binary files /dev/null and b/docs/.vuepress/public/defect_triage.png differ diff --git a/docs/.vuepress/public/dfsp_financial_positions_2.png b/docs/.vuepress/public/dfsp_financial_positions_2.png new file mode 100644 index 000000000..b549907fa Binary files /dev/null and b/docs/.vuepress/public/dfsp_financial_positions_2.png differ diff --git a/docs/.vuepress/public/disable_dfsp_position_ledger.png b/docs/.vuepress/public/disable_dfsp_position_ledger.png new file mode 100644 index 000000000..5ae883f7c Binary files /dev/null and b/docs/.vuepress/public/disable_dfsp_position_ledger.png differ diff --git a/docs/.vuepress/public/enable_dfsp_position_ledger.png b/docs/.vuepress/public/enable_dfsp_position_ledger.png new file mode 100644 index 000000000..ef732094e Binary files /dev/null and b/docs/.vuepress/public/enable_dfsp_position_ledger.png differ diff --git a/docs/.vuepress/public/finalise_settlement.png b/docs/.vuepress/public/finalise_settlement.png new file mode 100644 index 000000000..8121bcdf4 Binary files /dev/null and b/docs/.vuepress/public/finalise_settlement.png differ diff --git a/docs/.vuepress/public/finalising_settlement_popup.png b/docs/.vuepress/public/finalising_settlement_popup.png new file mode 100644 index 000000000..694410bb0 Binary files /dev/null and b/docs/.vuepress/public/finalising_settlement_popup.png differ diff --git a/docs/.vuepress/public/find_transfers.png b/docs/.vuepress/public/find_transfers.png new file mode 100644 index 000000000..4eea7f394 Binary files /dev/null and b/docs/.vuepress/public/find_transfers.png differ diff --git a/docs/.vuepress/public/frontend.png b/docs/.vuepress/public/frontend.png new file mode 100644 index 000000000..cbd35d0ff Binary files /dev/null and b/docs/.vuepress/public/frontend.png differ diff --git a/docs/.vuepress/public/implement.png b/docs/.vuepress/public/implement.png new file mode 100644 index 000000000..adb409a8e Binary files /dev/null and b/docs/.vuepress/public/implement.png differ diff --git a/docs/.vuepress/public/incident_mgmt_single_image.jpeg b/docs/.vuepress/public/incident_mgmt_single_image.jpeg new file mode 100644 index 000000000..f6c38c40a Binary files /dev/null and b/docs/.vuepress/public/incident_mgmt_single_image.jpeg differ diff --git a/docs/.vuepress/public/incident_mgmt_single_image.png b/docs/.vuepress/public/incident_mgmt_single_image.png new file mode 100644 index 000000000..5474a21b2 Binary files /dev/null and b/docs/.vuepress/public/incident_mgmt_single_image.png differ diff --git a/docs/.vuepress/public/mes_portal.png b/docs/.vuepress/public/mes_portal.png new file mode 100644 index 000000000..e157b8431 Binary files /dev/null and b/docs/.vuepress/public/mes_portal.png differ diff --git a/docs/.vuepress/public/mes_portal_request_types.png b/docs/.vuepress/public/mes_portal_request_types.png new file mode 100644 index 000000000..9381dd075 Binary files /dev/null and b/docs/.vuepress/public/mes_portal_request_types.png differ diff --git a/docs/.vuepress/public/mes_report_bug.png b/docs/.vuepress/public/mes_report_bug.png new file mode 100644 index 000000000..8a3fdfca9 Binary files /dev/null and b/docs/.vuepress/public/mes_report_bug.png differ diff --git a/docs/.vuepress/public/mes_technical_support.png b/docs/.vuepress/public/mes_technical_support.png new file mode 100644 index 000000000..5e60a1cd3 Binary files /dev/null and b/docs/.vuepress/public/mes_technical_support.png differ diff --git a/docs/.vuepress/public/microfrontendloading.png b/docs/.vuepress/public/microfrontendloading.png new file mode 100644 index 000000000..b25f49aad Binary files /dev/null and b/docs/.vuepress/public/microfrontendloading.png differ diff --git a/docs/.vuepress/public/mlns_position_popup.png b/docs/.vuepress/public/mlns_position_popup.png new file mode 100644 index 000000000..d174a653a Binary files /dev/null and b/docs/.vuepress/public/mlns_position_popup.png differ diff --git a/docs/.vuepress/public/mojaloop-sdk.png b/docs/.vuepress/public/mojaloop-sdk.png new file mode 100644 index 000000000..20990db3f Binary files /dev/null and b/docs/.vuepress/public/mojaloop-sdk.png differ diff --git a/docs/.vuepress/public/mojaloop_logo_med copy 2.png b/docs/.vuepress/public/mojaloop_logo_med copy 2.png new file mode 100644 index 000000000..74331d2b8 Binary files /dev/null and b/docs/.vuepress/public/mojaloop_logo_med copy 2.png differ diff --git a/docs/.vuepress/public/mojaloop_logo_med copy.png b/docs/.vuepress/public/mojaloop_logo_med copy.png new file mode 100644 index 000000000..74331d2b8 Binary files /dev/null and b/docs/.vuepress/public/mojaloop_logo_med copy.png differ diff --git a/docs/.vuepress/public/mojaloop_logo_med.png b/docs/.vuepress/public/mojaloop_logo_med.png new file mode 100644 index 000000000..74331d2b8 Binary files /dev/null and b/docs/.vuepress/public/mojaloop_logo_med.png differ diff --git a/docs/.vuepress/public/mttr.png b/docs/.vuepress/public/mttr.png new file mode 100644 index 000000000..6672547c2 Binary files /dev/null and b/docs/.vuepress/public/mttr.png differ diff --git a/docs/.vuepress/public/plan_approve.png b/docs/.vuepress/public/plan_approve.png new file mode 100644 index 000000000..bffa3366b Binary files /dev/null and b/docs/.vuepress/public/plan_approve.png differ diff --git a/docs/.vuepress/public/portal_login.png b/docs/.vuepress/public/portal_login.png new file mode 100644 index 000000000..b00b20f28 Binary files /dev/null and b/docs/.vuepress/public/portal_login.png differ diff --git a/docs/.vuepress/public/problem_mgmt.png b/docs/.vuepress/public/problem_mgmt.png new file mode 100644 index 000000000..4cd94d7d0 Binary files /dev/null and b/docs/.vuepress/public/problem_mgmt.png differ diff --git a/docs/.vuepress/public/raise_rfc.png b/docs/.vuepress/public/raise_rfc.png new file mode 100644 index 000000000..ae894b359 Binary files /dev/null and b/docs/.vuepress/public/raise_rfc.png differ diff --git a/docs/.vuepress/public/release_mgmt.png b/docs/.vuepress/public/release_mgmt.png new file mode 100644 index 000000000..a31843cec Binary files /dev/null and b/docs/.vuepress/public/release_mgmt.png differ diff --git a/docs/.vuepress/public/release_process.png b/docs/.vuepress/public/release_process.png new file mode 100644 index 000000000..a3f3b269a Binary files /dev/null and b/docs/.vuepress/public/release_process.png differ diff --git a/docs/.vuepress/public/release_service_components.png b/docs/.vuepress/public/release_service_components.png new file mode 100644 index 000000000..c9f2dcb6d Binary files /dev/null and b/docs/.vuepress/public/release_service_components.png differ diff --git a/docs/.vuepress/public/review_authorize.png b/docs/.vuepress/public/review_authorize.png new file mode 100644 index 000000000..7d71c8ed3 Binary files /dev/null and b/docs/.vuepress/public/review_authorize.png differ diff --git a/docs/.vuepress/public/rolepermissions.png b/docs/.vuepress/public/rolepermissions.png new file mode 100644 index 000000000..373ea01d0 Binary files /dev/null and b/docs/.vuepress/public/rolepermissions.png differ diff --git a/docs/.vuepress/public/security_incident_process.jpeg b/docs/.vuepress/public/security_incident_process.jpeg new file mode 100644 index 000000000..e27e16b3b Binary files /dev/null and b/docs/.vuepress/public/security_incident_process.jpeg differ diff --git a/docs/.vuepress/public/security_incident_process.png b/docs/.vuepress/public/security_incident_process.png new file mode 100644 index 000000000..4e60e123d Binary files /dev/null and b/docs/.vuepress/public/security_incident_process.png differ diff --git a/docs/.vuepress/public/security_overview.png b/docs/.vuepress/public/security_overview.png new file mode 100644 index 000000000..77aff024c Binary files /dev/null and b/docs/.vuepress/public/security_overview.png differ diff --git a/docs/.vuepress/public/settlementProcessAPI.svg b/docs/.vuepress/public/settlementProcessAPI.svg new file mode 100644 index 000000000..ac87eecfd --- /dev/null +++ b/docs/.vuepress/public/settlementProcessAPI.svg @@ -0,0 +1,505 @@ +Settlement ProcessBusiness Hub Operator UserBusiness Hub Operator UserSettlement BankSettlement BankMicro-frontendMicro-frontendExperience LayerExperience LayerProcess LayerProcess LayerReport APIReport APIMojaloopMojaloopClose a settlement window1User clicks close Settlement Window2Close Settlement Windowwindows Id3Add user informationPOST: /settlementWindows{SettlementWindowId}4Confirm that the settlement window is closed and wait retry with timeout if not.GET central-settlements/settlementWindows/{id}5Update UIInitiate Settlement6Initiate Settlement for these windows & CurrencyList of Settlement windows Ids[Optional] Currency or Settlement Model7POST: /settlements:initiate{"settlementWindows": [{"id": 0}], #settlement window id's (integer)"settlementModel":"defered net", # (string)"currency", :"XXX" # (currencyEnum)}8POST: /settlements:initiate{"settlementWindows": [{"id": 0}], #settlement window id's (integer)"settlementModel":"defered net", # (string)"currency", :"XXX" # (currencyEnum)"user": "hub operators name" # (string)}determine settlement Model/s9Load currencies for windows using GET central-settlements/settlementWindows/{id}10Load settlement models using GET central-ledger/settlementModels11Determine minimum list of settlement modelsloop[for settlement models]12Create settlementPOST: central-settlements/settlements{settlementModel, settlementWindowIds[]}13Advance settlement participant accountstate to PS_TRANSFERS_RECORDEDPUT: central-settlements/settlements/{id}Net creditparticipantposition ledgers are adjusted14Return reponse, success HTTP:200{["SettlementModel":"defered-net" #(string)"id":null, # optional (integer)"state": "state" # optional (string)"errorInformation": { # optional"errorCode": 0,"errorDescription": "string","extensionList": {"extension": [{"key": "string","value": "string" } ] } }]}15Update UI with settlement statusGenerate Settlement Matrix Report16Settlement Initiation Report Download17Add User18Settlement Initiation Report Download19report is downloaded20report is downloaded21Report is sent tosettlement bankto beginthe settlement transfersbetween participantsFinalise Settlement22TheSettlement Bankhas completed makingtransfers between participants.Thefinalisation reportthat is recieved fromthe Settlement Bank, includes the settlement accountbalances after all the transfers have been processed.It is possible that these account balances are notas expected. This would indicate that anadditionalfunds in / funds outhas occured in the settlementaccounts that has not yet been captured in theMojaloop Settlement ledgers.23Validate finalisation file24POST: /settlements:finalize25Fatal: Validate file formatLoad file into JSON object{"finalisationReference":"SettlementFinalisationFilename.xlsx" # (string),"settlementId" : 10 , # settlement batch id (integer)"participants" : [{"name": "payerfsp",# mojaloop participant name (string)"id": 1, # mojaloop database id (integer)"settlementAccountId": 1, # settlement account id for participant (integer)"externalBalance": 10000, # external balance of settlement account (number)"netSettlementAmount": {"amount": 0, # number"currency": "XXX" # currency string (CurrencyEnum)}} ] # all participants that are involved in the settlement}26Validate finalisationPOST: /settlements:finalizeload settlement data27Get settlement informationGET central-settlements/settlements/{id}28Get all participantsGET central-ledger/participants29Get all participants limitsGET central-ledger/participants/limits30For each participant get account balanceGET central-ledger/participants/{name}/accountsProcess validation31Fatal: Validate Participants and theiraccounts ids are valid, match,and are the correct type, and correct currency32Fatal: Validate Settlement Id non-matching33Fatal: Validate Participant Settlement datatransfer sum is zero34Fatal: Validate Participant Settlement datamatches net settlement amountCalculate Adjustments and Warnings35Non fatal: Validate Participant Settlementbalance is expectedReturn warnings if there are discrepencies36Non fatal: Validate Participant Settlementbalance is zero or positive37Return finalisation validation results{"finalisationId": "GUIDv4", # Guid version 4 (string)"valid":true, # (boolean) true if none failure error"errors": [{"type": "string", "message": "description", "errorInformation": {...}}],"warnings": [{"type": "string", "message": "description", "errorInformation": {...}}]}38Show validation results to user3940User confirms proceeding with finalisation41Confirm FinalisationPOST: /settlements:confirmFinalize{finalisationId:"GUIDv4", (string)"settlementId" : 10 , # settlement batch id (integer)balanceSettlementOption: true # (boolean)}42Confirm FinalisationPOST: /settlements:confirmFinalize{"finalisationId":"GUIDv4", (string)"settlementId" : 10 , # settlement batch id (integer)"balanceSettlementOption":true, # (boolean)"user":"userName" # (string)}loop[for each settlement debit participant]alt[if balanceSettlementOption is true]43Adjust settlment account according to settlement (funds Out)POST central-ledger/participants/{name}/accounts/{id}Confirm PUT /participants/{name}/accounts/{id}/transfers/{transferId}44Advance state to SettledPUT central-settlements/settlements/{sid}/participants/{pid}/accounts/{aid}PUT /settlements/{sid}/participants/{pid}Net debitparticipantposition ledgers are adjustedloop[for each settlement credit participant]alt[if balanceSettlementOption is true]45Adjust settlment account according to settlement (funds In)POST /participants/{name}/accounts/{id}reason: "Settlement Finanisation"extension list:[ { 'key'='user', 'value'='username'},{ 'key'='reference', 'value'='finalisatonReference'} ]46Advance state to SettledPUT central-settlements/settlements/{sid}/participants/{pid}/accounts/{aid}PUT /settlements/{sid}/participants/{pid}alt[if balanceSettlementOption is true]loop[For each participant rebalance Settlement account]47Get latest balanceGET central-ledger/participants/{name}/accounts48if < actual balance thenincrease balance (funds In)POST central-ledger/participants/{name}/accounts/{id}49if > actual balance thendecrease balance (funds Out)POST central-ledger/participants/{name}/accounts/{id}Confirm PUT /participants/{name}/accounts/{id}/transfers/{transferId}reason: "Settlement Rebalance"extension list:[ { 'key'='user', 'value'='username'},{ 'key'='reference', 'value'='finalisatonReference'} ]50Confirm correct balanceGET central-ledger/participants/{name}/accounts51Response{"state": "string","participants" : [{"name": "payerfsp",# mojaloop participant name (string)"id": 1, # mojaloop database id (integer)"settlementAccountId": 1, # settlement account id for participant (integer)"errors": [{"type": "string", "message": "description", "errorInformation": {...}}] # errorInformation std fspiop error information object}]}52SettlementProcessCompleted (Update settlement Status or display errors) \ No newline at end of file diff --git a/docs/.vuepress/public/settlementProcessFinaliseErrors.svg b/docs/.vuepress/public/settlementProcessFinaliseErrors.svg new file mode 100644 index 000000000..a6ca950ff --- /dev/null +++ b/docs/.vuepress/public/settlementProcessFinaliseErrors.svg @@ -0,0 +1,439 @@ +Settlement ProcessBusiness Hub Operator UserBusiness Hub Operator UserSettlement BankSettlement BankMicro-frontendMicro-frontendExperience LayerExperience LayerProcess LayerProcess LayerReport APIReport APIMojaloopMojaloopFinalise Settlement1 TheSettlement Bankhas completed makingtransfers between participants.Thefinalisation reportthat is recieved fromthe Settlement Bank, includes the settlement accountbalances after all the transfers have been processed. It is possible that these account balances are notas expected. This would indicate that anadditional funds in / funds outhas occured in the settlementaccounts that has not yet been captured in theMojaloop Settlement ledgers.2Validate finalisation file3POST: /settlements:finalize4Fatal: Validate file formatLoad file into JSON object{"finalisationReference":"SettlementFinalisationFilename.xlsx" # (string),"settlementId" : 10 , # settlement batch id (integer)"participants" : [{"name": "payerfsp",# mojaloop participant name (string)"id": 1, # mojaloop database id (integer)"settlementAccountId": 1, # settlement account id for participant (integer)"externalBalance": 10000, # external balance of settlement account (number)"netSettlementAmount": {"amount": 0, # number"currency": "XXX" # currency string (CurrencyEnum)}} ] # all participants that are involved in the settlement}5Validate finalisationPOST: /settlements:finalizeload settlement data6Get settlement informationGET central-settlements/settlements/{id}7Get all participants GET central-ledger/participants8Get all participants limits GET central-ledger/participants/limits9For each participant get account balance GET central-ledger/participants/{name}/accountsProcess validation10Fatal: Validate Participants and theiraccounts ids are valid, match,and are the correct type, and correct currency11Fatal: Validate Settlement Id non-matching12Fatal: Validate Participant Settlement datatransfer sum is zero13Fatal: Validate Participant Settlement datamatches net settlement amountalt[Success/Warnings]Calculate Adjustments and Warnings14Non fatal: Validate Participant Settlementbalance is expectedReturn warnings if there are discrepencies15Non fatal: Validate Participant Settlementbalance is zero or positive16Return finalisation validation results{"finalisationId": "GUIDv4", # Guid version 4 (string)"valid":true # (boolean) true if none failure error"warnings": [{"type": "string", "message": "description", "errorInformation": {...}}]}[Error]17Return Error, HTTP: code Ref: Finalize Settlement Validation Error Codes{"finalisationId": "GUIDv4", # Guid version 4 (string)"valid":false, # (boolean) false if failures"errors": [{"type": "string", "message": "description", "errorInformation": {...}}]}18Show validation results to user19 20User confirms proceeding with finalisation21Confirm FinalisationPOST: /settlements:confirmFinalize{finalisationId:"GUIDv4", (string)"settlementId" : 10 , # settlement batch id (integer)balanceSettlementOption: true # (boolean)}22Confirm FinalisationPOST: /settlements:confirmFinalize{"finalisationId":"GUIDv4", (string)"settlementId" : 10 , # settlement batch id (integer)"balanceSettlementOption":true, # (boolean)"user":"userName" # (string)}23validate finalisationId and settlementId against stored statealt[Validation Success]loop[for each settlement debit participant]alt[if balanceSettlementOption is true]24Adjust settlment account according to settlement (funds Out) POST central-ledger/participants/{name}/accounts/{id}25Confirm adjustment PUT central-ledger/participants/{name}/accounts/{id}/transfers/{transferId}26Advance settlement participant accountstate to PS_TRANSFERS_COMMITED PUT: central-settlements/settlements/{sid}/participants/{pid}27Advance settlement participant accountstate to SETTLED PUT: central-settlements/settlements/{sid}/participants/{pid}Net debitparticipantposition ledgers are adjustedloop[for each settlement credit participant]alt[if balanceSettlementOption is true]28Adjust settlment account according to settlement (funds In) POST /participants/{name}/accounts/{id}reason: "Settlement Finanisation"extension list:[ { 'key'='user', 'value'='username'},{ 'key'='reference', 'value'='finalisatonReference'} ]29Advance settlement participant accountstate to PS_TRANSFERS_COMMITED PUT: central-settlements/settlements/{sid}/participants/{pid}30Advance settlement participant accountstate to SETTLED PUT: central-settlements/settlements/{sid}/participants/{pid}alt[if balanceSettlementOption is true]loop[For each participant rebalance Settlement account]31Get latest balance GET central-ledger/participants/{name}/accountsalt[if latest balance < actual balance]32Increase balance (funds In) POST central-ledger/participants/{name}/accounts/{id}[if latest balance > actual balance]33Decrease balance (funds Out) POST central-ledger/participants/{name}/accounts/{id}34Confirm adjustment PUT /participants/{name}/accounts/{id}/transfers/{transferId}[if latest balance == actual balance]35do nothingreason: "Settlement Rebalance"extension list:[ { 'key'='user', 'value'='username'},{ 'key'='reference', 'value'='finalisatonReference'} ]36Confirm correct balance GET central-ledger/participants/{name}/accountsalt[Processing Success]37Response success, HTTP: 200{"settlement": {... map settlement object from settlements api }}[Processing Error]38Return Error, HTTP: code Ref:Finalize Settlement Confirmation Error Codes{"settlement": {... map settlement object from settlements api },"participantErrors" : [{"id": 1, # mojaloop database id (integer)"error": {"type": "string", "message": "description", "errorInformation": {...}} # errorInformation std fspiop error information object}]}[Validation failure]39Return Error, HTTP: code Ref:Finalize Settlement Confirmation Error Codes{"errorInformation": {"errorCode": 0,"errorDescription": "string","extensionList": {"extension": [{"key": "string","value": "string"}]}}} # errorInformation std fspiop error information object40SettlementProcessCompleted (Update settlement Status or display errors) \ No newline at end of file diff --git a/docs/.vuepress/public/settlementProcessInitiationErrors.svg b/docs/.vuepress/public/settlementProcessInitiationErrors.svg new file mode 100644 index 000000000..9452b5bf5 --- /dev/null +++ b/docs/.vuepress/public/settlementProcessInitiationErrors.svg @@ -0,0 +1,123 @@ +Settlement ProcessBusiness Hub Operator UserBusiness Hub Operator UserSettlement BankSettlement BankMicro-frontendMicro-frontendExperience LayerExperience LayerProcess LayerProcess LayerReport APIReport APIMojaloopMojaloopInitiate Settlement1Initiate Settlement for these windows & CurrencyList of Settlement windows Ids[Optional] Currency or Settlement Model2POST: /settlements:initiate{"settlementWindows": [{"id": 0}], #settlement window id's (integer)"settlementModel":"defered net", # (string)"currency", :"XXX" # (currencyEnum)}3POST: /settlements:initiate{"settlementWindows": [{"id": 0}], #settlement window id's (integer)"settlementModel":"defered net", # (string)"currency", :"XXX" # (currencyEnum)"user": "hub operators name" # (string)}determine settlement Model/s4Load currencies for windows using GET central-settlements/settlementWindows/{id}5Load settlementModels using GET central-ledger/settlementModels6Determine minimum list of settlementModels, return a map for each settlementModel containing a list of applicable settlementWindows7Validatealt[Validation Error]8Return Error HTTP: code Ref: Initiate Settlement Error Codes{"errorInformation": {"errorCode": 0,"errorDescription": "string","extensionList": {"extension": [{"key": "string","value": "string"}]}}} [Validation Success]loop[for settlement models]9Create settlement POST: central-settlements/settlements {settlementModel, settlementWindowIds[]}10Advance settlement participant accountstate to PS_TRANSFERS_RECORDED PUT: central-settlements/settlements/{id}11Advance settlement participant accountstate to PS_TRANSFERS_RESERVED PUT: central-settlements/settlements/{id}Net creditparticipantposition ledgers are adjusted12Return response, success/warnings HTTP:200[{"settlementModel":"defered-net" #(string)"settlement": {... map settlement object from settlements api }, #optional"errorInformation": { # optional"errorCode": 0,"errorDescription": "string","extensionList": {"extension": [{"key": "string","value": "string"}]}}}]13Update UI with settlement status \ No newline at end of file diff --git a/docs/.vuepress/public/settlement_details_popup.png b/docs/.vuepress/public/settlement_details_popup.png new file mode 100644 index 000000000..b9b709218 Binary files /dev/null and b/docs/.vuepress/public/settlement_details_popup.png differ diff --git a/docs/.vuepress/public/settlement_processing.jpg b/docs/.vuepress/public/settlement_processing.jpg new file mode 100644 index 000000000..cb01cf0c6 Binary files /dev/null and b/docs/.vuepress/public/settlement_processing.jpg differ diff --git a/docs/.vuepress/public/settlement_window_mgmt.png b/docs/.vuepress/public/settlement_window_mgmt.png new file mode 100644 index 000000000..fc2739647 Binary files /dev/null and b/docs/.vuepress/public/settlement_window_mgmt.png differ diff --git a/docs/.vuepress/public/settlement_window_mgmt_close.png b/docs/.vuepress/public/settlement_window_mgmt_close.png new file mode 100644 index 000000000..b2870a420 Binary files /dev/null and b/docs/.vuepress/public/settlement_window_mgmt_close.png differ diff --git a/docs/.vuepress/public/settlement_window_mgmt_selector.png b/docs/.vuepress/public/settlement_window_mgmt_selector.png new file mode 100644 index 000000000..063b7a7b9 Binary files /dev/null and b/docs/.vuepress/public/settlement_window_mgmt_selector.png differ diff --git a/docs/.vuepress/public/settlement_window_mgmt_settle_button.png b/docs/.vuepress/public/settlement_window_mgmt_settle_button.png new file mode 100644 index 000000000..f9632c41b Binary files /dev/null and b/docs/.vuepress/public/settlement_window_mgmt_settle_button.png differ diff --git a/docs/.vuepress/public/settlement_window_settlement_submitted.png b/docs/.vuepress/public/settlement_window_settlement_submitted.png new file mode 100644 index 000000000..fcb119519 Binary files /dev/null and b/docs/.vuepress/public/settlement_window_settlement_submitted.png differ diff --git a/docs/.vuepress/public/transfer_details_quote_parties.png b/docs/.vuepress/public/transfer_details_quote_parties.png new file mode 100644 index 000000000..7cc85b262 Binary files /dev/null and b/docs/.vuepress/public/transfer_details_quote_parties.png differ diff --git a/docs/.vuepress/public/transfer_details_quote_request.png b/docs/.vuepress/public/transfer_details_quote_request.png new file mode 100644 index 000000000..4d78fd830 Binary files /dev/null and b/docs/.vuepress/public/transfer_details_quote_request.png differ diff --git a/docs/.vuepress/public/transfer_details_quote_responses.png b/docs/.vuepress/public/transfer_details_quote_responses.png new file mode 100644 index 000000000..5d0af6352 Binary files /dev/null and b/docs/.vuepress/public/transfer_details_quote_responses.png differ diff --git a/docs/.vuepress/public/transfer_details_transfer_fulfilments.png b/docs/.vuepress/public/transfer_details_transfer_fulfilments.png new file mode 100644 index 000000000..831ec63ba Binary files /dev/null and b/docs/.vuepress/public/transfer_details_transfer_fulfilments.png differ diff --git a/docs/.vuepress/public/transfer_details_transfer_participants.png b/docs/.vuepress/public/transfer_details_transfer_participants.png new file mode 100644 index 000000000..1c7c25888 Binary files /dev/null and b/docs/.vuepress/public/transfer_details_transfer_participants.png differ diff --git a/docs/.vuepress/public/transfer_details_transfer_prepares.png b/docs/.vuepress/public/transfer_details_transfer_prepares.png new file mode 100644 index 000000000..982253b85 Binary files /dev/null and b/docs/.vuepress/public/transfer_details_transfer_prepares.png differ diff --git a/docs/.vuepress/public/transfer_details_transfer_state_changes.png b/docs/.vuepress/public/transfer_details_transfer_state_changes.png new file mode 100644 index 000000000..1e22ba9b5 Binary files /dev/null and b/docs/.vuepress/public/transfer_details_transfer_state_changes.png differ diff --git a/docs/.vuepress/public/update_participant.png b/docs/.vuepress/public/update_participant.png new file mode 100644 index 000000000..b6a1b720e Binary files /dev/null and b/docs/.vuepress/public/update_participant.png differ diff --git a/docs/.vuepress/public/userroles.png b/docs/.vuepress/public/userroles.png new file mode 100644 index 000000000..3cdc58318 Binary files /dev/null and b/docs/.vuepress/public/userroles.png differ diff --git a/docs/.vuepress/styles/index.styl b/docs/.vuepress/styles/index.styl new file mode 100644 index 000000000..61bf8beba --- /dev/null +++ b/docs/.vuepress/styles/index.styl @@ -0,0 +1,42 @@ +/** + * Custom Styles here. + * + * ref:https://v1.vuepress.vuejs.org/config/#index-styl + */ + +@import url('https://fonts.googleapis.com/css?family=Varela+Round') +@import url('https://fonts.googleapis.com/css?family=Open+Sans') + +h1, h2, h3 + font-family: 'Varela Round' + +h5 + font-size: 1.05rem + +p + font-family: 'Open Sans' + +// .home +// margin-top: 56px + +.home .hero img + max-width 450px!important + +.home .feature + max-width: 33% !important + +.home .hero .description + color: #000000 !important + max-width: 720px !important + +.navbar .site-name + display: none + +// .navbar +// top: 55px !important + +.home .hero #main-title + display: none + +// .main-content-wrapper +// margin-top: 75px diff --git a/docs/.vuepress/styles/palette.styl b/docs/.vuepress/styles/palette.styl new file mode 100644 index 000000000..78335ca83 --- /dev/null +++ b/docs/.vuepress/styles/palette.styl @@ -0,0 +1,14 @@ +/** + * Custom palette here. + * + * ref:https://v1.vuepress.vuejs.org/zh/config/#palette-styl + */ + +$accentColor = #00a3ff +$textColor = #000000 +$borderColor = #eaecef +$codeBgColor = #282c34 +// Set this to 7 when we want a custom banner above the navbar +$navbarHeight = 3.5rem +// set this to 3.5 when we want a custom banner above the navbar +$navbarBannerHeight = 0rem diff --git a/docs/.vuepress/theme/CHANGELOG.md b/docs/.vuepress/theme/CHANGELOG.md new file mode 100644 index 000000000..88e9ba443 --- /dev/null +++ b/docs/.vuepress/theme/CHANGELOG.md @@ -0,0 +1,188 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [4.9.0](https://github.com/appcelerator/docs-devkit/compare/v4.8.3...v4.9.0) (2020-11-10) + + +### Bug Fixes + +* fix color shades, sidebar sub groups and type meta padding ([ffc5817](https://github.com/appcelerator/docs-devkit/commit/ffc581761be5331d94bd6d222c24b044925b11a8)) + + +### Features + +* **theme:** custom color theme for prism.js ([#83](https://github.com/appcelerator/docs-devkit/issues/83)) ([c826dc0](https://github.com/appcelerator/docs-devkit/commit/c826dc0d34e6f2c149109490800a752b0d39aef0)) + + + + + +## [4.8.3](https://github.com/appcelerator/docs-devkit/compare/v4.8.2...v4.8.3) (2020-10-21) + + +### Bug Fixes + +* use axway theme gray-dk in place of hard-coded #aaa ([7723256](https://github.com/appcelerator/docs-devkit/commit/7723256)) +* use named axway colors in place of hard-coded hex values ([961cbb1](https://github.com/appcelerator/docs-devkit/commit/961cbb1)) + + + + + +## [4.8.2](https://github.com/appcelerator/docs-devkit/compare/v4.8.1...v4.8.2) (2020-10-19) + + +### Bug Fixes + +* scroll behavior and css adjustments ([c8cb639](https://github.com/appcelerator/docs-devkit/commit/c8cb639)) +* **theme:** add axway color variables ([df8c5b3](https://github.com/appcelerator/docs-devkit/commit/df8c5b3)) +* **theme:** try to use axway typography values for headers ([7fd1115](https://github.com/appcelerator/docs-devkit/commit/7fd1115)) +* **theme:** use axway blue colors for inline code tags ([16bb3e5](https://github.com/appcelerator/docs-devkit/commit/16bb3e5)) +* **theme:** use axway danger/success/warn colors for badges ([a543d9c](https://github.com/appcelerator/docs-devkit/commit/a543d9c)) +* **theme:** use axway danger/success/warn colors for custom blocks ([4a9cfe1](https://github.com/appcelerator/docs-devkit/commit/4a9cfe1)) +* **theme:** use page relativePath to generate edit link ([#70](https://github.com/appcelerator/docs-devkit/issues/70)) ([ca0e1c2](https://github.com/appcelerator/docs-devkit/commit/ca0e1c2)), closes [#48](https://github.com/appcelerator/docs-devkit/issues/48) + + + + + +# [4.8.0](https://github.com/appcelerator/docs-devkit/compare/v4.7.0...v4.8.0) (2020-10-08) + + +### Features + +* **theme-titanium:** allow frontmatter to contain editUrl for edit this page link ([dd6a1e2](https://github.com/appcelerator/docs-devkit/commit/dd6a1e2)) + + + + + +## [4.5.1](https://github.com/appcelerator/docs-devkit/compare/v4.5.0...v4.5.1) (2020-06-19) + + +### Performance Improvements + +* cache page lookup ([4c27c0f](https://github.com/appcelerator/docs-devkit/commit/4c27c0f)) + + + + + +# [4.5.0](https://github.com/appcelerator/docs-devkit/compare/v4.4.1...v4.5.0) (2020-06-18) + + +### Bug Fixes + +* mark all nested sidebar items active ([fcc5312](https://github.com/appcelerator/docs-devkit/commit/fcc5312)) +* nested sidebars without path ([62bacb1](https://github.com/appcelerator/docs-devkit/commit/62bacb1)) +* pass reactive data to ensure child component updates ([1776df0](https://github.com/appcelerator/docs-devkit/commit/1776df0)) +* sidebar css fixes ([396ac84](https://github.com/appcelerator/docs-devkit/commit/396ac84)) + + +### Features + +* support nested sidebars ([1e28793](https://github.com/appcelerator/docs-devkit/commit/1e28793)) + + + + + +## [4.0.1](https://github.com/appcelerator/docs-devkit/compare/v4.0.0...v4.0.1) (2019-12-11) + +**Note:** Version bump only for package vuepress-theme-titanium + + + + + +# 4.0.0 (2019-12-02) [YANKED] + +# 3.0.0 (2019-12-02) [YANKED] + +# 2.0.0 (2019-12-02) [YANKED] + +# 1.0.0 (2019-12-02) + + +### Bug Fixes + +* **theme:** show footer only if configured ([9d9f4d2](https://github.com/appcelerator/docs-devkit/commit/9d9f4d2)) +* add default theme color palette ([31d20e6](https://github.com/appcelerator/docs-devkit/commit/31d20e6)) +* **theme:** add bottom padding to home page ([6b2d0be](https://github.com/appcelerator/docs-devkit/commit/6b2d0be)) +* **theme:** add default content class ([d516092](https://github.com/appcelerator/docs-devkit/commit/d516092)) +* **theme:** apply latest theme-default ([7b15292](https://github.com/appcelerator/docs-devkit/commit/7b15292)) +* **theme:** guard against undefined paths ([ed03520](https://github.com/appcelerator/docs-devkit/commit/ed03520)) +* **theme:** height wrapper to avoid glitches ([7923ded](https://github.com/appcelerator/docs-devkit/commit/7923ded)) +* **theme:** mark versions dropdown as can-hide ([eecb704](https://github.com/appcelerator/docs-devkit/commit/eecb704)) +* **theme:** only show api sidebar button if page has api docs ([06513cb](https://github.com/appcelerator/docs-devkit/commit/06513cb)) +* **theme:** show version dropdown on versioned pages only ([ab18f4d](https://github.com/appcelerator/docs-devkit/commit/ab18f4d)) +* **theme:** test for available headers before accessing ([91bb50d](https://github.com/appcelerator/docs-devkit/commit/91bb50d)) +* respect locale in version dropdown ([3e80fe9](https://github.com/appcelerator/docs-devkit/commit/3e80fe9)) +* use versioned links in navbar ([9a45f85](https://github.com/appcelerator/docs-devkit/commit/9a45f85)) +* **theme:** use correct edit link for pages ([953b39e](https://github.com/appcelerator/docs-devkit/commit/953b39e)) +* **versioning:** more safeguards in case no versions were created yet ([0615344](https://github.com/appcelerator/docs-devkit/commit/0615344)) +* **versioning:** properly generate versioned edit links ([1be0e45](https://github.com/appcelerator/docs-devkit/commit/1be0e45)) + + +### Features + +* custom next version label ([85d0746](https://github.com/appcelerator/docs-devkit/commit/85d0746)) +* make footer configurable ([27e4e14](https://github.com/appcelerator/docs-devkit/commit/27e4e14)) +* update to VuePress 1.0.2 ([74d7ca8](https://github.com/appcelerator/docs-devkit/commit/74d7ca8)) +* **theme:** update code color ([15f81f8](https://github.com/appcelerator/docs-devkit/commit/15f81f8)) +* **versioning:** search through current version only ([ce69184](https://github.com/appcelerator/docs-devkit/commit/ce69184)) + + + + + +# [0.2.0](https://github.com/appcelerator/docs-devkit/compare/v0.1.5...v0.2.0) (2019-09-09) + +**Note:** Version bump only for package vuepress-theme-titanium + + + + + +## [0.1.2](https://github.com/appcelerator/docs-devkit/compare/v0.1.1...v0.1.2) (2019-07-27) + + +### Bug Fixes + +* **theme:** test for available headers before accessing ([91bb50d](https://github.com/appcelerator/docs-devkit/commit/91bb50d)) + + + + + +# 0.1.0 (2019-07-27) + + +### Bug Fixes + +* **theme:** show footer only if configured ([9d9f4d2](https://github.com/appcelerator/docs-devkit/commit/9d9f4d2)) +* add default theme color palette ([31d20e6](https://github.com/appcelerator/docs-devkit/commit/31d20e6)) +* **theme:** add bottom padding to home page ([6b2d0be](https://github.com/appcelerator/docs-devkit/commit/6b2d0be)) +* **theme:** add default content class ([d516092](https://github.com/appcelerator/docs-devkit/commit/d516092)) +* **theme:** apply latest theme-default ([7b15292](https://github.com/appcelerator/docs-devkit/commit/7b15292)) +* **theme:** guard against undefined paths ([ed03520](https://github.com/appcelerator/docs-devkit/commit/ed03520)) +* **theme:** height wrapper to avoid glitches ([7923ded](https://github.com/appcelerator/docs-devkit/commit/7923ded)) +* **theme:** mark versions dropdown as can-hide ([eecb704](https://github.com/appcelerator/docs-devkit/commit/eecb704)) +* **theme:** only show api sidebar button if page has api docs ([06513cb](https://github.com/appcelerator/docs-devkit/commit/06513cb)) +* **theme:** show version dropdown on versioned pages only ([ab18f4d](https://github.com/appcelerator/docs-devkit/commit/ab18f4d)) +* respect locale in version dropdown ([3e80fe9](https://github.com/appcelerator/docs-devkit/commit/3e80fe9)) +* use versioned links in navbar ([9a45f85](https://github.com/appcelerator/docs-devkit/commit/9a45f85)) +* **theme:** use correct edit link for pages ([953b39e](https://github.com/appcelerator/docs-devkit/commit/953b39e)) +* **versioning:** more safeguards in case no versions were created yet ([0615344](https://github.com/appcelerator/docs-devkit/commit/0615344)) +* **versioning:** properly generate versioned edit links ([1be0e45](https://github.com/appcelerator/docs-devkit/commit/1be0e45)) + + +### Features + +* custom next version label ([85d0746](https://github.com/appcelerator/docs-devkit/commit/85d0746)) +* make footer configurable ([27e4e14](https://github.com/appcelerator/docs-devkit/commit/27e4e14)) +* update to VuePress 1.0.2 ([74d7ca8](https://github.com/appcelerator/docs-devkit/commit/74d7ca8)) +* **theme:** update code color ([15f81f8](https://github.com/appcelerator/docs-devkit/commit/15f81f8)) +* **versioning:** search through current version only ([ce69184](https://github.com/appcelerator/docs-devkit/commit/ce69184)) diff --git a/docs/.vuepress/theme/LICENSE b/docs/.vuepress/theme/LICENSE new file mode 100644 index 000000000..8b53a7231 --- /dev/null +++ b/docs/.vuepress/theme/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2019-Present Axway Appcelerator + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/docs/.vuepress/theme/README.md b/docs/.vuepress/theme/README.md new file mode 100644 index 000000000..81afc9b46 --- /dev/null +++ b/docs/.vuepress/theme/README.md @@ -0,0 +1,5 @@ +# vuepres-theme-titanium + +> Supercharged version of the default theme for VuePress + +📖 View the [Documentation](https://titanium-docs-devkit.netlify.com/theme/). diff --git a/docs/.vuepress/theme/components/AlgoliaSearchBox.vue b/docs/.vuepress/theme/components/AlgoliaSearchBox.vue new file mode 100644 index 000000000..7b2a5807c --- /dev/null +++ b/docs/.vuepress/theme/components/AlgoliaSearchBox.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/docs/.vuepress/theme/components/ContentSidebar.vue b/docs/.vuepress/theme/components/ContentSidebar.vue new file mode 100644 index 000000000..2f59f3e77 --- /dev/null +++ b/docs/.vuepress/theme/components/ContentSidebar.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/docs/.vuepress/theme/components/ContentSidebarButton.vue b/docs/.vuepress/theme/components/ContentSidebarButton.vue new file mode 100644 index 000000000..befabe149 --- /dev/null +++ b/docs/.vuepress/theme/components/ContentSidebarButton.vue @@ -0,0 +1,28 @@ + + + diff --git a/docs/.vuepress/theme/components/ContentSidebarLink.vue b/docs/.vuepress/theme/components/ContentSidebarLink.vue new file mode 100644 index 000000000..ae94e2513 --- /dev/null +++ b/docs/.vuepress/theme/components/ContentSidebarLink.vue @@ -0,0 +1,89 @@ + + + diff --git a/docs/.vuepress/theme/components/DropdownLink.vue b/docs/.vuepress/theme/components/DropdownLink.vue new file mode 100644 index 000000000..22b716883 --- /dev/null +++ b/docs/.vuepress/theme/components/DropdownLink.vue @@ -0,0 +1,230 @@ + + + + + diff --git a/docs/.vuepress/theme/components/DropdownTransition.vue b/docs/.vuepress/theme/components/DropdownTransition.vue new file mode 100644 index 000000000..eeaf12b5c --- /dev/null +++ b/docs/.vuepress/theme/components/DropdownTransition.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/docs/.vuepress/theme/components/Footer.vue b/docs/.vuepress/theme/components/Footer.vue new file mode 100644 index 000000000..d7c7e21fc --- /dev/null +++ b/docs/.vuepress/theme/components/Footer.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/docs/.vuepress/theme/components/Home.vue b/docs/.vuepress/theme/components/Home.vue new file mode 100644 index 000000000..6e999e265 --- /dev/null +++ b/docs/.vuepress/theme/components/Home.vue @@ -0,0 +1,162 @@ + + + + + diff --git a/docs/.vuepress/theme/components/NavLink.vue b/docs/.vuepress/theme/components/NavLink.vue new file mode 100644 index 000000000..5d801edce --- /dev/null +++ b/docs/.vuepress/theme/components/NavLink.vue @@ -0,0 +1,96 @@ + + + + + diff --git a/docs/.vuepress/theme/components/NavLinks.vue b/docs/.vuepress/theme/components/NavLinks.vue new file mode 100644 index 000000000..5a6d5e0fd --- /dev/null +++ b/docs/.vuepress/theme/components/NavLinks.vue @@ -0,0 +1,166 @@ + + + + + diff --git a/docs/.vuepress/theme/components/Navbar.vue b/docs/.vuepress/theme/components/Navbar.vue new file mode 100644 index 000000000..f15018387 --- /dev/null +++ b/docs/.vuepress/theme/components/Navbar.vue @@ -0,0 +1,279 @@ + + + + + diff --git a/docs/.vuepress/theme/components/Page.vue b/docs/.vuepress/theme/components/Page.vue new file mode 100644 index 000000000..9571d5ab0 --- /dev/null +++ b/docs/.vuepress/theme/components/Page.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/docs/.vuepress/theme/components/PageEdit.vue b/docs/.vuepress/theme/components/PageEdit.vue new file mode 100644 index 000000000..50b015c26 --- /dev/null +++ b/docs/.vuepress/theme/components/PageEdit.vue @@ -0,0 +1,166 @@ + + + + + diff --git a/docs/.vuepress/theme/components/PageNav.vue b/docs/.vuepress/theme/components/PageNav.vue new file mode 100644 index 000000000..4c19aae5f --- /dev/null +++ b/docs/.vuepress/theme/components/PageNav.vue @@ -0,0 +1,163 @@ + + + + + diff --git a/docs/.vuepress/theme/components/PreviewBanner.vue b/docs/.vuepress/theme/components/PreviewBanner.vue new file mode 100644 index 000000000..e1096cc5d --- /dev/null +++ b/docs/.vuepress/theme/components/PreviewBanner.vue @@ -0,0 +1,48 @@ + + + + + + + \ No newline at end of file diff --git a/docs/.vuepress/theme/components/SearchBoxWrapper.vue b/docs/.vuepress/theme/components/SearchBoxWrapper.vue new file mode 100644 index 000000000..1b3dd2ab1 --- /dev/null +++ b/docs/.vuepress/theme/components/SearchBoxWrapper.vue @@ -0,0 +1,20 @@ + + + diff --git a/docs/.vuepress/theme/components/Sidebar.vue b/docs/.vuepress/theme/components/Sidebar.vue new file mode 100644 index 000000000..3a5b32c75 --- /dev/null +++ b/docs/.vuepress/theme/components/Sidebar.vue @@ -0,0 +1,167 @@ + + + + + diff --git a/docs/.vuepress/theme/components/SidebarArrow.vue b/docs/.vuepress/theme/components/SidebarArrow.vue new file mode 100644 index 000000000..8b3aadf3d --- /dev/null +++ b/docs/.vuepress/theme/components/SidebarArrow.vue @@ -0,0 +1,26 @@ + + + diff --git a/docs/.vuepress/theme/components/SidebarButton.vue b/docs/.vuepress/theme/components/SidebarButton.vue new file mode 100644 index 000000000..3f54afd55 --- /dev/null +++ b/docs/.vuepress/theme/components/SidebarButton.vue @@ -0,0 +1,40 @@ + + + diff --git a/docs/.vuepress/theme/components/SidebarGroup.vue b/docs/.vuepress/theme/components/SidebarGroup.vue new file mode 100644 index 000000000..56b1f421c --- /dev/null +++ b/docs/.vuepress/theme/components/SidebarGroup.vue @@ -0,0 +1,161 @@ + + + + + diff --git a/docs/.vuepress/theme/components/SidebarLink.vue b/docs/.vuepress/theme/components/SidebarLink.vue new file mode 100644 index 000000000..baf5bb107 --- /dev/null +++ b/docs/.vuepress/theme/components/SidebarLink.vue @@ -0,0 +1,124 @@ + + + diff --git a/docs/.vuepress/theme/components/SidebarLinks.vue b/docs/.vuepress/theme/components/SidebarLinks.vue new file mode 100644 index 000000000..4a3de2a3b --- /dev/null +++ b/docs/.vuepress/theme/components/SidebarLinks.vue @@ -0,0 +1,73 @@ + + + diff --git a/docs/.vuepress/theme/global-components/AppHeading.vue b/docs/.vuepress/theme/global-components/AppHeading.vue new file mode 100644 index 000000000..a3f63cf83 --- /dev/null +++ b/docs/.vuepress/theme/global-components/AppHeading.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/docs/.vuepress/theme/global-components/Badge.vue b/docs/.vuepress/theme/global-components/Badge.vue new file mode 100644 index 000000000..f2da7cd29 --- /dev/null +++ b/docs/.vuepress/theme/global-components/Badge.vue @@ -0,0 +1,54 @@ + + + diff --git a/docs/.vuepress/theme/index.js b/docs/.vuepress/theme/index.js new file mode 100644 index 000000000..4000e6b45 --- /dev/null +++ b/docs/.vuepress/theme/index.js @@ -0,0 +1,28 @@ +const path = require('path') + +// Theme API. +module.exports = (options, ctx) => ({ + globalLayout: './layouts/GlobalLayout.vue', + alias () { + const { themeConfig, siteConfig } = ctx + // resolve algolia + const isAlgoliaSearch = ( + themeConfig.algolia || + Object.keys(siteConfig.locales && themeConfig.locales || {}) + .some(base => themeConfig.locales[base].algolia) + ) + return { + '@AlgoliaSearchBox': isAlgoliaSearch + ? path.resolve(__dirname, 'components/AlgoliaSearchBox.vue') + : path.resolve(__dirname, 'noopModule.js') + } + }, + plugins: [ + ['@vuepress/search', { searchMaxSuggestions: 10 }], + '@vuepress/nprogress', + ['container', { type: 'tip' }], + ['container', { type: 'warning' }], + ['container', { type: 'danger' }], + require('./plugins/smoothScroll') + ] +}) diff --git a/docs/.vuepress/theme/layouts/404.vue b/docs/.vuepress/theme/layouts/404.vue new file mode 100644 index 000000000..4eef36d34 --- /dev/null +++ b/docs/.vuepress/theme/layouts/404.vue @@ -0,0 +1,28 @@ + + + + + diff --git a/docs/.vuepress/theme/layouts/GlobalLayout.vue b/docs/.vuepress/theme/layouts/GlobalLayout.vue new file mode 100644 index 000000000..5900262b8 --- /dev/null +++ b/docs/.vuepress/theme/layouts/GlobalLayout.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/docs/.vuepress/theme/layouts/Layout.vue b/docs/.vuepress/theme/layouts/Layout.vue new file mode 100644 index 000000000..0cbece3e4 --- /dev/null +++ b/docs/.vuepress/theme/layouts/Layout.vue @@ -0,0 +1,216 @@ + + + + + + diff --git a/docs/.vuepress/theme/noopModule.js b/docs/.vuepress/theme/noopModule.js new file mode 100644 index 000000000..b1c6ea436 --- /dev/null +++ b/docs/.vuepress/theme/noopModule.js @@ -0,0 +1 @@ +export default {} diff --git a/docs/.vuepress/theme/package.json b/docs/.vuepress/theme/package.json new file mode 100644 index 000000000..418a6ad64 --- /dev/null +++ b/docs/.vuepress/theme/package.json @@ -0,0 +1,26 @@ +{ + "name": "vuepress-theme-titanium", + "version": "4.9.0", + "description": "VuePress theme for Titanium projects", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Axway Appcelerator", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/appcelerator/docs-devkit.git", + "directory": "packages/vuepress/vuepress-theme-titanium" + }, + "dependencies": { + "@vuepress/plugin-nprogress": "^1.7.1", + "@vuepress/plugin-search": "^1.7.1", + "docsearch.js": "^2.6.3", + "lodash": "^4.17.15", + "stylus": "^0.54.5", + "stylus-loader": "^3.0.2", + "vuepress-plugin-container": "^2.1.5" + }, + "gitHead": "2c02c2ac571b8c02ffea735f2db16211ea21ae6c" +} diff --git a/docs/.vuepress/theme/plugins/smoothScroll/appHeading.js b/docs/.vuepress/theme/plugins/smoothScroll/appHeading.js new file mode 100644 index 000000000..d5b9b8e06 --- /dev/null +++ b/docs/.vuepress/theme/plugins/smoothScroll/appHeading.js @@ -0,0 +1,40 @@ +module.exports = function appHeading (md, options) { + md.core.ruler.push('app-heading', state => { + const slugs = {} + const tokens = state.tokens + tokens + .filter(token => token.type === 'heading_open' || token.type === 'heading_close') + .forEach(token => { + token.tag = 'app-heading' + if (token.type === 'heading_open') { + const title = tokens[tokens.indexOf(token) + 1] + .children + .filter(token => token.type === 'text' || token.type === 'code_inline') + .reduce((acc, t) => acc + t.content, '') + let slug = token.attrGet('id') + if (slug == null) { + slug = uniqueSlug(slugify(title), slugs, false) + } else { + slug = uniqueSlug(slug, slugs, true) + } + token.attrSet('id', slug) + token.attrSet('level', token.markup.split('').length) + token.attrSet('href', `#${slug}`) + } + }) + }) +} + +const slugify = (s) => encodeURIComponent(String(s).trim().toLowerCase().replace(/\s+/g, '-')) +const hasProp = Object.prototype.hasOwnProperty +const uniqueSlug = (slug, slugs, failOnNonUnique) => { + let uniq = slug + let i = 1 + if (failOnNonUnique && hasProp.call(slugs, uniq)) { + throw Error(`User defined id attribute '${slug}' is NOT unique. Please fix it in your markdown to continue.`) + } else { + while (hasProp.call(slugs, uniq)) uniq = `${slug}-${i++}` + } + slugs[uniq] = true + return uniq +} diff --git a/docs/.vuepress/theme/plugins/smoothScroll/enhanceApp.js b/docs/.vuepress/theme/plugins/smoothScroll/enhanceApp.js new file mode 100644 index 000000000..053a509df --- /dev/null +++ b/docs/.vuepress/theme/plugins/smoothScroll/enhanceApp.js @@ -0,0 +1,44 @@ +const SCROLL_OFFSET = 75 + +// fork from vue-router@3.0.2 +// src/util/scroll.js +function getElementPosition (el) { + const docEl = document.documentElement + const docRect = docEl.getBoundingClientRect() + const elRect = el.getBoundingClientRect() + return { + x: elRect.left - docRect.left, + y: elRect.top - docRect.top + } +} + +module.exports = ({ Vue, options, router }) => { + router.options.scrollBehavior = (to, from, savedPosition) => { + if (savedPosition) { + return window.scrollTo({ + top: savedPosition.y - SCROLL_OFFSET, + behavior: 'smooth' + }) + } else if (from.path === to.path && to.hash) { + if (Vue.$vuepress.$get('disableScrollBehavior')) { + return + } + const targetAnchor = to.hash + const targetName = targetAnchor.slice(1) + const targetElement = + document.getElementById(targetName) || + document.querySelector(`[name=${targetName}]`) + if (targetElement) { + return window.scrollTo({ + top: getElementPosition(targetElement).y - SCROLL_OFFSET, + behavior: 'smooth' + }) + } + } else { + const html = document.querySelector('html') + html.style.scrollBehavior = 'auto' + window.scrollTo({ top: 0 }) + html.style.scrollBehavior = '' + } + } +} diff --git a/docs/.vuepress/theme/plugins/smoothScroll/index.js b/docs/.vuepress/theme/plugins/smoothScroll/index.js new file mode 100644 index 000000000..33abfaac4 --- /dev/null +++ b/docs/.vuepress/theme/plugins/smoothScroll/index.js @@ -0,0 +1,16 @@ +const path = require('path') +// const appHeading = require('./appHeading') + +module.exports = (context, options) => ({ + name: 'smooth-scroll', + enhanceAppFiles: path.resolve(__dirname, 'enhanceApp.js') + /** + * https://github.com/vuejs/vuepress/pull/2669 + * + chainMarkdown (config) { + config.plugins.delete('anchor') + config.plugin('app-heading') + .use(appHeading, []) + } + */ +}) diff --git a/docs/.vuepress/theme/styles/arrow.styl b/docs/.vuepress/theme/styles/arrow.styl new file mode 100644 index 000000000..20bffc0dc --- /dev/null +++ b/docs/.vuepress/theme/styles/arrow.styl @@ -0,0 +1,22 @@ +@require './config' + +.arrow + display inline-block + width 0 + height 0 + &.up + border-left 4px solid transparent + border-right 4px solid transparent + border-bottom 6px solid $arrowBgColor + &.down + border-left 4px solid transparent + border-right 4px solid transparent + border-top 6px solid $arrowBgColor + &.right + border-top 4px solid transparent + border-bottom 4px solid transparent + border-left 6px solid $arrowBgColor + &.left + border-top 4px solid transparent + border-bottom 4px solid transparent + border-right 6px solid $arrowBgColor diff --git a/docs/.vuepress/theme/styles/code.styl b/docs/.vuepress/theme/styles/code.styl new file mode 100644 index 000000000..ce99536f9 --- /dev/null +++ b/docs/.vuepress/theme/styles/code.styl @@ -0,0 +1,198 @@ +.content + code + font-size .875rem + font-weight 400 + -webkit-font-smoothing auto + line-height 1.5 + color $codeColor + display inline-block + padding 0 0.25rem + background-color $inlineCodeBgColor + border-radius .125rem + .token + &.deleted + color $danger + &.inserted + color $success + +.content + pre, pre[class*="language-"] + font-size 0.875rem + font-weight 400 + line-height 1.5 + padding 1rem + margin 0.85rem 0 + background-color $codeBgColor + border-radius 6px + overflow auto + code + color $primary-ltr + padding 0 + background-color transparent + border-radius 0 + +div[class*="language-"] + position relative + background-color $codeBgColor + border-radius 6px + .highlight-lines + user-select none + padding-top 1.3rem + position absolute + top 0 + left 0 + width 100% + line-height 1.4 + .highlighted + background-color rgba(0, 0, 0, 66%) + pre, pre[class*="language-"] + background transparent + position relative + z-index 1 + &::before + position absolute + z-index 3 + top 0.8em + right 1em + font-size 0.75rem + color rgba(255, 255, 255, 0.4) + &:not(.line-numbers-mode) + .line-numbers-wrapper + display none + &.line-numbers-mode + .highlight-lines .highlighted + position relative + &:before + content ' ' + position absolute + z-index 3 + left 0 + top 0 + display block + width $lineNumbersWrapperWidth + height 100% + background-color rgba(0, 0, 0, 66%) + pre + padding-left $lineNumbersWrapperWidth + 1 rem + vertical-align middle + .line-numbers-wrapper + position absolute + top 0 + width $lineNumbersWrapperWidth + text-align center + color rgba(255, 255, 255, 0.3) + padding 1.25rem 0 + line-height 1.4 + br + user-select none + .line-number + position relative + z-index 4 + user-select none + font-size 0.85em + &::after + content '' + position absolute + z-index 2 + top 0 + left 0 + width $lineNumbersWrapperWidth + height 100% + border-radius 6px 0 0 6px + border-right 1px solid rgba(0, 0, 0, 66%) + background-color $codeBgColor + + +for lang in $codeLang + div{'[class~="language-' + lang + '"]'} + &:before + content ('' + lang) + +div[class~="language-javascript"] + &:before + content "js" + +div[class~="language-typescript"] + &:before + content "ts" + +div[class~="language-markup"] + &:before + content "html" + +div[class~="language-markdown"] + &:before + content "md" + +div[class~="language-json"]:before + content "json" + +div[class~="language-ruby"]:before + content "rb" + +div[class~="language-python"]:before + content "py" + +div[class~="language-bash"]:before + content "sh" + +div[class~="language-php"]:before + content "php" + +// Custom Prism.js theme based on the Palenight High Contrast theme for VSCode, +// enhanced with the colors from our theme. + +.token + &.attr-name, + &.property + &.selector + color $warning-lt + &.attr-value, + &.char, + &.regex, + &.string, + &.variable + color $success-lt + &.boolean, + &.number + color $warning + &.comment + color $gray-dk + &.constant, + &.tag + color $danger-lt + &.atrule + &.function + color #82AAFF + &.keyword + color $danger-lt + &.operator, + &.punctuation + color #89DDFF + +.language-md + .token + &.title + color $warning-lt + &.important + font-weight 400 + &.content + padding 0 + +.content + pre + &.language-yml + code + color $success-lt +.language-yml + .token + &.atrule + color $danger-lt + +.language-css, +.language-sass, +.language-scss, +.language-stylus, + .token + &.property + color #B2CCD6 diff --git a/docs/.vuepress/theme/styles/colors.styl b/docs/.vuepress/theme/styles/colors.styl new file mode 100644 index 000000000..9089647fe --- /dev/null +++ b/docs/.vuepress/theme/styles/colors.styl @@ -0,0 +1,3 @@ +/** Overrides of colors used for inline code blocks **/ +$codeColor = $primary +$inlineCodeBgColor = $primary-ltr diff --git a/docs/.vuepress/theme/styles/custom-blocks.styl b/docs/.vuepress/theme/styles/custom-blocks.styl new file mode 100644 index 000000000..f9e2cafe8 --- /dev/null +++ b/docs/.vuepress/theme/styles/custom-blocks.styl @@ -0,0 +1,45 @@ +.custom-block + .custom-block-title + font-weight 600 + margin-bottom -0.4rem + &.tip, &.warning, &.danger + padding .1rem 1.5rem + border-left-width .5rem + border-left-style solid + margin 1rem 0 + &.tip + background-color $success-ltr + border-color $succcess + &.warning + background-color $warning-ltr + border-color $warning + .custom-block-title + color $warning + a + color $warning-dk + &.danger + background-color $danger-ltr + border-color $danger + .custom-block-title + color $danger + a + color $danger-dk + +pre.vue-container + border-left-width: .5rem; + border-left-style: solid; + border-color: $success; + border-radius: 0px; + & > code + font-size: 14px !important; + & > p + margin: -5px 0 -20px 0; + code + background-color: $success !important; + padding: 3px 5px; + border-radius: 3px; + color $black + em + color $gray-dk + font-weight light + diff --git a/docs/.vuepress/theme/styles/mobile.styl b/docs/.vuepress/theme/styles/mobile.styl new file mode 100644 index 000000000..4769f90fa --- /dev/null +++ b/docs/.vuepress/theme/styles/mobile.styl @@ -0,0 +1,53 @@ +@require './config' + +$mobileSidebarWidth = $sidebarWidth * 0.82 +$mobileContentSidebarWidth = $contentSidebarWidth * 0.82 + +// narrow desktop / iPad +@media (max-width: $MQNarrow) + .sidebar + font-size 15px + width $mobileSidebarWidth + .content-sidebar-wrapper + width $mobileContentSidebarWidth + +// wide mobile +@media (max-width: $MQMobile) + .sidebar + position fixed + top $navbarHeight + bottom 0 + height auto + z-index 10 + transform translateX(-100%) + transition transform .2s ease + .content-sidebar-wrapper + width $contentSidebarWidth * 1.2 + position fixed + top $navbarHeight + right 0 + bottom 0 + height auto + z-index: 10; + transform translateX(100%) + transition transform .2s ease + .theme-container + display block + &.sidebar-open + .sidebar + transform translateX(0) + &.content-sidebar-open + .content-sidebar-wrapper + transform translateX(0) + &.no-navbar + .sidebar + padding-top: 0 + +// narrow mobile +@media (max-width: $MQMobileNarrow) + h1 + font-size 1.9rem + .content + div[class*="language-"] + margin 0.85rem -1.5rem + border-radius 0 diff --git a/docs/.vuepress/theme/styles/nprogress.styl b/docs/.vuepress/theme/styles/nprogress.styl new file mode 100644 index 000000000..f186a67ec --- /dev/null +++ b/docs/.vuepress/theme/styles/nprogress.styl @@ -0,0 +1,48 @@ +#nprogress + pointer-events none + .bar + background $accentColor + position fixed + z-index 1031 + top 0 + left 0 + width 100% + height 2px + .peg + display block + position absolute + right 0px + width 100px + height 100% + box-shadow 0 0 10px $accentColor, 0 0 5px $accentColor + opacity 1.0 + transform rotate(3deg) translate(0px, -4px) + .spinner + display block + position fixed + z-index 1031 + top 15px + right 15px + .spinner-icon + width 18px + height 18px + box-sizing border-box + border solid 2px transparent + border-top-color $accentColor + border-left-color $accentColor + border-radius 50% + animation nprogress-spinner 400ms linear infinite + +.nprogress-custom-parent + overflow hidden + position relative + +.nprogress-custom-parent #nprogress .spinner, +.nprogress-custom-parent #nprogress .bar + position absolute + +@keyframes nprogress-spinner + 0% + transform rotate(0deg) + 100% + transform rotate(360deg) diff --git a/docs/.vuepress/theme/styles/palette.styl b/docs/.vuepress/theme/styles/palette.styl new file mode 100644 index 000000000..0bf0bf285 --- /dev/null +++ b/docs/.vuepress/theme/styles/palette.styl @@ -0,0 +1,40 @@ +/**** Axway Colors ****/ +$black = #001e26 +$black-lt = #d0d0d0 +$black-ltr = #efefef +$danger = #d22630 +$danger-dk = #800008 +$danger-lt = #ff605a +$danger-ltr = #ffebee +$gray = #c8c9c7 +$gray-dk = #979896 +$gray-lt = #f4f5f4 +$gray-ltr = #fbfcfa +$primary = #006580 +$primary-dk = #003b53 +$primary-lt = #99c1cc +$primary-ltr = #eef3f4 +$secondary = #4a4f54 +$secondary-dk = #22272b +$secondary-lt = #707070 +$secondary-ltr = #f8f8f8 +$succcess = #228665 +$success-dk = #006448 +$success-lt = #7de3b9 +$success-ltr = #ecf7f3 +$tertiary = #9d4b70 +$tertiary-dk = #6c1d45 +$tertiary-lt = #c3a4b4 +$tertiary-ltr = #efe7eb +$warning = #ff9e18 +$warning-dk = #b95e04 +$warning-lt = #ffcf51 +$warning-ltr = #fff5e7 +$white = white + +/** Override of main colors used in Vuepress **/ +$accentColor = $danger +$textColor = $black +$lightTextColor = $gray-dk +$borderColor = $black-ltr +$codeBgColor = $secondary-dk diff --git a/docs/.vuepress/theme/styles/table.styl b/docs/.vuepress/theme/styles/table.styl new file mode 100644 index 000000000..b3a454ff3 --- /dev/null +++ b/docs/.vuepress/theme/styles/table.styl @@ -0,0 +1,15 @@ +table + width 100% + margin-bottom 1rem + + border-collapse: collapse; + border-spacing: 0; + tr + border-bottom: 1px solid $black-ltr + tbody tr:last-child + border-bottom 0 + td, th + padding .75rem + vertical-align top + text-align left + line-height 1.5rem \ No newline at end of file diff --git a/docs/.vuepress/theme/styles/theme.styl b/docs/.vuepress/theme/styles/theme.styl new file mode 100644 index 000000000..5e4de46b9 --- /dev/null +++ b/docs/.vuepress/theme/styles/theme.styl @@ -0,0 +1,266 @@ +@require './config' +@require './colors' +@require './nprogress' +@require './code' +@require './custom-blocks' +@require './arrow' +@require './wrapper' +@require './toc' +@require './table' + +// Custom vars +$contentSidebarWidth = 12rem + +html + scroll-behavior smooth + +html, body + padding 0 + margin 0 + background-color $white + +body + font-family -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif; + -webkit-font-smoothing antialiased + -moz-osx-font-smoothing grayscale + font-size 1rem + line-height 1.5rem + color $textColor + min-height 100vh + text-rendering: optimizeLegibility + +.theme-container + display flex + flex-flow row nowrap + min-height 100vh + +.page + flex 1 1 auto + min-width 0 + +.navbar + position: fixed + z-index: 20 + top: 0 + left: 0 + right: 0 + height: var(--navbar-total-height) + background-color: $white + box-sizing: border-box + border-bottom: 1px solid $borderColor + display: flex + flex-direction: column + padding-top: 0 + padding-bottom: 0 + padding-left: $navbar-horizontal-padding + padding-right: $navbar-horizontal-padding + +.banner-content { + height: var(--navbar-banner-height) + min-height: var(--navbar-banner-height) + width: 100% + display: block + box-sizing: border-box + padding: 0 + position: static +} + +.navbar-content { + height: var(--navbar-height) + min-height: var(--navbar-height) + padding: 0 $navbar-horizontal-padding + display: flex + align-items: center + justify-content: space-between + width: 100% + box-sizing: border-box +} + +.sidebar-mask + position fixed + z-index 9 + top 0 + left 0 + width 100vw + height 100vh + display none + +.sidebar + font-size 15px + background-color $white + position sticky + top: var(--navbar-total-height) + height: calc(100vh - var(--navbar-total-height)) + flex 0 0 auto + width $sidebarWidth + box-sizing border-box + border-right 1px solid $borderColor + overflow-y auto + overflow-x hidden + +.content-sidebar-wrapper + background-color $white + position sticky + top: var(--navbar-total-height) + height: calc(100vh - var(--navbar-total-height)) + width $contentSidebarWidth + align-self: flex-start; + flex 0 0 auto + padding 2rem 1rem 2rem 0 + box-sizing border-box + +.content:not(.custom) + @extend $wrapper + padding-top: var(--navbar-total-height) + + @media (min-width: $MQMobile) + padding-top: var(--navbar-total-height) + + > *:first-child + margin-top 0 + + a:hover + text-decoration underline + + p.demo + padding 1rem 1.5rem + border 1px solid $gray + border-radius 4px + img + max-width 100% + +.content.custom + padding 0 + margin 0 + + img + max-width 100% + +a + font-weight 500 + color $accentColor + text-decoration none + +kbd + background $gray-lt + border solid 0.15rem $gray + border-bottom solid 0.25rem $gray + border-radius 0.15rem + padding 0 0.15em + +blockquote + font-size .9rem + color $gray-dk + border-left .5rem solid $gray-ltr + margin 0.5rem 0 + padding .25rem 0 .25rem 1rem + + & > p + margin 0 + +ul, ol + padding-left 1.2em + +strong + font-weight 600 + +h1, h2, h3, h4, h5, h6 + > .header-anchor + font-size 0.85em + float left + margin-left -0.87em + padding-right 0.23em + margin-top 0.125em + opacity 0 + + &:hover + text-decoration none + + &:not(:hover):not(:focus) + opacity: 0 + + .content:not(.custom) > & + &:hover .header-anchor + opacity: 1 + +h1, h2, h3, h4, strong + color $black + font-weight 700 + +h1, h2 + letter-spacing -.025rem + +h1 + font-size 2.625rem + line-height 3.125rem + +h2 + font-size 2rem + line-height 2.5rem + padding-bottom .3rem + border-bottom 1px solid $borderColor + margin 1.5rem 0 + +h3 + font-size 1.5rem + line-height 2rem + margin-top 1.5rem + +h4 + font-size 1.25rem + line-height 1.625rem + margin-bottom 0 + +code, kbd, .line-number + font-family Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace + +p, ul, ol + line-height 1.7 + +hr + border 0 + border-top 1px solid $borderColor + +caption + padding-top .75rem + padding-bottom .75rem + line-height 1rem + font-size .75rem + color $lightTextColor + text-align left + caption-side bottom + +.theme-container + &.sidebar-open,&.content-sidebar-open + .sidebar-mask + display: block + + &.no-navbar + .content:not(.custom) > h1, h2, h3, h4, h5, h6 + margin-top 1.5rem + padding-top 0 + + .sidebar + top 0 + + +@media (min-width: ($MQMobile + 1px)) + .theme-container.no-sidebar + .sidebar + display none + +@require 'mobile.styl' + +// Adjust sidebar and content top offset for banner + navbar +:root { + --navbar-banner-height: 2.5rem; + --navbar-height: 4rem; + --navbar-total-height: calc(var(--navbar-banner-height) + var(--navbar-height)); +} + +.content:not(.custom) { + padding-top: var(--navbar-total-height); + @media (min-width: $MQMobile) { + padding-top: calc(7rem + var(--navbar-banner-height)); + } +} diff --git a/docs/.vuepress/theme/styles/toc.styl b/docs/.vuepress/theme/styles/toc.styl new file mode 100644 index 000000000..d3e71069b --- /dev/null +++ b/docs/.vuepress/theme/styles/toc.styl @@ -0,0 +1,3 @@ +.table-of-contents + .badge + vertical-align middle diff --git a/docs/.vuepress/theme/styles/wrapper.styl b/docs/.vuepress/theme/styles/wrapper.styl new file mode 100644 index 000000000..5bc7ee354 --- /dev/null +++ b/docs/.vuepress/theme/styles/wrapper.styl @@ -0,0 +1,8 @@ +$wrapper + margin 0 auto + padding 2rem 2.5rem + @media (max-width: $MQNarrow) + padding 2rem + @media (max-width: $MQMobileNarrow) + padding 1.5rem + diff --git a/docs/.vuepress/theme/templates/ssr.html b/docs/.vuepress/theme/templates/ssr.html new file mode 100644 index 000000000..35a5a247b --- /dev/null +++ b/docs/.vuepress/theme/templates/ssr.html @@ -0,0 +1,18 @@ + + + + + + {{ title }} + + {{{ userHeadTags }}} + {{{ pageMeta }}} + {{{ renderResourceHints() }}} + {{{ renderStyles() }}} + + + + {{{ renderState() }}} + {{{ renderScripts() }}} + + diff --git a/docs/.vuepress/theme/util/index.js b/docs/.vuepress/theme/util/index.js new file mode 100644 index 000000000..3e89476bf --- /dev/null +++ b/docs/.vuepress/theme/util/index.js @@ -0,0 +1,324 @@ +export const hashRE = /#.*$/ +export const extRE = /\.(md|html)$/ +export const endingSlashRE = /\/$/ +export const outboundRE = /^(https?:|mailto:|tel:)/ + +const normalizedMap = new Map() + +export function normalize (path) { + if (normalizedMap.has(path)) { + return normalizedMap.get(path) + } + const result = decodeURI(path) + .replace(hashRE, '') + .replace(extRE, '') + normalizedMap.set(path, result) + return result +} + +export function getHash (path) { + const match = path.match(hashRE) + if (match) { + return match[0] + } +} + +export function isExternal (path) { + return outboundRE.test(path) +} + +export function isMailto (path) { + return /^mailto:/.test(path) +} + +export function isTel (path) { + return /^tel:/.test(path) +} + +export function ensureExt (path) { + if (isExternal(path)) { + return path + } + const hashMatch = path.match(hashRE) + const hash = hashMatch ? hashMatch[0] : '' + const normalized = normalize(path) + + if (endingSlashRE.test(normalized)) { + return path + } + return normalized + '.html' + hash +} + +export function isActive (route, path) { + const routeHash = route.hash + const linkHash = getHash(path) + if (linkHash && routeHash !== linkHash) { + return false + } + const routePath = normalize(route.path) + const pagePath = normalize(path) + return routePath === pagePath +} + +export function resolvePage (pages, rawPath, base) { + if (!resolvePage.cache) { + resolvePage.cache = new Map() + pages.forEach((page, i) => { + resolvePage.cache.set(normalize(page.regularPath), i) + }) + } + if (isExternal(rawPath)) { + return { + type: 'external', + path: rawPath + } + } + if (base) { + rawPath = resolvePath(rawPath, base) + } + const path = normalize(rawPath) + const cache = resolvePage.cache + if (cache.has(path)) { + const page = pages[cache.get(path)] + return Object.assign({}, page, { + type: 'page', + path: ensureExt(page.path) + }) + } + console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`) + return {} +} + +function resolvePath (relative, base, append) { + const firstChar = relative.charAt(0) + if (firstChar === '/') { + return relative + } + + if (firstChar === '?' || firstChar === '#') { + return base + relative + } + + const stack = base.split('/') + + // remove trailing segment if: + // - not appending + // - appending to trailing slash (last segment is empty) + if (!append || !stack[stack.length - 1]) { + stack.pop() + } + + // resolve relative path + const segments = relative.replace(/^\//, '').split('/') + for (let i = 0; i < segments.length; i++) { + const segment = segments[i] + if (segment === '..') { + stack.pop() + } else if (segment !== '.') { + stack.push(segment) + } + } + + // ensure leading slash + if (stack[0] !== '') { + stack.unshift('') + } + + return stack.join('/') +} + +/** + * @param { Page } page + * @param { string } regularPath + * @param { SiteData } site + * @param { string } localePath + * @returns { SidebarGroup } + */ +export function resolveSidebarItems (page, regularPath, site, localePath, versions) { + const { pages } = site + let themeConfig = site.themeConfig + + let localeConfig = localePath && themeConfig.locales + ? themeConfig.locales[localePath] || themeConfig + : themeConfig + if (page.version && page.version !== 'latest') { + const versionedConfig = site.themeConfig.versionedSidebar && site.themeConfig.versionedSidebar[page.version] + localeConfig = localePath && versionedConfig.locales + ? versionedConfig.locales[localePath] || versionedConfig + : versionedConfig + themeConfig = versionedConfig + } + + const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar + if (pageSidebarConfig === 'auto') { + return resolveHeaders(page) + } + + const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar + if (!sidebarConfig) { + return [] + } else { + const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig) + if (config === 'auto') { + return resolveHeaders(page) + } + return config + ? config.map(item => resolveItem(item, pages, base)) + : [] + } +} + +/** + * @param { Page } page + * @returns { SidebarGroup } + */ +function resolveHeaders (page) { + const headers = groupHeaders(page.headers || []) + return [{ + type: 'group', + collapsable: false, + title: page.title, + path: null, + children: headers.map(h => ({ + type: 'auto', + title: h.title, + basePath: page.path, + path: page.path + '#' + h.slug, + children: h.children || [] + })) + }] +} + +export function groupHeaders (headers) { + // group h3s under h2 + headers = headers.map(h => Object.assign({}, h)) + let lastH2 + headers.forEach(h => { + if (h.level === 2) { + lastH2 = h + } else if (lastH2) { + (lastH2.children || (lastH2.children = [])).push(h) + } + }) + return headers.filter(h => h.level === 2) +} + +export function resolveNavLinkItem (linkItem) { + return Object.assign(linkItem, { + type: linkItem.items && linkItem.items.length ? 'links' : 'link' + }) +} + +export function versionifyUserNav (navConfig, currentPage, currentVersion, localePath, routes) { + return navConfig.map(item => { + // assign item to new object so we don't override the original values + item = Object.assign({}, item) + if (item.items) { + item.items = versionifyUserNav(item.items, currentPage, currentVersion, localePath, routes) + } else { + let link = item.link + if (currentPage.version !== currentVersion) { + const cleanPath = item.link.replace(new RegExp(`^${localePath}`), '') + link = `${localePath}${currentPage.version}/${cleanPath}` + if (!routes.some(route => route.path === link)) { + // Fallback to the un-altered default link + link = item.link + } + } + item.link = link + } + + return Object.assign({}, item) + }) +} + +/** + * @param { Route } route + * @param { Array | Array | [link: string]: SidebarConfig } config + * @returns { base: string, config: SidebarConfig } + */ +export function resolveMatchingConfig (regularPath, config) { + if (Array.isArray(config)) { + return { + base: '/', + config: config + } + } + for (const base in config) { + if (ensureEndingSlash(regularPath).indexOf(base) === 0) { + return { + base, + config: config[base] + } + } + } + return {} +} + +function ensureEndingSlash (path) { + return /(\.html|\/)$/.test(path) + ? path + : path + '/' +} + +function resolveItem (item, pages, base, groupDepth = 1) { + if (typeof item === 'string') { + return resolvePage(pages, item, base) + } else if (Array.isArray(item)) { + return Object.assign(resolvePage(pages, item[0], base), { + title: item[1] + }) + } else { + const children = item.children || [] + if (children.length === 0 && item.path) { + return Object.assign(resolvePage(pages, item.path, base), { + title: item.title + }) + } + return { + type: 'group', + path: item.path, + title: item.title, + sidebarDepth: item.sidebarDepth, + children: children.map(child => resolveItem(child, pages, base, groupDepth + 1)), + collapsable: item.collapsable !== false + } + } +} + +export function calculateCurrentAnchor (sidebarLinks) { + const anchors = [].slice + .call(document.querySelectorAll('.header-anchor')) + .filter(anchor => sidebarLinks.some(sidebarLink => sidebarLink.hash === anchor.hash)) + .map(el => { + return { + el, + hash: decodeURIComponent(el.hash), + top: el.getBoundingClientRect().top - 120 + } + }) + if (anchors.length === 0) { + return null + } + const l = anchors.length + if (anchors[0].top > 0 && anchors[0].top < 10) { + return anchors[0] + } + + if (anchors[l - 1].top < 0) { + return anchors[l - 1] + } + + for (let i = 0; i < l; i++) { + const anchor = anchors[i] + const nextAnchor = anchors[i + 1] + if (anchor.top < 0 && nextAnchor.top > 0) { + if (nextAnchor.top < 10) { + return nextAnchor + } + return anchor + } + } + + return anchors[0] +} diff --git a/docs/.vuepress/versions.json b/docs/.vuepress/versions.json new file mode 100644 index 000000000..9da960f67 --- /dev/null +++ b/docs/.vuepress/versions.json @@ -0,0 +1,3 @@ +[ + "v1.0.1" +] \ No newline at end of file diff --git a/docs/adoption/HubOperations/Onboarding/business-onboarding.md b/docs/adoption/HubOperations/Onboarding/business-onboarding.md new file mode 100644 index 000000000..a6fda7dcc --- /dev/null +++ b/docs/adoption/HubOperations/Onboarding/business-onboarding.md @@ -0,0 +1,20 @@ +# Business onboarding of DFSPs + +The onboarding journey for DFSPs comprises steps that happen outside the Mojaloop Hub. They are related to the business side of onboarding, and are useful for the Hub Operator to be aware of. + +::: tip NOTE +The steps of the DFSP application process and the business onboarding journey are defined by the Scheme, in conformance with local financial regulatory requirements. +::: + +Key milestones of the business onboarding journey are: + +1. The DFSP discovers the service offered by the Scheme, and indicates their intention and business reason to join the Scheme. +1. The DFSP signs an application agreement. +1. Documentation is shared with the DFSP, which allows the DFSP to assess the technical effort to integrate, as well as their business compatibility with the Scheme Rules. +1. The Scheme Operator performs due diligence for the candidate's eligibility. +1. The DFSP understands and signs a participation agreement (contract). +1. The DFSP completes a KYC procedure with the settlement bank. This is part of the process of opening a settlement bank account (also called liquidity account). +1. The DFSP develops new UI functionality/updates existing UI functionality to expose the Scheme-supported use case(s) to end users. +1. The DFSP opens and pre-funds their liquidity account at the settlement bank. + +In parallel with the business steps, after signing the participation agreement, the DFSP can start their [technical onboarding journey](technical-onboarding.md). \ No newline at end of file diff --git a/docs/adoption/HubOperations/Onboarding/onboarding-introduction.md b/docs/adoption/HubOperations/Onboarding/onboarding-introduction.md new file mode 100644 index 000000000..77e70bb4e --- /dev/null +++ b/docs/adoption/HubOperations/Onboarding/onboarding-introduction.md @@ -0,0 +1,6 @@ +# Introduction – Onboarding Guide for the Hub Operator + +This guide is aimed at the Operator of a Mojaloop Hub and provides information about the DFSP onboarding process. It provides a high-level overview of the onboarding journey that DFSPs take, acting as a checklist of onboarding activities. The aim is to help Hub employees have an understanding of the steps to complete when connecting DFSPs to the various Hub environments. + + + diff --git a/docs/adoption/HubOperations/Onboarding/technical-onboarding.md b/docs/adoption/HubOperations/Onboarding/technical-onboarding.md new file mode 100644 index 000000000..062d8fb21 --- /dev/null +++ b/docs/adoption/HubOperations/Onboarding/technical-onboarding.md @@ -0,0 +1,247 @@ +# Technical onboarding of DFSPs + +At a high level, onboarding to a Mojaloop Hub requires a DFSP to focus their efforts around the following major milestones: + +* [Integration](#api-integration) of their core backend with the Mojaloop Hub on the API level (this involves both coding and testing). +* [Connecting](#connecting-to-mojaloop-environments) to pre-production and production environments following rigorous Mojaloop security requirements. + +In addition to the steps that require DFSP involvement, the Hub Operator must also perform some onboarding activities in their [backend](#onboarding-in-the-hub-backend) independent from DFSPs. + +This section provides a high-level overview of all of these milestones. + +## API integration + +Within the context of the Mojaloop Financial Service Provider Interoperability (FSPIOP) API, a transfer happens in three main steps: + +1. Identifying the Payee (party lookup or discovery phase) +1. Agreeing the transfer (quote or agreement phase) +1. Executing the transfer (transfer phase) + +For further details on each of these phases, see **Module 2 - Static demo: An end-to-end example** of [Mojaloop training course](https://learn.mojaloop.io/) **MOJA-102**. + +These three phases correspond to the key resources of the Mojaloop FSPIOP API: + +* **Party lookup service**: Identifying the DFSP serving the Payee and the Payee itself (= the recipient of funds in a transaction) based on a Payee identifier (typically a MSISDN, that is, a mobile number). +* **Quotes service**: Requesting a quote and exchanging cryptographic proof to prepare and secure the transfer. A quote is a contract between a Payer DFSP and Payee DFSP for a particular financial transaction before the transaction is performed. It guarantees the agreement set by the Payer and Payee DFSPs about the Payer, the Payee, and transfer amount, and is valid during the lifetime of a quote and transfer of a specified financial transaction. +* **Transfers service**: Executing the transaction as per the agreed details and cryptographic proof. + +DFSPs can choose to: + +* connect directly to the Mojaloop Hub and implement the asynchronous Mojaloop version of these API services, or +* leverage an open-source integration component (the [Mojaloop-SDK](#mojaloop-sdk) or [Payment Manager OSS](#payment-manager-oss)) and implement a simplified, synchronous version of Mojaloop FSPIOP API services + +DFSPs with an in-house development team and experience with RESTful APIs will likely be able to manage the process internally and develop a direct connection to Mojaloop. However, it is recommended that DFSPs use one of the open-source integration components, as a direct connection requires additional code development and maintenance. Using the Mojaloop-SDK or Payment Manager OSS reduces the time it takes to integrate with the Mojaloop Hub and makes troubleshooting easier for the Hub Operator, thus reducing the overall cost of the system. + +While the DFSP is carrying out offline development work, the Hub Operator's role consists in answering ad-hoc questions around the specifics of the API, or - depending on the open-source tool chosen and the agreed deployment model - can even extend to doing some of the development too. + +### Open-source tools to facilitate API integration + +#### Mojaloop-SDK + +The [Mojaloop-SDK](https://github.com/mojaloop/sdk-scheme-adapter) presents a simplified, synchronous version of the Mojaloop FSPIOP API to a DFSP's backend system, allowing DFSPs to implement a simple API internally to interface with the Mojaloop Hub, while still being compliant with the Mojaloop FSPIOP API specification for interoperable external communications. + +The asynchronous pattern of the Mojaloop FSPIOP API (while it has many advantages) may not be suitable for client applications that operate in a synchronous request-response mode. The Mojaloop-SDK helps bridge this gap by offering a simplified request-response API, abstracting away the complexities of multiple request composition and asynchronous API details from end clients. + +![Mojaloop-SDK](../../../.vuepress/public/mojaloop-sdk.png) + +The Mojaloop-SDK must be downloaded from [GitHub](https://github.com/mojaloop/sdk-scheme-adapter) to the DFSP environment and integrated to the DFSP backend. It is provided as a Docker container image, and may be hosted on the same infrastructure as the core banking application or a virtual machine provisioned specifically for it. Ongoing maintenance may require some specialized support from a System Integrator trained in the software. + +Other than a simplified API, the Mojaloop-SDK also provides the security protocols required by Mojaloop "out of the box", by giving a simplified configuration interface to its users. This feature of the Mojaloop-SDK helps with the [connection step](#connecting-to-mojaloop-environments) of onboarding. + +#### Payment Manager OSS + +[Payment Manager OSS](https://pm4ml.github.io/documents/payment_manager_oss/latest/core_connector_rest/introduction.html) presents a use-case oriented, simplified, synchronous version of the Mojaloop FSPIOP API to a DFSP's backend system. The key integration component of Payment Manager is called Core Connector, it acts as a translator between a DFSP's core backend (CBS) and a component of Payment Manager (called Mojaloop Connector, which leverages the Mojaloop-SDK) that talks directly to the Mojaloop Hub. + +![Payment Manager OSS](../../../.vuepress/public/PM4ML_system_architecture.png) + +Core Connector is built in Apache Camel, a declarative Java-based language for integration engineers that does not require writing code from scratch. There is a ready-made Core Connector template available to simplify the development effort. The template provides a placeholder codebase for the API endpoints that need to be developed, and it must be customized to be aligned with the appropriate CBS technology. The flexibility provided by the template allows for Core Connector to be made to fit a DFSP's backend, rather than the other way around. + +The effort to customize a Core Connector template will differ depending on the chosen deployment option. When deploying Payment Manager, two options are available: + +* **Managed and hosted by System Integrator**: A System Integrator deploys Payment Manager in the cloud, and syncs up the Core Connector template with the DFSP's core backend implementation. +* **Self-hosted by DFSP**: The DFSP deploys Payment Manager on premise or in the cloud, and the customization of the Core Connector template can be done by a number of actors (depending on the outcome of an initial assessment of DFSP capabilities): + * the System Integrator + * the System Integrator and the vendor of the DFSP's core backend solution + * the DFSP and the vendor of the DFSP's core backend solution + +Payment Manager is provided as a set of Linux container images (Docker) and may be hosted on-premise using commodity server infrastructure or in appropriate cloud infrastructure where available. + +If the Hub Operator so chooses, it can assume a System Integrator role. + +Given that Payment Manager incorporates Mojaloop-SDK functionality, it also implements the security layer required by Mojaloop. This feature of Payment Manager helps with the [connection step](#connecting-to-mojaloop-environments) of onboarding. + +## Connecting to Mojaloop environments + +Once the DFSP has completed coding, they test their integration against a lab instance in a test environment provided by the Hub. This is where the connection phase of the technical onboarding journey begins, with a new set of responsibilities for the Hub Operator. + +The requirements around connecting are dictated by the multiple security protocols that any Mojaloop Hub and participating DFSPs must implement: + +* Two-way TLS with mutual X.509 authentication +* OAuth 2.0 authentication for sessions over the Hub API gateway +* IP-address-based whitelisting in firewall rules and API gateways +* JSON Web Signature (JWS) signing of messages +* Interledger Protocol (ILP) packet signing and validation + +If you are interested in more details, see [Security in Mojaloop](#security-in-mojaloop). + +Putting the above security measures into practice requires extensive information sharing and technical configuration from different teams at both the DFSP and the Mojaloop Hub. There are open-source tools available for the community to facilitate this process, both for DFSPs and the Hub Operator. + +### Open-source tools to facilitate connecting to Mojaloop environments + +#### Mojaloop-SDK + +The Mojaloop-SDK implements standard components that establish a uniform way of connecting DFSP systems to a Mojaloop Hub. It implements the following Mojaloop-compliant security functionality: + +* Two-way TLS with mutual X.509 authentication +* JSON Web Signature (JWS) signing of messages +* Generation of the Interledger Protocol (ILP) packet with signing and validation + +The Mojaloop-SDK can be downloaded from [GitHub](https://github.com/mojaloop/sdk-standard-components) hosted on the same infrastructure as the DFSP's core banking application or a virtual machine provisioned specifically for it. Following the generation, signing, and exchange of TLS and JWS certificates, DFSPs are required to configure TLS- and JWS-related environment variables in the Mojaloop-SDK. Finally, installing the certificates in the DFSP's firewalls and API gateway completes the certificate configuration part of the process. + +Obtaining the Hub API gateway credentials required for collecting OAuth 2.0 tokens and configuring them in the Mojaloop-SDK via environment variables must be done manually. + +Exchanging endpoint details with the Hub and configuring them in the Mojaloop-SDK via environment variables, as well as in firewall/gateway whitelists are manual steps too. + +#### Payment Manager OSS + +Payment Manager OSS provides all the security features that the Mojaloop-SDK provides, and more. Payment Manager comes with a Mojaloop Connection Manager (MCM) Client, which simplifies and automates certificate creation, signing and exchange, as well as the configuration of the connections required to different environments. How much of these processes is automated will differ depending on the chosen deployment option. Two options are available: + +* **Managed and hosted by System Integrator**: A System Integrator deploys Payment Manager in the cloud. +* **Self-hosted by DFSP**: The DFSP deploys Payment Manager on premise or in the cloud. + +When a DFSP opts for the **managed-hosted option**, the System Integrator (this role can be filled by the Hub Operator) can employ Infrastructure-as-Code and onboarding scripts to handle the following elements of the process in an automated way: + +* generation, signing, configuration, and installation of TLS certificates +* IP address whitelisting in firewalls and API gateways +* generation and configuration of client secret/key required to obtain OAuth 2.0 tokens + +Steps related to JWS certificates are carried out via the [Connection Wizard portal](https://pm4ml.github.io/documents/payment_manager_oss/latest/connection_wizard/index.html), an easy-to-use portal that Payment Manager provides for managing certificate and endpoint related processes in a guided way. DFSPs and the Hub Operator are required to generate JWS certificates using any tool of their preference and then share their public keys via the Connection Wizard portal. Configuring JWS certificates in Payment Manager is done via the Connection Wizard portal, while installing them in gateways is a manual step. + +When a DFSP opts for the **self-hosted option**, they use the [Connection Wizard portal](https://pm4ml.github.io/documents/payment_manager_oss/latest/connection_wizard/index.html) to manage certificate and endpoint related steps in a semi-automated way: + +* DFSPs enter their endpoint details and obtain the Hub's endpoints from the portal. They then configure this information in Payment Manager via environment variables as well as in firewall/gateway whitelists manually. +* DFSPs generate, sign, and configure TLS certificates at the click of a button via the Connection Wizard portal. +* DFSPs generate JWS certificates using a tool of their choice and share and configure them in Payment Manager at the click of a button in the Connection Wizard portal. + +Obtaining the Hub API gateway credentials required for collecting OAuth 2.0 tokens and configuring them in Payment Manager via environment variables must be done manually. + +#### MCM + +The Mojaloop Connection Manager (MCM) product is instrumental in simplifying and automating much of the information sharing and configuration around endpoints and certificates. MCM has an MCM Client and an MCM Server component, which talk to each other when exchanging endpoint details and certificates, and when signing Certificate Signing Requests. + +The MCM Client is incorporated into Payment Manager, whereas the MCM Server is within the boundaries of the Hub. MCM provides a portal for the Hub Operator to submit Hub endpoint information and Hub certificates, and to retrieve DFSP endpoint and certificate details submitted by the DFSP via Payment Manager. + +### Security in Mojaloop + +To understand what connecting a DFSP to a Mojaloop environment entails in detail, it is important to take a closer look at the security requirements of Mojaloop. + +Mojaloop requires the following security measures to be implemented in order to protect the data exchanged between DFSPs: + +* **Transport Layer Security** is a secure mechanism for exchanging a shared symmetric key over a network between two anonymous peers, with identity verification (that is, trusted certificates). It provides confidentiality (no one has read the content) and integrity (no one has changed the content). Mojaloop requires two-way TLS mutual authentication using X.509 certificates for securing bi-directional connections. DFSPs and the Mojaloop Hub authenticate each other to ensure that both parties involved in the communication are trusted. Both parties share their public certificates with each other and then verification/validation is performed based on that. +* Another security measure that is offered for authentication is the **OAuth tokens** that DFSPs are required to use when making an API call request. OAuth 2 is used to provide role-based access to Mojaloop Hub endpoints (API authorization). +* **IP address whitelisting** reduces the attack surface of the Mojaloop Hub. +* To protect the application level, Mojaloop implements **JSON Web Signature (JWS)** as defined in [RFC 7515 (JSON Web Signature (JWS))](https://tools.ietf.org/html/rfc7515), the standard for integrity and non-repudiation. Signing messages ensures the Payer DFSP and the Payee DFSP can trust that messages shared between each other have not been modified by a third party. +* The Mojaloop FSPIOP API implements support for the **Interledger Protocol (ILP)**. ILP is built on the concept of conditional transfers, in which ledgers involved in a financial transaction from the Payer to the Payee can first reserve funds out of a Payer account and later commit them to the Payee account. The transfer from the Payer to the Payee account is conditional on the presentation of a fulfilment that satisfies the condition attached to the original transfer request. + +![Security overview](../../../.vuepress/public/security_overview.png) + +The next sections provide background information about the steps involved in connecting to a Mojaloop environment. The information provided is written in a way so that DFSPs and the Hub can rely on PKI best practices and any proprietary tools and technologies that they prefer or have access to. + +::: tip +As mentioned above, using Payment Manager OSS, Mojaloop Connection Manager (MCM), and the Infrastructre-as-Code (IaC) that deploys the components making up the Mojaloop ecosystem, many of the steps in the processes described below can be done in an automated way. +::: + +#### Creating and sharing certificates + +##### TLS certificates + +Two-way or mutual TLS authentication (mTLS) relies on both parties (client and server) sharing their public certificates with each other and performing verification/validation based on that. + +The following high-level steps describe how connection is established and data is transferred between a client and server in the case of mTLS: + +1. The client requests a protected resource over the HTTPS protocol and the SSL/TLS handshake process begins. +1. The server returns its public certificate to the client along with a server hello. +1. The client validates/verifies the received certificate. The client verifies the certificate through the Certificate Authority (CA) for CA-signed certificates. +1. If the server certificate was validated successfully, the server requests the client certificate. +1. The client provides its public certificate to the server. +1. The server validates/verifies the received certificate. The server verifies the certificate through the Certificate Authority for CA-signed certificates. + +After completion of the handshake process, the client and server communicate and transfer data with each other, encrypted with the secret keys shared between the two during the handshake. + + + +The above process requires that before connecting to any environment (pre-production or production), the DFSP and the Mojaloop Hub each complete the following steps. + +1. Create a server certificate signed by your CA. +1. Share your server certificate and CA chain with the other party. +1. Install the other party's CA chain in your outbound firewall (validation/verification will happen against these installed certificates). +1. Generate a Certificate Signing Request (CSR) for your TLS client certificate and share with the other party. +1. Sign the other party's CSR using your CA. +1. Share the signed client certificate as well as your CA's root certificate with the other party. +1. Install your own client certificate signed by the other party's CA in your outbound API gateway. +1. Install the root certificate of the other party's CA in your outbound API gateway. + +##### JWS certificates + +Whenever an API client sends an API message to a counterparty, the API client should sign the message using its JWS private key. After the counterparty receives the API message, it must validate the signature with the sending party's public JWS key. JWS is used by the receiving party to validate that the message came from the expected sender, and that it has not been modified in transit. + +The above process requires that all DFSPs and the Mojaloop Hub itself have a JWS certificate and that before connecting to any environment (pre-production or production), the DFSP and the Mojaloop Hub each complete the following steps. + +1. Create a keystore (to hold your certificate and private key), an asymmetric key pair (a public key and a private key), and an associated certificate that identifies you. +1. Share your JWS public key. +1. Install the other parties' (the Hub and all other DFSPs) JWS public key in your inbound gateway. +1. Install your JWS private key in your outbound gateway. + +#### Sharing endpoint information + +The Mojaloop Hub and the DFSPs share endpoint information to: + +* whitelist the other party's public IP addresses in firewall rules in order to allow traffic +* configure the other party's callback URLs in API gateways + +Typically, access to any incoming and outgoing traffic for a DFSP will be controlled by the relevant Security team. The DFSP's firewall needs to be appropriately configured: + +* to access the Mojaloop Hub in any environment where the DFSP and the Hub interact, and +* for the Mojaloop Hub to make callbacks to the DFSP + +Apart from access to and from the Hub deployed in an environment, all other public access should be blocked to prevent any unauthorized/unwarranted access. + +Accordingly, access to the Mojaloop Hub is also regulated. DFSPs have to share their IP/IP range from which calls will be made to the Hub so that the firewall on the Hub can be configured appropriately. The Security team within the DFSP should be able to provide that information. + +#### Obtaining an OAuth token + +The Mojaloop Hub employs WSO2 technologies for integration between the Hub and DFSPs, and to provide a gateway to DFSPs. To connect to the various Hub environments, DFSPs must obtain access to WSO2. WSO2 offers an API Store portal where DFSPs can create API gateway accounts for application-level access, subscribe to APIs, and obtain OAuth tokens for use when interacting with the Mojaloop Hub. + +## Onboarding in the Hub backend + +Onboarding comprises certain steps that do not require any actions from DFSPs and are the sole responsibility of the Hub Operator. These steps are as follows: + +1. Configure the Hub API gateways that handle incoming and outgoing data flows from/to DFSPs. Mojaloop employs WSO2 technologies for gateway access, as well as DFSP authorization and authentication for message pass-through via the gateways. The WSO2 product stack can be deployed from code using a continuous integration and deployment (CI/CD) solution, provisioning can be done through automation scripts. +1. Create users and accounts, configure role-based access control. +1. Set up the Hub for managing the use cases supported by the Scheme: + - Configure Hub ledgers. + - Configure Hub notification emails. + - Configure settlement model. + - Onboard oracles. \ + Mojaloop provides a [provisioning script](https://github.com/mojaloop/testing-toolkit-test-cases/tree/master/collections/hub/provisioning/MojaloopHub_Setup) to perform all of the above steps in an automated way using the [Mojaloop Testing Toolkit (TTK)](https://github.com/mojaloop/ml-testing-toolkit). +1. Set up simulator DFSPs for initial validation activities. \ + Mojaloop provides [provisioning scripts](https://github.com/mojaloop/testing-toolkit-test-cases/tree/master/collections/hub/provisioning/MojaloopSims_Onboarding) to perform this step in an automated way using the Mojaloop Testing Toolkit (TTK). +1. Set up DFSPs in the Hub backend. For each DFSP: + - Add DFSP and create a currency for it. + - Add callback URLs for all API services. + - Add a Net Debit Cap and set initial Position to 0. + - Configure DFSP notification emails. \ + Similar to previous steps, the configuration of DFSP details can also be done via a provisioning script. + +## Testing and validation + +As DFSPs moves forward in their onboarding journey, they are required to perform tests in each environment. Business validation and technical requirements both need to be met when testing. Details of business validation are defined in the Scheme Rules. + +Here are some examples of the testing activities that DFSPs are expected to perform in the various pre-production environments: + +* end-to-end integration and application layer validation against simulators +* end-to-end integration and application layer validation against real, friendly DFSPs +* settlement process validation +* security setup validation +* validation of response time Service Level Agreements (SLAs) +* performance testing diff --git a/docs/adoption/HubOperations/Portalv2/accessing-the-portal.md b/docs/adoption/HubOperations/Portalv2/accessing-the-portal.md new file mode 100644 index 000000000..b47b21c7b --- /dev/null +++ b/docs/adoption/HubOperations/Portalv2/accessing-the-portal.md @@ -0,0 +1,92 @@ +# Accessing the portal + +On accessing the portal, you are prompted to log in. Enter your credentials on the login page. + + + +The portal implements role-based access control, meaning that the role you have determines the range of portal functionalities available to you. Currently, the following roles exist: + +* `portaladmin`: has full access to all portal functionalities +* `portaluser`: has limited access to portal functionalities + +The following table lists all available functionalities, the navigation paths where you can access them, and the relevant roles permissions. + + + ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Portal functionalities and navigation paths
FunctionalityNavigation pathportaladminportaluser

View settlement window details

Settlement > Settlement Windows

Close settlement windows

Settlement > Settlement Windows

Settle settlement windows

Settlement > Settlement Windows

Finalize settlement

Settlement > Settlement Windows

View settlement details

Settlement > Settlements

View DFSP financial details

Participants > DFSP Financial Positions

Disable and re-enable transactions for a DFSP

Participants > DFSP Financial Positions

Record deposits to or withdrawals from DFSPs' liquidity accounts

Participants > DFSP Financial Positions

Update a DFSP’s Net Debit Cap

Participants > DFSP Financial Positions

x

Search for transfer data

Transfers > Find Transfers

\ No newline at end of file diff --git a/docs/adoption/HubOperations/Portalv2/busops-portal-introduction.md b/docs/adoption/HubOperations/Portalv2/busops-portal-introduction.md new file mode 100644 index 000000000..01159a2a0 --- /dev/null +++ b/docs/adoption/HubOperations/Portalv2/busops-portal-introduction.md @@ -0,0 +1,23 @@ +# Introduction – Guide to Finance Portal v2 + +This guide is aimed at the Operator of a Mojaloop Hub and provides information about the Finance Portal, which facilitates the management of settlement-related processes on a daily basis. + +::: tip NOTE +The Finance Portal is labelled as "Business Operations Portal" on the portal user interface itself. +::: + +The portal provides functionality to: + +* [search for settlement windows and check settlement window details](managing-windows.md) +* [close and settle settlement windows](settling.md) +* [settle settlements](settling.md) +* [search for settlements and check settlement details](checking-settlement-details.md) +* [monitor DFSP financial details such as Balance, current Position, Net Debit Cap, percentage of NDC used](monitoring-dfsp-financial-details.md) +* [disable and re-enable transactions for a DFSP](enabling-disabling-transactions.md) +* [update a DFSP's Net Debit Cap](updating-ndc.md) +* [record deposits to or withdrawals from a DFSP's liquidity account](recording-funds-in-out.md) +* [search for transfer data](searching-for-transfer-data.md) + +::: tip NOTE +The Finance Portal currently only supports settlement processes that rely on the Deferred Net Settlement model. +::: \ No newline at end of file diff --git a/docs/adoption/HubOperations/Portalv2/checking-settlement-details.md b/docs/adoption/HubOperations/Portalv2/checking-settlement-details.md new file mode 100644 index 000000000..39dc18f94 --- /dev/null +++ b/docs/adoption/HubOperations/Portalv2/checking-settlement-details.md @@ -0,0 +1,52 @@ +# Checking settlement details + +The **Settlement > Settlements** page allows you to view certain details of settlements, such as: + +* settlement identifier +* state of the settlement +* the total value of transactions +* the identifiers of the DFSPs involved in the transactions, as well as the associated Multilateral Net Settlement Position in the chosen period + +![Checking settlement details](../../../.vuepress/public/check_settlement_details.png) + +The **Settlements** page provides a list of settlements that you can filter using various search criteria: + +* **Date**: Provides a drop-down list of time ranges. The default value is **Today**. \ +\ +The **Clear** option allows you to remove any date filters already applied. +* **From** and **To**: Displays the start time and end time of the time range selected in the **Date** field. When **Date** is set to **Custom Range**, you have to set the date and time yourself in the **From** and **To** fields. +* **State**: Provides a drop-down list of settlement states. + * **Pending Settlement**: A new settlement consisting of one or more settlement windows has been created. The Multilateral Net Settlement Position due to/from each participant has been calculated. + * **Ps Transfers Recorded**: The Hub has marked the affected transfers as `RECEIVED_PREPARE` in its internal records. + * **Ps Transfers Reserved**: The Hub has marked the affected transfers as `RESERVED` in its internal records. + * **Ps Transfers Committed**: The Hub has marked the affected transfers as `COMMITTED` in its internal records. + * **Settling**: Settlement is ongoing. + * **Settled**: Settlement has completed. + * **Aborted**: The settlement could not be completed and should be rolled back. +* **Clear Filters** button: Allows you to remove all filters you applied. + +As you apply search criteria, the list of results (settlements) is continuously updated. + +The following details are shown: + +* **Settlement ID**: The unique identifier of the settlement. +* **State**: The status of the settlement. +* **Total Value**: The total value of transactions within the settlement batch. +* **Open Date**: The date and time when the settlement was created in the Hub. +* **Last Action Date**: The date and time when the last action was taken on the settlement in the Hub (for example, funds have been reserved, funds have been committed). +* **Action**: **Finalize** button. Allows you to finalize a settlement. This button is only displayed for Pending Settlements. For details about finalizing a settlement, see [Settling](settling.md#finalizing-a-settlement). + +To view details for a particular settlement, click the settlement in the results list. The **Settlement Details** pop-up window is displayed. + +![Settlement details pop-up window](../../../.vuepress/public/settlement_details_popup.png) + +The following additional details are shown: + +* **DFSP**: The unique identifier of the DFSP. +* **Window ID**: The unique identifier of the settlement window being settled. +* **Debit**: Aggregated debit amount resulting from the transfers that the DFSP engaged in. +* **Credit**: Aggregated credit amount resulting from the transfers that the DFSP engaged in. + +::: tip NOTE +At the time of writing, the information that clicking the **View Net Positions** button should display is not available. It will be added in a future version of the portal. +::: \ No newline at end of file diff --git a/docs/adoption/HubOperations/Portalv2/enabling-disabling-transactions.md b/docs/adoption/HubOperations/Portalv2/enabling-disabling-transactions.md new file mode 100644 index 000000000..73bd59d63 --- /dev/null +++ b/docs/adoption/HubOperations/Portalv2/enabling-disabling-transactions.md @@ -0,0 +1,28 @@ +# Disabling and re-enabling transactions for a DFSP + +In certain cases, it may be necessary to make a DFSP inactive temporarily or permanently. An example scenario is when you observe highly suspicious behavior and the actual cause needs investigation, the risk of money loss being too high. + +The **Participants** > **DFSP Financial Positions** page provides an option to stop the sending and receiving of transfers for a particular DFSP by disabling its Position Ledger at the click of a button. + +(The Hub maintains a Position Ledger for each DFSP. The Position Ledger tracks how much a DFSP owes or is owed. Every time a transfer is processed, the Position in the Hub is adjusted in real time.) + +To disable transactions for a particular DFSP, complete the following steps: + +::: warning +Disabling a DFSP will stop all incoming and outgoing transactions for that DFSP, so ensure you apply this option with care. Once the risk has been cleared, remember to resume services for the DFSP. +::: + +1. Go to the **Participants** > **DFSP Financial Positions** page. +1. Find the entry of the DFSP you want to disable. +1. Click the **Disable** button. + + + +To resume services for the DFSP that you have disabled previously, complete the following steps: + +1. Go to the **Participants** > **DFSP Financial Positions** page. +1. Find the entry of the DFSP you want to enable. +1. Click the **Enable** button. + + + diff --git a/docs/adoption/HubOperations/Portalv2/managing-windows.md b/docs/adoption/HubOperations/Portalv2/managing-windows.md new file mode 100644 index 000000000..fede50285 --- /dev/null +++ b/docs/adoption/HubOperations/Portalv2/managing-windows.md @@ -0,0 +1,50 @@ +# Checking settlement window details + +The **Settlement Windows** page allows you to: + +* search for settlement windows based on multiple search criteria +* close an open settlement window +* settle a single window or settle multiple windows at once + +::: tip NOTE +Remember that settling must follow this procedure: + +* Close the settlement window that you want to settle. +* Settle closed window(s) of your choice. This creates a new settlement. +* Send settlement reports to DFSPs and the settlement bank, and obtain a confirmation from the bank that it has moved money in accordance with the report. +* Finalize the new settlement created in Step 2. + +Given that closing a window and initiating settlement by settling select windows are integral part of the settlement process, they are described in a section dedicated to [settling](settling.md). +::: + +A settlement window is a time period between two successive settlements. It has a start time and an end time, and any transfers that go through (and reach a `"COMMITTED"` state) during the time that the settlement window is open will be settled in bulk after the settlement window has closed. + +Transfers that take place in the same settlement window are settled in batch after the end of the settlement window. + +To access the **Settlement Windows** page, go to **Settlement** > **Settlement Windows**. + +![Managing settlement windows](../../../.vuepress/public/settlement_window_mgmt.png) + +The **Settlement Windows** page provides a list of settlement windows that you can filter using various search criteria: + +* **Date**: Provides a drop-down list of time ranges. The default value is **Today**. \ +\ +The **Clear** option allows you to remove any date filters already applied. +* **From** and **To**: Displays the start time and end time of the time range selected in the **Date** field. When **Date** is set to **Custom Range**, you have to set the date and time yourself in the **From** and **To** fields. +* **State**: Provides a drop-down list of settlement window states: + * **Open**: The settlement window is open, transfers are being accepted into the current open window. + * **Closed**: The settlement window is closed. It is not accepting any additional transfers and all new transfers are being allocated to a new, open settlement window. + * **Pending**: The settlement window is closed, but the settlement window still needs to be settled. A window can only be settled once the settlement bank has confirmed that all the participant DFSPs that engaged in transfers in the settlement window have settled their payments. + * **Settled**: The settlement bank has confirmed that all the affected DFSPs have settled their obligations towards one another. Following confirmation, the Hub Operator has settled the settlement window. + * **Aborted**: The settlement window was part of a settlement that got aborted. It is possible to add the aborted window to a new settlement. + * **Clear**: Allows you to remove any window state filters already applied. +* **Clear Filters** button: Allows you to remove all filters you applied. + +As you apply search criteria, the list of results (settlement windows) is continuously updated. The search results list displays the following details: + +* Window selector: Only displayed for **Pending** settlement windows. Clicking the window selector activates the **Settle Selected Windows** button. For details about settling a settlement window, see [Settling](settling.md#settling-a-closed-settlement-window). +* **Window ID**: The unique identifier of the settlement window. +* **State**: The state of the settlement window. +* **Opened Date**: The date and time when the settlement window was opened. +* **Closed Date**: The date and time when the settlement window was closed. +* **Action**: **Close Window** button. Allows you to close a settlement window. This button is only displayed for **Open** settlement windows as only open windows can be closed. For details about closing a settlement window, see [Settling](settling.md#closing-a-settlement-window). \ No newline at end of file diff --git a/docs/adoption/HubOperations/Portalv2/monitoring-dfsp-financial-details.md b/docs/adoption/HubOperations/Portalv2/monitoring-dfsp-financial-details.md new file mode 100644 index 000000000..0838ce654 --- /dev/null +++ b/docs/adoption/HubOperations/Portalv2/monitoring-dfsp-financial-details.md @@ -0,0 +1,24 @@ +# Monitoring DFSP financial details + +The **DFSP Financial Positions** page allows you to monitor DFSPs' financial details such as Balance, current [Position](settlement-basic-concepts#position), [Net Debit Cap](settlement-basic-concepts#liquidity-management-net-debit-cap), percentage of NDC used. + +To access the **DFSP Financial Positions** page, go to **Participants** > **DFSP Financial Positions**. + +![Monitoring DFSP financial details](../../../.vuepress/public/dfsp_financial_positions_2.png) + +The following details are displayed for each DFSP: + +* **Balance**: Reflects the balance of the DFSP's liquidity account at the settlement bank. +* **Current Position**: The current Position of the DFSP. \ +\ +The Position of a DFSP reflects – at a given point in time – the sum total of the transfer amounts sent and received by the DFSP. The Position is the sum of all outgoing transactions minus incoming transactions since the beginning of the settlement window, as well as any provisional transfers that have not yet been settled. \ +\ +Each attempted outgoing transfer results in the Position being recalculated by the Mojaloop Hub in real time, which, in turn, is compared to the Net Debit Cap. \ +\ +Once the settlement window is closed, then Positions are adjusted based on the settlement – the Position changes to the net amount of the transfers that were not initiated or not yet fulfilled when the settlement window was closed. +* **NDC**: The Net Debit Cap set for the DFSP. \ +\ +When pre-funding their liquidity account, DFSPs define the maximum amount that they can "owe" to other DFSPs, this is called the Net Debit Cap (NDC). The NDC acts as a limit or a cap placed on a DFSP’s funds available for transacting, and it can never exceed the balance of the liquidity account. This is required to ensure that a DFSP's liabilities can be met with funds immediately available to the settlement bank. \ +\ +The Position is continuously checked against the Net Debit Cap ((TransferAmount + Position) < = NDC) and if a transfer would cause the Position amount to exceed the NDC amount, the transfer is blocked. +* **% NDC Used**: A Position/NDC indicator to show the percentage of NDC used. diff --git a/docs/adoption/HubOperations/Portalv2/recording-funds-in-out.md b/docs/adoption/HubOperations/Portalv2/recording-funds-in-out.md new file mode 100644 index 000000000..c30c25e6d --- /dev/null +++ b/docs/adoption/HubOperations/Portalv2/recording-funds-in-out.md @@ -0,0 +1,31 @@ +# Recording funds in or funds out for a DFSP + +The **DFSP Financial Positions** page allows you to record funds in or funds out in the Hub's ledgers in the case of movement of funds initiated by the DFSP: a DFSP deposits funds in their liquidity account or withdraws funds from their liquidity account. + +To access the **DFSP Financial Positions** page, go to **Participants** > **DFSP Financial Positions**. + + + +To record funds in or funds out for a DFSP, complete the following steps: + +1. Click the **Update** button next to the DFSP for which you want to record funds in/out. \ +![](../../../.vuepress/public/add_withdraw_funds.png) \ +The **Update Participant** window pops up. +1. Select **Add / Withdraw Funds** from the **Action** drop-down menu. \ + +1. Select the **Add Funds** or **Withdraw Funds** option depending on the action you want to take. \ +To record a deposit, use **Add Funds**. \ +To record a withdrawal, use **Withdraw Funds**. \ + +1. Enter the amount added or withdrawn by the DFSP in the **Amount** field. \ +Do not specify a plus or a minus sign when entering the amount. Instead, ensure you have selected the right action in the previous step. +1. Click **Submit**. +1. On clicking **Submit**, a confirmation window pops up asking you to confirm the action, or confirm and also update the Net Debit Cap of the DFSP. \ + + +1. Click **Confirm Only** or **Confirm and Update NDC**. \ +\ +On clicking **Confirm Only**, the **Balance** value on the **DFSP Financial Positions** page gets updated and the Hub adjusts the ledgers. \ +\ +On clicking **Confirm and Update NDC**, the **Update Participant** window changes and allows you to update the Net Debit Cap (NDC). \ + diff --git a/docs/adoption/HubOperations/Portalv2/searching-for-transfer-data.md b/docs/adoption/HubOperations/Portalv2/searching-for-transfer-data.md new file mode 100644 index 000000000..bdd6cb294 --- /dev/null +++ b/docs/adoption/HubOperations/Portalv2/searching-for-transfer-data.md @@ -0,0 +1,189 @@ +# Searching for transfer data + +The Finance Portal provides a transfer search page, which allows you to find transfer data based on DFSP identifiers, end user identifiers, or transfer identifiers. This is useful when resolving issues. + +::: tip NOTE +The values displayed on the **Find Transfers** page are pulled from the Hub's central-ledger database. +::: + +## Finding transfers + +To find transfers, complete the following steps: + +1. Go to **Transfers** > **Find Transfers**. The **Find Transfers** page is displayed. \ + +1. Use the search filters to specify what you are looking for. You can fill in any number of search fields, in any combination. + * **Transfer ID**: Enter a full `transferId` or a fragment of a `transferId`. + * **Payer FSP ID**: Enter the full `fspId` or a fragment of the `fspId` of the Payer DFSP. + * **Payer ID Type**: Using the drop-down list, select the type of identifier used to identify the Payer (for example, **MSISDN** or **ACCOUNT_ID**). + * **Payer ID Value**: Enter the full identifier or a fragment of the identifier used to identify the Payer (for example, a phone number or a bank account number). + * **Payee FSPID**: Enter the full `fspId` or a fragment of the `fspId` of the Payee DFSP. + * **Payee ID Type**: Using the drop-down list, select the type of identifier used to identify the Payee. + * **Payee ID Value**: Enter the full identifier or a fragment of the identifier used to identify the Payee. + * **From** and **To**: Enter the start time and end time of the time range when the transfer(s) you are looking for happened. +1. Once you have set your search filters, click **Find Transfers**. The list of search results that meet the search criteria are displayed. + +Use the page navigation buttons at the bottom of the screen to navigate between pages of search results. + +You can remove all the filters you applied and start your search from scratch by clicking **Clear Filters**. + +Search results are displayed in columns. All columns are sortable: + +* Click a column header to change the sort order of the values displayed in the column. +* Click the magnifying-glass icon in the column header and enter a value that you are looking for. + +::: tip +The total number of transfers that get returned are limited to a thousand (1000) (this is to keep the load off the backend). If you are not able to find the transfer that you are looking for within the first thousand results, then start narrowing your search, using the search filters. \ + \ +If your search returns more than five hundred (500) results, the page will display an information message so you know that you do not necessarily see all results that meet your original search criteria and you should drill down more. +::: + +The following details are displayed for a transfer: + +::: tip NOTE +Transfers without quotes (that is "add/withdraw funds" transfers and settlement transfers) will display details for the following fields only: **Transfer ID**, **Timestamp**, **Amount**, **Currency**, **Status**. +::: + +* **Transfer ID**: The unique identifier of the transfer (corresponds to `transferId`). +* **Type**: The type of the transfer (corresponds to `transactionType` in Payment Manager and `transactionScenario` in the Mojaloop FSPIOP API). +* **Timestamp**: The date and time when the transfer request was created, as an [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted timestamp. +* **Payer FSPID**: The `fspId` of the Payer DFSP. +* **Payee FSPID**: The `fspId` of the Payee DFSP. +* **Amount**: The transfer amount. +* **Currency**: The currency of the transfer. +* **Status**: The state of the transfer (corresponds to `transferState` in Payment Manager and the Mojaloop FSPIOP API). +* **Payer Acct ID**: The identifier type and identifier value of the Payer's account. +* **Payee Acct ID**: The identifier type and identifier value of the Payee's account. + +## Transfer details + +To find out more details about a particular search result, click its entry in the search result list. A **Transfer Details** window pops up. This section provides information about the details that are displayed for a transfer. + +### Quote Requests + +The **Quote Requests** tab displays the `quoteId` and further information on sub-tabs. + +#### Quote Request sub-tab + + + +The **Quote Request** sub-tab displays the following details about the quote request: + +* **quoteId**: The unique identifier of the quote, decided by the Payer DFSP. +* **transactionReferenceId**: Corresponds to the `transactionId` specified in the quote request. +* **transactionRequestId**: Optional. Common ID between the DFSPs for the transaction request object, decided by the Payee DFSP. +* **note**: An optional memo attached to the transfer. +* **expirationDate**: An optional quote request expiration date, as an [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted timestamp. +* **amount**: The amount that the quote is being requested for. +* **createdDate**: The date and time when the quote request was created, as an [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted timestamp. +* **transactionInitiator**: Specifies if the initiator of the transfer is the **PAYER** or the **PAYEE**. +* **transactionInitiatorType**: Specifies the type of the initiator: + * **CONSUMER**: Consumer is the initiator of the transaction. For example: peer-to-peer transfer or loan repayment from wallet. + * **AGENT**: Agent is the initiator of the transaction. For example: loan repayment via an agent. + * **BUSINESS**: Business is the initiator of the transaction. For example: loan disbursement. + * **DEVICE**: Device is the initiator of the transaction. For example: merchant-initiated merchant payment authorized on POS. +* **transactionScenario**: Specifies the transaction scenario (corresponds to `transactionType` in Payment Manager). +* **transactionSubScenario**: Specifies the transaction sub-scenario defined by the scheme. +* **balanceOfPaymentsType**: The BoP code as defined in [the IMF's Balance of Payments Coding System](https://www.imf.org/external/np/sta/bopcode/). +* **amountType**: **SEND** for send amount, **RECEIVE** for receive amount. +* **currency**: The currency of the amount that the quote is being requested for. A three-letter alphabetic code conforming to [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html). + +#### Quote Parties sub-tab + + + +The **Quote Parties** sub-tab displays the following details about the Payer DFSP and Payee DFSP: + +* **quoteId**: The unique identifier of the quote, decided by the Payer DFSP. +* **partyIdentifierType**: The type of identifier used to identify the party (for example, **MSISDN** or **ACCOUNT_ID**). +* **partyIdentifierValue**: The value of the identifier used to identify the party (for example, a phone number or a bank account number). +* **fspId**: The unique identifier of the DFSP registered in the Hub (corresponds to `fspId`) - as provided in the quote. +* **merchantClassificationCode**: Used when the Payee is a merchant accepting merchant payments. +* **partyName**: The display name of the party. +* **transferParticipantRoleType**: The role that the DFSP is playing in the transfer. +* **ledgerEntryType**: The type of financial entry this party is presenting — principal value (that is, the amount of money that the Payer wants the Payee to receive) or interchange fee. +* **amount**: The amount that the quote is being requested for. +* **currency**: The currency of the amount that the quote is being requested for. A three-letter alphabetic code conforming to [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html). +* **createdDate**: The date and time when the quote request was created, as an [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted timestamp. +* **partySubIdOrTypeId**: A sub-identifier or sub-type for the party. +* **participant**: Reference to the resolved `fspId` (if supplied/known). + +#### Quote Errors sub-tab + +The **Quote Errors** sub-tab only displays information if there was an error in the quotes stage. + +### Quote Responses + + + +The **Quote Responses** tab displays details about the quote response: + +* **quoteId**: The unique identifier of the quote, decided by the Payer DFSP. +* **transactionReferenceId**: Corresponds to the `transactionId` specified in the quote request. +* **quoteResponseId**: The unique identifier of the quote response. +* **transferAmountCurrencyId**: The currency of the transfer amount. A three-letter alphabetic code conforming to [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html). +* **transferAmount**: The amount that the Payer DFSP should transfer to the Payee DFSP. +* **payeeReceiveAmountCurrencyId**: The currency of the amount that the Payee should receive in the end-to-end transaction. +* **payeeReceiveAmount**: The amount that the Payee should receive in the end-to-end transaction. +* **payeeFspFeeCurrencyId**: The currency of the Payee DFSP's part of the transaction fee (if any). A three-letter alphabetic code conforming to [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html). +* **payeeFspFeeAmount**: The Payee DFSP's part of the transaction fee (if any). +* **payeeFspCommissionCurrencyId**: The currency of the transaction commission from the Payee DFSP (if any). A three-letter alphabetic code conforming to [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html). +* **payeeFspCommissionAmount**: The transaction commission from the Payee DFSP (if any). +* **ilpCondition**: The ILP condition that must be attached to the transfer by the Payer side. +* **responseExpirationDate**: The quote's expiration date as an [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted timestamp. +* **isValid**: An indicator whether or not the quote response has passed request validation and duplicate checks. +* **createdDate**: The date and time when the quote request was created, as an [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted timestamp. +* **ilpPacket**: The ILP packet returned from Payee side in response to the quote request. + +### Transfer Prepares + + + +The **Transfer Prepares** tab displays details about the transfer request: + +* **transferId**: The unique identifier of the transfer. +* **amount**: The amount that the Payer DFSP should transfer to the Payee DFSP. +* **currencyId**: The currency of the transfer amount. A three-letter alphabetic code conforming to [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html). +* **ilpCondition**: The ILP condition that must be fulfilled to commit the transfer. +* **expirationDate**: The transfer's expiration date as an [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted timestamp. +* **createdDate**: The date and time when the transfer request was created, as an [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted timestamp. + +### Transfer Participants + + + +The **Transfer Participants** tab displays the following details about the participants of the transfer: + +* **transferParticipantId**: The internal identifier of the scheme participant (DFSP) for whom the report is requested, corresponds to `participantId` as recorded in the Hub. +* **transferId**: The unique identifier of the transfer. +* **participantCurrencyId**: The currency that the participant (DFSP) transacts in. A three-letter alphabetic code conforming to [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html). +* **transferParticipantRoleType**: The role that the DFSP is playing in the transfer. +* **ledgerEntryType**: The type of financial entry this party is presenting — principal value (that is, the amount of money that the Payer wants the Payee to receive) or interchange fee. +* **amount**: The transfer amount. +* **createdDate**: The date and time when the transfer request was created, as an [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted timestamp. + +### Transfer Fulfilments + + + +The **Transfer Fulfilments** tab displays the following details about the transfer response: + +* **transferId**: The unique identifier of the transfer. +* **ilpFulfilment**: The fulfilment of the ILP condition specified within the transfer request. +* **completedDate**: The date and time when the transfer was completed, as an [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted timestamp. +* **isValid**: An indicator whether or not the transfer fulfilment is valid. +* **settlementWindowId**: The identifier of the settlement window to which this transfer has been assigned. +* **createdDate**: The date and time when the transfer response was created, as an [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted timestamp. + +### Transfer State Changes + + + +The **Transfer State Changes** tab displays the following details about the states that a transfer goes through: + +* **transferStateChangeId**: The unique identifier of the transfer state. +* **transferId**: The unique identifier of the transfer. +* **enumeration**: The state of the transfer (corresponds to `transferState` in Payment Manager and the Mojaloop FSPIOP API). +* **description**: The description of what the state means. +* **reason**: The reason why the transfer moved into a particular state. +* **createdDate**: The date and time when the transfer reached a particular state, as an [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted timestamp. \ No newline at end of file diff --git a/docs/adoption/HubOperations/Portalv2/settlement-business-process.md b/docs/adoption/HubOperations/Portalv2/settlement-business-process.md new file mode 100644 index 000000000..31103b46e --- /dev/null +++ b/docs/adoption/HubOperations/Portalv2/settlement-business-process.md @@ -0,0 +1,68 @@ +# Settlement process + +It is important to define a business process around settlement management. The following high-level process serves as an example that you can customize to the specifics of your organization's needs. + + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Settlement business process
StepDetails

1

The Hub Operator closes the settlement window and initiates settlement for select windows using the Finance Portal.

2

The Hub Operator retrieves a DFSP Settlement Report for each DFSP that was active in the settlement window.

3

The Hub Operator emails the DFSP Settlement Report to each DFSP's nominated contact points.

4

DFSPs review their report and reconcile transactions against their own records in a timely manner.

+

The report provides information about the DFSP's bilateral settlement position with each DFSP they transacted with (either as a Payer DFSP or Payee DFSP) in the settlement window(s) being settled. It also provides the sum total of the transfer amounts sent and received by the DFSP in the settlement window(s).

5

The Hub Operator retrieves the Settlement Bank Report.

6

The Hub Operator notifies settlement bank contact points that settlement can be enacted, sharing the Settlement Bank Report.

The report acts as payment instructions to the bank, and provides the bilateral settlement position of each DFSP against every other DFSP that transacted in the settlement window(s) being settled. It also provides the sum total of the transfer amounts sent and received by each DFSP.

7

The settlement bank moves money between the settlement account and DFSPs' liquidity accounts, in accordance with the aggregated net Positions indicated in the Settlement Bank Report.

8

The settlement bank confirms that money moved, and (since the Hub Operator has no visibility of the balance of accounts held at the settlement bank) shares the balance of each DFSP’s liquidity account.

9

The Hub Operator finalizes the settlement using the Finance Portal.

10

The Hub Operator verifies DFSP liquidity account balances against the balances shown in the portal, and updates them if necessary, using the "add/withdraw funds" functionality of the portal. Note that this may cause the DFSP’s NDC to be recalculated, potentially causing the DFSP’s outbound transactions to be declined by the Hub.

11

The Hub Operator retrieves a DFSP Settlement Result Report for each DFSP.

12

The Hub Operator notifies each DFSP of the settlement result and their liquidity account balance by sending the DFSP Settlement Result Report to each DFSP.

\ No newline at end of file diff --git a/docs/adoption/HubOperations/Portalv2/settling.md b/docs/adoption/HubOperations/Portalv2/settling.md new file mode 100644 index 000000000..aa4e41b91 --- /dev/null +++ b/docs/adoption/HubOperations/Portalv2/settling.md @@ -0,0 +1,67 @@ +# Settling + +1. [Close the settlement window](#closing-a-settlement-window) that you want to settle. +1. [Settle closed window(s) of your choice](#settling-a-closed-settlement-window). This creates a new settlement. +1. Send settlement reports to DFSPs and the settlement bank, and obtain a confirmation from the bank that it has moved money in accordance with the report. +1. [Finalize the new settlement](#finalizing-a-settlement) created in Step 2. + +This section describes those steps of the process (Steps 1, 2, and 4) that you perform via the portal. + +## Closing a settlement window + +To close an open settlement window, complete the following steps: + +1. Go to **Settlement** > **Settlement Windows**. The **Settlement Windows** page displays. +1. Find the settlement window that you are looking for, [using the search filters](managing-windows.md). +1. The open window will have a **Close Window** button displayed next to it in the **Action** column. Click the **Close Window** button. + +![Closing a settlement window](../../../.vuepress/public/settlement_window_mgmt_close.png) + +Closing a window will automatically open a new window with the state of **Open**. + +## Settling a closed settlement window + +To settle one or more settlement windows, complete the following steps: + +1. Go to **Settlement** > **Settlement Windows**. The **Settlement Windows** page displays. +1. Find the settlement window that you are looking for, [using the search filters](managing-windows.md). The settlement window must be in the **Closed** state. +1. Click the window selector next to the settlement window(s) that you wish to settle. \ +\ + \ +\ +This activates the **Settle Selected Windows** button. Click the **Settle Selected Windows** button. \ +\ + +1. A **Settlement Submitted** window pops up, where you have the following options: + +* View submitted settlements +* Continue viewing windows \ +\ + \ +\ +If you wish to view the new settlement you have just created, click the **View Submitted Settlements** button. This takes you to the **Settlements** page, where you can search for the new settlement, [using the search filters](checking-settlement-details.md). The settlement will be in the **Pending Settlement** state. + +## Finalizing a settlement + +To finalize the settlement, complete the following steps: + +**Prerequisites:** + +* The settlement bank has confirmed that all the DFSPs' MLNS Positions have been settled. + +**Steps:** + +1. Go to **Settlement** > **Settlements**. The **Settlements** page displays. +1. Find the settlement that you are looking for, using the [search filters](checking-settlement-details.md). The settlement must be in the **Pending Settlement** state. \ +\ + +1. Click the **Finalize** button next to the settlement. A status window pops up that displays the states of the settlement with checkmarks being added as the settlement process progresses. \ +\ +When the settlement is finalized, you will see all states displayed with checkmarks next to them. The last state will say **State: SETTLED.** In addition, the **Close** button will be activated enabling you to return to the **Settlements** page. \ +\ + +1. Back on the **Settlements** page, when looking for the settlement, you should see the state of the settlement now display as **Settled**. + +::: tip +In case the settlement state is something other than **Settled**, then it means that the settlement has not finished for some reason. Click **Finalize** again to complete the unfinished settlement process. +::: \ No newline at end of file diff --git a/docs/adoption/HubOperations/Portalv2/updating-ndc.md b/docs/adoption/HubOperations/Portalv2/updating-ndc.md new file mode 100644 index 000000000..d8a8056ab --- /dev/null +++ b/docs/adoption/HubOperations/Portalv2/updating-ndc.md @@ -0,0 +1,22 @@ +# Updating the Net Debit Cap of a DFSP + +The **DFSP Financial Positions** page allows you to update the Net Debit Cap (NDC) of a DFSP. + +To access the **DFSP Financial Positions** page, go to **Participants** > **DFSP Financial Positions**. + +![Updating the NDC of a DFSP]("../../../.vuepress/public/dfsp_financial_positions_2.png") + +To update the Net Debit Cap of a DFSP, complete the following steps: + +1. Click the **Update** button next to the DFSP for which you want to update the NDC. \ + +The **Update Participant** window pops up. +1. Select **Change Net Debit Cap** from the **Action** drop-down menu. \ + +1. Enter the new NDC amount in the **Amount** field. \ + +1. Click **Submit**. +1. On clicking **Submit**, a confirmation window pops up asking you to confirm the action. \ + +1. Click **Confirm**. \ +On clicking **Confirm**, the **NDC** value on the **DFSP Financial Positions** page gets updated and displays the new NDC amount. \ No newline at end of file diff --git a/docs/adoption/HubOperations/RBAC/Role-based-access-control.md b/docs/adoption/HubOperations/RBAC/Role-based-access-control.md new file mode 100644 index 000000000..1e5bbd5eb --- /dev/null +++ b/docs/adoption/HubOperations/RBAC/Role-based-access-control.md @@ -0,0 +1,312 @@ +# RBAC Context +The Mojaloop Hub uses a Role-Based Access Control (RBAC) method for mitigating risk. + +## What is RBAC and how to design for it? + +Role-based access control (RBAC) is a method of restricting network access based on the roles of individual users within an enterprise. RBAC lets employees have access rights only to the information they need to do their jobs and prevents them from accessing information that doesn't pertain to them. + +The RBAC design for a hub operator, outlines the security control points that should be considered or extended in order to mitigate risk within a typical Mojaloop hub operations organisation. Some control points are business processes and organisational structure related, some control points are technical relating to the identification, authentication and authorisation layers, and some control points require monitoring. All three should be considered to create accountability and mitigate risk. + +This document covers: +1. RBAC Overview.
+Where we discuss RBAC principles and organsational structures. +2. Technical implementation of the RBAC controls.
+Specificaly what is important for a Mojaloop Implementation and how to inforce this technically. +3. Role recommendations +4. Monitoring requirements and approach. + +## RBAC Overview + +### Principle of least privilege + +RBAC uses the security principle of least privilege. Least privilege means that a user has precisely the amount of privilege that is necessary to perform a job. The aim of this is to minimize the likelihood of issuing a user with excess permissions to complete actions in Mojaloop ecosystem. + +### Zero Trust Mojaloop Implementation + +A zero trust network is one in which no person, device, or network enjoys inherent trust. All trust, which allows access to information, must be earned, and the first step of that is demonstrating valid identity. A system needs to know who you are, confidently, before it can determine what you should have access to. + +Mojaloop's inherent design will implement a Zero Trust approach in its architecture and deployment requiring all entities that interact to first authenticate themselves, then seek authorization to access and process data depending on the role they belong to. + +### Segregation of Duties + +Segregation of Duties focuses on mitigating the risk of internal fraud by setting boundaries between roles assigned to an employee, and between the conflict of interest that may result from an employee's responsibilities, ensuring no single user can have end to end functional control of a business process and its data. It requires more than one individual to create, process and complete an action. + +### Audit + +Audit would need to work collaboratively with the business and the IT teams to Segregate these duties wherever possible and assign an appropriate mitigation control in cases wherein it is not feasible to do so. In addition, these controls would need to be monitored on a quarterly basis and the results need to be reported to senior management. + +Some contextual definitions include: +1. **Action** : a distinct event triggered by a user that results in: + - Creation of a data asset + - Reading or accessing of a data asset + - Update or effecting changes to the state of a data asset + - Delete or the removal of a data asset from an application or database. +2. **Permission** : authority to perform a specific action in the context of an application or service +3. **Role** : applications, actions and data access required to perform the tasks related to a single role +4. **User - role relationship** : The role (roles) assigned to each user that defines the permissions they have + +## Technical RBAC implementation + +An individual who needs to access the various Mojaloop Hub management portals can be registered and an “account” generated, which can be used to access various aspects of an operational instance of a Mojaloop Hub and to provide a basis for auditing that access by tying activities to the original registration. For the purposes of this document, an “account” is a digital identity, a means of authenticating (linking) the person asserting that identity to the original registration, and a set of attributes, which will include - among other things - a set of access rights, or rights that are enabled through the possession of those attributes. + +The registration process involves identity verification, background checking, and so on. The individual is then issued with credentials - a login account ID/digital identity and at least one authentication method, which may include a password and two-factor authentication (2FA). + +::: tip NOTE +The scope of this document is not limited to Mojaloop Hub operators. It also addresses aspects of DFSP operator access to the Payment Manager portals. +::: + +### 2FA considerations + +It should be noted that 2FA via a mobile phone may be inappropriate for some roles, since highly sensitive roles may require that mobile phones are locked away while the individual is “on shift”. This will necessitate other 2FA methods, such as key fobs. + +### Users, actions and roles in a Mojaloop context + +Mojaloop will have 2 Broad categories of users: + +1. **Human**
+These are hub and DFSP users who through various interfaces will interact with Mojaloop. DFSP users will interact with Mojaloop through the Payment Manager and portals that will be made available during the onboarding process. +2. **Non-human**
+These will automate the business processes and automate tasks that would otherwise be done by a human. These will communicate via API calls that will affect actions to fulfil business requirements. + +The context of this document will focus on Human users only. + +### User Lifecycle Management + +The "User Account Lifecycle" defines the collective management processes for every user account. These processes can be broken down into Creation, Review/Update, and Deactivation—or "CRUD". If any organization utilizes IT resources of any kind, they rely on user accounts to access them. + +### Onboarding + +The Onboarding process will have some activities involving user creation both at DFSP end and at the Hub. These will be as follows: + +1. Hub: The following users will be created + - Hub Operators + - Hub Administrators +2. DFSP + - DFSP Operators + - DFSP administrators (only applicable to Payment manager). + + +### Process of Segregation Of Duties determination + +1. Define user management workflows and processes. These are all business processes that make up Mojaloop business actions in Mojaloop. Examples include Onboarding. +1. Rationalise all User security access requirements for Applications of Mojaloop as outlined in the table below: + - Define business and application functions for users and APIs + - Define role profiles + - Define function & competence profiles + - Gather a list of applicable SOD conflicts by defining segregation of duties roles + - Role profile matrix table (with example data): + +| **Roles and Permissions** **Matrix** | Hub Users | Administrator | Standard Maker User | Standard Checker User | Standard Read Only | DFSP Users | Administrator | Standard Maker User | Standard Checker User | Standard Read Only | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| Onboarding Roles | X | | | | | | | | | | +| Create User Account | X | | | | | | | | | | +| Create DFSP Profile | X | | | | | | | | | | +| Create DFSP User | X | | | | | | | | | | +| +| **Finance Portal** | +| View Reports | | | X | X | X | | | X | X | X | +| Platform Configuration | | | | | | | | | | | +| + +3. Reconfigure any conflicting roles + - Business approvals + - Maker checker user creation +4. Periodic System Access & User Authorisation reporting +5. Separation of IT-security and Operational IT security that will support user management activities + +### Best Practices for RBAC and Mojaloop Identity Management + +1. All user ids should be unique and have a unique format that can be correlated in the hub but not meaningful to outsiders. +2. DFSP Users will not have access to any administrative role Hub +3. All non-human users must be restricted from logging on to the application front ends. +4. DFSP users will be trained on the roles and best practices +5. Enforce automated user provisioning and life cycle management. +6. Classify actions performed in Mojaloop to identify business risky actions that require additional controls. +7. Additional controls to mitigate RBAC risks can include: + - Multifactor authentication (MFA) + - Audit logging with alerts + - Auto user profile deactivation / disabling +8. Mojaloop will monitor user inactivity and disable inactive users over a specified period +9. Enforce centralised policy enforcement across identities e.g. Password policy, login policies, MFA, risk based authentication etc. +10. Identify and closely monitor privileged identities that have permissions to perform sensitive actions. +The following apply to privileged users: + - Advanced privileges must be requested for and approved on a case-by-case basis; + - Administrators should have their privileged permissions for the minimum time possible; + - Administrators should only have the permissions required to complete a specific task; + - Membership in administrative groups must be reviewed regularly; + - Enforce multi-factor authentication for administrative users; + - Keep access logs, audits, and set-up real-time notifications when access is activated. +11. Mojaloop will configure audit logs and alerts for all user actions in Mojaloop. Where possible explore identity analytics via applicable open source tools. + +### Automated Identity Management and RBAC Control + +The tools preferred for user and identity management in a Mojaloop deployment are: + +1. **KeyCloak Identity Management engine** – Store and process API authentication controls as well as act as API gateway. +2. **WSO2 Identity management engine** – Store and process user role profiles and broker self onboarding of DFSP users. + +## Designing Roles within your organisaion + +A user with an account that allows access to the Hub will have roles associated with that account, which define what they can do once they are authenticated themselves and are logged in. + +Many roles apply to multiple portals, however, some roles may be specific to individual portals. + +Care should be taken when assigning multiple roles to an account, or multiple accounts to an individual natural person. This is due to the potential that arises for the circumvention of controls. Part of the purpose of RBAC is to ensure that more than one person must be in the authorization chain for important actions, thereby reducing the vulnerabilities around bad actors. + +### Mojaloop ecosystem portals + +The Mojaloop ecosystem offers a number of portals, which support varying degrees of access control and RBAC. These are split into two groups: + +- Hub portals, which are related to the operation of the Hub itself +- Payment Manager portals, which relate to the management of a specific DFSP’s connection to the Hub + +### RBAC in Mojaloop Hub + +In the Mojaloop Hub environment, RBAC is implemented through a combination of tools - Ory Oathkeeper for identity management, and Keycloak for access control (including roles and maker/checker). + +The Hub itself has the following portals: + +- **Hub Operator onboarding:**
+Currently there is no bundled Identity and Access Management (IAM) solution for Hub operators, though the function is partly filled through the use of WSO2. Development work is underway to develop a comprehensive IAM solution based around Ory and Keycloak. This will see an admin operator created alongside the deployment of the Hub, which acts as a first foundational step in this area. +- **Finance Portal:**
+It has two principal functions: the management of settlement operations, and the management of the liquidity position of individual DFSPs (and related to this, their Net Debit Cap (NDC) value). +Access to the Finance Portal is currently limited to a simple username/password access control function. +- **Participant lifecycle:**
+Controlling and configuring access to the Hub by DFSPs. +From a technical perspective, this is currently achieved through use of the Mojaloop Connection Manager (MCM). However, it is envisaged that MCM itself will be developed to present an API, which can be used to develop a UI that would be available to Hub Operators and to DFSPs. +- **Hub operations:**
+These include transaction searches, status and performance monitoring, dashboarding and overall tech ops. +Currently these are achieved through the use of Prometheus/Grafana and a range of other tools, with standard access control embedded in these tools themselves. It is envisaged that this will be migrated into the Ory/Keycloak solution, as this develops. + +Other Hub operations, such as Fraud Management and Case/Dispute Management, are add-on modules that implement their own access control to manage access to their sensitive functions. These are not addressed in this document. + +In addition to the above access control measures, it should be noted that access to all of these functions is only possible via a VPN, with individual credentials controlling access. + +As well as these portals, there are two other primary means of accessing the Hub, neither of which is subject to RBAC: + +- The first of these is transactions, which are strictly controlled according to their own multi-layered cybersecurity measures. +- And secondly, bulk payments (government-to-person - G2P), which are supported by means of an API that is subject to the same controls as other, single transactions. It is envisaged that bulk payments will be a service that is provided to DFSPs (and their customers) by means of a secure API, with the DFSP operating a bulk payment portal for use by their customers. It is possible that the operator of an instance of the Mojaloop Hub might make available a white label bulk payment portal, which interfaces with the Hub bulk payment API, for customization by any DFSP that wishes to offer the service to their customers. (Note that this is not a unique approach: a similar approach has been proposed, for example, for merchant payments, with a white label app for QR code transactions being made available for DFSPs to incorporate into their mobile wallets.) + +The access controls around either single or bulk payments are not therefore discussed further in this document. + +### Payment Manager for integration + +Payment Manager is currently one of the primary mechanisms for integrating DFSPs to a Mojaloop Hub. Whereas the Hub is singular in a scheme, there is a separate instance of Payment Manager for each DFSP. The portals offered by Payment Manager must therefore be secured by means of RBAC to limit access to authorized representatives of the DFSP. + +In the Payment Manager environment, RBAC is implemented solely through Keycloak. + +The following portals are available: + +- **User/Operator onboarding:** +Payment Manager includes Keycloak for IAM. On deployment, a single admin user is created, which can be used to create further user accounts. +- **Hub connection management:** +This includes the ability to configure the Hub connection from the Payment Manager side, and by implication to disable it. It is therefore a controlled function, with different controls for viewing versus modification. +- **Transaction investigation:** +It is possible to investigate transaction queries using the Payment Manager portal. This is potentially an issue if Personally Identifiable Information (PII) is available through the portal. + +### Foundational accounts + +At the time that a Hub is first stood up, Ory/Keycloak will be used to create a foundational user account with administrator privileges. A system administrator will be assigned this account. Note that the system administrator will not be assigned any operational roles beyond those of a system administrator. + +All functions carried out using Ory/Keycloak are subject to system-level logging for audit purposes. + +The system administrator will then use Ory/Keycloak to create further user accounts, subject to standard identity and background checks for each individual (defined under the Scheme Rules associated with a particular Mojaloop deployment) before their accounts are created. + +These new user accounts will be assigned one of these roles: + +- OPERATOR +- MANAGER + +A user account may not have both OPERATOR and MANAGER roles. + +### Further accounts + +In addition to the system administrator, the foundational accounts will have the ability to use Ory/Keycloak to add further accounts. However, for these users, this activity will be subject to maker/checker controls. A user with role OPERATOR will be able to set up a user account (with processes in place to ensure that due diligence around identity verification and background checks have taken place). However, this account will not be activated until a person with role MANAGER approves it. + +A role will be assigned to each of these accounts, as they are created. As well as the roles associated with the foundational accounts, the following roles may be assigned to new user accounts: + +- ADMINISTRATOR +- FINANCE_MANAGER + +A user account cannot have more than one of OPERATOR, MANAGER, ADMINISTRATOR or FINANCE_MANAGER, in order to ensure separation of: + +- Financial management from other Hub operations tasks +- Operator and managerial roles in maker/checker functions + +::: tip NOTE +Assigning the ADMINISTRATOR or FINANCE_MANAGER roles is subject to a higher degree of identity verification and background checks than any other roles, due to the sensitive nature of the associated functions. These additional checks are set out in the Scheme Rules. +::: + +### Finance Portal / Business Operational Framework + +Many functions (such as the viewing of DFSP positions, the status of settlement windows, and so on) of the Finance Portal are available to all logged-in users, regardless of their role. However, the following functions may only be carried out by users with specific roles: + +- Settlement processing + - Close settlement window + - Initiate settlement +- DFSP liquidity management + - Add/withdraw funds + - Change NDC + +All of these are subject to maker/checker controls, so that a user with role ADMINISTRATOR can initiate the action, but it must be approved by a user with role FINANCE_MANAGER. + +### Participant lifecycle + +This portal provides a single interface for a Hub Operator to add and maintain DFSPs on the Hub ecosystems. + +There are some standardised functions that are subject to RBAC: + +- Create DFSP +- Create DFSP Accounts +- Suspend DFSP + +Each of these is subject to maker/checker controls, so that a user with role OPERATOR can set up the changes, and they must be approved by a user with role MANAGER. + +In addition, there is a significant workload in technical onboarding a DFSP, in particular around the establishment of the technical operating environment (certificates and so on). This is not subject to RBAC. This is not considered a significant risk, since there is no value without being able to create a DFSP and the associated accounts on the Hub itself - activities that are subject to RBAC. + +### Hub operations + +Access to the reporting functions of Prometheus/Grafana is not subject to RBAC controls - any signed-in/authenticated user, with any RBAC role assigned, may view the reports and dashboards. + +Creating a new report/dashboard is a restricted function, and is only available to users with the MANAGER role. + +As noted earlier, the operations and reporting portals will be migrated into the Ory/Keycloak environment in order to facilitate these controls. + +### Payment Manager + +The Payment Manager operator functionality is subject to RBAC controls, but maker/checker is not required. + +#### User/Operator onboarding + +On deployment of Payment Manager, a single admin user account is created using Keycloak. Note that the admin user will not be assigned any operational roles beyond those of a system administrator. + +All functions carried out using Keycloak are subject to system-level logging for audit purposes. + +The admin user will use Keycloak to create further user accounts, subject to standard identity and background checks for each individual (defined under the Scheme Rules associated with a particular Mojaloop deployment) before their accounts are created. + +These new user accounts will be assigned one of the following roles: + +- OPERATOR +- MANAGER + +A user account may not have both OPERATOR and MANAGER roles. + +### Dashboards + +The Payment Manager dashboards are available to any logged-in/authenticated user with role OPERATOR or MANAGER. + +### Hub connection management + +Viewing the settings for the Payment Manager/Hub connection is available to any logged-in/authenticated user with role OPERATOR or MANAGER. However, modifying the settings is a controlled function. Only a user with role MANAGER may modify the settings. + +### Transaction investigation + +Carrying out transaction investigations using the facilities of the Payment Manager portal is a controlled activity, due to the potential for revealing PII data. It is therefore only available to logged-in/authenticated users with role MANAGER. + +## Monitoring +Monitoring is the fourth pillar of mitigating the RBAC risk. Designing and configurating this is very dependent on the maturity of the Scheme, the scheme rules, the use cases being used, and the participants classes. +As a starting point for designing your monitoring, consider these categories: +1. External Security threat monitoring +1. Internal Security treat monitoring e.g. Auditing +1. Scheme rule enforcement monitoring + diff --git a/docs/adoption/HubOperations/Settlement/ledgers-in-the-hub.md b/docs/adoption/HubOperations/Settlement/ledgers-in-the-hub.md new file mode 100644 index 000000000..2e574a4c4 --- /dev/null +++ b/docs/adoption/HubOperations/Settlement/ledgers-in-the-hub.md @@ -0,0 +1,367 @@ +# Ledgers in the Hub + +## Managing risk + +Elements of the settlement process sit outside the control of the Hub, so it is important that there are a number of controls in place to prevent funds disappearing and to ensure there is always liquidity to support operation of the Hub. Other than the [Net Debit Cap](settlement-basic-concepts.md#liquidity-management-net-debit-cap), the Hub employs a number of internal ledgers to manage risk and ensure liquidity. These ledgers are as follows: + + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LedgerDefinitionType of transfer recorded in ledger

DFSP Position Ledger

Tracks how much a DFSP owes or is owed. Every time a transfer is processed, the Position in the Hub is adjusted in real time.

P2P transfer: A person-to-person transaction between DFSP end users.
+
+Settlement transfer: The flow of funds between DFSPs aimed at reconciling the ledgers and updating Positions for a given settlement window.

DFSP Settlement Ledger

The DFSP’s liquidity account held at the settlement bank mirrored in the Hub. Acts as a reconciliation account and mirrors the movement of real funds.

Funds transfer (in and out): The movement of funds initiated by the DFSP or the confirmation by the settlement bank that settlement has completed.

Hub Multilateral Net Settlement (HMLNS) Ledger

Used to capture the balancing journal entry for the net settlement amongst DFSPs. After a settlement window has been closed and settled amongst all the DFSPs, its balance will return to zero.

Settlement transfer: The flow of funds between DFSPs aimed at reconciling the ledgers and updating Positions for a given settlement window.

Hub Reconciliation Ledger

Ensures that movements in and out of the liquidity accounts and recorded in the Settlement Ledgers are balanced. The balance is the amount that the Hub Operator is administering in all the participant DFSPs' Settlement Ledgers.
+
+Acts as a control account, and tracks the movement of funds across all DFSP Settlement Ledgers (which mirror the movement of real funds).

Funds transfer (in and out): The movement of funds initiated by the DFSP or the confirmation by the settlement bank that settlement has completed.

+ +## Understanding accounting principles + +In accounting, a positive net position (more debits) is treated as an asset, while a negative net position (more credits) is treated as a liability. The Mojaloop Hub applies these same principles but from the Hub's perspective. What does that mean? + +A transfer is recorded by the Hub as a debit (DR) on the Payer DFSP side because the transfer reduces the amount that is owed back to that DFSP (reduced liability from the Hub's perspective). So while the Payer DFSP itself will treat the transfer as an increase in their liability in their own system, the Hub treats the transfer as an increase in their asset. + +The same transfer is recorded by the Hub as a credit (CR) on the Payee DFSP side because the transfer increases the amount owed to that DFSP (increased liability from the Hub's perspective). + +Recording a transaction in two accounts as opposing debit and credit entries (of equal amounts) is what we call "double entry" in accounting. + +Applying the above accounting principles to a deposit by a DFSP in the DFSP's liquidity account, the amount creates a liability from the Hub's perspective (the money needs to be paid back). The amount that is entered in the Hub is therefore negative. This way at any point, the amount the Hub owes to any DFSP can be quickly calculated by adding the DFSP's Position to their liquidity account balance. The double entry for the DFSP Settlement Ledger is added to the Hub Reconciliation Ledger. + +## Settlement: an example + +This section demonstrates how a transaction is logged in the various ledgers, using a simple example. + +Let’s take the following example: DFSP1 sends 50 USD to DFSP2. Here is how this example transaction is recorded in the Hub ledgers. + +### Step 1a: Reserving the transfer amount for the sender in the Position Ledger + +The DFSP Position Ledger is used for keeping track of changes in the Position of a DFSP. Once a settlement window is closed and the settlement process is started, the transfer amount is reserved in the Hub’s Position Ledgers maintained for the DFSPs as well as in the Hub Multilateral Net Settlement Ledger. Reserving the transfer amount for the Payer DFSP (DFSP1) guarantees that the funds cannot be used for another transfer. + + ++++++ + + + + + + + + + + + + + + + + + + + + +
DFSP1 Position LedgerHub Multilateral Net Settlement Ledger

DR

CR

DR

CR

50 USD

50 USD

+ +### Step 1b: Reserving the transfer amount for the recipient in the Position Ledger + +Similarly, the Position of the Payee DFSP is also tracked through the DFSP's Position Ledger. + + ++++++ + + + + + + + + + + + + + + + + + + + + +
DFSP2 Position LedgerHub Multilateral Net Settlement Ledger

DR

CR

DR

CR

50 USD

50 USD

+ +### Step 2a: Committing the transfer amount for the sender in the Position Ledger + +Following the reservation of the transfer amount, the next step is to commit the amount in the same ledgers as before. + + ++++++ + + + + + + + + + + + + + + + + + + + + +
DFSP1 Position LedgerHub Multilateral Net Settlement Ledger

DR

CR

DR

CR

50 USD

50 USD

+ +### Step 2b: Committing the transfer amount for the recipient in the Position Ledger + +Committing the transfer amount for the Payee DFSP (DFSP2) allows the DFSP to send funds to other DFSPs if desired. + + ++++++ + + + + + + + + + + + + + + + + + + + + +
DFSP2 Position LedgerHub Multilateral Net Settlement Ledger

DR

CR

DR

CR

50 USD

50 USD

+ +### Step 3: Reserving the transfer amount for the sender in the Settlement Ledger + +Once Positions are in a controlled state and corresponding debit and credit entries have been recorded in the Hub Multilateral Net Settlement Ledger, the transaction must be recorded and reserved in the DFSP Settlement Ledgers and the Hub Reconciliation Ledger as well to ensure that funds are not released inadvertently for another Funds-Out operation. + + ++++++ + + + + + + + + + + + + + + + + + + + + +
DFSP1 Settlement LedgerHub Reconciliation Ledger

DR

CR

DR

CR

50 USD

50 USD

+ +### Step 4a: Committing the transfer amount for the recipient in the Settlement Ledger + +Once real money has moved on DFSPs' liquidity accounts, transfer amounts can be committed in the DFSP Settlement Ledgers and the Hub Reconciliation Ledger. Money movement is recorded for the Payee DFSP first. + + ++++++ + + + + + + + + + + + + + + + + + + + + +
DFSP2 Settlement LedgerHub Reconciliation Ledger

DR

CR

DR

CR

50 USD

50 USD

+ +### Step 4b: Committing the transfer amount for the sender in the Settlement Ledger + +Finally, the transfer amount is committed on the sender side too. + + ++++++ + + + + + + + + + + + + + + + + + + + + +
DFSP1 Settlement LedgerHub Reconciliation Ledger

DR

CR

DR

CR

50 USD

50 USD

+ +## Adding/withdrawing funds: an example + +### Adding funds + +As the funds of the liquidity accounts will fluctuate, the DFSPs will either add funds to fund their net sends, or look to make withdrawals. Deposits can happen whenever desired, but the Hub Reconciliation Ledger does need to be updated regularly, to avoid reconciliation issues. Whenever a change is made to the external account (that is, the DFSP's liquidity account), the Net Debit Cap must also be assessed. + +In the following example, DFSP1 adds 100,000 USD to their liquidity account. This is how the deposit amount is recorded in the Hub's ledgers. + + ++++++ + + + + + + + + + + + + + + + + + + + + +
DFSP1 Settlement LedgerHub Reconciliation Ledger

DR

CR

DR

CR

100,000 USD

100,000 USD

+ +### Withdrawing funds + +As a withdrawal could lead to an impact on the Net Debit Cap and the ability to transact, the NDC must be re-calculated in light of the DFSP's new balance (the balance must never be lower than the NDC). + +In the following example, DFSP2 withdraws 100,000 USD from their liquidity account. This is how the withdrawal amount is recorded in the Hub's ledgers. + + ++++++ + + + + + + + + + + + + + + + + + + + + +
DFSP2 Settlement LedgerHub Reconciliation Ledger

DR

CR

DR

CR

100,000 USD

100,000 USD

\ No newline at end of file diff --git a/docs/adoption/HubOperations/Settlement/settlement-basic-concepts.md b/docs/adoption/HubOperations/Settlement/settlement-basic-concepts.md new file mode 100644 index 000000000..5f28f7fe3 --- /dev/null +++ b/docs/adoption/HubOperations/Settlement/settlement-basic-concepts.md @@ -0,0 +1,129 @@ +# Basic concepts + +This section collects key concepts and elements of the settlement management process. + +## Liquidity cover + +As described in the [Introduction](settlement-management-introduction.md), one of the characteristics of a real-time payments system is that creditor DFSPs are required to disburse funds to their customers before they are reimbursed by the debtor DFSP. To mitigate the risk that a creditor DFSP will not receive the funds that it is due, Mojaloop requires that debtor DFSPs should provide credible evidence that they have sufficient good funds to meet the obligations they incur as a consequence of transacting in the system. + +This credible evidence is called *liquidity cover*. The Mojaloop system does not stipulate what forms it should take; and, for any given DFSP, it may take multiple forms. It might be: + +- funds deposited in an account over which the Mojaloop Hub has some control +- a line of credit from another financial institution +- collateral of some other kind + +However, any liquidity cover used in a Mojaloop scheme must have the following characteristics: + +- It must be capable of being converted into settlement payments *immediately* on demand from the Mojaloop scheme. +- It must be attested to by reliable evidence in the Mojaloop scheme's possession. +- It must not be convertible by the DFSP into other forms (for example, by withdrawing funds from a bank account, or drawing down funds from a line of credit) without the prior knowledge and approval of the Mojaloop scheme. + +The liquidity cover attributed to a given DFSP is liquidity cover for a given settlement model and currency, and is attributable to the scheme as a whole. That is to say that Mojaloop does not allow participants to maintain liquidity cover that is applicable only to their transfers with a specific DFSP or DFSPs. + +When a DFSP asks the Mojaloop Hub to make a transfer, the Mojaloop Hub checks that the debtor DFSP has sufficient liquidity cover to guarantee that the transfer can be settled if it completes successfully. It does this by comparing the DFSP's total good funds against the sum of the following items: + +1. The sum of transfers which have been completed but not yet settled, and to which the DFSP is *either* the creditor *or* the debtor party. +1. The sum of transfers which have been started but which have not yet completed, and to which the DFSP is the debtor party. +1. The amount of the proposed transfer. + +If the total of these three items is greater than the amount of good funds available to the debtor DFSP, then the transfer will be rejected by the Mojaloop Hub. Note that, in this arrangement, a DFSP's liquidity is credited with the effect of transfers where it is the beneficiary as soon as the transfer is completed, without needing to wait for the funds to be settled. Mojaloop does this to keep to a minimum the amount of liquidity that participants are required to maintain. + +## Settlement model + +Different schemes will want to settle funds between their participants in different ways. These will depend on who is operating the scheme, how much traffic there is through the scheme, and many other variables. + +Mojaloop is designed to support the industry standard ways of settling between participants. These are as follows: + +- Multilateral deferred net settlement +- Bilateral deferred net settlement +- Immediate gross settlement + +The meaning of the component terms of these settlement types is as follows. + +Settlements are *deferred net* if a number of transfers are settled together. Net settements (in which a number of transfers are settled together) are by definition deferred (since it takes time to construct a batch.) + +Settlements are *gross* if each transfer is settled separately. Gross settlements may be immediate or deferred. They are *deferred* if approval for settlement from outside the Hub is required, and *immediate* if the Hub can proceed to settlement of a transfer without requiring any external approval. At present, Mojaloop only supports immediate gross settlements. + +Settlements are *bilateral* if each pair of participants settles with each other for the net of all transfers between them. Settlements are *multilateral* if each participant settles with the Hub for the net of all transfers to which it has been a party, no matter who the other party was. + +A settlement model specifies a way in which a Mojaloop Hub will settle a set of transfers. In the simple case, there is only one settlement model and it settles all the transfers that are processed by the Hub. However, Mojaloop supports more than one settlement model for a single scheme. This allows, for instance, a scheme to define different settlement models for different currencies, or for different ledger account types. + +If a scheme defines more than one settlement model, it is the responsibility of the scheme to ensure that a given transfer can only belong to a single settlement model. For example, suppose that a scheme defines a settlement model for all transfers that require currency conversion (defined as: all transfers where the source currency and the target currency are different from each other), and also a settlement model for all transfers where the source currency is Kenyan shillings (KES). In this case, a transfer which converted from Kenyan shillings to South African rand could potentially belong to both models. + +## Settlement window + +Every transfer that is completed in the Hub is assigned to the currently open settlement window. The settlement window is a way of grouping transfers together. Assigning transfers to a settlement window happens independently of the settlement models that are used to settle the transfers. This means that if a scheme has defined more than one settlement model, transfers that belong to the different settlement models will share a settlement window. + +There is no deterministic way of assigning transfers to a particular settlement window. When a scheme administrator creates a new settlement window, there is no way to tell in advance which transfers will be assigned to the new settlement window and which transfers will be assigned to the old settlement window. + +A settlement window can have the following states: + +* `OPEN`: The settlement window is open, transfers are being accepted into the current open window. +* `CLOSED`: The settlement window is closed. It is not accepting any additional transfers and all new transfers are being allocated to a new, open settlement window. +* `PENDING_SETTLEMENT`: The settlement window is closed, the [Multilateral Net Settlement Positions](#multilateral-net-settlement-position) have been calcluated for each DFSP but settlement with the partner settlement bank has not happened yet. +* `SETTLED`: The settlement bank has confirmed that all the participant DFSPs that engaged in transfers in the settlement window have settled their payments, and the Hub Operator has settled the window. + +Closing a settlement window automatically opens the next one. + +### Settlements and settlement windows + +A Hub Administrator may request settlements for a given settlement model and for one or more settlement windows. + +If a scheme only has a single settlement model, then settling transfers for that model in a given settlement window will settle all the transfers in that window. If, on the other hand, a scheme has defined more than one settlement model, then settling transfers belonging to a particular settlement model for a given settlement window will mean that some of the transfers in that window have been settled, while others have not. + +It is particularly important to understand the implications of this where an Immediate Gross settlement model has been defined. In this case, individual transfers will be settled as soon as they have been completed. If the scheme only has an Immediate Gross settlement model, then all transfers will be settled as they are completed, and the settlement window will become irrelevant. If, on the other hand, the scheme mixes Gross and Net settlement models, or if the scheme has defined more than one Net settlement model, then it is possible for a given settlement window to contain some transfers which have been settled and some which have not been settled; and, in the case of transfers which are settled by a Gross settlement model, for transfers which have been settled to appear even in a currently open settlement window. This creates potential complications in defining the overall status of a settlement window. + +Mojaloop deals with this situation by always assigning the settlement window a state which is the minimum state of the transfers within it. *Minimum state* is defined by the sequence of settlement window states given above. So, for instance, if a settlement window contains transfers which have already been settled (because they are settled Gross) and other transfers whose settlement process has not yet started, then the settlement window's state will be `OPEN`. If a settlement window has been closed, and it contains transfers which belong to two different settlement models, one of which is being settled (and whose state is therefore `PENDING_SETTLEMENT`) and the other is not (and whose state is therefore `CLOSED`,) the overall state of the settlement window will be `CLOSED`. + +## Liquidity management (Net Debit Cap) + +As described above, Mojaloop requires participants to pre-fund transfers where they are the debit party by providing credible evidence to the Mojaloop Hub that they can meet all their current settlement demands. There may, however, be circumstances in which a participant does not want all of its liquidity cover to be used as cover for transfers. For instance, a participant might be a recipient in a remittance channel and therefore an overall net creditor; or a participant might deposit extra funds to cover periods when their accounts are not open to receive funds. + +To cover these possibilities, Mojaloop allows either participants or Hub Administrators to reserve part of their available liquidity cover, so that only part of it can be used to provide liqidity cover for transfers. This is called the Net Debit Cap (NDC). The NDC acts as a limit or a cap placed on a DFSP's funds available for transacting, and it can never exceed the balance of the liquidity account. This is required to ensure that a DFSP's liabilities can be met with funds immediately available to the settlement bank. + +When calculating whether or not a transfer is covered by available liquidity, the Hub will take into account any restriction on the amount of available funds specified by the Net Debit Cap. + +## Position + +The Position of a DFSP reflects the total unsettled obligations of a DFSP for a given settlement model at a given point in time: that is to say, the amount of funds that a DFSP will eventually be required to settle with the scheme. A DFSP's Position for a given settlement model is the net of the following elements: + +1. All completed but unsettled transfers that belong to the settlement model and where the DFSP is the debtor party. +2. All completed but unsettled transfers that belong to the settlement model and where the DFSP is the creditor party. +3. All transfers that have been requested but have not yet completed which belong to the settlement model and where the DFSP is the debtor party. + +For the Payer DFSP, this sum total includes transfer amounts that are pending and have not yet been completed. Note that if an abort or timeout happens, the affected transfers will not complete and the reservation for that transfer will be removed. + +The Position is the total position across all settlement windows that have not yet been settled. The amount of a participant's position only changes when some of the transfers which make up its position are settled. + +## Net Settlement Positions + +As described above, a deferred net settlement can be either multilateral or bilateral. When a Hub Administrator requests a settlement, the Hub will calculate how much each participant owes, or is owed, as a consequence of the transactions that are to be settled. The transactions to be settled are defined as all transactions which: + +- Belong to the settlement window(s) that are to be settled. +- Belong to the settlement model that is being settled. + +If the settlement is *multilateral*, then a DFSP will receive only one figure as the amount it owes, or is owed, as a consequence of the settlement. This figure is the net of all the transactions to be settled. + +If the settlement is *bilateral*, then a DFSP may receive multiple figures as the amount it owes, or is owed, as a consequence of the settlement. Each figure represents the net of the DFSP's transactions with a particular DFSP. The net of all these values will be equal to the overall figure which it would owe, or be owed, in a multilateral net settlement. + +## Settlement reports + +To facilitate DFSP reconciliation and settlement at the settlement bank, the Hub provides various settlement reports. A Scheme can choose to have several different reports for different purposes. Below are some examples: + +* DFSP Settlement Report: A report issued to a DFSP when settlement has been initiated. It provides the DFSP's bilateral settlement position with each DFSP they transacted with (either as a Payer DFSP or Payee DFSP) in the settlement window(s) being settled. It also provides the Multilateral Net Settlement Position of the DFSP (the sum total of the transfer amounts sent and received by the DFSP in the settlement window(s)). +* Settlement Bank Report: A report issued to the settlement bank when settlement has been initiated. It provides the bilateral settlement position of each DFSP against every other DFSP that transacted in the settlement window(s) being settled. It also provides the Multilateral Net Settlement Position of each DFSP (the sum total of the transfer amounts sent and received by the DFSP). +* DFSP Settlement Result Report: A report issued to a DFSP when settlement has been finalised. It provides details about the balance of the DFSP's liquidity account, and the money movements arising from the closure of the settlement window. + +## Finance Portal + +The [Finance Portal](busops-portal-introduction.md) (commonly referred to as "Finance Portal v2") is a web portal used by the Hub Operator to manage settlement-related processes on a daily basis. The portal provides functionality to: + +* monitor details such as the balance, [Position](#position), [Net Debit Cap](#liquidity-management-net-debit-cap) of DFSPs +* update a DFSP's [Net Debit Cap](#liquidity-management-net-debit-cap) +* manage settlement windows + +* record deposits to or withdrawals from DFSPs' liquidity accounts + +::: tip NOTE +The Finance Portal currently only supports settlement processes that rely on the Deferred Net Settlement model. +::: \ No newline at end of file diff --git a/docs/adoption/HubOperations/Settlement/settlement-management-introduction.md b/docs/adoption/HubOperations/Settlement/settlement-management-introduction.md new file mode 100644 index 000000000..b3b724d23 --- /dev/null +++ b/docs/adoption/HubOperations/Settlement/settlement-management-introduction.md @@ -0,0 +1,7 @@ +# Introduction – Settlement Management Guide + +When a payment is made in a real-time payments system like Mojaloop, the DFSP who is the custodian of the beneficiary's account (the creditor DFSP) agrees to credit the beneficiary with the funds immediately. But the creditor DFSP has not yet received the funds from the DFSP who is the custodian of the debtor's account: all that has happened so far is that the debtor DFSP has incurred an obligation to reimburse the creditor DFSP, and that obligation has been recorded in the Mojaloop Hub. + +The process of settlement is the process by which a debtor DFSP reimburses a creditor DFSP for the obligations that the debtor DFSP has incurred as a consequence of transfers. + +This guide describes how settlements are managed by the Mojaloop Hub and the partner settlement bank(s), and introduces the main building blocks of settlement processing. \ No newline at end of file diff --git a/docs/adoption/HubOperations/TechOps/change-management.md b/docs/adoption/HubOperations/TechOps/change-management.md new file mode 100644 index 000000000..205adaee8 --- /dev/null +++ b/docs/adoption/HubOperations/TechOps/change-management.md @@ -0,0 +1,388 @@ +# Change management + +The purpose of the change management process is to control the lifecycle of all changes, enabling changes to be made with minimum disruption to IT services. + +::: tip NOTE +The processes described in this section represent best practices and act as recommendations for organizations fulfilling a Hub Operator role. +::: + +## Objectives + +The objectives of change management are to: + +* Respond to changing business requirements while maximizing value and reducing incidents and re-work +* Respond to Requests for Change (RFCs) that will align services with business needs +* Ensure that changes are recorded and evaluated, and that authorized changes are managed in a controlled manner +* Optimize overall business risk + +## Scope + +The scope of change management should include changes to all architectures, processes, tools, metrics and documentation, as well as changes to all configuration items (CIs) across the whole service lifecycle. + +All changes must be recorded and managed in a controlled environment across all CIs. These can be physical assets such as servers or networks, virtual assets such as virtual servers or storage, or other types of assets such as agreements or contracts. + +Change management is not responsible for coordinating all of the service management processes to ensure the smooth implementation of projects. + +## Roles and responsibilities + +The roles listed below indicate some of the crucial stakeholders needed to make the change management process effective. + +### Change Manager + +The Change Manager acts as the lead, responsible for the overall change management process. + +The primary responsibilities of the Change Manager are: + +* Driving the efficiency and effectiveness of the change management process +* Producing management information +* Monitoring the effectiveness of change management and making recommendations for improvement +* Adherence to the change management process +* Planning and managing support for change management tools and processes +* Verifying that RFCs are correctly completed and allocated to change authorities (if applicable) +* Communicating decisions of change authorities to affected parties +* Monitoring and reviewing activities +* Publishing the change schedule and projected service outage +* Conducting post-implementation reviews to validate the results of change requests +* Determining business satisfaction with change requests + +### Change Coordinator + +Change Coordinators are Support staff members who handle the details of a change request. + +The responsibilities of a Change Coordinator include: + +* Gathering appropriate information based on the type of change being investigated +* Associating related configuration items, incidents, and services to the change request +* Providing status updates to requesters +* Reviewing change plans and schedules. Planning activities include scheduling the change request, assessing risk and impact, creating plans, defining and sequencing the tasks needed to accomplish the change request, and scheduling people and resources for each task. +* Reviewing all completed tasks. In the [Implement](#step-4-implement) stage, at least one task related to the change request is in progress. +* Conducting post-implementation reviews to validate the results of the change request +* Determining requester satisfaction with the change request + +### Change Initiator + +A Change Initiator is a person who initiates or requests a change, from a business or a technical role. Various people can initiate a change, this role is not exclusive to a single person. The change initiator/requester is required to provide all necessary information and justification for the change. + +Other responsibilities of a Change Initiator include: + +* Completing and submitting a change proposal (if required) +* Completing and submitting a Request for Change (RFC) +* Attending Change Advisory Board (CAB) meetings to provide further information +* Reviewing changes when requested by Change Management + +### Change Implementer + +This is the individual deemed as the owner of the change request throughout the request lifecycle. Implementing a change requires maker/checker approval, that is, all changes require one person to perform the change and another to validate the change. + +Responsibilities of a Change Implementer include: + +* Liaising with the change requester for business and technical queries and issues, if any +* Creating an RFC and updating its status whenever required +* Checking and deciding an implementation date, ensuring that it does not conflict with other activities, for example, lead times, change windows, and so on +* Assessing and managing the risk involved during the change request lifecycle +* Testing and implementing the change +* Coordinating and communicating with any other impacted team prior to submitting the change (in the absence of the Change Coodinator) +* Once the change is approved, creating a remedial case for the scheduled change +* Executing the change as on the scheduled date and time +* Providing closure status after successful completion +* Documenting the change procedure after its implementation + +### Change Approver + +This is an individual who provides first-level approval to a Request for Change before it goes to Change Advisory Board review. Change Approvers are scoped for different Hub changes, meaning that this role may be occupied by different individuals at various hierarchal levels of the change management framework, each with their own area where they act as an approver. + +Responsibilities of a Change Approver include: + +* Reviewing all RFCs submitted by the change initiators/requesters +* Ensuring that the change request has reached the necessary standard of readiness to warrant a decision by the Change Manager and the CAB +* Reviewing and commenting on the content within the Change Record, namely: Change Plan, Implementation, Test and Remediation Plan, and Schedule +* Granting approval once satisfied that all relevant criteria have been met and concerns addressed OR rejecting approval by giving clear concerns and reservations about the content of the Change Record +* The outcome of failed changes where negative outcome is a result of an undetermined approval + +### Technical SME + +The Technical Subject Matter Expert (SME) is an individual who is an authority in a particular technical area or topic. In relation to change manangement, the SME is responsible for: + +* Providing the detailed Implementation, Testing and Remediation Plans +* Attendance at CAB meeting to answer questions and concerns about the change to approvers and Change Management (if invited) +* The implementation of change tasks and updating the relevant records in the change management tool with respect to implementation status +* Reviewing and re-working a change as requested, and contributing to the review of a change post-implementation + +### CAB Member + +The Change Advisory Board (CAB) involves members from different domains, including information security, operations, development, networking, Service Desk, and business relations, among others. A member of the CAB has the following responsibilities: + +* Circulating RFCs within their area of responsibility and coordinating feedback +* Reviewing RFCs and recommending whether they should be authorized +* Reviewing successful, failed, and unauthorized changes +* Reviewing the change schedule and projected service outage + +### CAB Chair + +The CAB Chair is responsible for: + +* Convening and chairing CAB meetings +* Overseeing the overall change management process +* Ensuring that the CAB fulfils the charter on policies and procedures related to changes + +## Change types + +The change management process handles the following change types. + +### Standard changes + +A standard change is a change to a service or other configuration item that has been pre-authorized and so does not need to go through the approval process. In order to be considered a candidate for becoming a standard change, at least three successful minor changes must have been implemented. A request for a standard change must then be submitted to the Change Advisory Board for approval. + +The risk for a standard change must be low and well-understood, the tasks must be well-known, documented and proven, and there must be a defined trigger to initiate it, such as an event or service request. + +Examples of standard changes include: operating system (OS) upgrade, patch deployment, and so on. + +### Minor changes + +A minor change is a non-trivial change that has low impact and low risk. These are non-trivial changes that do not occur frequently but they still undergo every stage of the change lifecycle, including CAB approval. It is important to document relevant information for future reference. Over time, a minor change can be converted into a standard change. + +Examples of minor changes include: website changes, performance improvements. + +For a change to be classified as a minor change, it must have a lead time of less than 3 days. + +### Major changes + +A major change is a high-risk and high-impact change that could interrupt production live environments if not planned properly. Change evaluation is crucial to determine the schedule and approval workflow. A major change requires management approval along with CAB approval. The Request for Change (RFC) of a major change must contain a detailed proposal on cost-benefit, risk-impact analysis and financial implications, if any. + +Effectively, all changes that imply downtime, specifically downtime that affects DFSP onboarding and testing activities on lower environments should be classified as major changes and should be reviewed by the CAB. These changes should be implemented in coordination with the Technical Project Manager. + +For a change to be classified as a major change, it must have a lead time of 5 days or more. + +### Emergency changes + +An emergency change is a change that must be completed as soon as possible. An emergency change will only be accepted if it is linked to a Severity 1 Incident, which has a corresponding S1 ticket in the Service Desk tool. The Service Manager will instigate the opening of an emergency change and will instruct the Technical SME to raise it. + +### Summary of lead times and approval matrix + + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Change typeLead time to implementReview and approval

Standard change

3 working days

Pre-approved

Minor change

3 working days

    +
  1. CAB

  2. +
  3. Business Approvers (where applicable)

  4. +

Major change

5 working days

    +
  1. CAB

  2. +
  3. Business Approvers (where applicable)

  4. +

Emergency change

ASAP

Emergency CAB or Business Owner

+ +## Change Advisory Board + +The Change Advisory Board (CAB) supports change management in assessing, prioritizing, and scheduling changes. The CAB must have full visibility of all changes that could have moderate or higher risk to services and configuration items. It is important that within the CAB, there are members who can provide expertise that is adequate to assess all changes from both a business and a technical point of view. + +There are permanent CAB members who are invited to all meetings but to ensure that there is a clear understanding across all stakeholder needs, other people will be asked to participate due to their expertise for a change that is to be discussed. If applicable, the external supplier may also be invited. + +### CAB meeting + +The CAB meeting can be held face-to-face or electronically. It may be more convenient to hold electronic meetings, however it may be more difficult to deal with questions this way. This will be the responsibility of the CAB Chair to decide depending on the situation. It is expected that CAB meetings will be electronic due to the limitations of timescales. + +A CAB meeting is a formal meeting with a designated structure. Prior to any CAB meeting, the changes to be discussed must be circulated to all members. The CAB Chair is responsible for ensuring this is completed but may delegate the task to the CAB Co-Chair or any CAB Member. + +All change representatives must attend or send a delegate. If there is no attendance, then the change will not be discussed and therefore not approved. All CAB attendees must come to the meeting prepared to discuss the changes they represent and to express views and opinions based on their particular area they represent. + +The CAB meeting is the forum to discuss previous changes both successful and failed, and review lessons learned. + +An agenda for the CAB meeting must be circulated prior to the meeting. The CAB Chair is responsible for ensuring that the structure is followed, minutes are taken, and action items are gathered to be distributed after the meeting. + +## Change management process + +This section provides a summary of the key activities of the change management process. Specific instructions on how to perform process activities within the context of a Service or Function may be provided by local operating procedures within a procedure manual. + +All changes must be raised in the Service Desk tool. + +The following figure provides a high-level summary of the change management process with the key activities: + +![High-level summary of change management process activities](../../../.vuepress/public/change_mgmt_flow.png) + +### Step 1: Raise Request for Change (RFC) + +#### Objective + +The objective of this activity is to ensure that the types of change requests are adhered to so that the process can respond to and manage the environment while protecting the business. + +The following figure provides a summary of the fist step of the change management process. + +![Change management process – Initiating a change by raising an RFC](../../../.vuepress/public/raise_rfc.png) + +#### Prerequisites + +Prerequisites for changes should be in line with the requirements for releases as described in the [release management process](release-management.md). The following should be clearly captured in the Service Desk tool while preparing the Change Record: + +* Handover from relevant team to Operations team, including full review of the following: + * Change Ticket or Change Record: Reason for the change including impact, risks, limitations. The categorization matrix for the change can be the same as for incidents. For details on the incident categorization matrix, see [Incident categorization matrix](incident-management.md#incident-categorization-matrix). + * Change runbook: Steps required to make the change and roll back the change if needed + * Test results from lower environment: Evidence that the change was tested successfully and causes no regression + * Test plan for higher environment: What specific tests need to be run to validate the change + * All related documentation including architecture, flowcharts, setup/configuration information, and so on have been updated +* Pre-change testing: Verify environment stability by reviewing the last Golden Path (GP) test results +* Post-change testing: Execution of the agreed tests to validate the change, and execution of the full GP tests to confirm no regression on the environment + +#### Inputs + +Inputs to the RFC are: + +* Service Requests +* Requests from [Incident Management](incident-management.md) to apply workarounds/fixes +* Requests from [Incident Management](incident-management.md) to make emergency changes to resolve Severity 1 incidents +* New functionality requests from Project Management Office +* Maintenance requests for change + +#### Outputs + +Change Records containing details of RFCs for review. + +### Step 2: Review and authorize + +#### Objective + +Changes are reviewed, and a technical approval stage determines if the required mandatory minimum information is captured to allow for an effective planning and scheduling phase. + +The following figure provides a summary of the "review and authorize" step of the change management process. + +![Change management process – Review and authorise](../../../.vuepress/public/review_authorize.png) + +#### Inputs + +Change Record for review. + +#### Outputs + +Change Record with technical approval. + +### Step 3: Plan and approve + +#### Objective + +Qualified Change Records that have passed an initial assessment in the previous process steps are planned and approved. The risk level of the change will direct the approval path. + +The following figure provides a summary of the "plan and approve" step of the change management process. + +![Change management process – Plan and approve](../../../.vuepress/public/plan_approve.png) + +#### Inputs + +Initially authorized Change Record. + +#### Outputs + +Fully planned and approved Change Record. + +### Step 4: Implement + +#### Objective + +The relevant Technical SMEs carry out the planned activities, recording any deviations, and undertaking remedial activities where applicable in accordance with the change plans to implement the requested changes. + +The following figure provides a summary of the "implement" step of the change mangement process. + +![Change management process – Implement](../../../.vuepress/public/implement.png) + +#### Inputs + +Approved Change Record. + +#### Outputs + +Implemented change, failed change, backed out change, remediated failed change. + +### Step 5: Close + +The final activity of the process ensures that changes that are subject to a post-implementation review receive the necessary attention and that remedial activities are understood and executed. + +The following figure provides a summary of the "close" step of the change mangement process. + +![Change management process – Close](../../../.vuepress/public/close.png) + +#### Inputs + +Successful changes, failed changes, failed changes with remediation. + +#### Outputs + +Closed changes. + +## Governance + +**Meeting name:** Change Advisory Board meeting + +**Meeting frequency:** Weekly + +**Meeting purpose:** + +* Review and approve/reject proposed changes in a business and technical context +* Prioritize proposed changes according to business needs +* Perform post-implementation review of completed changes and determine/document lessons learned +* Review previously approved changes but not implemented in the previous change window and recommend follow-up action + +**Meeting chair (process role):** CAB Chair + +**Recommended attendees (process roles):** + +* Standing CAB Members +* Business representatives +* Change Initiator/Implementer + +**Inputs:** + +* Change Schedule +* Change Record + +**Outputs:** + +* Approval/rejection +* Updated Change Records +* Action items + +### Governance for change communication + +The following guidelines apply to change communication: + +* Standard changes will be communicated to the internal stakeholders. +* Major, minor, and emergency changes shall be communicated to all the relevant business and technical stakeholders. +* Changes will be communicated after CAB approvals. +* At the start of the approved change window, an email update and a Slack notification (or similar) should be sent to the relevant stakeholders. +* At the end of the approved change window, an email update and a Slack notification (or similar) should be sent to the relevant stakeholders. +* External communication to customers (DFSPs) and partners of the Hub will be performed by the Service Manager. + +The notification must include the following details: + +* Title and description of change +* Impact to business +* Change window +* Contacts/Change Coordinator \ No newline at end of file diff --git a/docs/adoption/HubOperations/TechOps/defect-triage.md b/docs/adoption/HubOperations/TechOps/defect-triage.md new file mode 100644 index 000000000..4ee0332a0 --- /dev/null +++ b/docs/adoption/HubOperations/TechOps/defect-triage.md @@ -0,0 +1,93 @@ +# Defect triage + +The purpose of the defect triage process is to ensure that all the bugs identified in the Hub Operator's Production environment are captured, evaluated, and submitted to a Mojaloop Support team, a team dedicated to running Support services for the technical operations of a Mojaloop Hub. This team can be insourced or outsourced (or even part insourced and part outsourced), depending on the level of expertise or capacity within the scheme's hosting organization. If it is decided to outsource this function, there are organizations within the Mojaloop community that do provide different levels of support as a service. (For more information and referrals, contact the Mojaloop Foundation.) + +::: tip NOTE +The processes described in this section represent best practices and act as recommendations for organizations fulfilling a Hub Operator role. +::: + +::: tip NOTE +The process proposed here applies to bugs identified in the Hub Operator's Production environment, and new features or enhancements are outside its scope. However, to facilitate business conversations, Hub Operators can submit requests for new features or enhancements and those will be passed on to the Product teams in the community. +::: + +There needs to be a specific team that is responsible for the evaluation and resolution planning of each bug raised in the various environments (Production, Staging, QA, Dev, and so on). It can be a Support team or a QA/Development team. Within the remainder of this section, this team is referred to as the "Mojaloop Support Triage team". + +The Triage team has the following members: + +* Mojaloop Product Manager (core Mojaloop) +* Product Manager of extensions or other components implemented in the Hub - Payment Manager, PortX, and so on +* Hub Technical Subject Matter Expert (Product Delivery, that is Development and QA) +* Operations representative (Technical Operations and Infrastructure) + +## Bugs identified in a Hub Operator Production environment + +*Hub Operator steps:* + +1. An incident ticket is raised in the Hub Operator's [Service Desk](key-terms-kpis.md#key-terms) tool by a Hub L1 Support Engineer, as per the [incident management process](incident-management.md). +1. The ticket is escalated to the Hub L2/L3 team for in-depth investigation and analysis, as required. +1. The Hub L2/L3 team evaluates if the behavior is a new bug or a known issue, and whether a bug ticket/record already exists. If it is a known bug and a Mojaloop Support ticket already exists, then the L1 engineer must update the existing ticket with new details and information, and the priority and impact/severity (level of impact on the Hub or to its users) may be adjusted accordingly. The L1 engineer must communicate this back to the reporter/client DFSP (as referred to, in point 6). New bugs will follow the rest of the process below. +1. The Hub L2/L3 team confirms that the Production issue can be reproduced in lower environments running the same version as the Production (PRD) environment. That is, the bug is not a user error or an environmental issue. +1. The Hub L3 team may escalate to the Hub Technical Operations Manager, and report the bug via the Mojaloop Support Service Desk tool, adding all details of their analysis (including clear steps to reproduce the bug, the expected behavior, the actual behavior and any log files and details from the L2/L3 investigations), in addition to the identifier of the incident ticket created in Step 1 for easy tracking. +1. Response/acknowledgement/communication is sent back to the client DFSP within the agreed timelines. + +*Mojaloop Support team steps:* + +1. The Mojaloop Support team reviews, allocates a team member as owner, and acknowledges receipt of the bug. +1. Following an initial review of the issue raised, the Mojaloop Support team member forwards the issue to the Triage team for further evaluation. \ +The review of the ticket is conducted to a) establish good understanding of the issue raised, including the severity level and priority set by the Hub Operator; b) confirm completeness of the information provided, including log files, clear description, steps to reproduce, screenshots, and so on. +1. The Triage team evaluates the bug: enhancements/new feature requests are passed on to the community Product teams. Operational impact, severity, and priority are reviewed and the bug resolution is assigned to the relevant Product Manager. For details on prioritization, see [Prioritization of bugs](#prioritization-of-bugs). +1. The Product Manager clones the bug into their Product Delivery team's product backlog, which links both issues for reference and progress tracking. The Product Manager also reviews and sets priority against other items in their product backlog. +1. The Mojaloop Support Engineer assigned to the Mojaloop Support bug ticket monitors the cloned ticket and handles all communication between the Product Manager and the Hub Operator on the progress of the bugs, including sharing any remediation steps (for example, workarounds or alternative ways of using the affected functionality). Each subsequent update from the Product Delivery team should also be shared in the Product Manager bug ticket for visibility to the Hub Operator. The Product Manager assignee must remain the owner of the Product Manager bug ticket until the bug is resolved. +1. The Product Manager communicates the resolution plan and timelines back to the Support team via the original Product Manager bug ticket. The resolution plan is then communicated to the Hub Operator. \ +\ +For details on what happens if the Hub Operator does not agree with the proposed prioritization and resolution plan, see [Escalation process](#escalation-process). +1. The bug is resolved following the standard development process of the allocated Product Delivery team and is included in a release, which will be made available to the Hub Operator or can be offered as an ad-hoc (patch) release, if required. +1. The Mojaloop Support ticket is closed once the bug fix release is deployed and validated in the Hub Operator's environment. + +## Bugs identified during deployment/change window in Hub environment + +Deployments into Hub environments are the responsibility of the Hub Operator's team, and bugs identified during the deployment should be raised via the standard process (that is, a ticket is raised as per the Hub’s incident management process and then escalated to the Mojaloop Support team if required). In addition: + +* The Hub team will evaluate if the behavior is a known issue or a new defect. For known issues, the release should proceed and be completed as planned with the known bug reported as part of the post-deployment report. +* For new defects identified, the release/change can be rolled back depending on severity. This can be decided by the deployment team. In the case of a roll-back, regression tests must be executed to confirm that the previous working version is stable on the environment and the bug reported as part of the post-deployment report. +* The bug is captured via the Mojaloop Support Service Desk tool and will be handled via the process described above. + +## Escalation process + +If there is any discrepancy between the priority assigned or the client's (Hub Operator's) expectations and the resolution plan provided by the Mojaloop Support team, the [incident management escalation matrix](incident-management-escalation-matrix.md) governs what happens next. Accordingly, the incident will be set as priority P1 or any other lower priority type and stakeholders will be informed. + +The Mojaloop Support Team Lead and the Hub Operator Program Manager must be informed immediately. The Hub Operator Program Manager is a manager at the Hub organization who is responsible for translating the Scheme's business needs into technical operations directives. + +## Ownership and responsibility + +The creator of the Service Desk ticket (the Hub Operator's Support Engineer) remains the owner until the ticket is resolved. + +Priority and severity must be aligned, discussed, and negotiated between the Mojaloop Support Triage team and the Hub Operator's Operations team. + +Information from triage discussions and from the Product Delivery team must be shared in the Service Desk ticket by the Mojaloop Support Engineer. + +The Product Manager who is assigned the bug, must ensure that cross-referencing and tracking is in place to ensure the flow of information required or produced by the Product Delivery team's evaluation. + +The Product Manager who is assigned the bug, must determine and communicate the resolution plan back to the Mojaloop Support team/engineer, via the ticket only. + +### Prioritization of bugs + +The prioritization of bugs is the responsibility of Subject Matter Experts (SMEs) in the Mojaloop Support Triage team. + +All bugs are evaluated based on the expected behavior of the system and the actual behavior observed (and reproduced). The operational impact and the urgency of the bug must be captured by the Hub Operator's Operations team in order for this to be considered by the Triage team in the prioritization. + +Every bug is evaluated against the Product roadmap and backlog. + +New features or enhancement requests are channelled to the Product team and not handled by this process. This is communicated back to the requester via the Operations team. + +::: tip +Priority is the order in which the bug will be fixed. The higher the priority, the sooner the bug will be resolved. \ +\ +Severity is the level of impact on the Hub or to its users. \ +\ +These two factors work hand in hand. For example, a cosmetic bug like a typo on a webpage will likely be ranked as low severity but could be a quick and easy fix and ranked high priority. Hence, it is important to set these values with due consideration. +::: + +## Process flowchart + + diff --git a/docs/adoption/HubOperations/TechOps/incident-management-escalation-matrix.md b/docs/adoption/HubOperations/TechOps/incident-management-escalation-matrix.md new file mode 100644 index 000000000..2c600508e --- /dev/null +++ b/docs/adoption/HubOperations/TechOps/incident-management-escalation-matrix.md @@ -0,0 +1,51 @@ +# Appendix A: Incident management escalation matrix + +This section provides information about key roles to contact when an incident occurs. + +::: tip NOTE +The incident management escalation matrix provided below acts as an example only. The actual names of roles may be different in your organization. +::: + + + ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Support chain for incidents
Name of teamManager NEscalation N+1Escalation N+2

Level 1 Customer Support

L1/L2 Operations Support Team Leader

Service Manager

Technical Operations Manager

Level 2 Customer Support

Service Manager

Technical Operations Manager

Product Owner of the Hub / Program Manager

Level 3 Customer Support

Service Manager

Technical Operations Manager

Product Owner of the Hub / Program Manager

Level 4 Customer Support

Service Manager

Technical Operations Manager

Product Owner of the Hub / Program Manager

\ No newline at end of file diff --git a/docs/adoption/HubOperations/TechOps/incident-management.md b/docs/adoption/HubOperations/TechOps/incident-management.md new file mode 100644 index 000000000..be5e7bb50 --- /dev/null +++ b/docs/adoption/HubOperations/TechOps/incident-management.md @@ -0,0 +1,695 @@ +# Incident management + +The main objective of incident management is to restore normal service operation as quickly as possible and to minimize the impact on business operations, thus ensuring that the best possible levels of service quality and availability are maintained. "Normal service operation" is defined here as service operation within [service level agreements (SLAs)](service-level-agreements.md). + +This is achieved through a robust, well-aligned incident management process and guided by a Service Desk system that helps capture all issues, and track turnaround time (TAT) from the time an issue is reported to time of resolution and closure. + +The process of incident management involves detecting an incident, recording it with all the appropriate information, analyzing the issue, correcting the defects, and restoring the service in accordance with the stipulated TAT. + +This section collects the main processes, concepts, and principles around incident management. + +::: tip NOTE +The processes described in this section represent best practices and act as recommendations for organizations fulfilling a Hub Operator role. +::: + +::: tip NOTE +Throughout this section, the terms "client", "customer", "end user", and "user" all designate a DFSP employee. When these words are used in any other sense, the meaning of the word is called out and explained in detail. +::: + +## Incident management in a single image + +The following figure defines the process flow and key concepts of incident management in a single image. + + + + + +## Process boundaries + +The incident management process starts when: + +* an incident is triggered by a phone call/email/Service Desk interaction from users or customers +* an incident is found by way of an internal process or tool, for example, there is an event alert from one of the alert tools or monitoring systems +* Support staff at all levels (L1, L2, L3 Support Engineers) or the Service Manager directly raise an incident + +The incident management process ends: + +* for the customer: when ticket status in the Service Desk tool is changed to "Closed" +* for the Service Desk team: when the incident is solved and validation for closure is sent to the customer + +The boundaries of incident management stipulate that the process takes into account the following prerequisites: + +* A Service Level Agreement (SLA) between the Community (for example, Mojaloop), holding companies (for example, the Hub), and Digital Financial Service Providers (DFSPs) is in place. +* An SLA between the Implementing Partner (the Hub) and third-party Software Vendors (for example, Microsoft, Oracle, and so on) is in place. +* There is an existing operational level agreement (OLA). This agreement describes the responsibilities of each internal Support group towards other Support groups, including the process and time frame for delivery of their services. + +## Incident management step-by-step + +This section provides a detailed description of the incident management process. All incidents raised go through the following main steps. + +### Step 1: Report and log incident, change request, or question + +Issues, change requests, or questions can be reported and logged via the Service Desk tool as soon as they occur. The Service Desk tool is the primary channel for receiving incident-related queries. Emails, phone calls, and instant messaging can be used as secondary channels. + +The status of tickets as captured in the Service Desk system can take the following values: + +* **In Progress**: An incident that has been received via the Service Desk and assigned to a Support Engineer. Resolution efforts have commenced. +* **Escalated**: An incident that has been escalated to any party outside the Operations team, including the Product Delivery team or external L4 service providers. +* **Pending**: An incident that has been temporarily put on hold or awaiting feedback from the user or from another ticket that must be resolved before this ticket can be resolved. \ +\ +Bearing in mind that using the "Pending" status stops the SLA clock, the only reason that justifies the usage of "Pending" is when client action is required. This has to be an action that is the responsibility of the client/customer or their vendor and is a prerequisite to the continuation of the process; for example, requesting essential information or approval to solve the request. Tickets with Severity 1 and 2 must not be set to status "Pending". Restoring a service or a function of a service seldom depends on customer action. The only exception is when the customer stops the investigation or implementation of a solution or denies a necessary approval. In any case, the customer’s decision has to be documented. +* **Cancelled**: An incident that has been cancelled. An incident can only be cancelled when the customer initiates it. +* **Resolved**: An incident that was worked on by a Support Engineer and was fixed, and an alert has been triggered to the user to reopen if not satisfied. +* **Closed**: An incident that was closed once the resolution was acknowledged by the end user. + +All relevant information relating to incidents must be logged so that a full historical record is maintained. By maintaining accurate and complete incident records, future assigned Support group personnel are better able to resolve recorded incidents. + +### Step 2: Categorize and prioritize + +The end user/requester is assigned a ticket number for reference and ease of access when the issue is acknowledged and actioned by the Support Team. The ticket should be visible by the requester (the DFSP employee who raised the issue) at all Support levels. + +The requester will be automatically notified by email of any changes, status updates, requests for more information, readiness for testing, or final resolution with regards to the ticket. + +We generally classify support requests into: + +* Incident +* Service Request +* Change Request or Request for Change (RFC, such as features, enhancements) + +Incidents are categorized and sub-categorized based on the IT service or business area that the incident is causing a disruption to. + +These are some of the sample service categories: + +* Infrastructure +* Mojaloop +* Security +* Settlements +* Onboarding + +The severity of an incident can be determined using a [categorization matrix](#incident-categorization-matrix). Based on their severity, incidents can be categorized as: + +* Critical = S1 +* Severe = S2 +* Average = S3 +* Minor = S4 + +Once the incident is categorized, it gets automatically routed to an L1 Support Engineer with the relevant expertise. + +### Step 3: Investigate and resolve + +The assigned Support resource will be in charge of investigating the issue, as well as preparing the incident record, and communicating with the client on how to resolve the issue. + +Incident investigation may include any of the following actions: + +* Information gathering and analysis +* Research, including reproducing the issue +* Acquiring additional information from other sources + +Incident resolution may include any of the following actions: + +* Providing a resolution or steps towards a resolution +* Configuration changes + +Based on the complexity of the incident, it may have to be broken down into sub-tasks or tasks. Tasks are typically created when an incident resolution requires the contribution of multiple technicians from various departments. + +While the incident is being processed, the Support Engineer needs to ensure the Service Level Agreement is not breached. An SLA is the acceptable time within which an incident needs a response (response SLA) or resolution (resolution SLA). SLAs can be assigned to incidents based on their parameters like service category, requester, impact, urgency, and so on. In cases where an SLA is about to be breached or has already been breached, the incident can be escalated functionally or hierarchically to ensure that it is resolved at the earliest. + +An incident is considered resolved when the L1/L2/L3 Support Team has come up with a temporary workaround or a permanent solution for the issue. Workarounds may be: + +* instructions provided to the customer on how to complete their work using an alternative method +* temporary fixes that assist a system to work as expected but which do not resolve the issue permanently + +Workarounds need to be documented and communicated to the Service Desk so they can be added to the Knowledge Base. (It is good practice to maintain a repository of Knowledge Base articles, which describe the workaround or resolution steps of incidents that occurred in the past.) This will ensure that workarounds are accessible to the Service Desk to facilitate resolution during future recurrences of the incident. + +### Step 4: Escalate + +Incident escalation is recognition that there is the possibility of an incident exceeding the agreed resolution timeliness at each Support level. Clear escalation management allows the Support Team to identify, track, monitor, and manage situations that require increased awareness and swift action. + +There are two types of escalation: + +* **Functional escalation**: This type of escalation comes to play when a Support level team (for example, L1) is unable to resolve the issue or stay within the agreed timeline (meaning that the targeted time for resolution is exceeded). Therefore, the case is proactively assigned to the next service level (for example, L2). +* **Hierarchical escalation**: This type of escalation acts as a means to inform all the parties involved, in a proactive manner, of a potential SLA breach. This helps in bringing order, structure, responsibility, ownership, focused management, and resource mobilization for the purpose of delivering effective and efficient services. + +### Step 5: Close incident + +An incident can be closed once the issue is resolved and the user acknowledges the resolution and is satisfied with it. + +## Incident categorization matrix + +One of the most important stages in incident management is incident categorization. This not only helps sort incoming tickets but also ensures that the tickets are routed to the Support Engineers most qualified to work on the issue. Incident categorization also helps the Service Desk system apply the most appropriate SLAs to incidents and communicate those priorities to end users. Once an incident is categorized, Support Engineers can diagnose the incident and provide the end user with a resolution. + +The following table provides guidance as to how to classify the severity of an incident. + + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
Incident categorization matrix
Severity codeCriteria

Severity 1

    +
  • Extensive impact to the business, Production system outage, normal operation is not possible.

  • +
  • Any incident that resulted in a major outage of the Hub, including connectivity of multiple partners/DFSPs.

  • +
  • Any incident that presents major financial risks and has contractual implications.

  • +
  • A security incident with a major impact on the privacy or availability of the Hub, partners/DFSPs, or customer data.

  • +

Severity 2

    +
  • Partial outage of the Hub.

  • +
  • Key functionality is impaired with no workaround available.

  • +

Severity 3

    +
  • Minor/moderate functional impact to a single user or small group of users. A workaround exists.

  • +

Severity 4

    +
  • A minor incident with (almost) no impact or detriment to the system functionality but nevertheless still a valid bug.

  • +
+ +Key: + +* Severity 1 = Critical +* Severity 2 = Severe +* Severity 3 = Average +* Severity 4 = Minor + +The severity code assigned to an incident will determine the solution time and will be used by the Service Desk to assign resources to the request. + +In addition to severity, in some cases the priority of an incident may also have to be considered. Priority is assigned by the Hub Operator (rather than the client) and is the order in which the incident will be fixed. The higher the priority, the sooner the incident will be resolved. Consider the following example: a cosmetic bug like a typo on a webpage will likely be ranked as low severity but could be a quick and easy fix and ranked high priority. Hence, it is important to give severity and priority due consideration. + +The following table provides guidance as to how to assign priority to an incident. + + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
Priority matrix
Priority codeCriteria

Priority 1

A severe issue has occurred affecting multiple users within a service recipient (>50% of service recipient users) to the extent that they are unable to perform their assigned work functions, OR the service recipient or areas outside of the service recipient are affected.

Priority 2

An issue has occurred affecting either several users (affects >10 but no more than 50% of all service recipient users) OR a named power user of the service to the extent that they are unable to perform their assigned work functions and a business unit is affected.

Priority 3

An issue has occurred affecting a single user OR (affects <10 users OR no more than 25% of all users) to the extent that they are unable to perform their assigned work functions.

Priority 4

An issue has occurred affecting a single user, causing decreased functionality to a single application. There is a workaround for the user to perform their assigned work functions, but the outage causes a decrease in their productivity.
+ +## Security incidents + +This section describes the procedure that a Hub Operator is recommended to implement for handling security events/incidents. Security incidents may be classified as Severity 1, Severity 2, Severity 3, or Severity 4 incidents. Regardless of its categorization, follow the steps outlined in the table below if an incident is security-related. + + + ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Security incident management
StepAdditional action or informationRole

Step 1: A suspected security event/incident is received through the Service Desk via a ticket assigned to the security team (L1) for initial review and triage.

Step 2: Invoke the triage process.

Step 2a:

+
    +
  • Identify artifacts of the incident.

  • +
  • Identify affected devices, systems, or users.

  • +
    +
  • Gather the key indicators of a threat.

  • +
  • Retrieve logs.

  • +
  • Look up artifacts (IP addresses, usernames, URLs, hostnames, and so on).

  • +
  • Review logs to find out if there is any law/regulation that is being violated by the incident (if it is a severe incident, it might damage the reputation of the organization).

  • +

L1 Information Security Officer (ISO)

Step 2b:

+
    +
  • Evaluate situation: impact assessment.

  • +
  • Estimate the potential effect of the event or incident.

  • +
    +
  • Review available indicators of compromise.

  • +
  • Assess impact based on the criticality of the affected system.

  • +
  • Review audit logs.

  • +
  • Draw a timeline of events.

  • +

L1 ISO

Step 2c:

+

Collect evidence.

    +
  • Collect and collate all available information to allow for categorization.

  • +

L1 ISO

Step 2d:

+

Determine categorization.

    +
  • Based on collected information, assign a category to the ticket.

  • +
  • L1 security will update categorizations as appropriate.

  • +
+

Example categories are:

+
    +
  • Denial of Service (DOS)

  • +
  • Malicious code

  • +
  • Unauthorized access

  • +
  • Data leak/loss

  • +
  • Data breach (breach of regulation related to data protection)

  • +
  • Inappropriate usage

  • +

L1 ISO

Step 2e:

+

Take basic steps to mitigate the effect on the environment.

Basic steps may include tasks such as: +
    +
  • Locking down an endpoint.

  • +
  • Deploying anti-malware where required.

  • +
  • Review security Standard Operating Procedures (SOPs) (if applicable) for any additional steps that may be required.

  • +
+

If mitigation steps taken are successful in resolving the reported issue, L1 Security will update the ticket and proceed to Step 8 (Close Issue).

L1/L2 ISO

Step 3: Make an assessment whether the reported issue is an event or an incident.

The assessment decision is taken by the L1 Security team in collaboration with L2 Security.

L1/L2 ISO

Step 4.1: If reported issue is categorized as an "event", follow these steps:

Step 4.1a:

+

Perform event follow-up.

Event follow-up examples include: +
    +
  • Verify and install anti-malware on all hosts.

  • +
  • Trigger tickets requesting patching of systems and/or review of event by Operations team.

  • +

L1/L2 ISO

Step 4.1b:

+

Go to Step 8.

L1 ISO

Step 4.2: If reported issue is categorized as an "incident", follow these steps:

Step 4.2a:

+

L1 ISO to escalate to L2 ISO for further investigation by re-assigning the ticket to the L2 Security group for follow-up.

L1 ISO

Step 4.2b:

+

L2 ISO to acknowledge receipt of the ticket from L1 and proceed to open Security Incident Report.

L2 ISO

Step 4.2c:

+

L2 ISO to review and verify incident severity and categorization.

L2 ISO

Step 5.1: If reported incident is categorized as an "S1" incident, follow these steps:

Step 5.1a:

+

Update Security Incident Report.

L2 ISO

Step 5.1b:

+

Inform stakeholders via secure email.

Stakeholders are documented in Appendix A: Incident management escalation matrix.

L2 ISO

Step 5.1c:

+

Proceed to Step 6.

L2 ISO

Step 5.2: If reported incident is categorized as an "S4" incident, follow these steps:

Step 5.2a:

+

Proceed to Step 6.

L2 ISO

Step 6: Contain and eradicate.

Step 6a:

+

Review and update mitigation actions to reduce impact.

Example mitigation actions include:

+
    +
  • Change passwords.

  • +
  • Lock down access.

  • +

L2 ISO

Step 6b:

+

Collect evidence.

L2 ISO

Step 6c:

+

Perform root cause analysis and identify/implement a fix.

L2 ISO

Step 6d:

+

Update incident Standard Operating Procedures (SOP) as necessary.

SOP updates are reviewed by L3 before adoption.

L2 ISO

Step 6.1: If Step 6 is successful, follow these steps:

Step 6.1a:

+

Update Security Incident Report and ticket.

Ensure ticket does not contain sensitive security information.

L2 ISO

Step 6.1b:

+

Communicate with stakeholders via secure email.

Stakeholders are documented in Appendix A: Incident management escalation matrix.

L2 ISO

Step 6.1c:

+

End system or service lockdown.

L2 ISO

Step 6.1d:

+

Proceed to Step 8.

L2 ISO

Step 6.2: If Step 6 is unsuccessful, follow these steps:

Step 6.2a:

+

Escalate to the L3 Security team.

L2 ISO

Step 6.2b:

+

Inform the business team.

L2 ISO

Step 6.2c:

+

L3 to proceed with Step 7.

L3 ISO

Step 7: L3 to review and resolve issue.

Step 7a:

+

Review activities and incident history documented by L1 and L2.

L3 ISO

Step 7b:

+

Provide guidance for further containment action.

L3 ISO

Step 7c:

+

If L3 resolves the issue, go to Step 8.

L3 ISO

Step 7d:

+

If L3 cannot resolve the issue, they may escalate to the system/software OEM or procure specialist services (subject to approval) for support.

If L3 cannot resolve the issue, they may escalate to the system/software OEM or procure specialist services (subject to approval) for support. A decision may be required on triggering the disaster recovery plan, including formation of a "war room".

A disaster recovery plan (DRP) is a bespoke arrangement, based on the Hub Operator's technical capabilities, as well as risk appetite. It is part of a Hub Operator's IT Security policies. It is necessary to assess details of the Hub Operator's DRP policy and expectations, and fine-tune the rollout to fit their needs. Details need to be worked out during implementation (preferably during the design phase) as the various options available may have cost implications.

L3 ISO

Step 8: Close the issue.

Step 8a:

+

Restore affected systems.

L1 / L2 / L3 ISO

Step 8b:

+

Update Security Incident Report.

L2 / L3 ISO

Step 8c:

+

Identify and communicate lessons learned.

L2 / L3 ISO

Step 8d:

+

Incident response team to review relevant recommendations for possible adoption.

This review session may include Tech Operations and Service Management teams, depending on severity.

L1 / L2 / L3 ISO

Step 8e:

+

Update stakeholders.

L2 / L3 ISO

Step 8f:

+

Close issue.

L1 / L2 / L3 ISO

Step 9: L3 ISO to modify and revise breach policies and procedures.

L3 ISO

+ +The following figure shows a summary of the process described above. + +![Security incident management](../../../.vuepress/public/security_incident_process.png) + +### Security Incident Report template + +When writing a Security Incident Report, it is good practice to use a template created for this purpose. + +## Roles and responsibilities + +This section provides generic guidelines on the proposed roles and responsibilities within the incident management process. + +::: tip NOTE +It is convenient to describe the running support for the technical operations of the Mojaloop Hub as levels. This document describes four levels. Levels are convenient because each level of support requires a different degree of knowledge of and access to the system. In other words, levels refer to different roles/Support teams within your organization. + +Some of these teams can optionally be outsourced, depending on the level of expertise or capacity within your organization. If you decide to outsource Support functions, there are organizations within the Mojaloop community that do provide different levels of Support as a service. (For more information and referrals, contact the Mojaloop Foundation.) +::: + +### End user/user/requester/L0 + +*Role* + +This is the stakeholder who experiences a disruption in service and raises an incident ticket to initiate the process of incident management. + +*Responsibilities* + +* Contact the Service Desk to raise a new incident request. +* Follow up on an existing request. +* Monitor the communication channel for any feedback from Support Engineers. +* Clearly communicate all the required or requested information to Support Engineers. +* Acknowledge the restoration of service and completion of the ticket. +* Respond to follow-up surveys after ticket resolution completing the feedback loop. + +### Level 1 Team/Service Desk + +*Role* + +This is the first point of contact (Support Level 1) for requesters or end users when they want to raise a request or incident. This role is responsible for basic Service Desk resolution, initial diagnostics, and the investigation of Service Desk tickets. + +*Responsibilities* + +* Log all incoming incident requests with appropriate parameters, such as severity and priority (if the latter is applicable). +* Assign tickets to Support Engineers based on the parameters above (severity and priority). +* Analyze and resolve incident to restore service. +* Escalate unresolved incidents to the Level 2 Team. +* Gather all required information from the requesters and send them regular updates on the status of their request. +* Act as a point of contact for requesters, and, if needed, coordinate between the Level 2 Team and end users. +* Verify the resolution with the end user and collect feedback while updating the tickets. +* Monitor feedback and surveys related to the actions that L1 took to resolve the issue for the purpose of analyzing the quality of service offered. + +### Level 2 Team (Application, Infrastructure, Security and Business Operations Support L2) (Customer Support Team) + +*Roles* + +This support function is made up of engineers or Business Operations Subject Matter Experts (SMEs) with advanced knowledge of the Hub. The L2 Team is expected to provide in-depth troubleshooting, technical analysis, transaction analysis, and support to resolve incidents reported. They usually receive more complex requests from end users; they also receive requests in the form of escalations from the L1 Team. + +*Responsibilities* + +* Carry out incident diagnosis. +* Document the steps followed to resolve the incident and submit Knowledge Base articles. (For every incident, the Support Team updates the Knowledge Base. The purpose of Knowledge Base articles is to enable end users and Support personnel to resolve issues on their own.) +* Handle intermediate incidents, for example, incidents related to Applications, Infrastructure, Log Analysis, Transactions Analysis, and so on. +* If the incident is resolved, confirm the resolution with the end user. +* Support DFSP onboarding. + +### Level 3 Team (Application, Infrastructure, and Security Support L3) (Technical Support Team) + +*Roles* + +This level is usually comprised of Specialist Engineers who have advanced knowledge of particular domains of the Hub – for example, knowledge of infrastructure components or system applications, or expertise in security engineering. + +*Responsibilities* + +* Perform deep analysis and/or reproduce the issue in a test environment in order to diagnose the issue properly and to test the solution. +* Interpret and analyze the code and data using information triaged from L1 and L2. +* If unresolved, escalate the incident to "L4" support partners to identify the underlying issue or to external vendors, DFSPs or Settlement Bank (transactions queries or transfer reports) as applicable. +* Provide subject matter expertise. +* Document the incident and update the Knowledge Base. (For every incident, the Support Team updates the Knowledge Base. The purpose of Knowledge Base articles is to enable end users and Support personnel to resolve issues on their own.) + +### Incident Manager/Service Manager + +*Role* + +The Service Manager monitors the effectiveness of the process. The Service Manager manages the process to restore normal service operation as quickly as possible and to minimize the impact on business operations. + +*Responsibilities* + +* Serve as the point of contact for all S1 incidents reported. +* Plan and facilitate all the activities involved in the incident management process. +* Ensure that the correct process is followed for all tickets, and correct any deviations. +* Coordinate and communicate with the Process Owner. +* Align customer expectations with the SLAs by being the interface between customers and the Operations team. +* Identify incidents that need to be reviewed and carry out the review. + +### Process Owner: Technical Operations Manager + +*Role* + +This is the owner of the process followed for managing incidents. This role also acts as a coordinator between teams and organizations. The Technical Operations Manager analyzes, modifies, and improves the process to ensure it best serves the interests of the organization. + +*Responsibilities* + +* Accountable for the overall quality of the process. Oversees the management of and compliance with the procedures, data models, policies, and technologies associated with the process. +* Owns the process and supporting documentation for the process from a strategic and tactical perspective. +* Ensures the incident management process aligns with other organization policies, for example, HR Policy, Security Policy, Level One Guiding Principles, and so on. +* Defines [key performance indicators (KPIs)](key-terms-kpis.md) and aligns them with critical success factors (CSFs), and ensures that these objectives are realized. +* Designs, documents, reviews, and improves processes. +* Establishes continuous service improvement (CSI) and ensures the procedures, policies, roles, technology, and other aspects of the incident management process are reviewed and improved upon. +* Stays informed about industry best practices and incorporates them into the incident management process. + +## Outputs of the incident management process + +The incident management process produces the following outputs. Note that the only mandatory output for Security or S1 incidents is the Root Cause Analysis (RCA), and all other outputs listed below might feed into the RCA. + +* Resolved or closed incidents. This is the most desired outcome of the incident management process. The closed incident record contains accurate details of the incident attributes and the steps taken for resolution or workaround. +* Requests for Change (RFC). +* Resolution metrics (Mean Time Between Failures, Mean Time To Repair, Mean Time To Acknowledge, and Mean Time To Failure). For details on KPIs, see the [Glossary](key-terms-kpis.md). +* Successfully implemented change through the change management process. +* RCA document complying to the RCA template. +* Restored service. +* Updated Knowledge Base database. +* Notification through various channels (Service Desk, email, call, and so on) on the initiation, resolution, and closure of an S1 incident to various stakeholders. +* Updated Daily Operation Report and management report to ascertain the decisions made with regards to service improvements, resource allocation/reallocation. +* Accurately recorded service and/or component outage details (for example, start, end, duration, outage classification, and so on). + +## Impact on other processes + +The incident management process interfaces with a number of other processes, feeding into and impacting each other: + +* **Change Management process**: The objective of the change management process is to ensure that standardized methods and procedures are used for efficient and prompt handling of all changes, in order to minimize the impact of change-related incidents upon service availability or quality, and consequently improve the day-to-day operations of the organization. +* **Release Management process**: Release and deployment management is defined as the process of managing, planning, and scheduling the rollout of IT services, updates, and releases to the production environment. The primary goal of this process is to ensure that the integrity of the live environment is protected and that the correct components and validated features are released for customer use. +* **Incident Communication process**: Incident communication is the process of alerting users that a service is experiencing some type of outage or degraded performance. This is especially important for services where 24/7 availability is expected. Incident communication is important for all partners, customers, and their customers. diff --git a/docs/adoption/HubOperations/TechOps/key-terms-kpis.md b/docs/adoption/HubOperations/TechOps/key-terms-kpis.md new file mode 100644 index 000000000..7fc61af60 --- /dev/null +++ b/docs/adoption/HubOperations/TechOps/key-terms-kpis.md @@ -0,0 +1,80 @@ +# Glossary + +This section acts as a glossary of Technical Operations terms and provides definitions of: + +* key terms guided by Information Technology Infrastructure Library (ITIL) best practices +* Key Performance Indicators (KPIs), that is, metrics that help determine whether specific incident management goals are met + +## Key terms + +**Change management:** Change management is the process of recording, approving, executing, closing, and reviewing all changes. The change can be either contractual (such as initial signature of contract, SLA upgrade, new resources needed, and so on), or operational arising from a change request. + +**Escalation:** The acknowledgement of the fact that an incident requires additional resources in order to meet service level targets or user expectations, taking into account the criticality, impact, and urgency of the incident. + +**Helpdesk/Service Desk:** The Single Point of Contact between the service provider and users. A typical Service Desk manages incidents and service requests, and also handles communication with the users. + +**Incident:** An unplanned interruption to an IT service, or reduction in the quality of an IT service. The failure of a configuration item that has not yet impacted service is also an incident; for example, the failure of one disk from a mirror set. + +**Incident management process (IMP):** The process of managing the lifecycle of all incidents. The primary purpose of incident management is to restore normal IT service operation as quickly as possible with the support of a whole organization in place. + +**Incident record/ticket:** A record containing the details of an incident. Each incident record (also known as a ticket) documents the lifecycle of a single incident. + +**Priority:** A category used to identify the relative importance of an incident or change. Priority is used to identify required times for actions to be taken. + +**Release management:** Release management is the process of managing, planning, scheduling, implementing, and controlling a software build through different stages and environments, with the goal of delivering features to customers or end users. + +**Request for Change (RFC):** The Request for Change (or simply Change Request) is a formal request for the implementation of a change. The RFC is a precursor to the "Change Record" and contains all information required to approve and execute a change. + +**Role:** A set of responsibilities, activities, and authorities granted to a person or team. Roles are used to assign owners to the various incident management processes, and to define responsibilities for the activities in the detailed process definitions. + +**Root cause analysis (RCA):** RCA is a collective term that describes a wide range of approaches, tools, and techniques used to uncover causes of incidents. It is called at each urgent incident, and every time an incident occurs more than once. + +**Service Level Agreement (SLA):** An agreement between an IT service provider and a customer. The SLA describes the IT service, documents service level targets, and specifies the responsibilities of the IT service provider and the customer. + +**Severity:** A measure of the effect of an incident on business processes. + +**TAT (Turnaround Time):** This is the time taken from when the incident is reported to the time it is resolved and closed. It includes Guaranteed Intervention Time (GIT) and Guaranteed Resolution Time (GRT). + +## Key Performance Indicators (KPIs) + +**Availability rate (Service availability rate):** The whole technical solution’s availability to provide the service per DFSP. + +**Average Incident Closure Duration:** Average amount of time between the registration of incidents and their closure. + +**Average Incident Response Time:** The average amount of time (for example, in minutes) between the detection of an incident and the first action taken to repair the incident. + +**Average Number of Incidents Solved By Service Desk:** Average number of incidents solved by Service Desk relative to all open incidents. + +**Guaranteed Intervention Time (GIT):** The time elapsed between the time an incident is reported (for example, an email is sent to the Service Desk tool) and the time that an acknowledgement response is returned to the reporter of the issue. + +**Guaranteed Resolution Time (GRT):** Sum of total time spent on resolving an issue from all parties. (The issue status must be “In Progress” or “Escalated” to count towards the sum total. Issue status “Pending” or “Closed” are not taken into account when calculating the sum total.) + +**Incidents Completed Without Escalation:** The percentage (%) of incidents completed within the SLA without any escalation. + +**Incident Queue Rate:** The number of incidents closed, relative to the number of incidents opened in a given time period. + +**Mean Time Between Failures (MTBF):** The average time between repairable failures of a technology product. The metric is used to track both the availability and reliability of an IT service or any other configuration item, to assess if they can perform their agreed function without interruption. The higher the time between failures, the more reliable the system. + +**Mean Time To Acknowledge (MTTA):** The average time it takes from when an alert is triggered to when work begins on the issue. This measures how long it takes an organization to respond to complaints, outages, or incidents across all departments on average. This metric is useful for tracking a team's responsiveness and an alert system's effectiveness. + +**Mean Time To Detect (MTTD) – "Proactive actions":** The difference between the onset of any event that is deemed revenue impacting and its actual detection by the technician who then initiates some specific action to recover the event back to its original state. This is not the same as starting the Mean Time To Repair (MTTR) clock (that is, once the technician receives a ticket). The onset of any revenue impacting event is almost always recorded at some specific time by some specific equipment. The key element is to bring the detection tool into the technician's environment, and then measure the difference between the event's timestamp and the technician's first action indicating recognition of the event (MTTD). + +**Mean Time To Failure (MTTF):** The average time between non-repairable failures of a technology product (mostly hardware). + +**Mean Time To Repair (MTTR):** Refers to the average amount of time required to repair a system and restore it to full functionality. \ +\ +The MTTR clock starts ticking when the repairs start and it goes on until operations are restored. This includes repair time, testing period, and return to the normal operating condition. + +**Mean Time To Recovery:** Mean Time To Recovery is a measure of the time between the point at which the failure is first discovered until the point at which the service returns to operation. So, in addition to repair time, testing period, and return to normal operating condition, it captures failure notification time and diagnosis. + +**Old Incident Backlog:** Number of open incidents older than 28 days (or any other given time frame) relative to all open incidents. + +**Percentage Of Incidents Solved Within Deadline/Target:** Number of incidents closed within the allowed duration time frame, relative to the number of all incidents closed in a given time period. A duration time frame is applied to each incident when it is received, and sets a limit on the amount of time available to resolve the incident. The applied duration time frame is derived from the agreements made with the customer about resolving incidents. + +**Percentage Of Incidents Solved Within SLA Time:** Total number of incidents resolved within SLA time, divided by the total number of incidents. + +**Percentage Of Outage Due To Incidents:** Percentage of outage (unavailability) due to incidents, relative to the service hours. + +**Percentage Of Overdue Incidents:** Number of overdue incidents (not closed and not solved within the established time frame) relative to the number of open (not closed) incidents. + +**Percentage Of Repeated Incidents:** Percentage of incidents that can be classified as a repeat incident, relative to all reported incidents within the measurement period. A repeat incident is an incident that has already occurred (multiple times) in the measurement period. diff --git a/docs/adoption/HubOperations/TechOps/problem-management.md b/docs/adoption/HubOperations/TechOps/problem-management.md new file mode 100644 index 000000000..a5c10e250 --- /dev/null +++ b/docs/adoption/HubOperations/TechOps/problem-management.md @@ -0,0 +1,131 @@ +# Problem management + +The overall objective of problem management is getting to the root cause of incidents (Severity 1 incidents or incidents that occurred more than once) or the potential causes of incidents, and then instigating actions to improve or correct the situation at once. + +The problem management procedure ensures that: + +* problems are properly logged +* problems are properly routed +* problem status is accurately reported +* queue of unresolved problems is visible and reported +* problems are properly prioritized and handled in the appropriate sequence +* resolution provided meets the requirements of the agreed upon service level agreement (SLA) +* resolution of root cause issues or problems is done + + +## Identifying problems + +A problem is declared by the relevant service management stakeholder in the following situations: + +* when there is an incident whose cause the incident owner cannot establish within set service level agreement +* when there are repeat occurrences of an incident with considerable impact to business +* when there is a service degradation or deviation from expected behavior that is likely to affect business in future if not mitigated, and whose mitigation is not well established + +In any of the scenarios above, or any other scenario that the Problem Manager may deem applicable, a problem record will be opened and the problem management process kicked off. + +If a problem turns out to be caused by a defect in the product, a bug is raised in accordance with the [defect triage process](defect-triage.md). + +## Categorizing and prioritizing problems + +In order to determine if SLAs are met, it is necessary to categorize and prioritize problems quickly and correctly. + +The goal of proper categorization is to: + +* identify the service impacted +* associate problems with related incidents +* indicate which Support groups need to be involved +* provide meaningful metrics on system reliability + +For each problem, the specific service will be identified. + +The priority assigned to a problem will determine how quickly it is scheduled for resolution. Priority is set based on a combination of the related incidents’ severity and impact. + +The table below provides guidance as to how to classify a problem. For guidance on how to read this table, see the following examples: + +* A problem with High severity and Low impact will be classified as a Medium-priority problem (check the cell at the junction of High severity and Low impact). +* A problem with Medium severity and High impact will be classified as a High-priority problem (check the cell at the junction of Medium severity and High impact). + + + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Problem priority matrix
SEVERITY

Low
+
+The problem prevents the user from performing a portion of their duties.

Medium
+
+The problem prevents the user from performing critical time-sensitive functions.

High
+
+A service or a major portion of a service is unavailable.

IMPACT

Low
+
+The problem affects one or two members of personnel.

+

Degraded service levels but still processing within SLAs.

Low

Low

Medium

Medium
+
+Degraded service levels but not processing within SLA constraints or able to perform only minimum level of service.

+

The cause of the problem seems to affect multiple functional areas.

Medium

Medium

High

High
+
+All users of a specific service are affected.

+

A customer-facing service is unavailable.

High

High

High

+ +## Documenting workarounds + +A workaround defines a temporary way of overcoming the adverse effects of a problem. Workarounds may be: + +* instructions provided to the customer on how to complete their work using an alternative method +* temporary fixes that assist a system to work as expected but which do not resolve the issue permanently + +Workarounds need to be documented and communicated to the Service Desk so they can be added to the Knowledge Base. This will ensure that workarounds are accessible to the Service Desk to facilitate resolution during future recurrences of the incident. + +In cases when a workaround is found, it is important to document all details of the workaround within the Problem Record and that the Problem Record remains open. + +## Documenting known errors + +When a diagnosis is made to identify a problem and its symptoms, a Known Error Record must be raised and placed in the Known Error documentation. If repeat incidents or problems arise, they can be identified and service restored more quickly. Any workarounds or solutions should also be documented in the particular problem's Known Error Record. + +In some cases it may be advantageous to raise a Known Error Record even earlier in the overall process – just for information purposes, for example – even though the diagnosis may not be complete or a workaround may not have yet been found. + +The Known Error Record must contain all known symptoms so that when a new incident occurs, a search of known errors can be performed and the appropriate match found. + +## Process + +The following figure shows a summary of the process described above. + +![Problem management](../../../.vuepress/public/problem_mgmt.png) diff --git a/docs/adoption/HubOperations/TechOps/release-management.md b/docs/adoption/HubOperations/TechOps/release-management.md new file mode 100644 index 000000000..380fed1f2 --- /dev/null +++ b/docs/adoption/HubOperations/TechOps/release-management.md @@ -0,0 +1,108 @@ +# Release management + +Release management handles the processes around managing, planning, scheduling, and controlling a software change through deployment and testing across various environments. + +::: tip NOTE +The processes described in this section represent best practices and act as recommendations for organizations fulfilling a Hub Operator role. +::: + +::: tip NOTE +This section references a "Mojaloop Support team": a team dedicated to running Support services for the technical operations of a Mojaloop Hub. Note that this team can be either an insourced or an outsourced unit, depending on the level of expertise or capacity within your organization. If you decide to outsource Support functions, there are organizations within the Mojaloop community that provide different levels of Support as a service. (For more information and referrals, contact the Mojaloop Foundation.) +::: + +## Release components and environments + +When accepting new releases from Mojaloop Open Source for Switch services and other components that are needed, the releases are taken through a series of testing activities in progressively higher environments, starting with development/QA environments and ending with production-level testing. + +The recommended environment setup comprises of multiple environments all serving different purposes, as depicted in the diagram below. + + + +A Hub-specific implementation of Mojaloop is built on a number of service components (Mojaloop OSS, extensions or other components, potential customizations), and releases will include new features, enhancements, or bug fixes of all of these components. + + + +## Development and testing (Definition of Done) + +Standard development and QA practices – followed by the Mojaloop Development/Product Delivery team – include the following as part of the Definition of Done. The recommendation is for the Hub Operator to adopt a similar strategy. + +* Unit tests developed for every piece of code written. +* Code, unit tests, and documentation have been peer reviewed. +* Integration tests have been developed and executed. +* Full regression tests have been executed successfully on commit (merge to master branch). +* Release notes have been created with the following details: + * Description of changes + * List of changed components/services + * List of user stories and bugs in the release + * Highlight of any fundamental (breaking) changes impacting any functionality, API solution, or system architecture +* Deployment runbook created, with deployment and rollback instructions including environment variables, database update scripts, and deployment prerequisites. +* Maintenance of regression test definitions, baseline test results from Mojaloop OSS, and Scheme-specific validation criteria (tests) added on top of them. +* Maintenance of a knowledge base of any new or significant changes to functionality, products, architecture, and so on, regarding Mojaloop OSS and other components, as well as customizations done for the Scheme. The knowledge base acts as the basis of knowledge handover to the Operations team. This handover includes full review of the deployment runbook and other release artifacts, such as release packages and database scripts, which will help the Operations team greatly in day-to-day operations, validation, debugging of issues, and maintenance. + +## Mojaloop releases + +The standard practice for Mojaloop releases is as follows: + +* All new versions of the individual applications, components, and microservices that make up Mojaloop, are available via Helm charts in the public repositories here: +* Unit tests and some functional integration tests are produced with each component version. +* The Mojaloop release also includes automated end-to-end regression tests. Test suites are versioned, with the version number corresponding to the version number of the Mojaloop release. +* A release package is produced, once every Program Increment (PI), for new versions of Mojaloop. This includes upgrades to individual applications, components, and microservices within Mojaloop. \ +\ +A Program Increment is a timeboxed interval during which an Agile team delivers incremental value. +* All Mojaloop maintenance updates, new features, and bug fixes are made available to users of Mojaloop as part of the release cycles, once in each PI period. + +## Product releases of extensions/additional components + +It is recommended that the standard practice for the product releases of extensions/additional components is in line with the Mojaloop release process [above](release-management.md#mojaloop-releases): + +* All new product versions are made available via release packages and described within the release notes. +* A release package includes automated end-to-end tests for each product release. Test suites are versioned, with the version number corresponding to the version number of the product release. +* Product releases are in line with the Mojaloop release cadence, once in each PI period. +* All product maintenance updates, new features, and bug fixes are made available to client DFSPs of extensions/additional products as part of the release cycle, once in each PI period. + +## Bugs and hotfixes + +Bugs and hotfixes are handled in the following way: + +* All bug fixes (both Mojaloop and other products) are included in the release packages. +* Likewise, hotfixes are also provided via a release. It is not recommended to deploy hotfixes directly from the specific application package releases, as deploying only a single component of a release (as opposed to deploying the release that includes the updated component) can result in the Hub being out of sync with the application package release. +* Bugs are tracked, managed, and prioritized as defined in the [defect triage process](defect-triage.md): + * The Service Desk tool is used for managing all bugs. + * A Mojaloop Support Triage team with representatives from both Mojaloop and other Product Delivery and Product Management teams are involved in analyzing urgency and impact to determine prioritization of bugs, including resolution planning/scheduling and communication back to the Hub Operator. + +## Environments and QA strategy + +In order to validate a deployment of a newly released Mojaloop version against the latest other products (extensions/additional components), an environment is to be set up by the Scheme with all the components needed along with the specific configuration that the Scheme uses. This allows the QA/validation and/or Mojaloop Support teams (a team dedicated to running Support services for the technical operations of a Mojaloop Hub) to carry out the deployment and testing of Mojaloop releases against the latest versions of other products. + +::: tip NOTE +The environment set up by the Mojaloop Support team for validation should follow a standard infrastructure, replicating or simulating a corresponding production setup as much as possible, so that any issues, bugs can be identified early in the process. A production setup typically includes API gateways, DMZs, cluster setup based on security zones, along with all the required components and customizations (including Scheme Rules) done by the Scheme. The Hub Operator must ensure that their production infrastructure is fully in sync with the Mojaloop Support team's infrastructure standards. +::: + +Following the successful deployment and validation of a release on the standard infrastructure and architecture, and after successfully running the latest version of Mojaloop and other products, the release is approved and can be shared/made available (via the Support Team's client server/repo). The Hub team can then schedule the deployment into the Hub Operator's (potentially bespoke) environment. + +The QA strategy employed by the Mojaloop and the extension products' Product Delivery teams ensures that new code of each and every service component has undergone comprehensive testing before it gets released. The QA strategy of the Mojaloop Support team, on the other hand, should focus on validating the deployability of the integrated service components and the interoperability of the products, guaranteeing that there is a working Mojaloop Switch, which then can be deployed in a Hub Operator's environment. + +## Release process + +The recommendation for Hub implementations is to stay in line with the Mojaloop release cadence of one release every PI period and avoid deploying individual changes directly from the master branch of specific applications, components, or services within Mojaloop. This recommendation ensures that the integrity of the applications remains cleaner and in line with the source repositories. + +For every release, the Mojaloop Support team is recommended to take the following steps: + +::: tip NOTE +Hub Operators must be informed of the target release date well ahead of time. +::: + +1. The Mojaloop Support team review all release artifacts including release notes and associated documentation, and create or enhance the deployment runbook as soon as the release is made available. +1. The Mojaloop Support team conduct deployment and validation of the planned Mojaloop and other product releases in a temporary Mojaloop Support environment (using the standard Mojaloop Support infrastructure but matching the client's – that is, the Hub Operator's – application versions). +1. Following the successful deployment and validation of a release on the standard Mojaloop Support infrastructure and architecture, and after successfully testing the latest version of Mojaloop and other products, the release is approved and made available to the Hub Operator. +1. The Hub Operator team confirm readiness (and optionally, target deployment window) for the deployment into the Hub Operator's Development environment. \ +\ +It is the Hub Operator's responsibility to carry out deployment into the Development environment and subsequent validation. Alternatively, they can request Mojaloop Support to perform these activities on their behalf. + +### Deployments by the Mojaloop Support team + +If the Hub Operator requests the Mojaloop Support team to perform deployment into the Hub Operator's Development environment, then the Mojaloop Support team sends out an email (or any other form of communication depending on the Hub Operator’s preferences) with information on the target release date, the range of features included in the release, and the deployment window. Following deployment, further communication is sent out to confirm that the deployment has been carried out, validated, and the deployment window has closed. + +## Process flowchart + + \ No newline at end of file diff --git a/docs/adoption/HubOperations/TechOps/service-level-agreements.md b/docs/adoption/HubOperations/TechOps/service-level-agreements.md new file mode 100644 index 000000000..c07bd71d1 --- /dev/null +++ b/docs/adoption/HubOperations/TechOps/service-level-agreements.md @@ -0,0 +1,35 @@ +# Appendix B: Service Level Agreements + +The timelines indicated in the following table are example target response times for handling incidents. They can act as a starting point for the Hub Operator to work out their own timelines. + +::: tip NOTE +The response cannot be an automated response. +::: + + + ++++ + + + + + + + + + + + + + + + + + + + + +
Example incident response timelines and SLA
Incident severityTarget response time

Severity 1

Within 2 hours

Severity 2

Within 4 business hours

Severity 3-4

Within 8 business hours

\ No newline at end of file diff --git a/docs/adoption/HubOperations/TechOps/tech-ops-introduction.md b/docs/adoption/HubOperations/TechOps/tech-ops-introduction.md new file mode 100644 index 000000000..e2a9f3323 --- /dev/null +++ b/docs/adoption/HubOperations/TechOps/tech-ops-introduction.md @@ -0,0 +1,31 @@ +# Introduction – Technical Operations Guide + +The Mojaloop Hub operates a number of environments that need managing and maintaining on a daily basis. The standard procedures described in this document outline the operations processes that enable the Hub Operator to handle all aspects of managing a live service. + +The following procedures need to be in place: + +- [**Incident management**](./incident-management.md): Managing incidents that have been reported to the Technical Operations team or that reached the team via alerts or monitoring activities. + +- [**Problem management**](./problem-management.md): Getting to the root cause of incidents or the potential causes of incidents, and instigating actions to improve or correct the situation at once. + +- [**Change management**](./change-management.md): Controlling the lifecycle of all changes, enabling changes to be made with minimum disruption to IT services. + +- [**Release management**](./release-management.md): Managing, planning, scheduling, and controlling a software change through deployment and testing across various environments. + +- [**Defect triage**](./defect-triage.md): Ensuring that all the bugs identified in the client’s Production environment are captured, evaluated, prioritized, and submitted to the Service Desk. + +A quick overview of the environments managed by the Hub Operator is provided below: + +- **Development**: Non-production software development environment where Mojaloop OSS code is merged with customizations. Gives developers fast test feedback on new code submissions. Digital Financial Service Providers (DFSPs) do not interact with this environment. Developer and QA access only. + +- **User Acceptance Testing (UAT)**: Testing environment for user acceptance and regression testing to validate new releases. + +- **Sandbox (SBX)**: Testing environment to validate DFSP connectivity on both API and security requirements. + +- **Staging (STG)**: Pre-production environment that mirrors production as closely as possible. Validation of new releases and DFSP integration. + +- **Production (PRD)**: Production environment compatible with production release. + +::: tip +A [Glossary](./key-terms-kpis.md) is provided to help clarify common Technical Operations terms used throughout this document. If you encounter a term that needs explaining, it is worth checking the glossary to see if a definition has been provided. +::: \ No newline at end of file diff --git a/docs/adoption/Scheme/platform-operating-guideline.md b/docs/adoption/Scheme/platform-operating-guideline.md new file mode 100644 index 000000000..8a174d79e --- /dev/null +++ b/docs/adoption/Scheme/platform-operating-guideline.md @@ -0,0 +1,555 @@ +# Platform Operating Guideline Template + +- Version: 2.0 + - Author: Carol Coye Benson (Glenbrook), Michael Richards (ModusBox) + - Date: October 2019 + - Description: + +--- + +## **About the Mojaloop Community Business Document Project** + +This document is part of the Mojaloop Community Business Document Project. The project is intended to support entities (countries, regions, associations of providers or commercial enterprises) implementing new payments systems using Mojaloop code. These entities will also need write Business Rules that participants in the system will follow. + +The Mojaloop Community Business Document Project provides templates for Business Rules and related documents. There are many choices involved in implementing a new payment system: the templates show some of the choices and, where appropriate, commentary is provided on how the particular choice is related to the goals of a Level One aligned system. + +The following documents are part of the project: + +- Scheme Key Choices + +- Scheme Participation Agreement Template + +- Scheme Business Rules Template + +- Platform Operating Guideline Template + +- Exception Management Operating Guideline Template + +- Uniform Glossary + +## **Introduction** + +A Scheme implementing a Level One aligned system, including those using Mojaloop reference code in the platform, will need to write Business Rules for the Scheme. A template for those Business Rules is included in this project. The Business Rules introduce the concept of Associated Documents, which are part of the Business Rules and have the same force — DFSPs signing the Business Rules are also bound to follow provisions in Associated Documents. + +The Platform Operating Guideline is an important Associated Document that describes how the Scheme Platform will operate, and specifies the obligations and responsibilities of the Scheme, the Platform Operator, and the DFSPs. + +This document is a template for such a Platform Operating Guideline. Many provisions in it, however, will vary depending on what choices the Scheme has made: some of these choices are described in the "Scheme Key Choices" document which is a part of this project. + +The Business Rules template that is part of this project can be used independent of a scheme's choice of platform. This Platform Operating Guideline is more specific to the use of Mojaloop as a platform. + +## **Table of Contents — Platform Operating Guideline Template** + +[1 - About This Document](#_1-about-this-document) + +[1.1 - Scheme Services](#_1-1-scheme-services) + +[1.2 - Open API Specification](#_1-2-open-api-specification) + +[1.3 - Scheme Use Cases](#_1-3-scheme-use-cases) + +[1.4 - Scheme Supported Identifiers](#_1-4-scheme-supported-identifiers) + +[2 - The Account Lookup Service](#_2-the-account-lookup-service) + +[2.1 - Description of the Account Lookup Service](#_2-1-description-of-the-account-lookup-service) + +[2.2 - Party Request](#_2-2-party-request) + +[2.3 - Parties Query](#_2-3-parties-query) + +[2.4 - Parties Query Response](#_2-4-parties-query-response) + +[3 - The Quote Service](#_3-the-quote-service) + +[3.1 - Description of the Quote Service](#_3-1-description-of-the-quote-service) + +[3.2 - Quote Request](#_3-2-quote-request) + +[3.3 - Quote Response](#_3-3-quote-response) + +[4 - The Transfer Service](#_4-the-transfer-service) + +[4.1 - Description of the Transfer Service](#_4-1-description-of-the-transfer-service) + +[4.2 - Transfer Request](#_4-2-transfer-request) + +[4.3 - Request to Pay](#_4-3-request-to-pay) + +[5 - The Settlement Service](#_5-the-settlement-service) + +[5.1 - Transfer Settlement](#_5-1-transfer-settlement) + +[5.2 - Fee Settlement: Processing Fees](#_5-2-fee-settlement-processing-fees) + +[5.3 - Fee Settlement: Interchange Fees](#_5-3-fee-settlement-interchange-fees) + +[6 - The Scheme Management Service](#_6-the-scheme-management-service) + +[6.1 - Description of the Scheme Management Service](#_6-1-description-of-the-scheme-management-service) + +[6.2 - The Registration Process](#_6-2-the-registration-process) + +[6.3 - DFSP Customer Service](#_6-3-dfsp-customer-service) + +[6.4 - Scheme System Management](#_6-4-scheme-system-management) + +[7 - The Fraud Management Service](#_7-the-fraud-management-service) + +[8 - Appendix: Scheme Supported Use Cases and System Parameters](#_8-appendix-scheme-supported-use-cases-and-system-parameters) + +[9 - Appendix: Merchant Category Codes](#_9-appendix-merchant-category-codes) + +## 1. About This Document + +These Platform Operating Guidelines specify operational and technical requirements for DFSPs and for the Scheme. From time to time the Scheme will issue additional Operational Bulletins, which will describe additional operational features of the Scheme and specify additional requirements of DFSPs. + +### 1.1 Scheme Services + +- Scheme Services are used by DFSPs to exchange interoperable transactions, and to manage their involvement with the Scheme. + +- The Scheme Account Lookup Service enables DFSPs in the system to identify the DFSP who manages the Transaction Account for an intended Payee or other counterparty to a Transfer. + +- The Scheme Transfer Service enables a Payer DFSP to send a Transfer to a Payee DFSP, thereby effecting a transfer of funds from a Payer to a Payee. + +- The Scheme Settlement Service enables DFSPs to settle their financial obligations to the Scheme with respect to Transfers. + +- The Scheme Management Service enables the Scheme to grant and revoke access to Scheme by DFSPs, manages the ongoing interactions of DFSPs with Scheme, monitors the effective operation of Scheme, and provides tools for DFSPs to manage their involvement with Scheme. + +- The Scheme Fraud Management Service enables DFSPs to collaborate on certain elements of fraud management in order to reduce costs and improve results. + +- DFSPs are required to follow the procedures detailed below for using Scheme. + +### 1.2 Open API Specification + +Scheme protocols are based on the operational and data models defined in the specifications document "Open API for FSP Interoperability Specification" version 1.0 dated \[xx\]. Where the Scheme departs from this specification, such departures are documented here and will supersede the relevant sections of that document. The Scheme may update the version used by issuing an Operational Bulletin. + +### 1.3 Scheme Use Cases + +Some rules and operational specifications vary by Use Cases and Secondary Use Cases supported by Scheme. Scheme recognizes Use Cases and Secondary Use Cases by a combination of required data components and system inference. This is detailed in an Appendix to this document. + +### 1.4 Scheme Supported Identifiers + +The Scheme supports certain Identifiers, or payment addresses, for use in making Transfers. The Identifier identifies the Payee whose Transaction Account is credited for the Transfer. Supported Scheme Identifiers are listed in an Appendix to the Business Rules. + +For each scheme supported identifier, this document should specify what the identifier is and how it is resolved (how it is determined which Payee DFSP is responsible for the transaction account associated with that identifier. + +#### 1.4.1 Example: The MSISDN Identifier + +Each scheme will have its own guidelines for each identifier; the provisions below could vary significantly depending on choices made. + +- MSISDN's are mobile numbers which are globally unique. MSISDN's are the Transaction Account Identifier for DFPSs who are Mobile Network Operators and who are providing Transaction Accounts to their customers. + +- Use of the MSISDN as a Payee Identifier is limited to Transaction Accounts provided by DFSPs who are the Mobile Network Operator responsible for that MSISDN. + +::: tip NOTE +If MSISDN's are used for other Transaction Accounts, they are aliases, and a separate protocol for resolving them must be specified. +::: + +- A Party Request for an MSISDN is resolved by a MSISDN directory service determined by the Scheme. The Scheme may specify directory service maintenance obligations for Mobile Network Operator DFSPs from time to time. + +#### 1.4.2 Example: The Bank Account Number Identifier + +Each scheme will have its own guidelines for each identifier; the provisions below could vary significantly depending on choices made. + +- Bank Account numbers are assigned to customers by Bank DFSPs who are providing Transaction Accounts to their customers. + +- The Bank Account Number, together with a Bank Code, form the Scheme Bank Account Number Identifier. Payer DFSPs are responsible for correctly formatting the Bank Account Number Identifier according to formats that will be specified by the Scheme. + +- Use of the Bank Account Number Identifier is limited to Transaction Accounts which are provided by DFSPs who are Banks. + +- A Party Request for a Bank Account Identifier is sent by the Payer DFSP to Scheme. Scheme checks that the Bank Code in the Bank Account Identifier is associated with a Bank active in Scheme. + +#### 1.4.3 Example: The Scheme Merchant Identifier + +Each scheme will have its own guidelines for each identifier; the provisions below could vary significantly depending on choices made. + +- The Merchant ID is a Scheme-defined identifier used for person-to-business payments. + +- Use of the Merchant ID is limited to DFSPs who are providing Transaction Accounts to merchants, billers, government agencies or other enterprise entities who are receiving payments from their customers over Scheme. It may be used for both in-person and remote payments. The term "merchant" used in this section includes all of these types of receivers of payments. + +- Use of the Merchant ID is limited to Transfers of the P2B or P2G Use Cases + +- A merchant may request multiple merchant IDs from their DFSP; these may be used by the merchant for different outlets, tills, or stores. There is no limit to the number of merchant IDs that can be linked to a single Transaction Account. A given merchant ID, however, may only be linked to a single Transaction Account. + +- The Merchant ID is issued by Scheme to the DFSP who is providing the merchant with the Transaction Account into which payments will be made. + +- The Merchant ID is issued as a number, which may be displayed by a merchant physically or digitally. + +- Merchant ID's may be rendered as QR codes by DFSPs or their merchant customers. QR codes must be rendered under format and brand guidelines that will be issued by the Scheme. DFSPs are prohibited from using other QR code data formats or brands to receive payments through Scheme. + +- DFSPs are required to display Scheme branding. Scheme brand requirements will be specified by the Scheme. Scheme branding must be visible to the customer in the merchant store, or on the device the paying customer is using to purchase remotely. + +- Registration Requirements. DFSPs will request a Merchant ID for a customer using a Scheme API specific to this purpose. DFSPs will be required to provide: + + - DFSP ID + + - The Transaction Account number which will receive the funds paid to the merchant. This may be either an MSISDN or a bank account number. + + - The \[business registration or tax ID\] of the merchant. Any number of merchant IDs may be associated with the same business registration or tax ID. + + - The Merchant Name + +- DFSPs requesting a Merchant ID from Scheme warrant that they have completed the required KYC information for the merchant account at the time of the request. + +- DFSPs are required to provide adequate training information to their customers. + +- Disabling Merchant IDs. DFSPs may request that a Merchant ID be disabled. Scheme will immediately disable this Merchant ID, but will retain it in the Scheme system for reporting purposes. Quote Requests or Transfer Requests made to this Merchant ID will be refused by Scheme and returned the Payer DFSP. + +The Scheme may wish to provide some mechanism for porting a Merchant ID from one DFSP to another. + +#### 1.4.4 The Scheme ID Identifier + +This ID would be similar to the Merchant ID above but would be meant for consumers as well as businesses, and could be expressed in phrases rather than as a number. Note each scheme will have its own guidelines for each identifier; the provisions below could vary significantly depending on choices made. + +- The Scheme ID is a Scheme-defined identifier. + +- DFSPs are required to offer their customers the option of requesting a Scheme ID. + +- Scheme IDs can be in any form, subject only to restrictions of length which Scheme will specify from time to time. Scheme reserves the right to refuse the use of any specific requested Scheme ID. + +Schemes may wish to enable Scheme ID's + +- Customers may request any number of Scheme IDs, subject to limits imposed by their DFSP. Multiple Scheme IDs can be associated with a single Transaction Account. Each Scheme ID, however, can be associated with only a single Transaction Account. + +- Registration Requirements. DFSPs will request a Scheme ID for a customer using a Scheme API specific to this purpose. DFSPs will be required to provide in this API: + + - DFSP ID + + - The requested Scheme ID + + - The Transaction Account number which will receive the funds paid to the customer. This may be either an MSISDN or a bank account number. + + - If the Transaction Account Holder is a merchant or business, the \[business registration or tax ID\] of the Account Holder. Any number of Scheme IDs may be associated with the same business registration or tax ID. + +- DFSPs requesting a Scheme ID from Scheme warrant that they have completed the required KYC information for the customer account at the time of the request. + +- Disabling Scheme Identifiers. DFSPs may request that a Scheme ID be disabled. Scheme will immediately disable this Scheme ID, but will retain it in the Scheme system for reporting purposes. Quote Requests or Transfer Requests made to this Scheme ID will be refused by Scheme and returned to the Payer DFSP. + +The Scheme may wish to provide some mechanism for porting a Scheme ID from one DFSP to another. + +The following sections describe each service and the obligations and responsibilities of stakeholders. Each service consists of processes: most of the processes are linked to specific API calls specified in the [Open API Specification](#_1-2-open-api-specification) section of this document. + +## 2. The Account Lookup Service + +### 2.1 Description of the Account Lookup Service + +- The Account Lookup Service allows DFSPs to map specific Identifiers for individual customers to the DFSP that provides a Transaction Account for that customer. Identifiers are used to identify individuals, merchants, billers, government agencies or other enterprises. Any Identifier Type supported by Scheme has a defined Identifier Service, the parameters of which are shown in the section "Scheme Supported Identifiers" of this document. + +- All Identifier Services ensure that Identifiers used for Scheme Transactions are unique within Scheme and are associated with a single DFSP who provides the relevant Transaction Account for that customer. Any Identifier must be associated with a single Transaction Account. + +- DFSPs must complete the Account Lookup process immediately before initiating a Quote process unless otherwise permitted in these Guidelines. + +### 2.2 Party Request + +- A Party Request is sent by a Payer DFSP to the Platform. The Party Request must contain the following key data elements: + + - The Identifier for the intended Payee + + - The Payer DFSP identifier + +The scheme may define additional key data elements which will be required in the Parties Request. + +- The request is forwarded from the Platform to the Account Lookup Service for that Identifier type. + +- The Identifier Service returns to the Account Lookup Service the identification of the DFSP associated with that Identifier, if a reference is found. If it is not, a negative response is returned and this is communicated by the Platform to the Payer DFSP. If a reference is found, the Account Lookup Service then associates the identified DFSP with the correct Scheme DFSP ID. + +### 2.3 Parties Query + +- If the Party Request succeeds in identifying a Payee DFSP, the Platform then executes a Parties Query to the identified DFSP to determine if the DFSP is willing to accept a Quote Request directed to that Identifier. + +### 2.4 Parties Query Response + +- The identified DFSP responds either with a positive Parties Query Response or with an error response. If positive, the Parties Query Response must contain the following key data elements: + + - The full Name of the Payee + + - The Payer DFSP Identifier + + - The Transaction Account Type, which specifies whether the Account is a bank account or a wallet + + - The Transaction Account Holder Type, which specifies whether the Transaction Account Holder is a consumer, a merchant (including other enterprise types) or a government agency. + + - If the Payee is a Merchant, the Merchant Category Code. These codes are found in an appendix to this document. + +The scheme may define additional data elements required in the Parties Query Response. + +- The Platform responds to the Payer DFSP with the result of the Parties Query Response + +## 3. The Quote Service + +#### 3.1 Description of the Quote Service + +- The Quote Process precedes the Transfer Process, and allows the Payer and Payee DFSP to exchange certain information prior to the Transfer. + +- The Quote Process must be completed before a Payer DFSP initiates the Transfer Process. This is true for all Use Cases and Secondary Use Cases. + +- The steps in the Quote Process are shown below. + +#### 3.2 Quote Request + +- A Quote Request is sent by a Payer DFSP to the Payee DFSP; the Quote Request is recorded by the Platform. The Quote Request must contain the following key data elements: + + - The Transfer Amount + + - The Amount Type set as a Send Amount. + + - The complete set of Party Information that was returned from the Parties Request Response. + + - The Full Name of the Payer (the Transaction Account Holder at the Payer DFSP) + + - Transaction Type data required for the Use Case and Secondary Use Case of the Transaction, as specified in the Use Case Appendix to this document. + + - An expiry time, the allowable parameters of which will be specified by the scheme from time to time. + +The scheme may define additional key data elements which will be required in the Parties Query Response. + +- A Quote Request for an amount above the Scheme Transaction Value Limit will be rejected by the Platform and returned to the Payer DFSP. + +### 3.3 Quote Response + +- A Quote Response is sent by the Payee DFSP to the Payer DFSP; the Quote Response is recorded by the Platform. The Payee DFSP is required to respond to a Quote Request. + +- The Quote Response must contain the following key data elements: + + - The Transfer Amount + + - An expiry time, the allowable parameters of which will be specified by the Scheme from time to time. + + - The signed Transaction Object which contains the parameters of the transfer. The Transaction Object is the authoritative description of the transaction for the purposes of Scheme reporting, fraud management and dispute resolution. + +The scheme may define additional key data elements which will be required in the Parties Query Response. + +- The Quote Response is signed by the Payee DFSP and defines the parameters of the Transaction; the Payer DFSP cannot change these parameters in the Transfer Process. + +## 4. The Transfer Service + +### 4.1 Description of the Transfer Service + +- The Transfer Service is the means by which the actual transfer of funds is accomplished between Payer DFSP and Payee DFSP. The Transfer Request is the key process within the service. A Transfer Request must be preceded by a Quote process. + +### 4.2 Transfer Request + +- A Transfer Request is sent by a Payer DFSP to the Payee DFSP via the Transfer Service at Scheme. The Platform records the Transfer Request. The Transfer Request must contain the following key data elements: + + - The Payer and Payee DFSP Identifiers + + - The Transaction Amount + + - An ILP packet representing the Transaction Object + + - An expiry time, the allowable parameters of which will be specified by the Scheme from time to time. + +The scheme may define additional key data elements which will be required in the Transfer Request. + +- The Transfer Request is signed by the Payer DFSP + +- The Platform performs a Transfer Approval process to determine if the proposed Transfer can be settled. The Transfer Approval process is further defined in the Settlement Service section of this document. + +- If the Transfer Request fails the Transfer Approval process, the Transfer Request is returned to the Payer DFSP. + +- If the Transfer Request passes the Transfer Approval process, the Platform reserves the funds specified in the Transfer Request in the Payer DFSP's Position Ledger. This is further defined in the Settlement Service section of this document. + +- The Payee DFSP determines if they will accept the Transfer. + +- If not accepted, an error response is returned to the Platform. The Platform releases the reservation of funds in the Payer DFSP's Position Ledger and returns an error condition to the Payer DFSP. + +- If accepted, the Payee DFSP returns a signed Transfer Response indicating that the Transfer has been Fulfilled. The Platform replaces the provisional debit with a debit in the Payer DFSP's Position Ledger and credits the Payee's DFSP's Position Ledger with a credit in the amount of the Transfer. + +- The Platform then sends a confirmation of the fulfilled Transfer to the Payer DFSP and to the Payee DFSP. + +- If the Platform does not receive a signed Transfer Response within the expiry period in the Transfer Request, the transfer will be cancelled and Scheme will notify the Payee and Payer DFSPs of this. + +- Payer and Payee DFSPs are required: + + - To notify their customers of the status of a transfer on a timely basis + + - To immediately debit and credit the Transaction Accounts of their customers upon fulfillment of the Transfer + + - To release any reserved funds immediately if a Transfer has been refused or cancelled + +### 4.3 Request to Pay + +_This section has not yet been written._ + +## 5. The Settlement Service + +This document presents a template for the settlement processes both for transfers and for scheme fees. There are multiple possible approaches to settlement, which are discussed in the "Key Choices" document that is part of this project. The template below covers two models: net settlement and continuous gross settlement. Mojaloop reference code supports a number of different settlement models, including these. + +### 5.1 Transfer Settlement + +#### 5.1.1 Description of the Transfer Settlement Service + +- Transfer Settlement is the means by which DFSPs settle their financial obligations to each other. There are five processes to Transfer Settlement: the Ledger Process, the Net Debit Cap Process, the Transfer Approval Process, the Settlement Posting Process and +the Settlement Account Management Process. + +- \[_Net settlement option_\] DFSPs are required to open a Settlement Bank account with the Scheme Settlement Bank. \[_Continuous gross settlement option_\] DFSPs are required to become joint owners of the Scheme Pooled Settlement bank account at the Scheme Settlement Bank, and to use or open such other individual bank accounts at the Scheme Settlement Bank as necessary to transfer funds into and out of the Scheme Pooled Settlement bank account. + +#### 5.1.2 The Platform Ledger + +- The Platform is responsible for maintaining a DFSP Position Ledger for each DFSP. This operation runs on a continual basis. \[_Continuous gross settlement option_\] The DFSP Position Ledger of each DFSP, less any provisional entries, represents the ownership share of that DFSP in the Scheme Pooled Settlement Bank Account. + +- The Position Ledger records: + + - All Fulfilled Transfer as debits to the Payer DFSP's ledger and credits to the Payee DFSP's ledger + + - All Transfer Requests as provisional debits to the Payer DFSP's ledger. These provisional debits are removed when the Transfer is Fulfilled, refused by the Payee DFSP, or expires. + + - \[_Net settlement option only_\] Settlement Entries delivered to and accepted by the Scheme Settlement Bank for that DFSP. + + - \[_Continuous gross settlement option only_\] Transfers into and out of the Scheme Pooled Settlement Bank account made by DFSPs. + +- The DFSP Ledger Position is the sum of all of the items listed above. This is used in the Transfer Approval Process. + +#### 5.1.3 Net Debit Cap Process + +- The Net Debit Cap for a DFSP is a value that the Platform uses during the Transfer Approval Process. The Net Debit for a DFSP is the sum of: + + - \[_Net Settlement Option only_\] A value set by the scheme that is intended to represent the funds the DFSP has available in its Settlement Bank Account + +Note the scheme may be able to automate the calculation of value described above, or it may choose to manually input this into the Platform Operator section of the Scheme Portal. + +- The Scheme Margin for that DFSP. This is a value, determined by the Scheme, that is specific to a given DFSP. This value may be a percentage of the DFSP Ledger Position or it may be an absolute value. The Scheme may change the Scheme Margin for any DFSP at its discretion. It may have the effect of either increasing or decreasing a DFSP's ability to execute transactions. + +- The DFSP Discretionary Margin. This is a value, determined by an individual DFSP, which lowers the absolute value of the Net Debit Cap. The DFSP Discretionary Margin is set within allowable parameters defined by the Scheme. This has the effect of decreasing the DFSP's ability to execute transactions. + +#### 5.1.4 Transfer Approval Process + +- Transfer Approval. When the Platform receives a Transfer Request from a Payer DFSP, the Platform will approve or reject the request based on a comparison of the amount of the requested transfer to the Payer DFSP's Current Ledger Position less the Payer DFSP's Net Debit Cap. + +- If the requested transfer is less this sum, the Platform will forward the request to the Payee DFSP. If it is more than the value of the Net Debit Cap, the Platform will reject the request and return it to the Payer DFSP. + +#### 5.1.5 Settlement Posting Process + +- \[_Net settlement option only_\] The scheme will define the parameters of the Settlement Windows used for the scheme; this will include the frequency of windows or other parameters (value limits, etc.) chosen for defining settlement windows. + +- \[_Net settlement option only_\] At the end of each defined settlement window, the Platform will calculate the net settlement position of every DFSP: this position is the balance in the DFSP Position Ledger. These balances become the Settlement Entries for that window. + +- \[_Net settlement option only_\] The Platform will send Settlement Entries for each DFSP to the scheme-chosen Settlement Bank + +- \[_Net settlement option only_\] The Settlement Bank will post Settlement Entries to the Settlement Bank Account of each DFSP, and send confirmation to the Platform of the completion of this process. + +Scheme rules will need to account for provisions and procedures in the event of a failure of the process described above. + +#### 5.1.6 Settlement Account Management Process + +- \[_Net settlement option_\] DFSPs may add funds to their Scheme Settlement Bank Account at their discretion. The Scheme will provide instructions on how to do this. \[_Continuous Gross settlement option_\] DFSPs may transfer funds into the Scheme Pooled Settlement Bank Account at their discretion. The Scheme will provide instruction on how to do this. + +- \[_Continuous Gross Settlement option only_\] The Scheme will provide and end-of-day report to DFSPs showing their share of ownership in the Scheme Pooled Settlement Bank Account. + +- DFSPs may request withdrawal of funds from their \[_Net settlement option_\] Settlement Bank Account through the Scheme Portal \[_Continuous gross settlement option_\] DFSPs may request withdrawal of funds from the Scheme Pooled Settlement Bank Account through the Scheme Portal. The scheme will review the requested withdrawal, and, if approved, execute the transfer on behalf of the DFSP. The purpose of this review is to ensure that a DFSP's share of the Settlement Bank Account is sufficient to support Transfers in process: this approval will not be unreasonably denied. + +#### 5.1.7 Scheme Settlement Reporting + +- The scheme will provide, through the Scheme DFSP Portal, information for DFSPs which includes for each DFSP: + + - The current Net Debit Cap and its components + + - The current Ledger Position and its components, including Fulfilled Transfers for all DFPSs and Provisional Transfers for Payer DFSPs + + - Alerts at certain levels of the Current Ledger Position: these levels to be determined by the DFSPS and/or the Scheme from time to time + +- Tools to enable DFSPs to forecast their anticipated transfer volume based on historical data + +### 5.2 Fee Settlement: Processing Fees + +This section is not yet written. + +### 5.3 Fee Settlement: Interchange Fees + +This section is not yet written. + +## 6. The Scheme Management Service + +::: tip NOTE +There is a parallel Platform Operator Service that is necessary for the operation of the platform which is not described in this document. +::: + +### 6.1 Description of the Scheme Management Service + +- The Scheme Management Service is provided by the Scheme to assist DFSPs in their use of Scheme Services. Many of these functions are provided through the Scheme Portal, which is made available to Scheme DFSPs. + +- The following processes are part of the Scheme Management Service: + +### 6.2 The Registration Process + +- The Registration Process enables DFSP application for participation and for operational and technical on-boarding. It covers the following areas: + + - Forms and processes for DFSP application for Participation in Scheme. + + - Forms and processes for obtaining digital certificates and digital signatures for use with the Platform. + + - Processes for downloading Scheme-provided software artifacts including SDKs and APIs. + + - Processes for testing technical readiness to access the Platform and Services. + + - Processes for receiving Scheme approval and certification for accessing the Platform and Services. + +### 6.3 DFSP Customer Service + +- The scheme will provide both an online and a telephone help desk for DFSPs. + +- The Scheme Portal will provide means by which DFSPs can designate Portal administrators and users, and update DFSP Profile information. + +### 6.4 Scheme System Management + +- The scheme will provide, through the Scheme Portal, means by which DFSPs can see their current Position Ledger, their Net Debit Cap, and their recent and historical activity with Scheme. + +- The scheme will provide, through the Scheme Portal, means by which DFSPs can use historical data, including their Positions and Net Debit Cap histories, to forecast upcoming volumes and required settlement funding levels. + +- The scheme will provide means by which DFSPs can obtain updates to software artifacts that they have previously downloaded. + +- The scheme will provide, through the Scheme Portal, means by which DFSPs can request a withdrawal from their share of the Scheme Settlement Bank Account. + +- The scheme will provide, through the Scheme Portal, means by which DFSPs can view their share of the balance in the Scheme Settlement Bank Account. + +## 7. The Fraud Management Service + +_This section has not yet been written, but is expected to include the +following sections:_ + +1. _Description of the Fraud Management Utility — Purpose and Scope_ + +2. _The Shared Transaction Database_ + +3. _Fraud Categorization Scheme_ + +4. _Reporting of Known Bad Actors or Transactions_ + +5. _Anomaly and Fraud Detection Algorithms and Processes_ + +6. _DFSP Reporting_ + +7. _Real-time Transaction Interception Options_ + +## 8. Appendix: Scheme Supported Use Cases and System Parameters + +_This is the same table as appears in the Business Rules document, but it has added the systemic codes necessary for the Platform to recognize a transaction as belonging to a given use case or secondary use case. A scheme would only define Secondary Use Cases if it wanted to write rules and/or specify fees that are unique to that Secondary Use Case._ + +_This table is an example of a table of Use Cases and Secondary Use Cases that a scheme might support._ + +| Use Case Code | Use Case | Secondary User Case | Required Data Elements | Other Methods of Use Case Determination | +| :--- | :----- | :--------- | :-------------------------- | :------------------------------------------- | +| 1.0 | P2P | Person to Person | API Setting
Scenario=Transfer

Initiator = Payer

Initiator Type = Consumer

Recipient Type = Consumer
| | +| 1.1 | P2P | Wallet to wallet | Transaction Account Type for Payer DFSP is Wallet and for Payee DFSP is Wallet | +| 1.2 | P2P | Bank to bank | Transaction Account Type for Payer DFSP is Bank and for Payee DFSP is Wallet | +| 1.3 | P2P | Wallet to bank | Transaction Account Type for Payer DFSP is Wallet and for Payee DFSP is Bank | +| 1.4 | P2P | Bank to Wallet | Transaction Account Type for Payer DFSP is Bank and for Payee DFSP is Wallet. | +| 2.0 | Bulk Payment | | API Settings
Scenario=Transfer

Initiator = Payer

Recipient Type = Consumer
| +| 2.1 | B2P | Bank to bank | Initiator Type = Business | +| 2.2 | G2P | Government to Person | Initiator Type = Government | +| 3.0 | P2B | Person to Business | API Settings
Scenario=Transfer

Initiator = Payer

Initiator Type = Consumer

Recipient Type = Business
| +| 3.1 | P2B | Till Number Purchase | Initiator Type = Device | | +| 3.2 | P2B | QR code Purchase | tbd | | +| 3.3 | P2B | Online Purchase | Merchant ID Code = tbd | | +| 3.4 | P2B | Bill Payment | | tbd: a data element in the Quote Request will include the Payer’s account number at the biller | +| 3.5 | P2B | Person to Business - Other | | | +| 4.0 | P2G | | API Settings
Scenario=Transfer

Initiator = Payer

Recipient Type = Government
| +| 4.1 | P2G | Person to Government | | | +| 4.1 | P2G | Till Number Purchase | Initiator Type = Device | | +| 4.2 | P2G | QR code Purchase | tbd | | +| 4.3 | P2G | Online Purchase | Merchant ID Code = tbd | | +| 4.4 | P2G | Bill Payment | | tbd: a data element in the Quote Request will include the Payer’s account number at the biller | + +## 9. Appendix: Merchant Category Codes + +_The scheme will want to specify codes to recognize the type of merchant being paid. The term "merchant" here is used broadly to include all types of non-consumer payments acceptors. A merchant category code scheme might want to recognize industries, domains (in-person stores vs remote or online) and/or merchant size._ diff --git a/docs/adoption/Scheme/scheme-business-rules.md b/docs/adoption/Scheme/scheme-business-rules.md new file mode 100644 index 000000000..cd76ddded --- /dev/null +++ b/docs/adoption/Scheme/scheme-business-rules.md @@ -0,0 +1,543 @@ +# Scheme Business Rules Template + +- Version: 4.0 + - Author: Carol Coye Benson (Glenbrook) + - Date: October 2019 + - Description: + +--- + +## **About the Mojaloop Community Business Document Project** + +This document is part of the Mojaloop Community Business Document Project. The project is intended to support entities (countries, regions, associations of providers or commercial enterprises) implementing new payments systems using Mojaloop code. These entities will also need write Business Rules that participants in the system will follow. + +The Mojaloop Community Business Document Project provides templates for Business Rules and related documents. There are many choices involved in implementing a new payment system: the templates show some of the choices and, where appropriate, commentary is provided on how the particular choice is related to the goals of a Level One aligned system. + +The following documents are part of the project: + +- Scheme Key Choices + +- Scheme Participation Agreement Template + +- Scheme Business Rules Template + +- Platform Operating Guideline Template + +- Exception Management Operating Guideline Template + +- Uniform Glossary + +## **Introduction** + +Payments Schemes around the world are in the process of implementation, or considering implementation, of Mojaloop-based payments systems. Mojaloop is open-source software for financial services companies, government regulators, and others taking on the challenges of interoperability and financial inclusion. The Bill & Melinda Gates Foundation has provided funding and support for Mojaloop through The Level One Project, a vision for digital financial markets based on principles of interoperability, collaboration, and inclusion. + +Schemes implementing Mojaloop will need to write Business Rules which govern the rights and responsibilities of participants in the system. This document provides a template for those Business Rules. The template is structured as a detailed outline: the actual wording of rules will be determined by implementing Schemes and the jurisdictions within which they operate. In many parts of the document, we simply suggest a topic which a Scheme might want to consider writing a rule about: again, the specifics of the rule will vary by Scheme. + +Before Business Rules are written, Schemes need to make major business decisions about how the system and its ecosystem partners will work. These decisions are described in a separate document within the Mojaloop Community Business Document Project, "Scheme Key Choices". People are encouraged to read that document first. + +Scheme Business Rules Template + +## **Table of Contents** + +[1 - About These Scheme Business Rules](#_1-about-these-scheme-business-rules) + +[2 - Scheme Goals](#_2-scheme-goals) + +[3 - Participation in Scheme](#_3-participation-in-scheme) + +[4 - Scheme Business Rules](#_4-scheme-business-rules) + +[5 - Responsibilities and Obligations of the Scheme](#_5-responsibilities-and-obligations-of-the-scheme) + +[6 - Participant Responsibilities and Obligations of Participants](#_6-participant-responsibilities-and-obligations-of-participants) + +[7 - Liability - Allocation of Responsibilities](#_7-liability-allocation-of-responsibilities) + +[8 - Security, Risk Management, and Data Confidentiality](#_8-security-risk-management-and-data-confidentiality) + +[9 - Scheme Platform and Services](#_9-scheme-platform-and-services) + +[10 - Exception Management](#_10-exception-management) + +[11 - Appendix: Associated Documents](#_11-appendix-associated-documents) + +[12 - Appendix: Onboarding and Exit Processes](#_12-appendix-onboarding-and-exit-processes) + +[13 - Appendix: Scheme Services](#_13-appendix-scheme-services) + +[14 - Appendix: Scheme Supported Use Cases](#_14-appendix-scheme-supported-use-cases) + +[15 - Appendix: Scheme Fee Schedule](#_15-appendix-scheme-fee-schedule) + +[16 - Appendix: Risk Management, Security, Privacy, and Service Standards](#_16-appendix-risk-management-security-privacy-and-service-standards) + +## **A Guide to This Document** + +Section Headings and bulleted entries underneath section headings are actual proposed wording, or suggested sections for a rules document. Text in italics are comments which can be used when a scheme drafts the actual language of a rules document. + +## 1. About These Scheme Business Rules + +### 1.1 These are the Scheme Business Rules + +::: tip NOTE +The Mojaloop software can be used for bilateral exchanges among DFSPs, as well as within a Scheme structure that uses a switch. This document assumes the latter; that the Scheme is either providing, hiring, or otherwise arranging that interoperable transactions are exchanged through a switch. Some of the concepts in these rules apply only to this configuration; others would be useful in bilateral agreements as well. +::: + +### 1.2 Scheme Ownership + +
    Who owns the scheme, what opportunities exist for ownership participation. Reference to other documents (charter, by-laws, etc.)
+ +### 1.3 Defined Associated Documents + +- These rules include the Associated Documents listed in an Appendix to these rules. Associated Documents are part of, and have the force of, the Operating Rules. + +
    Associated Documents should include the Platform Operating Guideline and the Uniform Glossary. This does not include various technical documents that may be referenced in the Business Rules or the Platform Operating Guideline.
+ +### 1.4 Scheme Business Rules are Binding on Participants + +
    This repeats the provision in the Scheme Participation Agreement. Note that Scheme Business Rules are only binding on the DFSPs that participate in the Scheme. The Scheme may write rules that require certain provisions of these rules be passed on to Participant customers (for example, merchants) or partners (for example, processors) - but this is an obligation of the Participant to the Scheme, not the other parties.
+ +### 1.5 Rules May Be Amended + +
    Details of amendment process are specified elsewhere.
+ +### 1.6 Terms are Defined in Uniform Glossary + +
    The glossary is a separate document, rather than be internal to the Business Rules document. This is to ensure consistency in terminology as the service evolves and the Platform Operating Guideline changes.
+ +## 2. Scheme Goals + +
    This is a section that allows a Scheme to state the objectives of the Scheme. We suggest support of interoperable financial transactions, financial inclusion, and gender equality. This is also an opportunity to reference support for the Level One Project Design Principles, a national or regional payments strategy (or digital economy strategy), or a Scheme-specific set of design principles.
+ +## 3. Participation in Scheme + +### 3.1 Participation Eligibility + +- Eligibility Criteria + +
    A statement as to which types of institutions are eligible to apply to be a participant in the Scheme. The Level One design principle is that any licensed provider of transaction accounts in a jurisdiction covered by the Scheme should be eligible to apply
+ +- Approval Criteria + +
    Scheme provisions for acceptance of applications, including high level statements of required information from applicant, such as demonstration of a sustainable ability to meet financial obligations and compliance obligations. The actual application process is in an Appendix to these Rules. The technical certification requirements can be listed in the Platform Operating Guideline.
+ +### 3.2 Licensing + +
    This concept may or may not apply when the Scheme operator is a government entity. If the concept to licensing is not included in the rules, there needs to be a provision in "Participation Eligibility" section with respect to terminating a participant.
+ +- A Participant is granted a License to participate in the Scheme and to use the Scheme Property in accordance with the Scheme Business Rules. + +- A Participant may use Scheme Property only in accordance with the Scheme Business Rules. Licenses will limit use of Scheme Property to the Participant's provision of services in connection with the Scheme and according to the Rules. + +- Licenses will not be exclusive. + +### 3.3 Tiered Access + +
    Schemes may choose to allow some applicants to access join the Scheme as indirect participants. This section specifies the conditions for this. Some Schemes separately enable technical indirect participation and settlement indirect participation.
+ +
    If this is allowed, defined terms (such as Sponsor Bank and Indirect Participant) are required. This section should clearly show what the obligations of each party are; this can refer to the obligation sections appearing later.
+ +### 3.4 Departure from Participation + +
    Provisions for Scheme suspension or termination of a Participant's participation in the Scheme. The Scheme may suspend, limit or disqualify a Participant from participating in the Scheme if it determines that the Participant's inability to observe a Rule unduly burdens the Scheme or other Participants or poses undue risks to the integrity of the Scheme or the reputation of the Scheme
+ +
    Provisions for Participants to terminate their participation in the Scheme
+ +## 4. Scheme Business Rules + +### 4.1 Scope of the Scheme Business Rules + +- These Rules apply to each Participant and govern the rights and responsibilities of Participants and of the Scheme. + +- These Rules may be superseded to the extent that they conflict with any Applicable Laws. Nothing in these Rules shall be applied to require the Scheme or any Participant to violate Applicable Law. + +- All matters regarding interpretation of the Rules and all disputes arising in connection with participation in the Scheme will be subject to the laws of \[xxxx\] + +
    Provisions should be made for resolution of disputes among Participants or between Participants and the Scheme.
+ +### 4.2 Changes to the Scheme Business Rules + +- Participants may from time to time provide suggestions or requests for modification of the Rules. + +- Participant suggestions for modifications to the Rules may be used by the Scheme or by other Participants in connection with the Scheme without compensation or attribution to the Participant who makes the suggestion or request. + +- Changes to the Rules will be made according to a consultative procedure: + +- A Participant(s) or the Scheme may propose a change to the Scheme Business Rules. + +- The Scheme will publish proposals to all Participants and request comments and suggestions on these; all comments received will be published to all participants. + +- The Scheme may include with the publication of a proposed change its independently determined suggestion for the wording of a change in the Rules, + +
    Scheme should have a defined process for adopting changes, which may include Participant voting or decision by the Scheme. If there is voting, rules here should specify the parameters.
+ +- The Scheme may grant variances to the Rules upon application from Participants. + +- Provisions for urgent changes may be made by the Scheme to meet risks or regulatory requirements. + +## 5. Responsibilities and Obligations of the Scheme + +### 5.1 Defining and Providing Scheme Services + +- The Scheme defines the set of Scheme Services that are provided to Participants. The defined list of Scheme Services is shown in an Appendix to these Rules. + +
    Scheme Services
+ +- The Scheme specifies how Scheme Services are provided to Participants - they may be operated by the Scheme entity, by another entity under contract to the Scheme, or there may be some other arrangement. This section gives the Scheme the right to define new services, change existing services, etc. + +- The Scheme may define service level standards for itself, and for participants in using these services + +- For outsourced Platform services, the Scheme specifies services to be provided. The Scheme may specify the service level agreements for providers of these services + +- For the Scheme Settlement Service, the Scheme selects and contracts with a Settlement Bank(s) for inter-Participant Settlement. + +- The Scheme establishes a Transaction Value Limit which sets the maximum value of any Transfer made through the Scheme Platform. DFSPs may set lower values for their customers. + +- The Scheme should consider if it will guaranty to the Payee DFSP any Fulfilled Transfer made in accordance with these Rules + +
    The Scheme should consider if it will guaranty to the Payee DFSP any Fulfilled Transfer made in accordance with these Rules.
+ +### 5.2 Writing, Updating, and Maintaining the Rules + +- The Scheme writes, updates, and maintains the Business Rules. + +- The Scheme is responsible for informing Participants of any changes to the Rules, all fees, policies that may impact Participants' use of the Scheme, or any other important and relevant information. + +- The Scheme is responsible for establishing a policy, and communicating this to Participants, for enforcement of the Rules; + +- The Scheme is responsible for establishing policies with respect to granting variances to the Rules to Participants, + +### 5.3 Other Scheme Responsibilities + +- The Scheme administers Participant on-boarding and exit processes. These processes are listed in an Appendix to these rules. + +- The Scheme monitors the ongoing eligibility of Participants under the requirements established for Participation + +- The Scheme defines a set of Use Cases and Secondary Use Cases. These are listed in an Appendix to these rules + +- The Scheme establishes the Fee Schedule and defines the processes by which Fees are collected. The Fee Schedule is in an Appendix to these rules + +- The Scheme sets the Scheme Brand and establishes guidelines for its use. These guidelines appear in an Associated Document. + +- The Scheme measures the progress of the Scheme and its Participants + +- The Scheme defines policies and procedures for Security, Risk Management, and Data Confidentiality for the Scheme and its Participants. + +- The Scheme defines policies and procedures for the management of Transaction Exceptions. + +- The Scheme engages in activities to promote and encourage the adoption and usage of the Scheme. + +- The Scheme plans for long-term enhancement and expansion of the Platform to meet evolving market needs and opportunities in the advancement of the Scheme's goals. + +## 6. Participant Responsibilities and Obligations of Participants + +- Participants are obliged to comply with these Business Rules and with the Associated Documents to these Rules. + +- Participants must comply with all Applicable Law with respect to their participation in the Scheme within the territories in which they operate and within which they use Scheme Services. The Scheme assumes no responsibility for Participants' compliance with Applicable Law. + +- Participants are required to permit use and disclosure of Personal Information as required by these Business Rules and to provide disclosures to their Customers and obtain consents where necessary regarding such use and disclosure of Personal Information as required by Applicable Law. + +- Participants agree to pay fees to the Scheme and to other Participants as specified in these rules. + +- Participants will adhere to Scheme brand specifications as specified in these rules. + +- Participants will use Scheme Services as specified in these rules. + +
    Schemes will need to consider if they want to: 1) require the use of the scheme for scheme-eligible transactions (assuming the rules authority to do this); 2) require the use of the scheme platform for "on-us" transactions (would require separate, probably zero processing fee for such transactions); if "on-us" transactions don't go through the platform, if the scheme wants to require reporting of "on-us" transactions to the scheme, for use with a fraud utility.
+ +- All transfers made using the Scheme Brand or described as being made with the Scheme will be made using Scheme Services. + +
    Schemes will need to consider if they want to state the above rule. Some Schemes may want Participants to use the Scheme brand for on-us transactions which do not use Scheme Services. This could be worded to say "all interoperable transfers"
+ +- _\[Net Settlement Option\]_ Participants will open a Settlement Bank Account with the scheme-specified Settlement Bank, or make available an existing account for these purposes, as allowed by the Scheme. _\[Continuous Gross Settlement Option\]_ Participants will become a joint owner of the Scheme Pooled Settlement Account and sign Scheme Settlement Bank Account Agreement to that effect. Participants will transfer money into and out of that outcome from their existing reserve, clearing, or trust accounts at the Scheme Settlement Bank, as Scheme Operating Guidelines specify. + +- Participants will share information with the Scheme as strictly necessary for the operation of the Scheme, including for due diligence, technical onboarding, configuration, transactions management and other purposes as specified in the Rules. + +- Participants will be required by the Scheme to meet Security, Risk Management and Data Confidentiality standards specified by the Scheme. + +- Participants will provide adequate customer service to their customers in connection with the Scheme. + +- Participants must exclude customers from use of the Scheme upon request by the Scheme when the Scheme reasonably determines that a customer poses risk to the Scheme, which may include financial, legal, security, reputational risk or any other risk. + +- Participants will not, and will not permit customers, to use the Scheme for illegal purposes, including illegal goods or services; illegal payments, such as bribery, money laundering or financing of terrorism; poaching or trafficking in protected animal species or products. + +
    Schemes can consider if they want to specify that Participants contractually prohibit customers from using Scheme Services for illegal purposes and will discontinue Scheme Services for customers who they know, or suspect are using Scheme Services to initiate or receive transfers for illegal purposes
+ +### 6.1 Responsibilities and Obligations of Participants as Payer DFSPs + +- A Participant who originates a Quote Request or a Transfer Request is acting as a Payer Participant under these Rules. + +- A Participant may initiate a Transaction on behalf of its Payer for any Use Case or Secondary Use Case supported by the Scheme. + +- A Payer Participant is obligated to settle a Transfer upon submission of a Transfer Request, unless such Transfer Request is refused by the Payee DFSP or expires without fulfillment. + +- The Payer Participant warrants upon submission of each Transfer Request, that the Transfer is coming from an account that is KYC- and AML-compliant and is executed in accordance Applicable Law, and that the Payer has been provided all disclosure and has provided all consents necessary to conduct the Transfer in accordance with these Business Rules and under Applicable Law. + +- The Payer Participant warrants upon submission of a Request for Transfer, that the Transfer Request has been authorized by their Payer, and that their communications with their Payer have been properly authenticated in accordance with these Business Rules and Applicable Law. + +- The Payer Participant acknowledges that the Platform will reject a Transfer Request if the proposed Transfer would violate these Business Rules, such as exceeding the Payer Participant's Net Debit Cap. + +### 6.2 Responsibilities and Obligations of Participants as Payee DFSPs + +- A Participant who receives and responds to a Quote Request or a + Transfer Request is acting as a Payee Participant under these Rules. + +- A Payee Participant who receives a Quote Request is required to respond, in the absence of technical issues, with a Quote Response if: + + - The Payee's Transaction Account with the Payee Participant is in good standing and capable of receiving, at that point in time, the Transfer Amount and + + - Acceptance of the Transfer will not put the Payee account into a status not permitted by Applicable Law or the Participant's account policies and agreements. + + - The Payee Participant affirms, upon initiation of a Quote Response other than an error response, that the Payee account has been Validated — it is open, in good standing, and able to accept the proposed Transfer Amount at that point in time. + +- The Payee Participant affirms, upon initiation of a Quote Response other than an error response, that a Transfer to the designated account complies at that point in time with applicable AML/CTF and KYC requirements. + +- A Payee Participant who receives a Transfer Request is required, in the absence of technical issues, to respond with a Transfer Response with the Transaction State "Committed" if: + + - They have received a Quote Request and responded with a Quote Response for the Transaction and + + - The Quote Response has not yet expired + + - The Payee's Transaction Account with the Payee Participant is in good standing and capable of receiving, at that point in time, the Transfer Amount and + + - Acceptance of the Transfer will not put the Payee account into a status not permitted by Applicable Law or the Participant's account policies and agreements and + + - The Transfer Request on the Transaction has not expired. + +- A Payee Participant who sends a Transfer Response with a Transaction State "Committed" must post that Transfer to the Payee's account within \[X time\]. + +- A Payee Participant who receives a Transfer Request which does not meet the above criteria is required to respond with a Transfer Response with the Transaction State "Aborted". + +- The Payee Participant must affirm, upon submission of each Transfer Response with a Transaction State "Committed", that the Transfer is being credited to an account that is AML-compliant and is executed in accordance with any account volume limitations, or any other regulation that apply in the territories in which they operate, and that the Payee has been provided all disclosure and has provided all consents necessary to conduct the Transfer in accordance with the Rules and under Applicable Law. + +## 7. Liability - Allocation of Responsibilities + +- Each Participant is responsible for errors made by them, and for fraud committed by its employees or contractors, in accordance with Applicable Law. + +- The Scheme will not be held responsible for, and each Participant will indemnify and defend the Scheme from claims arising from actions or omissions of the Participants, of their Customers or contractors. + +- The Scheme may elect to defend any claim in circumstances where the Scheme determines that the resolution of a claim may have an adverse impact on the finances, operations or reputation of the Scheme. + +- The Scheme shall be held responsible for its own errors in processing Transfers within limits prescribed by the Rules. + +- The Scheme will compensate Participants for costs of funds to the extent that a Participant is wrongly deprived of funds for a period of time as a result of errors made by the Scheme. + +- Each Participant is responsible for the actions and omissions of any contractors engaged by them to provide services in connection with the Scheme to the same extent as if committed by the Participant. + +- The Scheme may allocate responsibility among Participants for consequences of unauthorized use of or access to data by a Participant or for a Security Incident suffered by one Participant that impacts other Participants or the Scheme in accordance with principles stated in the Rules. + +## 8. Security, Risk Management, and Data Confidentiality + +### 8.1 Confidentiality and Protection of Personal Information + +- Confidential Information of the Scheme that is disclosed to Participants will be held in confidence by Participants and will be used only for the purposes permitted by the Rules. Scheme Confidential Information may include proprietary technology and other matters designated by the Scheme. + +- Transaction data will not be owned by the Scheme and will be owned by a Participant as it relates to its Customer's Transactions. + +- The confidentiality of Transaction data and any Personal Information processed in the Platform will be protected by the Scheme and Participants according to Applicable Law. + +- Statistics or data which identify a Participant or from which the Participant may be identified will not be disclosed to other Participants. The Scheme may prepare for internal use and disclose to third parties for promotional purposes statistics based on aggregate, anonymized data as permitted by Applicable Law. + +- The Scheme will make disclosures of Confidential Information to comply with Applicable Law or the directive of a Regulatory Authority. + +- The Scheme will protect Personal Information in its possession or under its control from misuse and otherwise treat such information in accordance with Applicable Law protecting privacy of individuals. + +- The Scheme will maintain industry leading security measures to protect information from unauthorized access and use. + +- Participants will notify the Scheme and acknowledge that the Scheme may notify other Participants, of any Security Incident in the systems or premises of the Participant, its affiliated entities or any third-party vendor engaged by the Participant to provide services in support of the Participant's participation in the Scheme. + +- The Scheme may conduct investigations into Security Incidents. Participants will cooperate fully and promptly with the investigation. Such investigations will be at the expense of the affected Participant. + +- The Scheme may require a Participant to conduct investigations of Security Incidents and may require that such investigations be conducted by qualified independent security auditors acceptable to the Scheme. + +- The Scheme may impose conditions of continued participation on the affected Participant regarding remedy of the causes of the Security Incident and ongoing security measures. + +- The investigation and report, as well as remedies that may be required will be held confidential to the extent permitted by Applicable Law. + +### 8.2 Risk Management Policies + +
    This section assumes that the development of risk management policies by the Scheme and its participants will be evolving. This section contemplates that some of these policies will (eventually) be in the Rules; others will not.
+ +- Risk management policies and procedures may be stated in the Rules, in Associated Documents, or in other written policy documents created by the Scheme and distributed to Participants + +- Risk management policies and procedures will include fiscal soundness, system integrity, compliance with Applicable Law, particularly as to Anti-Money Laundering/Combatting Terrorism Financing measures, privacy of personal information and data security + +- Risk management functions include procedures applicable to Participants for monitoring of risks, including reporting requirements and audits + +### 8.3 Business Continuity + +- Provisions to ensure business continuity on the part of the Scheme, its vendors, and Participants. + +## 9. Scheme Platform and Services + +- The Scheme defines the set of Scheme Services which Participants access to use the system. These are listed in an Appendix to this document. The core Scheme Services necessary for inter-operability are considered to be the Scheme Platform. + +- Technical and operational details on the use of Scheme Services, including the Scheme Platform, are provided in Associated Documents. This list of Associated Documents is an Appendix to this document. + +## 10. Exception Management + +- Problems may occur during execution of a Transaction that result in exception cases, which may require or may be facilitated by inter-Participant communication. Exception cases may include errors on the part of any party, fraud, or other service anomalies. + +- The Scheme will create and maintain protocols by which Participants may determine the type of exception and suggested or required actions on the part of Participants to resolve the exception. These protocols are contained in an Associated Document. + +- The following principles govern exception management: + + - Participants involved will cooperate in good faith. + + - Each Participant agrees that they will not contact the other Participant's customer directly during the process of dispute resolution. + + - Participants agree to cooperate with each other and with the Scheme to share information about suspected or confirmed fraud. + +### 10.1 Transaction Irrevocability + +- Participants agree that Fulfilled Transfers executed via the Platform are irrevocable. A Transfer which has been credited to a Payee's account as a result of a Scheme Transfer may not be revoked without the consent of the Payee. + +- The Scheme may instruct a Participant to initiate a corrective transaction between Participants in an amount determined by the Scheme to be necessary to correct errors caused by Payer DFSP, the Payee DFSP, or the Scheme.  The conditions under which such corrective transactions may be made are specified by the Rules.  + +- Errors on the part of the Payee DFSP, the Payer DFSP, or the Scheme which result in erroneous or duplicate posting of a Transfer to a Payee's account may be corrected by the Payee Participant, as long as the instructions in the Fulfilled Transfer are not revoked or altered in any way. + +## 11. Appendix: Associated Documents + +- Uniform Glossary + +- Platform Operating Guideline + +- Brand Guideline + +- Exception Management Protocols + +## 12. Appendix: Onboarding and Exit Processes + +## 13. Appendix: Scheme Services + +Scheme Services include: + +- Scheme Platform, which includes + + - The Transfer Service + + - The Directory Service + + - The Settlement Service + + - Scheme Management Service + +- Other Shared Services + + - Fraud Management Utility + +## 14. Appendix: Scheme Supported Use Cases + +
    Use Cases are defined by what type of customer is paying what other type of customer, and by the purpose of the payment. Secondary use cases are sub-sets of Use Cases and are used to demonstrate more finite differences in transfers. All transfers made via Scheme Services may be categorized by one, and only one, Use Case and Secondary Use Case.
+ +
    The Use Case and Secondary Use Case of a Transaction may require different operational and technical details to apply, as specified in the Platform Operating Guideline; different interchange fees to apply, as specified in an Appendix to these rules; different requirements for exception management procedures to apply, as specified in an Associated Document to these rules
+ +
    All Scheme Supported Use Cases and Secondary Use Case are defined by attributes of the transactions, which are specified in the Platform Operating Guide.
+ +
    The following is an example of a table of Use Cases and Secondary Use Cases that a scheme might support.
+ +
    A scheme would only define Secondary Use Cases if it wanted to write rules and/or specify fees that are unique to that Secondary Use Case
+ +| | Use Case | Secondary Use Case | +| :---: | :--------: | :-------------------------- | +| 1.0 | P2P | Person to Person | +| 1.1 | P2P | Wallet to wallet | +| 1.2 | P2P | Bank to bank | +| 1.3 | P2P | Wallet to bank | +| 1.4 | P2P | Bank to Wallet | +| 2.0 | Bulk Payment | | +| 2.1 | B2P | Business to Person | +| 2.2 | G2P | Government to Person | +| 3.0 | P2B | Person to Business | +| 3.1 | P2B | Till Number Purchase | +| 3.2 | P2B | QR code Purchase | +| 3.3 | P2B | Online Purchase | +| 3.4 | P2B | Bill Payment | +| 3.5 | P2B | Person to Business - Other | +| 4.0 | P2G | | +| 4.1 | P2G | Person to Government | +| 4.1 | P2G | Till Number Purchase | +| 4.2 | P2G | QR code Purchase | +| 4.3 | P2G | Online Purchase | +| 4.4 | P2G | Bill Payment | + +## 15. Appendix: Scheme Fee Schedule + +1. Processing Fees + + - Processing fees are calculated by \[define\] + + - Processing fees apply to fulfilled transfers + + - Processing fees are charged to \[which party or parties\] + + - Processing fees for "on-us" transfers (where Payer and Payee DFSP are the same) \[are or are not charged\] + + - Processing fees will be calculated and billed to Participants \[define\] + + - Provision for how Participants will pay processing bills \[define\] + +2. Membership or Participation Fees + + - Membership or Participation Fees are charged to \[define\] + + - Specify basis, how collected, etc. + +3. Interchange Fees + + - Interchange fees are set by the Scheme + + - The amount of the fee and the direction (which Participant pays which) vary by Use Case and by Secondary Use Case. Some Use Cases and Secondary Use Cases will not have interchange. + + - \[Define how the platform will collect and disburse interchange: on a transaction basis or a periodic basis.\] + +## 16. Appendix: Risk Management, Security, Privacy, and Service Standards + +
    Schemes may or may not want to specify standards or require that Participants comply with other established standards. Schemes may furthermore specify different standards for different categories of Participants. The list below is given purely as an example.
+ +Participants must adhere to the following practices of service quality security, data privacy and customer service as they apply to a Participant in connection with the Scheme. + +- Participants will establish a risk management framework for identifying, assessing and controlling risks relative to their use of the Scheme. + +- Participants will ensure that the systems, applications and network that support the use of the Scheme are designed and developed securely. + +- Participants will implement processes to securely manage all systems and operations that support the use of the Scheme. + +- Participants will implement processes to ensure that systems used for the Scheme are secure from unauthorized intrusion or misuse. + +- Participants will implement processes to ensure the authentication + of their customers in creating and approving transactions that use + the Scheme. + +- Participants will develop effective business continuity and + contingency plans. + +- Participants will manage technical and business operations to allow + timely responses to API calls received from the Scheme Platform or + from other Participants via the Scheme Platform. + +- Participants will establish written agreements governing their + relationship with agents, processors, and other entities providing + outsourced services that pertain to the Scheme. + +- Participants will develop policies and processes for ongoing + management and oversight of staff, agents, processors, and other + entities providing outsourced services that pertain to the Scheme. + +- Participants will ensure that customers are provided with clear, + prominent, and timely information regarding fees and terms and + conditions with respect to services using the Scheme. + +- Participants will develop and publish customer service policies and + procedures with respect to services using the Scheme. + +- Participants will provide an appropriate mechanism for customers to + address questions and problems. Participants will specify how + disputes can be resolved if internal resolution fails. + +- Participants will comply with good practices and Applicable Laws + governing customer data privacy. + +- Participants will ensure that Customers are provided with clear, + prominent, and timely information regarding their data privacy + practices. diff --git a/docs/adoption/Scheme/scheme-key-choices.md b/docs/adoption/Scheme/scheme-key-choices.md new file mode 100644 index 000000000..1d4e3fe8e --- /dev/null +++ b/docs/adoption/Scheme/scheme-key-choices.md @@ -0,0 +1,408 @@ +# Scheme Key Choices + +- Version: 5.0 + - Author: Carol Coye Benson (Glenbrook) + - Date: October 2019 + - Description: + +--- + +## **About the Mojaloop Community Business Document Project** + +This document is part of the Mojaloop Community Business Document Project. The project is intended to support entities (countries, regions, associations of providers or commercial enterprises) implementing new payments systems using Mojaloop code. These entities will also need write Business Rules that participants in the system will follow. + +The Mojaloop Community Business Document Project provides templates for Business Rules and related documents. There are many choices involved in implementing a new payment system: the templates show some of the choices and, where appropriate, commentary is provided on how the particular choice is related to the goals of a Level One aligned system. + +The following documents are part of the project: + +- Scheme Key Choices + +- Scheme Participation Agreement Template + +- Scheme Business Rules Template + +- Platform Operating Guideline Template + +- Exception Management Operating Guideline Template + +- Uniform Glossary + +## **Introduction** + +Payments Schemes around the world are in the process of implementing, or considering implementation, of Mojaloop-based payments systems. Mojaloop is open-source software for financial services companies, government regulators, and others taking on the challenges of interoperability and financial inclusion. Mojaloop is based on the specification "Open API for FSP Interoperability Specification", which was developed to provide an open API specification for mobile money interoperability. + +The Bill & Melinda Gates Foundation has provided funding and support for Mojaloop. Mojaloop is open source reference code which demonstrates the principles of the Level One Project, a vision for digital financial markets based on principles of interoperability, collaboration, and inclusion. + +Schemes implementing Mojaloop will need to make a number of business choices about the design of the system. These choices, when made, will affect both the technical implementation of Mojaloop and the Business Rules which the Scheme will write, and which Participant DFSPs will agree to follow. This document describes and discusses some of the most significant of these choices. Where appropriate, recommendations for best practices are made to align with the Level One Project (L1P) Design Principles. + +Although this document is written as a contribution to the Mojaloop community, the issues described here are pertinent to any Level One aligned payments system, regardless of the technical implementation chosen. + +## **Choices Described in this Document** + +[1 - Choice: Ownership of Scheme](#_1-choice-ownership-of-scheme) + +[2 - Choice: Participation in the Scheme](#_2-choice-participation-in-the-scheme) + +[3 - Choice: Relationship of Scheme to Platform](#_3-choice-relationship-of-scheme-to-platform) + +[4 - Choice: Scope of Scheme Rules and Scheme Rules Authority](#_4-choice-scope-of-scheme-rules-and-scheme-rules-authority) + +[5 - Choice: Use Cases](#_5-choice-use-cases) + +[6 - Choice: QR Codes](#_6-choice-qr-codes) + +[7 - Choice: Payments Addressing](#_7-choice-payments-addressing) + +[8 - Choice: Interparticipant Settlement](#_8-choice-interparticipant-settlement) + +[9 - Choice: Tiered Access](#_9-choice-tiered-access) + +[10 - Choice: Scheme Fees and End User Pricing](#_10-choice-scheme-fees-and-end-user-pricing) + +[11 - Choice: Brand Management](#_11-choice-brand-management) + +[12 - Choice: Scheme Connections to Other Schemes](#_12-choice-scheme-connections-to-other-schemes) + +[13 - Choice: Scheme Use by Other FSPs](#_13-choice-scheme-use-by-other-fsps) + +[14 - Choice: Scheme Risk Management Standards](#_14-choice-scheme-risk-management-standards) + +[15 - Choice: Exception Management](#_15-choice-exception-management) + +## 1. Choice: Ownership of Scheme + +The Scheme is the entity that writes the rules for the payment system. As such, the scheme controls multiple aspects of the delivery of scheme services, including how the technical and operational platform will be delivered to participating DFSPs. Common models in for Scheme ownership in the payments industry include: + +- An association of participating DFSPs, with or without partial ownership by the Central bank + +- A Central Bank or other government entity + +- A commercial entity + +The association model maximizes DFSP control of the Scheme and may encourage DFSPs to join and use the scheme. A government or central-bank controlled scheme may make regulatory supervision of DFSPs more effective and may make decision-making simpler: a government body may be willing to make infrastructure decisions that are for the good for the ecosystem as a whole, rather than optimizing individual DFSP benefits. A commercial entity may be faster to implement a new system and may be more effective in some situations in creating a sustainable operating model. + +### 1.1 Level One Alignment — Scheme Ownership + +Any of these ownership structures can deliver on the goals of L1P and financial inclusion. The Level One Design Principles suggest "self-governance by DFSPs" (the first model) as a preferred design, based on a belief that participation in governance can increase DFSP commitment to the scheme. Other designs can work, however, as long as the Scheme and its members have some form of participatory governance and operate with transparency and open communications. + +The most important Level One principle is that the Scheme itself should operate on a "not for loss" (sustainable cost recovery) model. The latter is particularly important in order to deliver on the L1P goal of creating an ultra-low-cost payment system. This principle is predicated on the idea that DFSPs may, of course, operate on a for-profit basis in delivering payment services. The source of their revenues, however, may be primarily from \"[adjacencies](https://docs.gatesfoundation.org/documents/fighting%20poverty%20profitably%20full%20report.pdf)\" rather than fees related to the payment transaction itself. Note that the operating platform may be provided by a commercial entity, even if the Scheme itself is operated on a "not for loss" basis. This is discussed further below in "Choice: Relationship of Scheme to Platform". + +Many legacy bank payments systems worldwide operate on the association model. ACH systems and domestic debit card systems (such as the U.S. ACH and Canada's Interac system) use this model and deliver ultra-low processing costs to participating DFSPs. Some new mobile payments systems, such as India's UPI system and Peru's BIM system also use this model. + +Several countries provide services through the Central Bank: Mexico's SPEI model is notable here. Jordan's JoMoPay system started as a Central Bank system and has moved to the association model. + +The global card networks, notably Visa and MasterCard, started as association models and have moved to a commercial model. Many FinTechs, such as PayPal or WeChat Payments, operate closed-loop systems on a commercial model. + +## 2. Choice: Participation in the Scheme + +Mojaloop and L1P use the term "DFSP" (Digital Financial Services Provider) to mean any entity within the jurisdiction in which the payment system operates that is licensed in some manner to provide end-user transaction accounts which hold funds, and which can be used to make and receive payments. This definition includes bank, other depository financial institutions, and eMoney issuers (sometimes referred to as Mobile Money Operators). + +There are myriad other ecosystem participants who do not hold end-user transaction accounts: these include processors, aggregators, and some types of payments services providers. The relationship of these entities to the scheme and to DFSPs is discussed in [Choice: Scheme Use by Other FSPs](#_13-choice-scheme-use-by-other-fsps). + +The question of participation is twofold: first, which categories of DFSPs are supported by the Scheme, and secondly, what is the process by which DFSPs are allowed to participate. The term "open loop" is used to refer to a structure in which multiple DFSPs join and use the scheme to exchange transactions (interoperate). But an "open loop" scheme can either be one in which any DFSP in a supported category is eligible to join the scheme, or one in which participation is limited, and managed by invitation. An applicant DFSP may face certain eligibility criteria (size, financial health, etc.) before being admitted to the Scheme. + +The term "closed loop" is most often used to refer to a scheme which is not interoperable; in which the scheme entity has direct relationships with all end customers + +L1P is strongly in favor of open loop systems. Furthermore, L1P advocates for all licensed providers of transaction accounts to be eligible: in other words, both bank and eMoney Issuer categories should be included, and allowed to interoperate through the Scheme platform. + +There are a number of arguments which support this recommendation. The very concept of "financial inclusion" implies including previously excluded populations into the financial ecosystem of the country. In many countries, eMoney issuance or other structures have been approved by regulators to provide transaction accounts to populations that have not been able to be served economically by traditional banks. These eMoney issuers have frequently created closed-loop mobile wallets, and one of the goals of L1P and Mojaloop is to enable interoperability of these wallets. However, wallet holders need to pay not just other wallet holders, but merchants and other banked institutions, and banked individuals. Banked individuals and institutions also make payments to wallet holders. It makes sense that the same interoperable payment system should support both for efficiency reasons (why have multiple systems when a single system can connect all players?) and for economic reasons. + +The economic argument revolves around the nature of transactional processing systems: the more volume, the lower the unit cost. This principle is also supported in the [World Bank/CPMI PAFI Report](http://www.worldbank.org/en/topic/financialinclusion/brief/pafi-task-force-and-report): \"the framework promotes innovation and competition by not hindering the entry of new types of PSP\.... Increased interoperability of and access to infrastructures supporting the switching, processing, clearing and settlement of payment instruments of the same kind are promoted\... payment infrastructures, including those operated by central banks, have objective, risk-based participation requirements that permit fair and open access to their services.\" A related and important point is that Scheme rules should specify that an individual Participant cannot discriminate against any other individual Participant: unless constrained by other factors (regulatory account limits, etc.), Participants must receive transactions sent by other Participants in the Scheme. This ensures full interoperability. + +The second question is what eligibility criteria a potential DFSP must meet in order to actually join the scheme. Many payments schemes have fairly elaborate procedures to ensure that applicant DFSPs have the financial resources to comply with rules, and the technical wherewithal to meet the operational requirements of the rules. + +Some form of these requirements is necessary for any scheme. But modern technology and, in particular, pre-funded settlement models greatly reduce the risks to the scheme in dealing with smaller DFSPs. The Level One alignment issue here is to ensure that the scheme is not inadvertently discriminating against smaller DFSPs and in favor of large ones. The goal should be to ensure the minimum necessary qualifications to support the obligations that a DFSP applicant is undertaking. + +## 3. Choice: Relationship of Scheme to Platform + +Our definitions separate the concept of a scheme (the entity that rights the rules for a payment system) and a platform (the set of services that physically enable interoperability). Most often, but not necessarily, the platform operates as a switch which routes transactions from one DFSP to another: the alternative is bilateral physical connections among DFSPs. + +What is the relationship between the scheme and the platform? There are multiple models demonstrated in payments systems globally: + +1. Same entity: the scheme operates the platform. This is seen frequently in commercial systems (e.g. Visa) and also in Central Bank provided systems (e.g. Bank of Mexico SPEI) + +2. The scheme hires the platform: the switch and related services are operated by a separate entity, under contract to the scheme entity. The scheme pays the platform entity; this cost is recouped in fees from the scheme to its participating DFSPs. The U.K. Faster Payments system operates on this model (Faster Payments Scheme Ltd. hires Vocalink to operate the platform). + +3. The scheme sets for the parameters by which operator(s) manage transactions governed by the rules: if there are multiple operators, those entities must interoperate, again as specified in Scheme rules. Individual DFSPs choose the operator they wish to use to access the system. The U.S. ACH system works in this manner, as do several of the SEPA payments systems in Europe. + +4. No switch: this is really a variation of the model 3 above. Each DFSP independently and physically connects to each other DFSP, again within constraints set by the scheme rules. Debit cards in Australia work this way. + +### 3.1 L1P Alignment: Relationship of Scheme to Platform + +There is no single Level One Principle that argues in favor of one of these models vs. the other. Factors for consideration include: + +- The goal is that all of the ecosystem players (Scheme, Platform, DFSPs, etc.) encourage L1P-compliant behavior. A more controlled model (models 1 or 2) arguably makes this easier. + +- Having a low-cost system is a core tenet. However, it is debatable whether this is better achieved through Model 1 or Model 2. Models 3 and 4 bear the risk of excluding or disadvantaging smaller DFSPs or new system entrants. + +- In Models 2 and 3, the platform providers will have their own operating guidelines. There may be situations in which provisions of Scheme rules are not adequately reflected or implemented by the Platform. This is an issue of power and control. Model 1 avoids this problem but could create a \"vendor lock-in\" type of problem, where DFSPs have no choice but to pay the costs of the Scheme-controlled platform. + +## 4. Choice: Scope of Scheme Rules and Scheme Rules Authority + +### 4.1 Scope + +Scheme rules vary widely in scope from scheme to scheme. All cover the essential elements of scheme participation, party obligations, and the mechanics of interoperability. But many schemes go much further in terms of defining how DFSPs make payments services available to their customers, and under which terms. Two areas here are worthy of note: + +- Some schemes specify elements of the end-user experience. Examples of this include the card networks specifying card physical parameters and design requirements. Some systems (for example, Peru\'s BIM) specify how the mobile phone interface appears to a consumer. Other systems (for example, India\'s UPI) go so far as to provide the SKD\'s and API\'s that define what the end-user app can functionally do. Some systems may require that a DFSP receiving a credit-push transaction must post it to a customer\'s account within a specified amount of time +- Some schemes also specify elaborate liability provisions on interoperable transactions. These provisions may vary according to use case and particular attributes of a transaction. For example, in the card networks, liability may pass from the card issuer to the merchant acquirer if the merchant terminal does not meet certain specifications. + +### 4.2 Rules Authority + +As described above, the scheme is the entity that writes the rules for the payment system. But who approves these rules? There are two primary models in the market place: + +- DFSP Authority. In this model, all (or some) rules changes are voted on by participating DFSPs. The voting may be determined on a per-seat basis, or it may be determined on a volume-weighted basis. Many schemes have experimented with variations on this. + +- Scheme Authority with DFSP Participation. In this model, rules authority rests with the scheme entity, but some degree of formal or informal participation by DFSPs is included: this can either be formal (standing committees that meet to consider rule changes, rules amendment commentary periods specified in the rules, etc.) or informal (scheme representatives meet and/or request written feedback on proposed rules changes). + +### 4.3 L1P Alignment — Rules Scope and Authority + +There are two relevant Level One principles: one is for participatory governance, and the other is the mandate to deliver a low-cost system. Level One also recognizes the importance of a system that is convenient and easy for end-user customers to use, particularly poor consumers and merchants. Considerations therefore include: + +- Rules can create costs: the more elaborate the rules are specifying how DFSPs must deliver services to the customer, the higher the costs of complying with these rules will be. + +- Offsetting this is the value of having a common consumer experience - there is considerable evidence that having a common experience can help consumers self-educate in the use of services. Arguably, this is an important factor in scaling the system. But the further a scheme goes in writing rules that effect end-user experience, the more important it is that participating DFSPs have some voice in these rules. + +- Scheme experience has shown that explicit voting rules, although they sound good to DFSPs, often result in very long decision practices: this is one reason why some schemes use the second above, and use participating DFSPs as sounding boards, but do not grant rules authority. + +## 5. Choice: Use Cases + +One of the most important choices a scheme has to make is which use cases to support. Frequently, a real-time credit-push retail scheme starts with person to person (P2P) payments as the first use case: often, a scheme will indicate to the market that it intends to support other use cases in the future. As schemes evolve there are significant "sub use cases" to consider: in some Mojaloop implementations, the term "secondary use case" is used for this: as an example, if P2P is the use case, cross-border P2P might be a secondary use case; wallet-to-wallet and wallet-to-bank account might be secondary use cases. + +Business rules may vary by use case and/or secondary use case. This may include operational details (data fields used, etc.), scheme pricing (in particular, interchange) and even liability provisions. + +The Open API document used by the Mojaloop code includes the following list of use cases: + +- P2P Transfer +- Agent-Initiated Cash In +- Agent-Initiated Cash Out +- Agent-Initiated Cash Out Authorized on POS +- Customer-Initiated Cash Out +- Merchant-Initiated Merchant Payment +- Merchant-Initiated Merchant Payment Authorized on POS +- ATM-Initiated Cash Out +- Refund + +An implementing scheme will choose its own primary and secondary use cases, and the definitions of these will be in the Business Rules. Schemes should consider the following: + +- Eventual scheme-to-scheme interoperability will be easier (especially from one Mojaloop-implemented scheme to another) if the same primary use cases and definitions are used + +- Schemes may need to differentiate between a DFSP's ability to initiate transactions in a specific use case or secondary use case, and requirements that a DFSP needs to be able to support receiving transactions in a specific use case or secondary use case + +- Any rules that are written specific to a use case or secondary use case need to be systemically detectable (by labelling or inference) if the rule will be automatically applied: this is particularly important for business-case-specific interchange fees. How this is done should be part of the business documentation, in the Operating Guidelines. + +### 5.1 L1P Alignment — Use Cases + +There are two considerations here. One significant issue is the relationship between high volumes in a payment system and the ability to deliver ultra-low-cost processing fees to participating DFSPs. Almost all retail payments systems support multiple use cases, including those which started with a single use case. The card networks are an excellent example of this: started to support point of sale purchases, they now support online purchases, bill payment, salary payments, and B2B payments. Payment processing is a scale business: the more volume, the lower the unit costs can be. Level One strongly supports a payment system being used for multiple use cases: ideally, all retail (e.g. excluding large value B2B) use cases in a country. + +The other consideration is making the payment system easy for end-users to access and understand. The same system, with similar user interfaces, etc. for use cases will be easier for end-users (particularly poor or uneducated users) to use. + +## 6 Choice: QR Codes + +QR codes are emerging as a major enabler of merchant payments in developing countries. Both payment schemes and national payment authorities are deciding on formats, protocols, and scope for QR codes. Some of the decisions include: + +- Is the QR code presented by the merchant, and scanned by the consumer, or presented by the consumer and scanned by the merchant? Level One has a preference for merchant-presented QR codes, implemented in conjunction with push, not pull payments. A merchant-presented QR code can be combined with a till number to enable consumers with feature phones to easily pay the same merchant. + +- Is the QR code static (the same for all purchases), or is it dynamic? Rather than a choice, this is being seen as an evolution: most markets are starting with static QR codes, but have plans to move to dynamic codes. Dynamic codes function like a "request to pay" payment message in a push payment system, and can contain purchase-specific data. + +- Does the national approach to QR codes use a "shared QR code" approach, in which a single QR code can represent a merchant's payments credentials across multiple schemes? The most common way in which this approach is implemented is through the use of EMVCo QR code standards. An alternative is a single QR code approach, in which a QR code is used only to access either an interoperable payment scheme (for example, Mexico's CoDi system) or a closed-loop system (for example, China's WeChat Payments). A single QR code approach may create low-cost advantages by driving volume through a single national platform, while a cross-scheme approach may enable competition among multiple schemes. + +- If a shared QR code approach is used, is there a single national entity that controls which schemes a given merchant accepts? If so, who runs this "repository" function and what are its functions? Does it actually issue the QR code data string? If yes, does it sign the string and validate it? There is some speculation that a QR code repository could serve as a point of cross-payments system oversight and management of fraud. It could also tie into a national business registration scheme in some way. It is interesting to consider that a cross-scheme QR code repository might require its own business rules, which would become "meta rules" which would exist above the business rules of the individual schemes. + +- Does the QR code data string (the "payload") contain the merchant's "payment address", or does it point in some way to a place where this is stored? The latter approach provides more flexibility and supports a merchant's ability to change providers. + +- How is the consumer (and the merchant) protected from QR code fraud? + +- What are the economics of the transaction to the merchant? Level One has a strong preference for zero, or near-zero pricing to the small or poor merchant. + +## 7. Choice: Payments Addressing + +Any scheme implementing credit-push payments needs to specify how the payer and their Payer DFSP addresses the payment. The address needs in some way to be resolved into the payee's account number at the DFSP who provides their transaction account. The scheme needs to decide: + +- What types of payments addresses (sometimes called "identifiers") are used. Some payments addresses are institutional ID's and account numbers: a bank routing number and bank account number are an example of this. Other payments addresses may be account numbers without the institutional ID: a mobile phone number used to direct funds to an eMoney wallet provided by an MNO is an example of this. All other types of payments addresses are aliases of some sort. An alias may be an email address, a scheme-assigned merchant ID, a national identity number, or a mobile phone number used to direct funds to account other than that provided by an MNO eMoney issuer. An scheme-supported alias may also be a phrase: "payadamnu123". + +- For each type of payment address supported by the scheme, the scheme needs to determine how that payment address is resolved. At a minimum, the scheme needs to support a mechanism by which the address is mapped to a DFSP scheme participant responsible for the transaction account associated with that payment address. Resolution can be done in a number of different ways: + + - The scheme can maintain a directory mapping addressing to responsible DFSP ID's: this requires some type of DFSP registration process for addresses. + + - The scheme can maintain a directory which maps the address to the responsible DFSP and also specifies the account number: this requires a slightly different registration process. + + - Either of these types of directories can be maintained by a third party: scheme rules would establish how these directories are populated, maintained and used, and what the responsibilities of the various parties are. + + - A scheme may also use a broadcast method to determine the DFSP responsible for a given payment address ("do you claim this address"), but needs to develop a protocol to manage conflicts if more than one DFSP "claims" the address. + +- It is important to note that the resolution method can different for each type of supported payment address. Some supported payment address types may also be accompanied by particular data sets: for example, when a payment is being made in payment of an invoice, the payment address may be some type of alias, and that use of that alias may be tied to accompanying invoice data. Dynamic QR codes, as an example, will create a "request to pay" that may contain the scheme-supported merchant ID (an alias) and accompanying transaction data detail. + +The Open API specification and the Mojaloop reference code support a wide range of different address types: mobile number, bank account, national ID, aliases ("Quickshop\@abc"), etc. + +### 7.1 L1P Alignment — Payments Addressing + +Secure, easy payment addressing relates to two important concepts in Level One: convenience for the end-user and "openness". The latter is particularly important to enable competition and rapid scaling of a payment system. As schemes (Level One and otherwise) worldwide struggle to determine how to best solve the question of payments addressing, a few best practices appear to be emerging: + +- Although the use of the mobile number, in particular, as an address has an obvious appeal, there appears to be a trend to use aliases — identifiers with no additional meaning. This is demonstrated in India with the UPI system and in Australia's new real-time system, where the identifier is referred to as the PAYID. + +- Identifier portability is desirable, both from the perspective of user convenience and as a mechanism to avoid "DFSP lock-in". + +- As mentioned above, the directory needs to ensure uniqueness of the payment address within the payment system: any given address can only map to a single DFSP. However, a single DFSP transaction account can have multiple payment addresses which route to it. DFSPs have the opportunity to create value-added services for their customers, in which they differentiate the treatment of transactions routed to them via different payment addresses (subject, of course, to overall scheme business rules). + +## 8. Choice: Interparticipant Settlement + +Payment schemes need to determine how participant DFSPs will settle their financial obligations to each other arising from interoperable transactions. There are multiple decisions to be made on the settlement model. Existing settlement models used in legacy retail payment systems have important controls over risks. As a general statement, schemes to today have opportunities to make choices leveraging modern technology and connectivity to manage these risks in different ways. Some of the choices are: + +- Net, gross, or continuous gross settlement. Traditionally, net settlement has been used for retail payments systems (practically speaking, all systems except RTGS). Some real-time retail payment systems are now using gross settlement (Mexico's SPEI) or are planning to (Brazil). Some systems are using a continuous gross settlement account (U.S. RTP): in this approach, DFSPs jointly own a single account at the Settlement Bank, and ownership shares in the pooled account are determined, at any point in time, by the DFSPs ledger position at the platform. This approach uses no settlement entries, netting, or settlement entry posting. + +- Choice of settlement bank. Most interoperable retail payment systems use the country's central bank as the settlement bank, but there are examples (card network settlement in the U.S.) where a commercial bank is used as the settlement bank. + +- Dedicated or multi-purpose settlement accounts. Are the DFSP's settlement accounts, held at the settlement bank, dedicated to the purpose of scheme settlement, or are they used for other purposes (other scheme settlements, reserve balances, etc.) as well? In a continuous gross settlement model, the pooled account is always a dedicated account. + +- Same day or deferred settlement. In a net settlement model, are settlement entries posted to settlement bank accounts on the day of the transaction, or later? + +- Multiple or single settlement windows. In a net settlement model, is there a single settlement window per business day, or are there multiple? If multiple, are the windows defined by time periods, volume of transactions, or some other factor? + +- Prefunded or not. Are settlement entries (in a net system) or individual transactions (in a gross system) allowed to occur if there is not sufficient funding in the settlement bank account? If so, what mechanisms (lines of credit, collateral accounts, etc.) are used to support this risk? The term "prefunded" is used when scheme rules specify that the DFSP must have enough money in their settlement account to cover an outbound transaction: if not, the platform will refuse the transaction. + +- Dynamic position management or not. In a net settlement system which uses a switch, does the switch "know" the actual position of the sending DFSP before sending the transaction on to the receiving DFSP? + +- Automated or manual net debit cap calculation. The net debit cap is an amount that the system uses, in conjunction with dynamic position management, to determine whether or not an individual transaction is sent to the receiving DFSP. This can either be manually set by the scheme (individually for each DFSP) or automated: the latter requires a real-time connection between the (dedicated) settlement bank account and the switch. + +- Discretionary components of the net debit camp may be defined by the scheme. There are two types of these. A scheme discretionary component may add to, or subtract from, an individual DFSP's net debit cap. An addition can be used to create a safety margin; a subtraction can be used to extend overdraft capabilities to the DFSP. In the latter case, responsibility for the overdraft needs to be clearly agreed upon between the scheme and the settlement bank. + +### 8.1 L1P Alignment — Interparticipant Settlement + +Level One has a clear principle calling for same day settlement. Other than that, the most important considerations are how a given scheme will manage risk and costs for DFPS — liquidity costs in particular. This is a rapidly evolving area in payment systems, and it is expected that different schemes will make different choices. In general, it can be observed that automation supports scale, and that prefunding and multiple windows support low risk and low cost. + +The Mojaloop reference code supports a variety of different settlement mechanisms. + +## 9. Choice: Tiered Access + +Legacy retail payment systems (and wholesale systems) generally support tiered access — the ability of smaller institutions to access the system through correspondent relationships with larger institutions. This has been considered necessary as smaller institutions frequently had difficulty in meeting either the settlement obligations of full participation or the technical (particularly security) obligations of full participation. + +In countries with eMoney Issuance licenses (or with other non-bank or non-traditional DFSPs, or transaction account providers) the question becomes whether or not these non-traditional providers access the system directly or through a relationship with a traditional bank: in these cases, it is generally the settlement, and not the technical, issue in question. + +### 9.1 L1P Alignment — Tiered Access + +There is no single Level One principle which would direct a scheme on how to handle this issue. There are, however, both cost and risk issues to consider: + +- It should be noted that larger institutions have created very profitable businesses in serving these smaller institutions. These costs, born by the indirect participants, will in some way be passed on to end-users. Because of this, Level One schemes may want to avoid this model where possible. + +- The Level One principle of "Open Loop" suggests that a scheme should support the ability of all DFSPs to participate directly wherever possible: modern technology, such as that used by Mojaloop, and prefunded settlement models should make this simpler. + +- Legacy systems also tend to "hide" the activity of the smaller institution from the scheme or the hub. This may be undesirable from a regulatory or risk management point of view. Some new retail real-time payment systems (notably the U.S. RTP Network) are allowing both technical and settlement indirect access with full transparency of the smaller institution to the scheme and platform. + +- Another factor to consider is particular to countries with eMoney Issuance or other non-traditional DFSP providers. Under the L1P principle of DFSP involvement in governance decisions, it may be that asking eMoney Issuers to access a system "under" a bank participant may leave these DFSPs in a "second tier" position with respect to governance: this is arguably undesirable, and particularly in cases, which appear relevant in some countries, where the eMoney Issuers have a higher transaction volume than do their sponsoring banks. + +Note this section does not discuss access to the system by other FSPs: that is addressed in [Choice: Scheme Use by Other FSPs](#_13-choice-scheme-use-by-other-fsps). + +## 10. Choice: Scheme Fees and End User Pricing + +Fees associated with an interoperable payment scheme can be categorized as: + +- End-User Fees: the fees (or minimum balance requirements, etc.) assessed by a DFSP to their end-user customer. This includes fees charged to consumers, merchants, billers, governments or other enterprises. Some of these fees are specifically attached to the interoperable transfer itself (e.g. a "send transfer" fee, or a "merchant discount fee"); others are related (a "cash-out" fee, an ATM withdrawal fee). These fees are typically set by the DFSP. In some countries and situations, regulation or scheme rule agreements may apply to or influence the fees. Fees may either be fixed amounts; fixed amounts; percent-of-value amounts, or a combination of fixed and percent of value. In either case, fee schedules can differ based on which value-bands (for example, transactions lower than value "X" have this fee) or end-user transaction volume. + +- Processing Fees: the fee that the Scheme, and the Operator of the Platform (if different) charge to the DFSPs for use of the scheme and platform. As with end-user fees, processing fees can be fixed or variable and may also vary by value-band or transaction volume. + +- Interchange Fees: fees that one DFSP pays to another DFSP related to an interoperable transaction. Interchange Fees are normally set by the Scheme (in the Scheme Rules) and are physically tabulated and collected by the Scheme. The scheme and the operator of the Platform do not pay or receive these fees: they are a debit to one DFSP and a credit to the other. Both the rate of interchange fees and direction (does the Payer DFSP pay or receive?) may vary by use case and secondary use case. Interchange fees may be fixed, a percent of value, or a combination of the two. + +In addition to setting fee policies, schemes will need to decide on how fees are collected and (in the case of interchange fees) disbursed. There is an important consideration with interchange: should the fees be collected and disbursed as a part of the settlement of each transaction, or as an end-of-period (such as monthly) billing process? + +### 10.1 L1P Alignment: Fees + +One of the most important Level One concepts is to have an ultra-low-cost platform, with consumer and small merchant fees being as low as possible. An important element in achieving this for a payment system is reaching scale. Schemes will want to consider both of these factors as they set fee policies. Considerations include: + +- **End-user pricing.** Is the scheme in a position to put any controls or limitations on this? The answer will vary by jurisdiction. Some schemes have put limitations on the structure of fees (e.g. must be flat vs. percent of value), which parties can be charged (e.g. payers can be charged but not payees, etc.) or on what overall fees can be. Some schemes have not written this into rules but have encouraged informal agreement on fee policies (subject to regulatory approvals) to incent consumer usage. Other schemes have prohibited certain types of fee actions, such as charging surcharges for interoperable transactions. + +- **Processing Fees.** The goal here is for the scheme fees to DFSPs to be as low as possible (specifically and ideally, a fraction of a U.S. cent.). Best market practices are for these fees to be fixed, rather than percent-of-value: this makes sense given that the scheme and the platform are not taking value risk in processing the transactions. However, there is a challenge with purely fixed fees: how to avoid having fees that are too high for very low-value transactions. Some schemes are addressing this through value bands, with lower fixed charges for transactions under a certain value. Some schemes are establishing volume tiers to incent DFSPs. Schemes may wish to encourage (or even mandate) that DFSPs route "on-us" transactions (where payer and payee DFSP are the same institution) through the platform: if this is the case, the scheme may wish to set a zero fee for these transactions. Some schemes may also charge membership fees and/or onboarding fees to DFSPs. Finally, some schemes may provide a period of time after launch of the scheme in which all fees are waived. + +- **Interchange Fees**. This is a complex and often debated topic in the payment industry worldwide, and one which frequently attracts regulatory scrutiny. Schemes may want to consider: + + - Whether or not to have interchange at all. Some payments systems have this; many do not. Retail real-time payments systems worldwide are split on whether or not they support the use of interchange, and where they do, in which direction interchange flows for use cases such as P2P. + + - Interchange is a useful mechanism for a form of billing: where the receiver of a valuable service (such as a merchant who wants access to a consumer's payment account) has no relationship with the provider of that service (the consumer's DFSP). Another example of this is where one bank's ATM is used to disburse funds to another bank's customer. + + - Interchange is more questionable when it is being used to support legacy business models: for example, if an interoperable transaction causes a paying DFSP to "lose" a cash-out fee they would otherwise have gained, the scheme may specify an interchange rate in which the Payee DFSP pays the Payer DFSP to compensate for this loss. It may be practical to use interchange in these situations in the short run, but in the long run one can argue that the underlying business model needs to evolve. + + - Schemes should keep in mind that wherever interchange is used, a "hard cost" is being created that is being absorbed by, and probably passed on in end-user fees, by the interchange-paying-DFSP. + +## 11. Choice: Brand Management + +Should a scheme brand be used? Should the same brand be used for all use cases? Or should the only brand used be the brand of the DFSP who is offering a service to its customers? Not surprisingly, this is an issue that has been debated in payments systems through the years. + +### 11.1 L1P Alignment — Brand + +Level One has a clear design principle supporting a common brand: this is predicated on making the service understandable and easy to use for both consumers and merchants. A common scheme brand may be used in conjunction with DFSP brands: "Use DFSP SuperPay (DFSP brand) with XPay (Scheme brand) to pay your bills." + +Business rules will need to specify how and where the common brand is used. + +## 12. Choice: Scheme Connections to Other Schemes + +The advent of roughly similar real-time retail payments systems worldwide has led to many discussions about the desirability of connecting these schemes to each other. This can both facilitate transactions within a country, but notably has importance for cross-border payments of all kinds, including workers\' remittances. + +In legacy payment systems, this type of connection is rare on a scheme-to-scheme basis. Notable exceptions to this are the connection domestically of ATM networks, and the connection of domestic card schemes that are owned or controlled by global card networks. What happens, instead, is that DFSPs or other providers who have participation in multiple networks (either directly or through partnerships) create the effect of cross-scheme connection through individual deals: this is, essentially, how cross-border correspondent banking works. + +Mojaloop as a technology is designed to allow system-to-system connectivity. Schemes implementing Mojaloop systems will need to consider the balance between striking scheme-to-scheme business agreements (with concurrent technical connections) and/or allowing DFSPs in their scheme to connect to other schemes or DFSPs bilaterally. + +### 12.1 L1P Alignment — Connections to Other Schemes + +The relevant L1P principles here are low cost and "openness". The Mojaloop code in particular has the potential to turn cross-border transactions from ones that are governed by complex relationships (as in the case of traditional correspondent banking) into ones which are competed for in an open, interconnected marketplace. Schemes will need to evaluate the merits of this (arguably promoting lower costs) with the risks of dominance by major institutions. Scheme-to-scheme business arrangements may have a beneficial "level the playing field" characteristics. Hybrid relationships are also possible. This is an evolving area of the payment industry, and one where considerable variety of arrangements are both possible and likely. + +## 13. Choice: Scheme Use by Other FSPs + +A successful L1P aligned scheme will be used by many enterprises — merchants, billers, government agencies, etc. as well as individual people. There will also be a wide range of other FSPs (Financial Services providers) which are not DFSP's: in other words, which do not hold customer transaction accounts. This includes payments services providers: aggregators, merchant services providers, various DFSP processors, etc., all of which may want to connect to and use the scheme. + +As described in the "participation" choice above, a Level One aligned scheme includes as direct, settling participants only the entities that hold the end-user transaction accounts: the accounts that are debited and credited as a result of the interoperable transaction. + +Other entities may physically connect to the platform under a variety of business arrangements. The scheme will need to decide how involved scheme business rules are in dictating terms or standards for these arrangements. As a general principle, any other FSP connecting to the platform will need to be acting on behalf of a DFSP whose customer's transaction account is being debited (the payer DFSP) or credited (the payee DFSP). In legacy payments models, the DFSP retains all of the financial obligations and liabilities for the transaction: the third party is acting purely on behalf of the DFSP. Scheme business rules may specify requirements for the business arrangements between the DFSP and the third party. In some jurisdictions (notably India and the EU) regulation is driving changes to this model to allow other FSPs to have more direct involvement in schemes. Scheme rules will need to carefully describe and proscribe the parameters of these arrangements. + +Definitional note: we are purposefully not using the term "PSP" (Payment Service Provider) here, as in various jurisdictions this term is used to include transaction account providers, in some cases, and non-transaction account providers in other cases. As a further comment, in many countries today entities such as aggregators hold financial accounts at banks or eMoney Issuers and use those accounts to receive money from customers and disburse money to other customers. In this role, the aggregator is a customer of a DFSP (the bank or eMoney Issuer) and is also acting as a Financial Services Provider. It may be that these aggregators in the future will not need to intermediate the financial transaction, but instead provide directions that lead to direct transfer of funds, through the scheme, from one customer's transaction account to another's. + +### 13.1 L1P Alignment — Use by Other FSPs + +The principles here are, again, low cost and openness. Level One would encourage new players to be able to use and access the scheme, as long as their actions are controlled by the scheme in order to ensure safety and financial stability. + +## 14. Choice: Scheme Risk Management Standards + +Payments schemes, their platforms, and participating DFSPs and third parties all, obviously, need to operate according to strong risk management standards in order to ensure a healthy payments system ecosystem. + +The question for a scheme is the balance between defining these standards itself and relying on other standards. From a Business Rules perspective, this is a significant choice. Schemes may either: + +- Develop detailed risk management standards for DFSPs (and for the Platform) and conduct rigorous certification and/or audit processes to ensure compliance + +- Require DFSPs, the Platform and third parties to follow referenced national or global standards for risk management and security + +### 14.1 L1P Alignment — Risk Management Standards + +The Level One does not address which choice above is the better. But the concepts of a safe system for consumers to use, and a low-cost system clearly apply here. Some considerations: + +- A shared fraud management utility (which Level One principles do support) can cost-effectively handle some of the tasks of fraud management. This does not reduce an individual DFSP's compliance burden, but merely shifts how it meets that burden + +- The global card networks have effectively demonstrated the ability to automate elements of exception processing, focusing on those transactions which occur the most often + +- The Mojaloop community has expressed interest in codifying exceptions, and providing support through code for some processes + +- The Mojaloop community may also develop best practices documents for handling areas of risk management, including cybersecurity + +## 15. Choice: Exception Management + +Exception processing includes a wide variety of non-standard transactions and interactions among users and providers of a payment scheme. These include: + +- Errors on the part of end-users + +- Errors on the part of DFSPs, the Platform, or other FSPs + +- Fraud committed by end-user customers, including individuals, + merchants, billers, or other entities + +- Fraud committed by third parties, including hackers + +- Malicious attacks on the system or on individual DFPSs, including cyber-attacks. + +Schemes have important choices to make about how involved the scheme, and its Business Rules, are in defining how scheme participants handle these exceptions. Legacy payment systems show us a wide variety of models which are used, from systems where the scheme and Business Rules have minimal involvement in handling of exception processing (checking, most ACH systems) to systems where the scheme and its Business Rules are extensively involved (most card networks). Real-time retail payment systems worldwide are generally only in the early stages of deciding on how to handle these matters. + +### 15.1 L1P Alignment — Exception Processing + +There are two very important Level One design principles that relate to this. + +- One is the principle of transaction irrevocability. This means that a payment transaction that is successfully completed (in a Mojaloop implementation, one that has been fulfilled) may not be reversed without the consent of the payee. + +- The other is the commitment to a shared fraud management resource at the platform level. The idea is that the scheme and its platform will have a larger view of all transaction data and will be able to perform fraud detection and management tasks more effectively and at a lower cost than can individual DFSPs. This concept is in its very early stage of evolution as Level One systems are deployed, both with and without Mojaloop technology. + +Schemes will face significant challenges in this area as the long-anticipated rollout of merchant payments occurs, particularly in lesser developed markets that do not have highly penetrated card payments industries. The challenge will be to balance the desire to protect consumers from merchant fraud with the desire to have low-cost end-user pricing. In developed card payments markets, this is often provided by business rules which specify that a merchant's bank is responsible financially for fraud committed by the merchant. This works but results in relatively high transaction charges to the merchant, as their bank must cover their risk exposure under these rules. This financial model may or may not be sustainable in less developed economies. This is another are where we anticipate extensive evolution over the coming years. diff --git a/docs/adoption/Scheme/scheme-participation-agreement.md b/docs/adoption/Scheme/scheme-participation-agreement.md new file mode 100644 index 000000000..3fd84473e --- /dev/null +++ b/docs/adoption/Scheme/scheme-participation-agreement.md @@ -0,0 +1,76 @@ +# Scheme Participation Agreement Template + +- Version: 3.0 + - Author: Carol Coye Benson (Glenbrook) + - Date: October 2019 + - Description: + +--- + +## **About the Mojaloop Community Business Document Project** + +This document is part of the Mojaloop Community Business Document Project. The project is intended to support entities (countries, regions, associations of providers or commercial enterprises) implementing new payments systems using Mojaloop code. These entities will also need write Business Rules that participants in the system will follow. + +The Mojaloop Community Business Document Project provides templates for Business Rules and related documents. There are many choices involved in implementing a new payment system: the templates show some of the choices and, where appropriate, commentary is provided on how the particular choice is related to the goals of a Level One aligned system. + +The following documents are part of the project: + +- Scheme Key Choices + +- Scheme Participation Agreement Template + +- Scheme Business Rules Template + +- Platform Operating Guideline Template + +- Exception Management Operating Guideline Template + +- Uniform Glossary + +# Table Of Content + +[1 - Participation Application and Agreement](#_1-participation-application-and-agreement) + +[1.1 - Applicable Law](#_1-1-applicable-law) + +[1.2 - Signature Block: Applicant and Scheme](#_1-2-signature-block-applicant-and-scheme) + +# 1. Participation Application and Agreement + +::: tip NOTE +The goal of this document is to have it contain the minimal necessary provisions to evidence a DFSP's application to join the Scheme and abide by its Business Rules. In particular, future changes to the Business Rules should not result in a need to re-sign or amend this agreement. +::: + +The undersigned organization ("_Applicant_") hereby applies for participation in the \[Scheme\], a \[a legal form of company\] organized and existing under the laws of \[define\] and if accepted by \[Scheme\] agrees that Applicant's participation in the Scheme will be subject to the following terms and conditions. This Application and Agreement is dated \_\_\_\_\_\_\_\_\_\_\_\_\_\_and shall become effective and binding upon the Applicant as of the date shown below when signed on behalf of the \[Scheme\] (the "*Effective Date*"). From the Effective Date, Applicant shall be called a "*Participant*." Applicant acknowledges that this Participation Application and Agreement is supported by adequate mutual consideration. Terms not defined in this Application and Agreement will have the meanings as set forth in the Business Rules, as defined below. + +- Applicant shall be bound by and shall observe all of the provisions of the Business Rules. + +- The Business Rules comprise the Business Rules and the Associated Documents and other documents that may be designated as Associated Documents from time to time by the Scheme. Business Rules and Associated Documents include all other documents as designated in those documents. + +- The Scheme may amend the Business Rules from time to time as it deems appropriate, providing Participants such reasonable advance notice of changes or additions as the Scheme may find appropriate in the circumstances. + +- Participants will pay Fees as specified in the Business Rules. + +- Termination: + + - A Participant may terminate participation at any time without cause on X days' written notice. Such termination will be subject to provisions in the Business Rules regarding the costs and procedures for winding down the Participant's operations with respect to the Scheme. The Participant will remain liable for all Fees and other charges and liabilities incurred pursuant to the Business Rules through the effective date of termination. + + - The Scheme can terminate a Participant for causes provided in the Business Rules. + + - Termination of a Participant for cause will be subject to obligations upon termination and procedures specified in the Business Rules. + + - License. Participant is granted a license to participate, including use of Scheme Property, upon terms as specified in the Business Rules. Participant is licensed to provide Services using Scheme Processing Components and the Scheme Brand and to use Scheme Property in the following countries: + + - Information Submissions. Applicant warrants and represents that all information submitted to the Scheme in support of this Participation Application and Agreement is correct and complete as of the date of this application. + +## 1.1 Applicable Law + +- Choice of Law. This Application and Agreement and the Business Rules shall be construed and applied in accordance with the laws of \[specify\] and not by provisions of such laws which would determine which jurisdiction's laws would apply in the absence of this choice of law provision. + +- The Scheme and Participant will conduct all performance in connection with the Scheme in compliance with Applicable Law. + +- Business Rules will not be understood to require any action that would cause the Scheme or the Participant to violate Applicable Law. Any conflict between Applicable Law and a provision of the Business Rules will be resolved in accordance with procedures specified in the Business Rules. No such resolution shall require Participant or the Scheme to take any action or refrain from any action that would cause it to violate Applicable Law. + +The Applicant has caused this Application and Participation Agreement to be signed on behalf of Applicant by the individual indicated below subject to the Applicant's warranties and representations that such individual has been authorised by all necessary and appropriate company action to enter into this Application and Participation Agreement as of the date indicated above and that when signed on behalf of Applicant and accepted by the Scheme, will form a binding and enforceable obligation of Applicant as of the date indicated below. + +## 1.2 Signature Block: Applicant and Scheme diff --git a/docs/adoption/Scheme/scheme-uniform-glossary.md b/docs/adoption/Scheme/scheme-uniform-glossary.md new file mode 100644 index 000000000..2cd4d7d8b --- /dev/null +++ b/docs/adoption/Scheme/scheme-uniform-glossary.md @@ -0,0 +1,299 @@ +# Uniform Glossary Template + +- Version: 1.0 + - Author: Carol Coye Benson (Glenbrook) + - Date: October 2019 + - Description: + +--- + +## **About the Mojaloop Community Business Document Project** + +This document is part of the Mojaloop Community Business Document Project. The project is intended to support entities (countries, regions, associations of providers or commercial enterprises) implementing new payments systems using Mojaloop code. These entities will also need write Business Rules that participants in the system will follow. + +The Mojaloop Community Business Document Project provides templates for Business Rules and related documents. There are many choices involved in implementing a new payment system: the templates show some of the choices and, where appropriate, commentary is provided on how the particular choice is related to the goals of a Level One aligned system. + +The following documents are part of the project: + +- Scheme Key Choices + +- Scheme Participation Agreement Template + +- Scheme Business Rules Template + +- Platform Operating Guideline Template + +- Exception Management Operating Guideline Template + +- Uniform Glossary + +## **Introduction** + +This is a glossary of terms used in the Mojaloop Business Community Document Project, and contains other terms related to business topics. A more detailed technical glossary is available as part of the Open API for FSP Interoperability Specification. + +# Uniform Glossary Template + +| Term | Definition | +| :----- | :---------------------------------------------------------------------------------------------- | +| Access Channel | Places or capabilities that are used to initiate or receive a payment. Access channels can include bank branch offices, ATMs, terminals at the POS, agent outlets, mobile phones, and computers. | +| Account Lookup | A process that determines the DFSP responsible for a Transaction Account. | +| Account Lookup System | Account Lookup System is an abstract entity used for retrieving information regarding in which FSP an account, wallet or identity is hosted. The Account Lookup System itself can be hosted in its own server, as part of a financial switch, or in the different FSPs. | +| Account Validation | A status provided by a Quote Response API Call: a Payee DFSP indicates that an account is available to be credited with a proposed transfer amount. | +| Active User | A term used by many providers in describing how many of their account holders are frequent users of their service. | +| Addressing | The use of an identifier to direct a Payment from a Payer to a Payee, typically a mobile phone number or email address. | +| Adjacencies | Ways in which entities and/or DFSPs realize revenue from services that are not directly associated with a Payment---for example, loans made to Transaction Account holders. | +| Agent | An entity authorized by the provider to handle various functions such as customer enrollment, cash-in and cash-out using an agent till. | +| Agent Outlet | A physical location that carries one or more agent tills, enabling it to perform enrollment, cash-in and cash-out transactions for customers on behalf of one or more providers. National law defines whether an agent outlet may remain exclusive to one provider.Agent outlets may have other businesses and support functions. | +| Agent Till | An agent till is a provider-issued registered "line", either a special SIM card or a POS machine, used to perform enrollment, cash-in and cash-out transactions for clients. National law dictates which financial service providers can issue agent tills. | +| Agent-Initiated Cash-In | A Use Case defined in the API Specifications document. | +| Agent-Initiated Cash-Out | A Use Case defined in the API Specifications document. | +| Aggregator | A specialized form of a merchant services provider, who typically handles payments transactions for a large number of small merchants. Scheme rules often specify what aggregators are allowed to do. | +| Alias | A Payee Identifier that is mapped to a Payee DFSP and Transaction Account Number. | +| Anti-Money Laundering (AML) | Anti-Money Laundering refers to Applicable Law and, to the extent expressly adopted by the Scheme, good practice guidance, t regarding mitigation of money laundering risks. | +| API | Application Programming Interface: a technical interface implemented by a software protocol that allows systems to interact with each other via standard structures, without requiring a user system to know the internal implementation details of the system with which it is interacting. | +| Applicable Law | All treaties, conventions, laws, regulations, directives, official guidance or directives of a Regulatory Authority to the extent that they are binding, respectively, upon the Scheme, the Scheme or a Participant with regard to the Scheme\'s Services. | +| Applicant | An organization that has submitted or wishes to submit an application to become a Participant, but whose application has not been acted upon by the Scheme. | +| Application Program Interface (API) | A method of communication to allow interaction and sharing of data between different software or Technical Protocols. | +| Arbitration | The use of an arbitrator, rather than courts, to resolve disputes. | +| Associated Documents | The set of documents listed in Appendix A of these Rules. | +| ATM-Initiated Cash-Out via OTP | A Use Case defined in the API Specifications document. | +| Attribute | A characteristic of a Transaction, it being understood that specific rules may apply to Transactions with specific Attributes. | +| Authentication | The process of ensuring that a person or a transaction is valid for the process (account opening, transaction initiation, and so on) being performed. | +| Authorization | The permission given by the Payer or entity to make a Payment. | +| Authorized /institution entity | Non-financial institutions that have followed the appropriate authorization by State Bank and/or relevant regulatory authorities to partake in the provisioning of mobile financial services. | +| B2P | Business to Person; a Bulk Payment Secondary Use Case. | +| Bank | A chartered financial system within a country that has the ability to accept deposits and make and receive payments into customer accounts. | +| Bank Account | A Transaction Account offered by a Bank. | +| Bank Account Identifier | A type of Payee Identifier. | +| Bank Accounts and Transaction Services | A transaction account held at a bank. This account may be accessible by a mobile phone, in which case it is sometimes referred to as \"mobile banking\". | +| Bank to Bank | A P2P Secondary Use Case. | +| Bank to Wallet | A P2P Secondary Use Case. | +| Bank-Led Model| A reference to a system in which banks are the primary providers of digital financial services to end users.National law may require this.| +| Basic Phone | Minimum device required to use digital financial services. | +| Bill Payment | A P2B Secondary Use Case. | +| Biometric Authentication | The use of a physical characteristic of a person (fingerprint, IRIS, and so on) to authenticate that person. | +| Blacklist| A list or register of entities (registered users) that are being denied/blocked from a particular privilege, service, mobility, access or recognition. | +| Blockchain | A technology that creates distributed architectures. In payments systems, often a reference to a shared ledger that records and validates Transactions. +| Blockchain | The technology underlying bitcoin and other cryptocurrencies - a shared digital ledger, or a continually updated list of all transactions. | +| Brand | A word and/or mark approved by the Scheme for use by Participants. | +| Bulk Disbursement | A Use Case defined in the API Specifications document. | +| Bulk Payment | A Payment from a single Payer to multiple Payees, for example cash transfer programs from a government or NGO to a set of beneficiaries. | +| Bulk upload service | A service allowing the import of multiple transactions per session, most often via a bulk data transfer file which is used to initiate payments.Example: salary payment file. | +| Business | Entity such as a public limited or limited company or corporation that uses mobile money as a service; for example, making and accepting bill payments and disbursing salaries. | +| Cash Management | Management of cash balances at an agent. | +| Cash-In | Receiving eMoney credit in exchange for physical cash - typically done at an agent. | +| Cash-Out | Receiving physical cash in exchange for a debit to an eMoney account - typically done at an agent. | +| Chip Card | A chip card contains a computer chip: it may be either contactless or contact (requires insertion into terminal).Global standards for chip cards are set by EMV. | +| Clearing | The process within a Payment system in which a Payer DFSP and a Payee DFSP debit and credit their End User accounts. | +| Closed-Loop | A payment system used by a single provider, or a very tightly constrained group of providers. | +| Combatting Financing of Terrorism (CFT) | Initiatives to prevent individuals or entities from using payment systems to send funds to individuals or entities associated with terrorism. | +| Commission | An incentive payment made, typically to an agent or other intermediary who acts on behalf of a DFS provider.Provides an incentive for agent. | +| Commit | Part of a 2-phase transfer operation in which the funds that were reserved to be transferred, are released to the payee; the transfer is completed between the originating/payer and destination/payee accounts. | +| Condition | In the Interledger protocol, a cryptographic lock used when a transfer is reserved. Usually in the form of a SHA-256 hash of a secret preimage. When provided as part of a transfer request the transfer must be reserved such that it is only committed if the fulfillment of the condition (the secret preimage) is provided. | +| Corridor | Refers to any two countries in a cross-border Transaction and to the direction of the transfer. | +| Counterparty | The other side of a payment or credit transaction. A payee is the counterparty to a payer, and vice-versa. | +| Coupon | A token that entitles the holder to a discount or that may be exchanged for goods or services. | +| Credit Transfer | A Payment or Transfer of funds initiated by the Payer DFSP to the Payee DFSP. A Credit Transfer is often referred to as a 'credit push transfer' because the funds are 'pushed' from the Payer's Transaction Account. Credit Transfer contrasts with Direct Debit. | +| Cross-Border | A Transfer from a Payer DFSP domiciled in one country, to a Payee DFSP that is domiciled in another country. | +| Cross-FX Transfer | Transfer involving multiple currencies including a foreign exchange calculation. | +| Current Position | A Participant\'s current net position in the Position Ledger for a given Currency. | +| Customer | The Customer of the system. The term is used for both the Payer and the Payee. Individuals, merchants, billers, governments, and other enterprises are all customers. Sometimes refered to as end-users. | +| Customer-Initiated Cash-Out | A Use Case defined in the API Specifications document. | +| Customer-Initiated Purchase | A Use Case defined in the API Specifications document. | +| Customer-Initiated Purchase via QR | A Use Case defined in the API Specifications document. | +| DFSP (Digital Financial Services Provider) | A financial services provider that is licensed by a regulatory authority to provide Transaction Accounts which hold customer funds and are used to make and receive Payments. DFSPs have relationships with consumers, merchants, and other enterprises, and provide digital financial services to End Users. Used interchangably with FSP (Financial Services Provider). | +| Digital | Electronic communications between two individuals or entities that can occur on various electronic devices (e.g., mobile, tablet, computer). | +| Digital Liquidity | A practice of keeping value in Digital form, rather than exchanging the Digital value for cash (physical form). | +| Digital Payment | A broad term including any payment which is executed electronically. Includes payments which are initiated by mobile phone or computer. Card payments in some circumstances are considered to be digital payments. The term \"mobile payment\" is equally broad and includes a wide variety of transaction types which in some way use a mobile phone. | +| Direct Debit | A Payment or Transfer of funds initiated by the Payee DFSP to the Payer DFSP. A Direct Debit is often referred to as a 'debit pull transfer' because the funds are 'pulled' from the Payer's Transaction Account. Direct Debit contrasts with Credit Transfer. | +| Directory | A centralized or decentralized holding of payment identifiers to be used for Addressing, accessible by the payments system or DFSPs. | +| Dispute Resolution | A process specified by a provider or by the rules of a payment scheme to resolve issues between end users and providers, or between an end user and its counter party. | +| Domestic | Describes a Transaction between two DFSPs domiciled in the same country. | +| eMoney | Digital funds or value owned by a Transaction Account holder on a payment device such as chip, prepaid card, mobile phone, or on a computer system. National regulation specifies what types of DFSPs can issue eMoney. | +| eMoney Issuer | A DFSP licensed in the country to act as an eMoney Issuer. | +| End User | The customer of a DFSP. The customer may be a consumer, a merchant, a government, or another form of enterprise. | +| End-User Fees | Fees assessed by a DFSP to their en-end user customer. | +| Enterprise | Any non-individual person who is a customer of a DFSP: includes Merchants, Billers, Government Agencies, and other enterprises. | +| Escrow or Trust Account | An account held by a Non-Bank DFSP at a bank; normally a regulatory requirement to protect consumer deposits at the DFSP. | +| Exceptions | Transactions that are erroneous or fraudulent. | +| FATF | The Financial Action Task Force is an intergovernmental organization to combat money laundering and to act on terrorism financing.| +| Feature Phone | A mobile telephone without significant computational capabilities. | +| Fees | The payments assessed by a provider to their end user. This may either be a fixed fee, a percent-of-value fee, or a mixture. | +| Fiat Currencies | Official money issued by the central bank of a country or region as legal tender. | +| Financial Inclusion | The sustainable provision of affordable Digital financial services that bring the Low Income End Users into the formal economy. | +| Financial Inclusion | The sustainable provision of affordable digital financial services that bring the poor into the formal economy. | +| Financial Literacy | Consumers and businesses having essential financial skills, such as preparing a family budget or an understanding of concepts such as the time value of money, the use of a DFS product or service, or the ability to apply for such a service. | +| Fintech | A term used to describe the intersection of finance and technology. 'Fintechs' are entities providing innovative solutions in the finance space, leveraging technology. | +| Float | This term can mean a variety of different things. In banking, float is created when one party\'s account is debited or credited at a different time than the counterparty to the transaction. eMoney, as an obligation of a non-bank provider, is sometimes referred to as float. | +| Fraud | Criminal use of digital financial services to take funds from another individual or business, or to damage that party in some other way. | +| Fraud Risk Management | Tools to manage providers\' risks, and at times user\'s risks (for example, for merchants or governments) in providing and/or using DFS services. | +| FSP | The entity that provides a digital financial service to an end user (either a consumer, a business, or a government.) Used interchangably with DFSP (Digital Financial Services Provider). | +| Fulfilled Transfer | A transfer that has been accepted by the Payee DFSP and recorded as complete by the Scheme. Once a transfer has been recorded as complete by the Scheme, the Payer is obliged to honour the transaction when it appears in a Settlement. | +| Fulfillment | In the Interledger protocol, a secret that is the preimage of a SHA-256 hash, used as a condition on a transfer. The preimage is required in the commit message to trigger the transfer to be committed. | +| FX | Foreign Exchange. | +| G2P | A Bulk Payment Secondary Use Case. | +| Governance | The collection of management approaches, decisions, and oversight functions within the Scheme. Scheme Governance can set the tone for everything that occurs in the Scheme. | +| Government Agency | Any Transaction Account Holder which is some kind of government agency or department. | +| Government Payments Acceptance Services | Services which enable governments to collect taxes and fees from individuals and businesses. | +| Gross Settlement | A method of settling financial obligations among DFSPs and a Scheme. Gross Settlement processes each Transaction individually. The details of the Gross Settlement model are specified in Scheme rules. Gross Settlement contrasts to Net Settlement. | +| Hub | A term that may be used for the entity that operates the Platform on behalf of the Scheme. | +| Identifier Service | The way in which the Account Lookup Process works for a given type of Identifier. | +| Identity | A credential of some sort that identifies an end user. National identities are issued by national governments. In some countries a financial identity is issued by financial service providers. | +| Immediate Funds Transfer | A digital payment which is received by the payee almost immediately upon the payer having initiated the transaction. | +| Interchange | A structure within some payments schemes which requires one provider to pay the other provider a fee on certain transactions. Typically used in card schemes to effect payment of a fee from a merchant to a consumer\'s card issuing bank. | +| Interledger | The Interledger protocol is a protocol for transferring monetary value across multiple disconnected payment networks using a choreography of conditional transfers on each network. | +| International Remittance | Making and receiving payments to another person in another country. | +| Interoperability | The ability of an Customer with a Transaction Account with one Participant to exchange a transaction with an Customer who has a Transaction Account with a different Participant. | +| Interoperability Service for Transfers (IST) | A switch. | +| Irrevocable | A transaction that cannot be \"called back\" by the payer; an irrevocable payment, once received by a payee, cannot be taken back by the payer. | +| Know Your Customer (KYC) | Regulatory requirements for a DFSP to establish the Identity and activities of an End User or entity, both before opening a Transaction Account and over time. | +| Ledger | A record kept of transactions. | +| Level One Project | An initiative of the Bill & Melinda Gates Foundation to promote financial inclusion. | +| Liability | A legal obligation of one party to another; required by either national law, payment scheme rules, or specific agreements by providers. Some scheme rules transfer liabilities for a transaction from one provider to another under certain conditions. | +| License | The license granted to an Applicant by the Scheme upon acceptance of the Scheme Participation Agreement, which permits the Participant to participate in the Scheme and to use Scheme Property in accordance with the Rules. | +| Liquidity | The availability of liquid assets to support an obligation. Banks and non-bank providers need liquidity to meet their obligations. Agents need liquidity to meet cash-out transactions by consumers and small merchants. | +| Loans | Means by which end users can borrow money. | +| Merchant | An enterprise which sells goods or services and receives payments for such goods or services. | +| Merchant Acquisition | The process of enabling a merchant for the receipt of electronic payments. | +| Merchant Category Codes | A categorization set by a Scheme to differentiate among enterprise customers. | +| Merchant ID | A type of Payee Identifier. | +| Merchant Service Provider | A provider (bank or non-bank) who supports merchants or other payments acceptors requirements to receive payments from customers. The term \"acquirer\" is used specifically in connection with acceptance of card payments transactions. | +| Merchant-Initiated Purchase | A Use Case defined in the API Specifications document. | +| Merchant-Initiated Purchase via POS/OTP | A Use Case defined in the API Specifications document. | +| Merchant-Initiated Purchase via QR | A Use Case defined in the API Specifications document. | +| Microfinance Institution (MFI) | An entity that offers financial services to Low Income populations. Almost all MFIs give loans to their members, and many offer insurance, deposit and other services. MFI's are considered DFSPs in a Level One System if they provide Transaction Accounts to their customers. MFI's who are not DFSPs may connect directly to a Level One Platform, through a relationship with a DFSP. Scheme rules will specify how such MFI's may interact with the Platform. | +| Mobile Network Operator (MNO) | An enterprise which sells mobile phone services, including voice and data communication. | +| Money Transfer Operator | A specialized provider of DFS who handles domestic and/or international remittances. | +| MSISDN | Number uniquely identifying a subscription in a mobile phone network. These numbers use the E.164 standard that defines numbering plan for a world-wide public switched telephone network (PSTN). | +| Multilateral Net Settlement | A type of settlement that manages the positions of a group of participants in a scheme. | +| National Identity Document | A credential that identifies an End User. National Identity Documents are issued by national governments. | +| Near Field Communication | A communication technology used within payments to transmit payment data from an NFC equipped mobile phone to a capable terminal. | +| Net Debit Cap | A value that the Platform uses in determining whether a Payer DFSP can send a Request for Transfer, as defined in the Scheme Operating Rules. | +| Net Debit Cap Margin | A value set by a scheme which increases or decreases the Net Debit Cap of a participant. | +| Net Position | A value in a scheme participant\'s ledger, reflecting the net of obligations owed. | +| Net Settlement | A type of settlement that nets the position of a participant in a scheme, reflecting both obligations owed to and from other participants or the scheme. | +| Non-Bank | An entity that is not a chartered bank, but which is providing financial services to end users. The requirements of non-banks to do this, and the limitations of what they can do, are specified by national law. | +| Non-Bank-Led Model | A reference to a system in which non-banks are the providers of digital financial services to end users. Non-banks typically need to meet criteria established by national law and enforced by regulators. | +| Non-repudiation | Ability to prove the authenticity of a transaction, such as by validating a digital signature. | +| Not-for-Loss | A cost-recovery model with an additional set of funds available to cover investment requirement to operate the Platform. | +| Notification | Notice to a payer or payee regarding the status of transfer. | +| Off-Us Payments | Payments made in a multiple-participant system or scheme, where the payer\'s provider is a different entity as the payee\'s provider. | +| On-Us Payments | Payments made in a multiple-participant system or scheme, where the payer\'s provider is the same entity as the payee\'s provider. | +| Online Purchase | A P2B Secondary Use Case. | +| Open API Specification | The Open API for FSP Interoperability specification. | +| Open-Loop | A payment system or scheme designed for multiple providers to participate in. Payment system rules or national law may restrict participation to certain classes of providers. | +| Operating Rules | Rules written by a scheme which bind scheme participants. Sometimes called \"Business Rules\". | +| Operations Risk Management | Tools to manage providers\' risks in operating a DFS system. | +| Operator | An entity that provides and/or manages the Platform of a payments system. | +| Organization | An entity such as a business, charity or government department that uses mobile money as a service; for example, taking bill payments, making bill payments and disbursing salaries. | +| OTP | One-time Passcode. OTP is a credential which by definition can only be used once. It is generated and later validated by the same FSP for automatic approval. The OTP is usually tied to a specific Payer in a Payment. The generated OTP is usually a numeric between 4 and 6 digits. | +| Over The Counter Services | Services provided by agents when one end party does not have an eMoney account: the (remote) payer may pay the eMoney to the agent\'s account, who then pays cash to the non- account holding payee. | +| P2P | A Use Case defined in the API Specifications document. | +| Participant | A provider who is a member of a payment scheme, and subject to that scheme\'s rules. | +| Participant Discretionary Net Debit Cap Margin | A value set by a participant which decreases their Net Debit Cap. | +| Participation Agreement | An agreement entered into between each Participant and a Scheme. | +| Participation Fees | Fees for participation in a payment scheme (sometimes called membership fees). | +| Parties Query | An API Call to the Scheme Directory Service by which a Payer DFSP requests the identifier of the DFSP to which a payee identifier is registered. | +| Parties Query Response | The response from the Scheme Directory Service to a Parties Query. | +| Partner Bank | Financial institution supporting the FSP and giving it access to the local banking ecosystem. | +| Party | An entity which is using Scheme Services directly or indirectly. | +| Party Identifier | An item of information which uniquely identifies an Customer in an Interoperability implementation. | +| Party Identifier Type | An enumeration which distinguishes different types of Party Identifier. The full range of Party Identifier Types is given in the Open API Specification; the subset of Party Identifier Types supported by any given Schema are given in its Operating Rules. | +| Payee | The recipient of electronic funds in a payment transaction. | +| Payee DFSP | The role of a Participant who receives a Transfer on behalf of its customer Payee. | +| Payer | The payer of electronic funds in a payment transaction. | +| Payer DFSP | The Participant who sends a Transfer. | +| Payment | An exchange of funds, credentials, and other necessary information to complete obligation between End Users. A Transfer is a Payment. | +| Payment Device | Payment device is the abstract notion of an electronic device, other than the Payer's own device, that is capable of letting a Payer accept a transaction through the use of a credential (some kind of OTP).Examples of (Payment) Devices are ATM and POS. | +| Payment System | A broad term to describe the overall system, including the Scheme, Scheme Services, and Scheme Participants. | +| Payment System Operator | The entity that operates a payment system or scheme. | +| Payments Service Provider (PSP) | A term used in two ways: generally, as any company involved in the provision of payments services (including DFSPs); or for a provider that offers branded products or services to End Users, including merchants. PSPs may connect directly to a Level One Platform, through a relationship with a DFSP. Scheme rules will specify how PSPs may interact with the Platform. | +| Personal Information | Information related to any individual person, including Customers or employees of the Scheme or of a Participant from which the individual may be identified or recognized regardless of the form of such information. | +| Platform | The set of operational capabilities, often including a Switch, that implement the exchange of Payments in a Level One aligned interoperable payment system. | +| Platform | A term used to describe the software or service used by a provider, a scheme, or a switch to manage end user accounts and to send and receive payment transactions. | +| Pooled Settlement Account | A bank account at the Bank, which is jointly owned by scheme participants. | +| Position Ledger | A ledger kept by the platform which records Provisional Settlement Entries and Final Settlement Entries for a Participant in a given Currency. | +| Posting | The act of the provider of entering a debit or credit entry into the end user\'s account record. | +| Processing Fees | Fees billed by the Scheme to Participants for Processing done by the Scheme Platform. | +| Processor | An enterprise that manages, on an out-sourced basis, various functions for a DFSP. These functions may include transaction management, customer database management, and risk management. Processors may also do functions on behalf of payments systems, Schemes, or Switches. Processors may connect directly to a Level One Platform, acting on behalf of a DFSP. Scheme rules will specify how Processors may interact with the Platform. | +| Provisional Debit | A record wtihin a scheme Position Ledger of a Transfer Request that has not been fulfilled; recorded only on the Payer DFSP\'s Position Ledger | +| PSP | Payment Service Provider. | +| Pull Payment | A type of Transaction originated by the Payee's DFSP. Direct Debits, checks, and card payments are all Pull Payments. Pull Payments can bounce or fail for insufficient funds unless a separate Authorization is done (e.g., cards). | +| Push Payment | A type of Transaction initiated by the Payer DFSP. This is sometimes called a Credit Transfer. | +| QR Code Purchase | A P2B Secondary Use Case. | +| Quick-Response (QR) Code | A method of encoding and visualizing data in machine-readable form. There are multiple QR models. | +| Quote | A process by which a Payee DFSP acknowledges the validity of the Payee account to accept a transfer, and sets terms (and possibly fees) related to that transfer. | +| Quote Request | A request by a Payer DFSP for data relating to a proposed Transfer. | +| Quote Response | The response of a Payee DFSP to a Request for Quote. | +| Real Time Gross Settlement (RTGS) | A settlement model which settles transfers on an individual, rather than a net, basis. | +| Real Time Retail Payments (RTRP) | Retail Payments that are processed in real time (as initiated). | +| Receive Amount | The amount which is credited to a Payee\'s Transaction Account. | +| Reconciliation | Cross FSP Reconciliation is the process of ensuring that two sets of records, usually the balances of two accounts, are in agreement between FSPs. Reconciliation is used to ensure that the money leaving an account matches the actual money transferred. This is done by making sure the balances match at the end of a particular accounting period. | +| Recourse | Rights given to an end user by law, private operating rules, or specific agreements by providers, allowing end users the ability to do certain things (sometimes revoking a transaction) in certain circumstances. | +| Refund | A transfer which reverses a previous transaction. | +| Regulator | A governmental organization given power through national law to set and enforce standards and practices. Central Banks, Finance and Treasury Departments, Telecommunications Regulators, and Consumer Protection Authorities are all regulators involved in digital financial services. | +| Request for Quote | An API Call that initiates a Transaction in terms of which the Payer DFSP requests the Payee DFSP for information regarding a proposed Transfer. | +| Request for Transfer | A message that is passed from a Payer DFSP through the Platform to a Payee DFSP, that requests that a Transfer be made from the Payer to the Payee. | +| Request to Pay | A message by which a Payee 'requests' Payment from a Payer. A Request to Pay in a Level One System is often used to describe a merchant that requests a Push Payment from an End User. | +| Reserve | Part of a 2-phase transfer operation in which the funds to be transferred are locked (the funds cannot be used for any purpose until either rolled back or committed). This is usually done for a predetermined duration, the expiration of which results in the reservation being rolled back. | +| Retail Payment | A Payment or Transfer between End Users, typically a low value denomination. The term is often used to describe P2P, B2P or P2B Payments. | +| Reversal | The process of reversing a completed transfer. | +| Risk Management | The practices that enterprises do to understand, detect, prevent, and manage various types of risks. Risk management occurs at providers, at payments systems and schemes, at processors, and at many merchants or payments acceptors. | +| Risk-based Approach | A regulatory and/or business management approach that creates different levels of obligation based on the risk of the underlying transaction or customer. | +| Roll back | Roll back means that the electronic funds that were earlier reserved are put back in the original state. The financial transaction is cancelled. The electronic funds are no longer locked for usage. | +| Rules | The practices and standards necessary for the functioning of payment services defined by the Scheme. Rules are sometimes referred to as scheme rules, business rules, or operating rules. | +| Rules Modification | All changes, additions, deletions or other modifications to the Scheme Operating Rules or to any Associated Documents. | +| Saving and Investing | Keeping funds for future needs and financial return. | +| Savings Products | An account at either a bank or non-bank provider, which stores funds with the design of helping end users save money. | +| Scheme | A set of rules, practices, and standards necessary for the functioning of payment services. | +| Secondary Use Case | A subset of a Use Case. Specific Business Rules or Operating Guidelines may apply to Secondary Use Cases. | +| Secure Element | A secure chip on a phone that can be used to store payment data. | +| Security Access Code | A personal identification number (PIN), password/one-time password (OTP), biometric recognition, code or any other device providing a means of certified access to a customer's account for the purposes of, among other things, initiating an electronic fund transfer. | +| Security Incident | (i) Unauthorized access to or disclosure of Personal Information or Transaction Data related to Customers who are eligible to initiate or receive Transfers through the Scheme which has or is reasonably suspected to have occurred; or (ii) a confirmed breach of a Participant\'s networks or systems or their vendor\'s networks or systems that exposes Personal Information or Transaction Data related to the Scheme has or is reasonably expected to have occurred. | +| Send Amount | The amount which a Payer authorizes to be debited from their Transaction Account. | +| Sensitive Consumer Data | Consumer Sensitive Data means any or all information that is used by a consumer to authenticate identity and gain authorization for performing mobile banking services, including but not limited to User ID, Password, Mobile PIN, Transaction PIN. Also includes data relating to religious or other beliefs, sexual orientation, health, race, ethnicity, political views, trades union membership, criminal record. | +| Services | Elements of the scheme platform which delivers interoperability capabilities to scheme participants. | +| Settlement | A process by which Participants settle their obligations to each other and to the Scheme related to the exchange of Transactions as set out in the Settlement Operating Guidelines. | +| Settlement Bank | A bank appointed by the Scheme to be a partner in managing the Settlement and in which each Participant shall have a bank account for the purpose of Settlement. | +| Settlement Bank Account | The bank account held by a Participant at the Settlement Bank or at Bank agreed with the Settlement Bank, that is used for Settlement between the Scheme and the Participant. | +| Settlement Instruction | Means an instruction given to a settlement system by a settlement system participant or by a payment clearing house system operator on behalf of a Central Bank settlement system participant to effect settlement of one or more payment obligations, or to discharge any other obligation of one system participant to another system participant. | +| Settlement Obligation | Means an indebtedness that is owed by one settlement system participant to another as a result of one or more settlement instructions. | +| Settlement Window | A time period between two successive Net Settlements as scheduled in accordance with the Settlement Operating Guidelines. | +| Shared Service | A common set of services that participating DFSPs collaborate to develop and/or use. | +| Smart Phone | A device that combines a mobile phone with a computer. | +| Special Charter Banks | Banks in a country which are permitted to carry out a limited set of functions, as determined by regulation. Special Charter Banks that can only accept deposits and handle Payments are considered DFSPs in a Level One System. | +| Sponsor | An arrangement between an electronic money issuer and a bank, used for payment and collection of interchange fees by the electronic money issuers | +| Standards Body | An organization that creates standards used by providers, payments schemes, and payments systems. | +| Stored Value Account | Account in which funds are kept in a secure, electronic format. May be a bank account or an eMoney account. | +| Suspicious Transaction Report | If a financial institution notes something suspicious about a transaction or activity, it may file a report with the Financial Intelligence Unit that will analyze it and cross check it with other information.The information on an STR varies by jurisdiction. | +| Switch | A processing entity in a payments system that routes a Transaction from one DFSP to another DFSP. A system may operate its own Switch, or this function may be done by one or more third parties. | +| System | A term used to describe the Scheme, services, Platform, and Participants aligned with a Level One Project. | +| Systemic Risk | In payments systems, the risk of collapse of an entire financial system or entire market, as opposed to risk associated with any one individual provider or end user. | +| The Level One Project | An initiative of the Bill & Melinda Gates Foundation, within the Financial Services for the Poor program, that works to support countries or regions building interoperable, low-cost digital financial services systems to bring Low Income persons and merchants into the formal economy. | +| Tiered Acess | A provision set in scheme rules which allows one DFSP to participate in the system under sponsorship of another DFSP. | +| Til Number Purchase | A P2B Secondary Use Case. | +| Transaction | A set of related API Calls that are exchanged between Participants via the Scheme including a Transfer. | +| Transaction Account | A bank account or wallet offered a customer by a DFSP. | +| Transaction Account Holder | The customer of a DFSP who holds the Transaction Account provided by that DFSP. | +| Transaction Account Holder Type | A designation used to define whether or not the Transaction Account Holder is a Consumer, a Business, a Government Agency, or a Non-Profit Agency. | +| Transaction Account Type | A designation used to define a Transaction Account as either a Bank Account or an eMoney Wallet. | +| Transaction Cost | The cost to a DFS provider of delivering a digital financial service. This could be for a bundle of services (for example, a \"wallet\") or for individual transactions. | +| Transaction Fees | Fees for processing interoperable transactions set by a scheme. | +| Transfer | Generic term to describe any financial transaction where value is transferred from one account to another. | +| Transfer Amount | The amount the Payer DFSP Transfers to a Payee DFSP using the Scheme. | +| Transfer Request | A request by a Payer DFSP to make a Transfer. | +| Transfer Response | A Payee DFSP\'s response to a Transfer Request. | +| Trust Account | A means of holding funds for the benefit of another party. eMoney Issuers are usually required by law to hold the value of end users\' eMoney accounts at a bank, typically in a Trust Account. This accomplishes the goals of funds isolation and funds safeguarding. | +| Ubiquity | A term used to describe the ability to pay anyone and be paid by anyone. | +| Unbanked | Unbanked people do not have a transaction account. Underbanked people may have a transaction account but do not actively use it. Underserved is a broad term referring to people who are the targets of financial inclusion initiatives. It is also sometimes used to refer to a person who has a transaction account but does not have additional DFS services. | +| Uncovered Losses | Settlement Obligations that are not met by the responsible DFSP and are not discharged using collateral or other mechanisms. | +| Use Case | A term used to describe the purpose of the Payment. Specific Business Rules or Operating Guidelines may apply to Use Cases. | +| User ID | A unique identifier of a user. This may be an MSISDN, bank account, some form of DFSP-provided ID, national ID, and so on. In a transaction, money is generally addressed to a user ID and not directly to an account ID. | +| USSD | A communication technology that is used to send text between a mobile phone and an application program in the network. | +| Value-Added Services | Services or products provided to End Users that End Users will pay to use or access, often used in coordination with Adjacencies. | +| Voucher | A monetary value instrument commonly used to transfer funds to customers (Payees) who do not have an account at the Payer\'s FSP. This could be Payees with no account or account at another FSP. | +| Wallet | A Transaction Account offered to customers by electronic money issuers. | +| Wallet to Bank | A P2P Secondary Use Case. | +| Wallet to Wallet | A P2P Secondary Use Case. | +| Whitelist | A list or register of entities (registered users) that are being provided a particular privilege, service, mobility, access or recognition, especially those that were initially blacklisted. | +| Women's Economic Empowerment (WEE): | Increasing women's access and rights to economic resources through decent work opportunities, property and assets, Financial Inclusion, and Platforms. | diff --git a/docs/adoption/assets/cla/admin_configure.png b/docs/adoption/assets/cla/admin_configure.png new file mode 100644 index 000000000..1d8281bb4 Binary files /dev/null and b/docs/adoption/assets/cla/admin_configure.png differ diff --git a/docs/adoption/assets/cla/admin_sign_in.png b/docs/adoption/assets/cla/admin_sign_in.png new file mode 100644 index 000000000..a960e2dcd Binary files /dev/null and b/docs/adoption/assets/cla/admin_sign_in.png differ diff --git a/docs/adoption/assets/cla/cla_1.png b/docs/adoption/assets/cla/cla_1.png new file mode 100644 index 000000000..46718fc66 Binary files /dev/null and b/docs/adoption/assets/cla/cla_1.png differ diff --git a/docs/adoption/assets/cla/cla_2_1.png b/docs/adoption/assets/cla/cla_2_1.png new file mode 100644 index 000000000..18ae1809c Binary files /dev/null and b/docs/adoption/assets/cla/cla_2_1.png differ diff --git a/docs/adoption/assets/cla/cla_2_2.png b/docs/adoption/assets/cla/cla_2_2.png new file mode 100644 index 000000000..2e60fb762 Binary files /dev/null and b/docs/adoption/assets/cla/cla_2_2.png differ diff --git a/docs/adoption/assets/cla/cla_3.png b/docs/adoption/assets/cla/cla_3.png new file mode 100644 index 000000000..5e2ddc46d Binary files /dev/null and b/docs/adoption/assets/cla/cla_3.png differ diff --git a/docs/adoption/guides/Role-based-access-control.md b/docs/adoption/guides/Role-based-access-control.md new file mode 100644 index 000000000..ad1dff783 --- /dev/null +++ b/docs/adoption/guides/Role-based-access-control.md @@ -0,0 +1,297 @@ +# RBAC Context + +An individual who needs to access the various Mojaloop Hub management portals can be registered and an "account" generated, which can be used to access various aspects of an operational instance of a Mojaloop Hub and to provide a basis for auditing that access by tying activities to the original registration. For the purposes of this document, an "account" is a digital identity, a means of authenticating (linking) the person asserting that identity to the original registration, and a set of attributes, which will include - among other things - a set of access rights, or rights that are enabled through the possession of those attributes. + +### RBAC Design + +The RBAC design for a hub operator, outlines the security control points that should be considered or extended in order to mitigate risk within a typical Mojaloop hub operations organisation. Some control points are business processes and organisational structure related, some control points are technical relating to the identification, authentication and authorisation layers, and some control points require monitoring. All three should be considered to create accountability and mitigate risk. + +### Audit + +Audit would need to work collaboratively with the business and the IT teams to Segregate these duties wherever possible and assign an appropriate mitigation control in cases wherein it is not feasible to do so. In addition, these controls would need to be monitored on a quarterly basis and the results need to be reported to senior management. + +Some contextual definitions include + +1. **Action** : a distinct event triggered by a user that results in: + +- Creation of a data asset +- Reading or accessing of a data asset +- Update or effecting changes to the state of a data asset +- Delete or the removal of a data asset from an application or database. + +1. **Permission** : authority to perform a specific action in the context of an application or service +2. **Role** : applications, actions and data access required to perform the tasks related to a single role +3. **User - role relationship** : The role (roles) assigned to each user that defines the permissions they have + +## Users, actions and roles in a Mojaloop context + +Mojaloop will have 2 Broad categories of users: + +1. Human – These are hub and DFSP users who through various interfaces will interact with Mojaloop. DFSP users will interact with Mojaloop through the Payment Manager and portals that will be made available during the onboarding process. +2. Non-human – These will automate the business processes and automate tasks that would otherwise be done by a human. These will communicate via API calls that will affect actions to fulfil business requirements. + +The context of this document will focus on Human users only. + +## User Lifecycle Management + +The "User Account Lifecycle" defines the collective management processes for every user account. These processes can be broken down into Creation, Review/Update, and Deactivation—or "CRUD". If any organization utilizes IT resources of any kind, they rely on user accounts to access them. + +## Onboarding + +The Onboarding process will have some activities involving user creation both at DFSP end and at the Hub. These will be as follows: + +1. Hub: The following users will be created + 1.1 Hub Operators + 1.2. Hub Administrators +2. DFSP + 2.1 DFSP Operators + 2.2 DFSP administrators (only applicable to Payment manager). + +## Segregation of Duties + +Segregation of Duties focuses on mitigating the risk of internal fraud by setting boundaries between roles assigned to an employee, and between the conflict of interest that may result from an employee's responsibilities, ensuring no single user can have end to end functional control of a business process and its data. It requires more than one individual to create, process and complete an action. + +### Principle of least privilege + +RBAC uses the security principle of least privilege. Least privilege means that a user has precisely the amount of privilege that is necessary to perform a job. The aim of this is to minimize the likelihood of issuing a user with excess permissions to complete actions in Mojaloop ecosystem. + +### Zero Trust Mojaloop Implementation + +A zero trust network is one in which no person, device, or network enjoys inherent trust. All trust, which allows access to information, must be earned, and the first step of that is demonstrating valid identity. A system needs to know who you are, confidently, before it can determine what you should have access to. + +Mojaloop's inherent design will implement a Zero Trust approach in its architecture and deployment requiring all entities that interact to first authenticate themselves, then seek authorization to access and process data depending on the role they belong to. + +### Process of Segregation Of Duties determination + +1. Define user management workflows and processes. These are all business processes that make up Mojaloop business actions in Mojaloop. Examples include Onboarding. +2. Rationalise all User security access requirements for Applications of Mojaloop as outlined in the table below: + 2.1 Define business and application functions for users and APIs + 2.2 Define role profiles + 2.3 Define function & competence profiles + 2.4 Gather a list of applicable SOD conflicts by defining segregation of duties roles + 2.5 Role profile matrix table (with example data): + +| **Roles and Permissions** **Matrix** | Hub Users | Administrator | Standard Maker User | Standard Checker User | Standard Read Only | DFSP Users | Administrator | Standard Maker User | Standard Checker User | Standard Read Only | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| Onboarding Roles | X | | | | | | | | | | +| Create User Account | X | | | | | | | | | | +| Create DFSP Profile | X | | | | | | | | | | +| Create DFSP User | X | | | | | | | | | | +| +| **Finance Portal** | +| View Reports | | | X | X | X | | | X | X | X | +| Platform Configuration | | | | | | | | | | | +| + +3. Reconfigure any conflicting roles + 3.1 Business approvals + 3.2 Maker checker user creation +4. Periodic System Access & User Authorisation reporting +5. Separation of IT-security and Operational IT security that will support user management activities + +## Best Practices for RBAC and Mojaloop Identity Management + +1. All user ids should be unique and have a unique format that can be correlated in the hub but not meaningful to outsiders. +2. DFSP Users will not have access to any administrative role Hub +3. All non-human users must be restricted from logging on to the application front ends. +4. DFSP users will be trained on the roles and best practices +5. Enforce automated user provisioning and life cycle management. +6. Classify actions performed in Mojaloop to identify business risky actions that require additional controls. +7. Additional controls to mitigate RBAC risks can include: + 7.1 Multifactor authentication (MFA) + 7.2 Audit logging with alerts + 7.3 Auto user profile deactivation / disabling +8. Mojaloop will monitor user inactivity and disable inactive users over a specified period +9. Enforce centralised policy enforcement across identities e.g. Password policy, login policies, MFA, risk based authentication etc. +10. Identify and closely monitor privileged identities that have permissions to perform sensitive actions. The following apply to privileged users: + 10.1 Advanced privileges must be requested for and approved on a case-by-case basis; + 10.2 Administrators should have their privileged permissions for the minimum time possible; + 10.3 Administrators should only have the permissions required to complete a specific task; + 10.4 Membership in administrative groups must be reviewed regularly; + 10.5 Enforce multi-factor authentication for administrative users; + 10.6 Keep access logs, audits, and set-up real-time notifications when access is activated. +11. Mojaloop will configure audit logs and alerts for all user actions in Mojaloop. Where possible explore identity analytics via applicable open source tools. + +## Automated Identity Management and RBAC Control + +The tools preferred for user and identity management in a Mojaloop deployment are: + +1. **KeyCloak Identity Management engine** – Store and process API authentication controls as well as act as API gateway. +2. **WSO2 Identity management engine** – Store and process user role profiles and broker self onboarding of DFSP users. + +------- + +## Context + +An individual who needs to access the various Mojaloop Hub management portals can be registered and an “account” generated, which can be used to access various aspects of an operational instance of a Mojaloop Hub and to provide a basis for auditing that access by tying activities to the original registration. For the purposes of this document, an “account” is a digital identity, a means of authenticating (linking) the person asserting that identity to the original registration, and a set of attributes, which will include - among other things - a set of access rights, or rights that are enabled through the possession of those attributes. + +The registration process involves identity verification, background checking, and so on. The individual is then issued with credentials - a login account ID/digital identity and at least one authentication method, which may include a password and two-factor authentication (2FA). + +::: tip NOTE +The scope of this document is not limited to Mojaloop Hub operators. It also addresses aspects of DFSP operator access to the Payment Manager portals. +::: + +### 2FA considerations + +It should be noted that 2FA via a mobile phone may be inappropriate for some roles, since highly sensitive roles may require that mobile phones are locked away while the individual is “on shift”. This will necessitate other 2FA methods, such as key fobs. + +### Role-Based Access Control + +The Mojaloop Hub uses a Role-Based Access Control (RBAC) method. A user with an account that allows access to the Hub will have roles associated with that account, which define what they can do once they are authenticated themselves and are logged in. + +Many roles apply to multiple portals, however, some roles may be specific to individual portals. + +Care should be taken when assigning multiple roles to an account, or multiple accounts to an individual natural person. This is due to the potential that arises for the circumvention of controls. Part of the purpose of RBAC is to ensure that more than one person must be in the authorization chain for important actions, thereby reducing the vulnerabilities around bad actors. + +## Mojaloop ecosystem portals + +The Mojaloop ecosystem offers a number of portals, which support varying degrees of access control and RBAC. These are split into two groups: + +- Hub portals, which are related to the operation of the Hub itself +- Payment Manager portals, which relate to the management of a specific DFSP’s connection to the Hub + +## RBAC in Mojaloop Hub + +In the Mojaloop Hub environment, RBAC is implemented through a combination of tools - Ory Oathkeeper for identity management, and Keycloak for access control (including roles and maker/checker). + +The Hub itself has the following portals: + +- **Hub Operator onboarding:** +Currently there is no bundled Identity and Access Management (IAM) solution for Hub operators, though the function is partly filled through the use of WSO2. Development work is underway to develop a comprehensive IAM solution based around Ory and Keycloak. This will see an admin operator created alongside the deployment of the Hub, which acts as a first foundational step in this area. +- **Finance Portal:** It has two principal functions: the management of settlement operations, and the management of the liquidity position of individual DFSPs (and related to this, their Net Debit Cap (NDC) value). +Access to the Finance Portal is currently limited to a simple username/password access control function. +- **Participant lifecycle:** Controlling and configuring access to the Hub by DFSPs. +From a technical perspective, this is currently achieved through use of the Mojaloop Connection Manager (MCM). However, it is envisaged that MCM itself will be developed to present an API, which can be used to develop a UI that would be available to Hub Operators and to DFSPs. +- **Hub operations:** These include transaction searches, status and performance monitoring, dashboarding and overall tech ops. +Currently these are achieved through the use of Prometheus/Grafana and a range of other tools, with standard access control embedded in these tools themselves. It is envisaged that this will be migrated into the Ory/Keycloak solution, as this develops. + +Other Hub operations, such as Fraud Management and Case/Dispute Management, are add-on modules that implement their own access control to manage access to their sensitive functions. These are not addressed in this document. + +In addition to the above access control measures, it should be noted that access to all of these functions is only possible via a VPN, with individual credentials controlling access. + +As well as these portals, there are two other primary means of accessing the Hub, neither of which is subject to RBAC: + +- The first of these is transactions, which are strictly controlled according to their own multi-layered cybersecurity measures. +- And secondly, bulk payments (government-to-person - G2P), which are supported by means of an API that is subject to the same controls as other, single transactions. It is envisaged that bulk payments will be a service that is provided to DFSPs (and their customers) by means of a secure API, with the DFSP operating a bulk payment portal for use by their customers. It is possible that the operator of an instance of the Mojaloop Hub might make available a white label bulk payment portal, which interfaces with the Hub bulk payment API, for customization by any DFSP that wishes to offer the service to their customers. (Note that this is not a unique approach: a similar approach has been proposed, for example, for merchant payments, with a white label app for QR code transactions being made available for DFSPs to incorporate into their mobile wallets.) + +The access controls around either single or bulk payments are not therefore discussed further in this document. + +## Payment Manager for integration + +Payment Manager is currently one of the primary mechanisms for integrating DFSPs to a Mojaloop Hub. Whereas the Hub is singular in a scheme, there is a separate instance of Payment Manager for each DFSP. The portals offered by Payment Manager must therefore be secured by means of RBAC to limit access to authorized representatives of the DFSP. + +In the Payment Manager environment, RBAC is implemented solely through Keycloak. + +The following portals are available: + +- **User/Operator onboarding:** +Payment Manager includes Keycloak for IAM. On deployment, a single admin user is created, which can be used to create further user accounts. +- **Hub connection management:** +This includes the ability to configure the Hub connection from the Payment Manager side, and by implication to disable it. It is therefore a controlled function, with different controls for viewing versus modification. +- **Transaction investigation:** +It is possible to investigate transaction queries using the Payment Manager portal. This is potentially an issue if Personally Identifiable Information (PII) is available through the portal. + +## RBAC requirements + +### Mojaloop Hub + +#### Hub Operator onboarding + +##### Foundational accounts + +At the time that a Hub is first stood up, Ory/Keycloak will be used to create a foundational user account with administrator privileges. A system administrator will be assigned this account. Note that the system administrator will not be assigned any operational roles beyond those of a system administrator. + +All functions carried out using Ory/Keycloak are subject to system-level logging for audit purposes. + +The system administrator will then use Ory/Keycloak to create further user accounts, subject to standard identity and background checks for each individual (defined under the Scheme Rules associated with a particular Mojaloop deployment) before their accounts are created. + +These new user accounts will be assigned one of these roles: + +- OPERATOR +- MANAGER + +A user account may not have both OPERATOR and MANAGER roles. + +##### Further accounts + +In addition to the system administrator, the foundational accounts will have the ability to use Ory/Keycloak to add further accounts. However, for these users, this activity will be subject to maker/checker controls. A user with role OPERATOR will be able to set up a user account (with processes in place to ensure that due diligence around identity verification and background checks have taken place). However, this account will not be activated until a person with role MANAGER approves it. + +A role will be assigned to each of these accounts, as they are created. As well as the roles associated with the foundational accounts, the following roles may be assigned to new user accounts: + +- ADMINISTRATOR +- FINANCE_MANAGER + +A user account cannot have more than one of OPERATOR, MANAGER, ADMINISTRATOR or FINANCE_MANAGER, in order to ensure separation of: + +- Financial management from other Hub operations tasks +- Operator and managerial roles in maker/checker functions + +::: tip NOTE +Assigning the ADMINISTRATOR or FINANCE_MANAGER roles is subject to a higher degree of identity verification and background checks than any other roles, due to the sensitive nature of the associated functions. These additional checks are set out in the Scheme Rules. +::: + +#### Finance Portal + +Many functions (such as the viewing of DFSP positions, the status of settlement windows, and so on) of the Finance Portal are available to all logged-in users, regardless of their role. However, the following functions may only be carried out by users with specific roles: + +- Settlement processing + - Close settlement window + - Initiate settlement +- DFSP liquidity management + - Add/withdraw funds + - Change NDC + +All of these are subject to maker/checker controls, so that a user with role ADMINISTRATOR can initiate the action, but it must be approved by a user with role FINANCE_MANAGER. + +#### Participant lifecycle + +This portal provides a single interface for a Hub Operator to add and maintain DFSPs on the Hub ecosystems. + +There are some standardised functions that are subject to RBAC: + +- Create DFSP +- Create DFSP Accounts +- Suspend DFSP + +Each of these is subject to maker/checker controls, so that a user with role OPERATOR can set up the changes, and they must be approved by a user with role MANAGER. + +In addition, there is a significant workload in technical onboarding a DFSP, in particular around the establishment of the technical operating environment (certificates and so on). This is not subject to RBAC. This is not considered a significant risk, since there is no value without being able to create a DFSP and the associated accounts on the Hub itself - activities that are subject to RBAC. + +#### Hub operations + +Access to the reporting functions of Prometheus/Grafana is not subject to RBAC controls - any signed-in/authenticated user, with any RBAC role assigned, may view the reports and dashboards. + +Creating a new report/dashboard is a restricted function, and is only available to users with the MANAGER role. + +As noted earlier, the operations and reporting portals will be migrated into the Ory/Keycloak environment in order to facilitate these controls. + +### Payment Manager + +The Payment Manager operator functionality is subject to RBAC controls, but maker/checker is not required. + +#### User/Operator onboarding + +On deployment of Payment Manager, a single admin user account is created using Keycloak. Note that the admin user will not be assigned any operational roles beyond those of a system administrator. + +All functions carried out using Keycloak are subject to system-level logging for audit purposes. + +The admin user will use Keycloak to create further user accounts, subject to standard identity and background checks for each individual (defined under the Scheme Rules associated with a particular Mojaloop deployment) before their accounts are created. + +These new user accounts will be assigned one of the following roles: + +- OPERATOR +- MANAGER + +A user account may not have both OPERATOR and MANAGER roles. + +#### Dashboards + +The Payment Manager dashboards are available to any logged-in/authenticated user with role OPERATOR or MANAGER. + +#### Hub connection management + +Viewing the settings for the Payment Manager/Hub connection is available to any logged-in/authenticated user with role OPERATOR or MANAGER. However, modifying the settings is a controlled function. Only a user with role MANAGER may modify the settings. + +#### Transaction investigation + +Carrying out transaction investigations using the facilities of the Payment Manager portal is a controlled activity, due to the potential for revealing PII data. It is therefore only available to logged-in/authenticated users with role MANAGER. diff --git a/docs/adoption/index.md b/docs/adoption/index.md new file mode 100644 index 000000000..43305185f --- /dev/null +++ b/docs/adoption/index.md @@ -0,0 +1,42 @@ +# About the Mojaloop Adoption documents + +For a hub operator or central bank to use Mojaloop for its inclusive instant payment system (IIPS), the process of adoption and steps in the decision making are often very different compared to hiring a firm to provide a proprietary software. Using Mojaloop to build and own a platform provides greater control but also greater responsibility. Not having dependency on a single vendor means exactly that. + +The documentation and tools in this section are designed to help with the rationale for selecting to use Mojaloop and a recommended process for implementation. + +Building a payment system is far more than the technology platform. The scheme and operations are actually the factors of success. We developed Mojaloop to minimize operational burden and reduce the cost of implementing inclusive scheme rules like irrevocability and certainty. + +The process of building a payment system can be as important as some of the scheme decisions which come out of it. Every scheme owner and operator can develop their own process, but we recommend a process that is inclusive, transparent, and iterative to maximize ownership, trust and long term sustainability. + + + +Tools available for Adopters: + +* [**Scheme Choices**](#scheme-choices): documents that provide assistance with defining scheme rules, operating guidelines, as well as key business and design choices +* [**Hub Operations**](#hub-operations): guides that provide practical information about the various aspects of operating a Mojaloop Hub + +## Scheme Choices + +The [Platform Operating Guideline Template](./Scheme/platform-operating-guideline.md) provides a template for describing how the Scheme Platform will operate, and for specifying the obligations and responsibilities of the Scheme, the Platform Operator, and the DFSPs. + +The [Scheme Business Rules Template](./Scheme/scheme-business-rules.md) provides a template for defining the Business Rules that govern the rights and responsibilities of participants in a Mojaloop scheme. + +The [Scheme Key Choices](./Scheme/scheme-key-choices.md) document describes and discusses some of the most significant business and design choices that affect both the technical implementation of Mojaloop and the Business Rules which the Scheme will write, and which Participant DFSPs will agree to follow. + +The [Scheme Participation Agreement Template](./Scheme/scheme-participation-agreement.md) provides a template of the Scheme Participation Agreement that contains the minimal necessary provisions to evidence a DFSP's application to join the Scheme and abide by its Business Rules. + +The [Uniform Glossary Template](./Scheme/scheme-uniform-glossary.md) acts as a glossary of business terms. + +## Hub Operations + +These documents can serve as reference for adopters to build on and customize the hub operations portals and develop their own subsequently as needed. + +The [Technical Operations Guide](./huboperations/techops/tech-ops-introduction.md) outlines the operations processes that enable the Hub Operator to handle all aspects of managing a live service, such as incident management, problem management, change management, release management, defect triage. + +The [Settlement Management Guide](./huboperations/settlement/settlement-management-introduction.md) describes how settlements are managed by the Mojaloop Hub and the partner settlement bank(s), and introduces the main building blocks of settlement processing. + +The [Guide to Finance Portal v2](./huboperations/portalv2/busops-portal-introduction.md) is aimed at the Operator of a Mojaloop Hub and provides information about the Finance Portal, which facilitates the management of settlement-related processes on a daily basis. + +The [Roled-Based Access Control](./huboperations/rbac/Role-based-access-control.md) document discusses the security mechanism employed to control access to various aspects of an operational instance of a Mojaloop Hub. + +The [Onboarding Guide for the Hub Operator](./huboperations/onboarding/onboarding-introduction.md) is aimed at the Operator of a Mojaloop Hub and provides information about the DFSP onboarding process. It provides a high-level overview of the onboarding journey that DFSPs take, acting as a checklist of onboarding activities. diff --git a/docs/community/README.md b/docs/community/README.md new file mode 100644 index 000000000..36a969eed --- /dev/null +++ b/docs/community/README.md @@ -0,0 +1,20 @@ +# Welcome to Mojaloop Community + +## How do I get started? + +* A good first place to get started is the [Contributors' Guide](./contributing/contributors-guide.md), which provides information on how you can contribute to the project. +* If you would like an overview of the technologies used in the project, head over to the [Tools and Technologies](./tools/tools-and-technologies.md) section. +* To get a sense of the features we are building, view the [Product Roadmap](./mojaloop-roadmap.md). +* The [Project board](https://github.com/mojaloop/project#zenhub) showcases what is currently being worked on; you can start with a [good first issue](https://github.com/mojaloop/project/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). + +## Where can I get help? + +Join the [Mojaloop Slack Discussions](https://join.slack.com/t/mojaloop/shared_invite/zt-1qy6f3fs0-xYfqfIHJ6zFfNXb0XRpiHw) to connect with other members of the community. + +## What if I have more questions? +You can checkout some of our frequently asked questions in the [FAQ](../getting-started/faqs.md) section. Or better still head over to the community on [Slack](https://join.slack.com/t/mojaloop/shared_invite/zt-1qy6f3fs0-xYfqfIHJ6zFfNXb0XRpiHw). + +## How do I stay up to date with the project? +Subscribe by joining the [commmunity](https://community.mojaloop.io/) where you can be notified about upcoming [events](https://community.mojaloop.io/c/events/8) and [product announcements](https://community.mojaloop.io/c/announcements/9). + +You can also join our [Slack Announcements](https://mojaloop.slack.com/messages/CG3MAJZ5J) channel to receive information on the latest release. \ No newline at end of file diff --git a/docs/community/archive/discussion-docs/Mojaloop Performance 2020.pdf b/docs/community/archive/discussion-docs/Mojaloop Performance 2020.pdf new file mode 100644 index 000000000..719dec47e Binary files /dev/null and b/docs/community/archive/discussion-docs/Mojaloop Performance 2020.pdf differ diff --git a/docs/community/archive/discussion-docs/README.md b/docs/community/archive/discussion-docs/README.md new file mode 100644 index 000000000..67fffae5f --- /dev/null +++ b/docs/community/archive/discussion-docs/README.md @@ -0,0 +1,27 @@ +# Discussion Documents (Archive) + +## PI 10 +- [Performance Project](./Mojaloop%20Performance%202020.pdf) +- [Code Improvement Project](./code-improvement.md) +- [Cross Border Project](./cross-border.md) +- [PSIP Project](./pisp.md) + +## PI 9 + +- [Versioning Draft Proposal](./versioning-draft-proposal.md) +- [Code Improvement Project](./code-improvement.md) +- [Performance Project](./performance.md) +- [Cross Border Project](./crossborder.md) +- [PSIP Project](./pisp.md) + +## PI 8 + +- [Cross Border Meeting Notes Day 1](./cross-border-day-1.md) +- [Cross Border Meeting Notes Day 2](./cross-border-day-2.md) +- [ISO integration Overivew](./iso-integration.md) +- [Mojaoop Decimal Type; Based on XML Schema Decimal Type](./mojaloop-decimal.md) + +## PI 7 + +- [Workbench Workstream](./workbench.md) + diff --git a/docs/community/archive/discussion-docs/aws_tagging.md b/docs/community/archive/discussion-docs/aws_tagging.md new file mode 100644 index 000000000..a50c7b2ef --- /dev/null +++ b/docs/community/archive/discussion-docs/aws_tagging.md @@ -0,0 +1,127 @@ +# AWS Tagging Guidelines + Policies + +> **Note:** These guidelines are specific to the Mojaloop Community's AWS Environment for testing and validating Mojaloop installations, and are primarily for internal purposes. They may, however, be a useful reference to others wishing to implement similar tagging strategies in their own organizations. + +To better manage and understand our AWS usage and spending, we are implementing the following tagging guidelines. + +## Contents +- [Proposed tags and their meanings](#proposed-tags-and-their-meanings) + - [mojaloop/cost_center](#mojaloopcost_center) + - [mojaloop/owner](#mojaloopowner) +- [Manual Tagging](#manual-tagging) +- [Automated Tagging](#automated-tagging) +- [AWS Tagging Policies](#aws-tagging-policies) + - [Viewing Tag Reports + Compliance](#viewing-tag-reports--compliance) + - [Editing Tag Policies](#editing-tag-policies) + - [Attaching/Detaching Tag Policies](#attachingdetaching-tag-policies) + +## Proposed tags and their meanings + +We propose the following 2 tag _keys_: + +- `mojaloop/cost_center` +- `mojaloop/owner` + +### `mojaloop/cost_center` + +`mojaloop/cost_center` is a breakdown of different resources in AWS by the workstream or project that is incurring the associated costs. + +It loosely follows the format of `-[-subpurpose]`, where account is something like `oss`, `tips`, or `woccu`. +> Note: It's likely that most of the resources will be under the `oss` "account", but I managed to find some older resources that fall under the `tips` and `woccu` categories. We also want to plan for future types of resources that might be launched in the future. + +Some potential values for `mojaloop/cost_center` are: + +- `oss-qa`: Open source QA work, such as the existing dev1 and dev2 environments +- `oss-perf`: Open source performance work, such as the ongoing performance workstream +- `oss-perf-poc`: Performance/Architecture POC + +We also reserve some special values: +- `unknown`: This resource was evaluated (perhaps manually, or perhaps by an automated tool), and no appropriate `cost_center` could be determined. + - This will allow us to easily filter for the `mojaloop/cost_center:unknown` tags and produce a report +- `n/a`: This resource incurrs no cost, so we're not really worried about assigning a `cost_center` to it + - This can be useful for mass tagging resources that are hard to figure out where the belong, such as EC2 Security Groups + +### `mojaloop/owner` + +`mojaloop/owner` is a person who is responsible for the managing and shutdown of a given resource. + +The goal of this tag is to prevent long running resources that everybody else thinks _someone else_ knows about, but we no longer need. By applying this tag, we will be able to have a list of _who to go to_ in order to ask questions about the resource. + +The value can simply be a person's name, all lowercase: +- `lewis` +- `miguel` +- etc. + +Once again, we will reserve the following values: +- `unknown`: This resource was evaluated (perhaps manually, or perhaps by an automated tool), and no appropriate `cost_center` could be determined. + - This will allow us to easily filter for the `mojaloop/owner:unknown` tags and see what resources are 'orphaned' + + +## Manual Tagging + +We can use the "Tag Editor" in the AWS console to search for untagged resources. + +1. Log into the AWS Console +2. Under Resource Groups, select "Tag Editor" +![](./images/tagging_01.png) +3. From the tag editor, select a Region (I typically use "All regions"), and Resource Type (I also typically use "All resource types") +4. Now select "Search Resources", and wait for the resources to appear + +You can also search by tags, or the absense of tags to see what resources have not been tagged yet. +![](./images/tagging_02.png) + +5. Once you have a list of the resources, you can select and edit tags for many resources at once! +6. You can also export a `.csv` file of resources found in your search + + +## Automated Tagging + +We currently automate tagging on the following + +As we have a firmer grasp of our tagging guidelines, we need to introduce them into our tooling so that all of the grunt work of manual tagging. + +At the moment, this will look like introducing tags into: +1. Rancher - which currently manages our Kubernetes clusters for both QA and Performance purposes +2. IAC - The upcoming IAC code that will eventually be running our dev environments + + +## AWS Tagging Policies + +As of August 3, 2020, we have started introducing [AWS Tagging Policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_tag-policies.html) to better enforce tags and monitor our resources (especially with respect to costs). + + +### Viewing Tag Reports + Compliance + +1. Log in to the AWS Console +2. "Resource Groups" > "Tag Editor" +3. On the left sidebar, select "Tag Policies" + +From here you can see the tag policies "compliance report" + +![](./images/tagging_03.png) + + +### Editing Tag Policies + +> Note: This may require special admin priviledges to access these pages + +1. Log in to the AWS Console +2. Select "username@mojaloop" in the top right > "My Organization" +3. Select "Policies" > "Tag Policies" + +![](./images/tagging_04.png) + +4. From here, you can view the current tag policies + +![](./images/tagging_05.png) + +5. In the sidebar, you can click "View details" > "Edit policy" to edit the policy + + +### Attaching/Detaching Tag Policies + +1. Go to the "My Organization" page +2. Select the relevant account > "Tag policies" in the sidebar +3. From here you can Attach + Detach tag policies + +![](./images/tagging_06.png) diff --git a/discussions/code_improvement.md b/docs/community/archive/discussion-docs/code-improvement.md similarity index 100% rename from discussions/code_improvement.md rename to docs/community/archive/discussion-docs/code-improvement.md diff --git a/discussions/cross_border_day_1.md b/docs/community/archive/discussion-docs/cross-border-day-1.md similarity index 100% rename from discussions/cross_border_day_1.md rename to docs/community/archive/discussion-docs/cross-border-day-1.md diff --git a/discussions/cross_border_day_2.md b/docs/community/archive/discussion-docs/cross-border-day-2.md similarity index 100% rename from discussions/cross_border_day_2.md rename to docs/community/archive/discussion-docs/cross-border-day-2.md diff --git a/docs/community/archive/discussion-docs/cross-border.md b/docs/community/archive/discussion-docs/cross-border.md new file mode 100644 index 000000000..4deec6f8d --- /dev/null +++ b/docs/community/archive/discussion-docs/cross-border.md @@ -0,0 +1,396 @@ +**Cross-border Workstream Meeting** + +March 10th & 11th (London/remote) + +**Next Steps for PI:** + +• Proposal for how the CNP query and host oracle services and global goals - Adrian, Michael + +• Compound identifiers, ways in which this is captured in the system or expressed in apis - open + +• What information is captured in the data model or the extension list - Michael + +• Follow-up w/ SWIFT to discuss requirements - Matt + +**Open Items:** + +• Finalize CNP Requirements + +• Has to aggregate information and put them together into a single request & they will need to sign separately + +• Finalize FXP has to manage FX rates, the settlements and what expires when + +• CNPs can extend this and determine additional scheme rules + +• FXP handles rounding errors + +• FXP Guarantee a given rate + +• How do you get non-Mojaloop folks in the schema? + +• How do we integrate Mojaloop and some Mojaloop scheme to provide a full PVT payments - working group with Michael, Adrian, Sybrin, others as needed + +• How do we manage requests for regulatory reasons + +• Investigate identifier mappings (Map pathfinder accounts/mobile accounts to DFSP unique IDs) + +• Investigate Certification (Hash and PKKI) + + +Detailed Meeting Notes: +Day #1: + - Quote response + + ○ How do we code the SLA into the response + + ○ Ask a 2nd CNP to route + + ○ In the API - need to package up how to get it there + + ○ As a CMP in Mowali if I return a quote response the scheme has implications + + ○ Follow the whole route from payer to payee + + ○ Limiting the participation of CNP - they need to be the last hop + + § How to define the requirements of a CNP? + + - Message format + + ○ Http syntax + + ○ Started from the mojaloop scheme + + § Move towards the CNP should manage the conversion + + ○ SWIFT version + + ○ Security - TLS + + ○ Header/content encrypted in JWS + + - Retail system + + ○ Off network - remit to someone hub + + - Data Model + + ○ Structure: Ways in which we added new information, different routes, etc. + + ○ Privacy: Visibility and Security - only accessible to the people that can see it + + ○ Content of the data model + + - Transfer is done through the switch (movement of money) + + ○ In mowali - the amounts are expressed but the rate is important because it impacts settlements + + § Data flow - we add the rate when we send the quote back + + § Added in the extension list - should it be part of the standard? + + § Send and receive amount (differ currency) + + - Data element + + ○ Fee for each participant + + ○ Payer DFSP adds it up + + ○ Fee element for the transaction + + - Proposal + + ○ Account lookup service + + § List of local FSP + + ○ Switch - need to maintain state and lookup requests + + § Should look like a domestic transfer to the sender + + § Collect the information and send it back - + + ○ CNP - making assumptions to meet requirements + + § Do you need to see the route + + § Collecting different information downstream + + § Sending FSPs needs to know who is the receiver + + ○ CNP has to aggregate information and put them together into a single request & they will need to sign separately + + § Condition and fulfillment is part of a PKI structure + + § If there is more than one CNP - there needs to ensure the DFSP payee has to be certain the DFSP payer - connections + + § CNP needs to know everything, regulatory reporting - + + ○ Do we need to duplicate the structure in a Cross-network transfer? + + § Trying to prevent a rouge partner from joining + + § Trust the CNP to meet their SLAs + + ○ Mojaloop to another scheme - we don’t have control + + § Require they confirm receipt + + § How can I tell + + § How can I tell the person at the end got the money + + ○ External signing authority to confirm the money was received + + § If your scheme wants to participate in x-border then all the participants need to get signed + + § Public key - need to join a mojaloop network have to issue public keys + + § Central certificate issuing authority + + § Need a PKI structure in place + + ○ How do you get non-Mojaloop folks in the schema? + + § How do we integrate Mojaloop and some Mojaloop scheme to provide a full PVT payments - working group with Michael, Adrian, Sybrin, others as needed + + § Identify the participants - FSP, DFSP - all have signed + + § Parties - end users (Bob/Alice) + + § Single transaction (with multiple transfers) + + § No one commits their funds to everyone is satisfied + + § How to extend mojaloop and non-mojaloop scheme + + ○ Certification + + § Hash and PKKI + + § Gold and silver network + + § New partner - live on the network + + § Scheme decides requirement on the network + + § Self-signing cert + + ○ Liquidity + + § FXP does position mgmt + + § What requirements do we put on a FXP + + § Mobile money has less flexibility + + § Rules that happened across schemes + + ○ FXP has to manage the settlements, what expires when, etc.. + + § FXP has to manage the shortage of quote validity + + § Allow FXP to reject the requests + + ○ How do we manage requests for regulatory reasons + + § There is a dictionary + + □ Is the a requirement to share KYC? + + □ You can ask for many things - up to the participant + + □ Need to agree on the baseline scheme + +**Day #2:** + + - Switch data + + ○ Account numbers + + ○ Blacklist, white list (oversight and blocking) + + ○ Keeping it simple + + ○ Hub + + ○ Side service for folks that can do this + + § Mobile data capture + + § Side car + + § Digital process + + § Value added services for the hub (managed service) + + - Switch - need to maintain state and lookup requests + + - CNP can be an ordinary DFSP + + ○ All DFSP supports all the use cases + + ○ Full participants (might just provide a CNP or FXP service) + + - FXP definition and requirements + + ○ FXP - require rates/fees as part of the Quoting service - need standard industry rate + + § CNPs can extend this and determine additional scheme rules + + ○ FXP handles rounding errors + + ○ Guarantee a given rate + + ○ Manage settlement across schemas + + ○ FX rates + + ○ Should allow people that just do FX + + ○ Edge cases for failure + + § Details in the error messages to find the errors + + ○ FXP needs to point back the right information + + § How messages passed work + + § Edge cases - share what is done too date + + § Jo owns got a working API - identified + + § Changed the quote (intercepted the quote) -- + + § KYC extension list - extended the quote for this + + § Rates are in the extended list (are the list) + + § Where the FXP is applied ? + + § What do we do with fees downstream + + □ (payee DFSP takes place of the aggregation) + + - How to manage identifier resolution + + ○ 2 types of Identifiers + + § Global ones (pass to CNP) - to get a response + + § Local ones - expect the user to provide + + ○ Mojaloop we use identifiers as proxy + + ○ Merchant numbers might be specific to a scheme + + ○ Multiple identifiers for a single account + + ○ How do we uniquely identify the account? + + ○ Rely on CNP (restrict each identifiers in this scheme) + + ○ What sort of structures in place + + ○ Passport identification - place holders + + ○ Map pathfinder accounts/mobile accounts to DFSP unique IDs + + § Service - primary account is X + + § Each country has a service they provide + + § Each CNP understands the address scheme + + § Global one - need to know which ways to use + + ○ Sends a get parties to the switch + + § ALS never heard of them + + § 2 ways + + □ Global way (path finder and conversion to BIC) + - CNP + + ○ Not hosting anything + + ○ Route through the CNP - ask others + + ○ Constructing the alternative routes + + - Global registry does not exist + + ○ Ultimate beneficiary + + ○ Established communication + + ○ Challenge will we able to have 2 DFSPs share direct communication and will be a stretch? + + - Switch has schemes + + ○ A Hub operator following Scheme Rules may allow names of FSPs as decided by those Rules + + ○ The technology or the Admin API itself doesn’t restrict the names (apart from restrictions on length, type or characters, etc) + + ○ BGP: Border Gateway Protocol  + + - Query each CNP and then come up with optimizations, matrix that provides global route - goal would be not to query the CNP directly + +• How to connect with Mojaloop? + + - Any financial service can connect to Mowali + + - Scheme rules, technical + + - Regulatory + + - How do I assign stuff? - no one knows the steps + + - Mojaloop API - understand this. + + - 2 instances Mojaloop instances - TIPs and Mowali + + ○ WOCCU, Asia, US - applied for instance + + ○ Still pushing the boundries + + - What dos an integration look like + + ○ Need sandbox, simulators + + ○ Standard approach + +• Instance payment service + + - Get the flows flowing in a timely manner + + - Need real-time ledgers; what happens if they are offline? + + - Exception for off network (banks take advantage of float) + +• Discovery process (sending FSP) + + - Switch determines if they need to contact a FXP + + - What currency the receiving account can receive in + + - Multiple lookups + + - Data model - set of accounts, w/ one currency at a DFSP + + +Attendees: + + - Mike, Patricia - Thume + + - Michael R, Rob R, Sam - Modusbox + + - Kim, Lewis - Crosslake + + - Rolland, Greg, Phillip - Sybrin + + - Vanburn -- Terrapay + + - Megan, Simeon - Virtual diff --git a/discussions/images/cb_board_1.jpg b/docs/community/archive/discussion-docs/images/cb_board_1.jpg similarity index 100% rename from discussions/images/cb_board_1.jpg rename to docs/community/archive/discussion-docs/images/cb_board_1.jpg diff --git a/discussions/images/cb_board_2.jpg b/docs/community/archive/discussion-docs/images/cb_board_2.jpg similarity index 100% rename from discussions/images/cb_board_2.jpg rename to docs/community/archive/discussion-docs/images/cb_board_2.jpg diff --git a/discussions/images/cb_board_3.jpg b/docs/community/archive/discussion-docs/images/cb_board_3.jpg similarity index 100% rename from discussions/images/cb_board_3.jpg rename to docs/community/archive/discussion-docs/images/cb_board_3.jpg diff --git a/discussions/images/mojaloop_spokes.png b/docs/community/archive/discussion-docs/images/mojaloop_spokes.png similarity index 100% rename from discussions/images/mojaloop_spokes.png rename to docs/community/archive/discussion-docs/images/mojaloop_spokes.png diff --git a/docs/community/archive/discussion-docs/images/tagging_01.png b/docs/community/archive/discussion-docs/images/tagging_01.png new file mode 100644 index 000000000..4379443ce Binary files /dev/null and b/docs/community/archive/discussion-docs/images/tagging_01.png differ diff --git a/docs/community/archive/discussion-docs/images/tagging_02.png b/docs/community/archive/discussion-docs/images/tagging_02.png new file mode 100644 index 000000000..b86ac0a91 Binary files /dev/null and b/docs/community/archive/discussion-docs/images/tagging_02.png differ diff --git a/docs/community/archive/discussion-docs/images/tagging_03.png b/docs/community/archive/discussion-docs/images/tagging_03.png new file mode 100644 index 000000000..d8ab17646 Binary files /dev/null and b/docs/community/archive/discussion-docs/images/tagging_03.png differ diff --git a/docs/community/archive/discussion-docs/images/tagging_04.png b/docs/community/archive/discussion-docs/images/tagging_04.png new file mode 100644 index 000000000..a2913b226 Binary files /dev/null and b/docs/community/archive/discussion-docs/images/tagging_04.png differ diff --git a/docs/community/archive/discussion-docs/images/tagging_05.png b/docs/community/archive/discussion-docs/images/tagging_05.png new file mode 100644 index 000000000..ba54dbf64 Binary files /dev/null and b/docs/community/archive/discussion-docs/images/tagging_05.png differ diff --git a/docs/community/archive/discussion-docs/images/tagging_06.png b/docs/community/archive/discussion-docs/images/tagging_06.png new file mode 100644 index 000000000..8c4eb717f Binary files /dev/null and b/docs/community/archive/discussion-docs/images/tagging_06.png differ diff --git a/discussions/ISO_Integration.md b/docs/community/archive/discussion-docs/iso-integration.md similarity index 100% rename from discussions/ISO_Integration.md rename to docs/community/archive/discussion-docs/iso-integration.md diff --git a/docs/community/archive/discussion-docs/mojaloop-decimal.md b/docs/community/archive/discussion-docs/mojaloop-decimal.md new file mode 100644 index 000000000..119e51501 --- /dev/null +++ b/docs/community/archive/discussion-docs/mojaloop-decimal.md @@ -0,0 +1,38 @@ +# Mojaloop Decimal Type; Based on XML Schema Decimal Type + +## Decimal value type + + Definition: decimal represents a subset of the real numbers, which can be represented by decimal numerals. The value space of decimal is the set of numbers that can be obtained by multiplying an integer by a non-positive power of ten, i.e., expressible as _i_ × 10-n where _i_ and _n_ are integers and _n_ ≥ 0. Precision is not reflected in this value space; the number 2.0 is not distinct from the number 2.00. The order relation on decimal is the order relation on real numbers, restricted to this subset. + Req: All Level One processors must support decimal numbers with a minimum of 18 decimal digits. However, Level One processors may conform to a scheme-defined limit on the maximum number of decimal digits they are prepared to support, which must be 18 or more digits, in which case that scheme-defined maximum number must be clearly documented. + +## Lexical representation + +decimal has a lexical representation consisting of a finite-length sequence of decimal digits (#x30 – #x39) separated by a period as a decimal indicator. An optional leading sign is allowed. If the sign is omitted, "+" is assumed. Leading and trailing zeroes are optional. If the fractional part is zero, the period and following zero(es) can be omitted. For example: -1.23, 12678967.543233, +100000.00, 210., 452 + +## Canonical representation + + The canonical representation for decimal is defined by prohibiting certain options from the Lexical representation (§3.2.3.1). Specifically, the preceding optional "+" sign is prohibited. The decimal point is required. Leading and trailing zeroes are prohibited subject to the following: there must be at least one digit, which may be a zero, to the right and to the left of the decimal point. + + This canonical form conforms to XML Decimal lexical representation, so it would be accepted by any XML schema conforming system. + + What others write in canonical form, we can read as a lexical representation; what we write in canonical form, others can read as a lexical representation. But we reject exponential formats on reading and we won’t write exponential form. We can directly compare the canonical string representations of two values for equality. + + When exchanging messages, a lexical form that shows implied precision using trailing zeros is preferred to pure canonical form if it improves clarity. E.g. We might write “5.00” instead of “5.0” where the unit of exchange is commonly specified precise to two decimal places, as in USD, EUR, or GBP. This lexical representation option is permitted within valid lexical forms of both XML decimal and Mojaloop decimal. + +## Validators + + Decimal Lexical Validator (what our message receivers accept): + +```^[-+]?(([0-9]+[.]?[0-9]*)|([.]?[0-9]+))$``` + +Decimal Canonical Validator (the form we store and compare; this pattern could be used to assert canonical form in generated messages): + +```^([0]|([-]?[1-9][0-9]*))[.]([0]|([0-9]*[1-9]))$``` + +## Translating Between External and Internal Forms + + When converting from lexical or canonical form to a binary internal representation, the value space of the internal representation must be large enough to hold the scheme-specific range of decimal values, with a significand defined as the signed integer range –10_m_–1..10_m_–1, and a non-positive integer exponent in the range –_m_..0, where _m_ is the maximum number of decimal digits, at least 18, and as defined by the specific Level One scheme. + +An implementation must not translate between decimal external representations and any floating-point binary internal representation. And all calculations on internal representations of decimal values must produce results as if they were performed in decimal long hand on the external representation. + +It should be noted that the value space of a signed 64-bit binary integer is sufficiently large to encode a signed 18-digit decimal significand and the value space of a signed 6-bit binary integer is sufficiently large to encode its required non-positive base-ten exponent. diff --git a/docs/community/archive/discussion-docs/performance-project.md b/docs/community/archive/discussion-docs/performance-project.md new file mode 100644 index 000000000..a554f6610 --- /dev/null +++ b/docs/community/archive/discussion-docs/performance-project.md @@ -0,0 +1,175 @@ +# Performance Workstream + +Wednesday, March 11, 2020 + +## Performance Goals: + +- Current HW system achieving stable 1k TPS, peak 5k and proven horizontal scalability + 1. More instances = more performance in almost linear fashion. + 1. Validate the minimum infrastructure to do 1K TPS (fin TPS) + 1. Determine the entry level configuration and cost (AWS and on-premise) + +## POCs: + +Test the impact or a direct replace of the mysql DB with an shared memory network service like redis (using redlock alg if locks are required) + +Test a different method of sharing state, using a light version of event-drive with some CQRS + +## Resources: + +- Slack Channel: `#perf-engineering` +- [Mid-PI performance presentation](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/March2020-PI9-MidPI-Review) +- [Setting up the monitoring components](https://github.com/mojaloop/helm/tree/master/monitoring) + +## Action/Follow-up Items: + +- What Kafka metrics (client & server side) should we be reviewing? - Confluent to assist +- Explore Locking and position settlement - Sybrin to assist + 1. Review RedLock - pessimistic locking vs automatic locking + 2. Remove the shared DB in the middle (automatic locking on Reddis) + +- Combine prepare/position handler w/ distributed DB +- Review node.js client and how it impact kafka, configuration of Node and ultimate Kafka client - Nakul +- Turn back on tracing to see how latency and applications are behaving +- Ensure the call counts have been rationalized (at a deeper level) +- Validate the processing times on the handlers and we are hitting the cache +- Async patterns in Node + 1. Missing someone who is excellent on mysql and percona + 2. Are we leveraging this correctly + +- What cache layer are we using (in memory) +- Review the event modeling implementation - identify the domain events +- Node.js/kubernetes - +- Focus on application issues not as much as arch issues +- How we are doing async technology - review this (Node.JS - larger issue) threaded models need to be optimize - Nakul + +## Meeting Notes/Details + +### History + +1. Technology has been put in place, hoped the design solves an enterprise problem + +2. Community effort did not prioritize on making the slices of the system enterprise grade or cheap to run + +3. OSS technology choices + +### Goals + +1. Optimize current system +2. Make it cheaper to run +3. Make it scalable to 5K TPS +4. Ensure value added services can effectively and securely access transaction data + +### Testing Constraints + +1. Only done the golden transfer - transfer leg +2. Flow of transfer +3. Simulators (legacy and advance) - using the legacy one for continuity +4. Disabled the timeout handler +5. 8 DFSP (participant organizations) w/ more DFSPs we would be able to scale + +### Process + +1. Jmeter initiates payer request +2. Legacy simulator Receives fulfill notify callback +3. Legacy simulator Handles Payee processing, initiatives Fulfillment Callback +4. Record in the positions table for each DFSP + - a. Partial algorithm where the locking is done to reserve the funds, do calculations and do the final commits + - b. Position handler is Processing one record at a time + +5. Future algorithm would do a bulk + +- One transfer is handler by one position handler + - Transfers are all pre-funded + +1. Reduced settlement costs +2. Can control how fast DFSPs respond to the fulfill request (complete the transfers committed first before handling new requests) +- System need to timeout transfers that go longer then 30 seconds + - Any redesign of the DBs + - Test Cases + +- Financial transaction + - End-to-end + - Prepare-only + - Fulfil only + +- Individual Mojaloop Characterization + - Services & Handlers + - Streaming Arch & Libraries + - Database + - What changed: 150 to 300 TPS? + +- How we process the messages +- Position handler (run in mixed mode, random + - Latency Measurement + +1. 5 sec for DB to process, X sec for Kafka to process +2. How to measure this? + +### Targets + +1. High enough the system has to function well +2. Crank the system up to add scale (x DFSPs addition) +3. Suspicious cases for investigations +4. Observing contentions around the DB +5. Shared DB, 600MS w/ out any errors + - Contention is fully on the DB + - Bottleneck is the DB (distribute systems so they run independently + + + +- 16 databases run end to end +- GSMA - 500 TPS +- What is the optimal design? + +### Contentions + +1. System handler contention + - Where the system can be scaled +1. If there are arch changes that we need to make we can explore this + - Consistency for each DFSP + - Threading of info flows - open question + +1. Sku'ed results of single DB for all DFSPs +1. Challenge is where get to with additional HW + - What are the limits of the application design +1. Financial transfers (in and out of the system) + - Audit systems + - Settlement activity + - Grouped into DB solves some issues + - Confluent feedback + +1. Shared DB issues, multiple DBs + +1. Application design level issues + +1. Seen situations where we ran a bunch of simulators/sandboxes + - Need to rely on tracers and scans once this gets in productions + - Miguel states we disable tracing for now + +### Known Issues + +1. Load CPU resources on boxes (node waiting around) - reoptimize code +2. Processing times increase over time + +## Optimization + 1. Distributed monolithic - PRISM - getting rid of redundant reads + 2. Combine the handlers - Prepare+Position & Fulfil+Position + +### What are we trying to fix? + 1. Can we scale the system? + 2. What does this cost to do this? (scale unit cost) + 3. Need to understand - how to do this from a small and large scale + 3. Optimized the resources + 4. 2.5 sprints + 5. Need to scale horizontal + 6. Add audit and repeatability - + +### Attendees: + +- Don, Joran (newly hired perf expert) - Coil +- Sam, Miguel, Roman, Valentine, Warren, Bryan, Rajiv - ModusBox +- Pedro - Crosslake +- Rhys, Nakul Mishra - Confluent +- Miller - Gates Foundation +- In-person: Lewis (CL), Rob (MB), Roland (Sybrin), Greg (Sybrin), Megan (V), Simeon (V), Kim (CL) diff --git a/docs/community/archive/discussion-docs/psip-project.md b/docs/community/archive/discussion-docs/psip-project.md new file mode 100644 index 000000000..d517d6f10 --- /dev/null +++ b/docs/community/archive/discussion-docs/psip-project.md @@ -0,0 +1,21 @@ +# PISP (3rd party payment initiation) + +## Goal: + +Updated Mojaloop specification documents, and POC implementation of a PISP + + +## Action Items: + +- Revisit /authorizaitons resource: [Michael] and raise with CCB +- Identity provider research and follow-up: [Matt de Haast] +- Share all sequence diagrams: [JJ] +- Outline proposal at high level including new API calls - Unassigned +- Mapping account information (info about accounts for PISP) - [Lewis] + +## Links: + +- [London Meeting Notes](./pisp_meeting_march_2020.md) +- [WIP Separate Docs Repo with sequence diagrams](https://github.com/jgeewax/mojaloop-pisp) +- [End to End Sequence Diagram](https://plantuml-server.kkeisuke.app/svg/xLhhRnkv4V--VmKX571iI8eaEx4Z875aoyu9Tt44hz8WWFg1sgMaFQz87ScreXRvtpl3nxuaEx7H5bVW0kJXvN1cE9pvpODvhpILEbkbWKvqoiXu58w9bfIhEPDa9MAMJlcBJ2LyGJuo6Iqfr-IM_P4nfOaMP4otv2DI7GOqqaAImPQf9ILKaSj1i0RUIPIiSLF3i1wirmrSXB_th8PCtZC90eVNuVZG40wxLRfma-XeQPR2wihWjz2o9ZNET0j7GOwECHaurhrTGbOXl724n-vmZOiblOVpmVh5-r2is6R99BD4bnS15veH0IS0rIRBH96r56kXQ4fYmHI1PIB1T8ba10svW6zWmi5uH82tCWTh1oXOaSrIa5mvu9fmefUCg6Z9LeniaZGbdB4Ozw_e7IDw8ppFVj0z9AEveSzl4fH9UA8Ju1MJsPPGSzDD4edrrb3-aQ7oagcru8eXN_oAH47l6UnoohqSVnEB9C8lCqOoPOz1LSIafd1GC2fGIZGAcko7WiV04RwhfTXmD5IQSDOEHXg9gLBP2WKigUu7hNU4WkMYJ6cuF4be1imv69dgH72aZwYK2T2BJ1DXRUwf3nI9sNqICMHZt2FETC9G8JXbQbbWI9H323I0suxP77IAQxSeinHsKmxIrap2VeYnHPP0C06n2XWie4S5Rz-IOQ8YTAmjUVisk1oqta7yz4Ta8x8qXlFUMVCwcLF-jswdWrzAJeeUdDoZAs7emU_Mks6txwBrMNmWCeVTbbNb0znJejj1p2fYO1sbV07Zet6jDB3ZseJa7TkUJ_b8muV1-wjKEG6uAOGzIRIqPePhhL30fXT7Hn-k9kIb2H6cZeuE2xr24eGj8xVNwVN9w01kVC4qcT7e3W-p5LbPJpX628TuL639U2GOj50_exP5aygfaHc8jYj4hHczKsIEm5WwueuDGz2rGpxzsYGBOyaoIpXF0IomOUAYY2Y3bWPR-87EyU2EYqrWvE1F2jq8dGvilW9VxyCFS1M880547q16dC8-gWpS454BzBaKgy0TqpiaUU2AIbxob2jwzWsLvJrwGnUxDtJS7nevzeRC1Urd1zW_F7Otz6DLGoH6xhTC0uxS5-W1iGz2LXObZ3YRIio6iFyBI0LrtKSC4S0EmI5rbFRj6l3u4Ry1pH_onT9HftooB6kPw_149pK-WL0GRfLcAq34jP1QJNdEcbF0l7tySq2w7FGd01M57Pf49ekbFaV8izo_CjK4qS0dnx3BakvBkZO92F16BS6WKux-Zy3gqe_X1yf1MaqW6kg0LGcqK82xRyZ8H1IP2RqqB6131lVY_BhleWEbkp1prOPTk2WlsEeYk35SVRnALqqvFdb6BsAsI0KsyCOfev1HgRehRQgXDWQkByOGmUj6_t48abeCLgiRvWeMj2LBxZ6HaHLJYYwOjNyg17YRpIb0BJY3R9-A3MRc0wI6ofF7LCPGF_vEWNhjzmVZJo40XpaGAY2uApWL-MKo6R_ijhi177lqQTmAHIOZrhTLXVis1Cg4cu3fU_i4_me8_6hiyXp5ZJvfdCN79_CttRWLTqxFMYUTqzFMMU_rSQiNTKvEpqvVpwFvwqRJyZ0N2PiiI_T9wkqe7a6eLXRAYvFj6dT1cJeQX8vNdGPhaNd29DALOhJH95NokLfRlQsBDVBLx-PVtqkQofgc3bRsgng9rJfbtsuWKdSMhU14AksM6zQxQaSnP2ajg2RqBg6D2ittGj_cVzU8fQHRfwxQSF2G3UbAP5nxkRTNbrUZlryrAejL2-VV6X269Q6DA9EIyMYBIv_3OQCYfkIOJbQ99LJ6dCf467FU3cx2wwlRCcTN4GjpvF7WwmEh_X2Ndsx2pn-1gA81XdTng-G-iJMzFohxjawa2Iea0ipej3gzLlVLfDVhTq_xlRFscxDNhKwt3uSsE_uHV2zL327YLWXAC5j_ED0p6Qht7m4qwEQ6lQSawfuHlKSdgBS72yaOGYyPBr4pgBgHFeTUQEpkeL0dfXU3l41D_rGaTyFF7w04kXPpUpzNzlGga3jOG6_Kj9oniI4sM3LBjmMK-YxE7kG6Vp1WZ1cJHsaMCrNKTpKSj1OsM0rPCi7QmpEgeQsh1n_4smiFjqOT6sMdKU-OdNMYdq7OadOEdb_DmIwzUUlupQpNEddJdRNEkgUiTK8xnxtESNmoxvxisVn_1V5_8VnV2FyaX2TFXlWdONWDlQ7LSDXdCSOCH_8H5rQoEsZtpDPf3Aq3bIoVIjdMfsYJV45Th3srBIh3AjRY6rOTfb4tIiCFIrY7W_85zCn2tc57q0w-i5BrZdsEW-LIYrSQTpK39N8OZYZl1_IGVEOn12hYjgtqfO2KerIz0GzcX-JMYd3ZACtaQeUCl63jHPlC6LE7NhHll8hkmIRRkWsBgT_-PFf8osTJw4ZPurFRuxIA0PrXZxE0fCtQTWXQICK43dlsuVNvOK1JJMw4w_NuWVR2XjYKcGi960G-AHh2jYUvJfnHpLJEkwOLaQUqikxbvimEwB1LfSenCHjSKtTk5DiZT9BdvReH_1srfxok_Cu1m_wra1lCv3-OoUuhAIeNjJEBnWdfbclS6D4KYePiaMwRq9D5D0FcPXQon3aWpfAmQmueEJeQVvuS7H7sBM9hRGUTXJBKswPDBZ8DKOGH3a4Yjm6TuG3Lze6WfMotsrKtxFg9Ht5Er00gGB0OHD6JHsH-r3YvFlV__hHi0dqRMcq8EZYIguMA2ieVPihDQKepQtSiWrdOo99iNHzhEpUoedmLwSzYYiAz6wezTQMenFAt7BXeutkQ9Z7LhC9iojri3UVNKApzqq2EUhalb8wEdbz-selwNsbNlkYVIXVMz1-0PbMsFIX4TulmoetX9Cd0eCyp5bHn4uYHvP7_Rbhpuwh7vvT-eFMOc18oU2CN3n8c8AHYwTmy4KI2Gscs0bT57uQb0ydyk4jW-eWW8ULF0owuLbio1x1XSYqJRlnvjRjdPuu67Gy18cXnM5oetIwc_Gy7eX_wXrLkJddFBdSKyp3WqWBSbPyVcOZ3oH6aZh4KCpe3kFezKte7dFqECm_Vm4S0BjsSSYY2uPpADsSp1ZU07dl7J6PsdgaOub8zFBgF5GzTbqH_udZFpAO5bDHTb_1iDSDNA-m4bKPNg7HoVdsHt3FktvfCJBHnokkc_kxDRPwb-D36gvAWFO3BC7wCRV34Vy-xuDA0jES7fFcppepoEpCiLVa8jcgV8F-yeLoRrq_VnLRrADSwWPZ39_lSLyp7CHct2SuXZLH4-0LSx99HI5mGBzvcPRRcKR1mDsSXZZKR68D2DiITK0skayY27LmoP3C0VsFpmc0gYo9mFJHYyLZkVD5C4inCD0v0vThZIQcE6LLAeF95KwL4PAg7ANUfn4EPlUhpwaLyOOW6xZnVyGR5joPHK5qmsIHmFUsg_6gPyVXRxGyhZOT75iRdj11_vje3Id2TxTRJVxvYPCftgf5AhL5r438QJhbnPpHmOlwlnjpNnG_cn3pU3PJcFhx_gUOhfh1vncF05Kno1JrSi1SXRPVauhPTFEHCbXYsQ6RphBtAyFy-r3995NZHBV3tU_WZMwN_1W00.svg) +- [Initial PISP Design Doc, v5](https://github.com/mojaloop/documentation-artifacts/blob/master/presentations/January%202020%20OSS%20Community%20Session/%5BEXTERNAL%5D%20Mojaloop_%20PISP%20Credit%20Transactions(3).pdf) diff --git a/docs/community/archive/discussion-docs/versioning-draft-proposal.md b/docs/community/archive/discussion-docs/versioning-draft-proposal.md new file mode 100644 index 000000000..790dd4452 --- /dev/null +++ b/docs/community/archive/discussion-docs/versioning-draft-proposal.md @@ -0,0 +1,281 @@ +--- +Authors: Lewis Daly, Matthew De Haast, Samuel Kummary +Proposal Name: Mojaloop Versioning Proposal +Solution Proposal Status: Draft +Created: 26-Feb-2020 +Last Updated: 17-Mar-2020 +Approved/Rejected Date: N/A +--- + +# Mojaloop Versioning, A Proposal + +_Note: This document is a living draft of a proposal for versioning within Mojaloop. Once the proposal is ready, it will be submitted to the CCB for approval._ + +## Overview + +The aim is to produce a proposal that keeps the versioning Scheme simple to use and clear regarding compatibility issues. However, it needs to include all the details needed for a Mojaloop ecosystem as well. + +Goal: +Propose a standard for a new 'Mojaloop Version', which embodies: +1. Helm: Individual Service Versions, Monitoring Component Versions +2. API Versions: FSPIOP API, Hub Operations / Admin API, Settlement API +3. Internal Schema Versions: Database Schema and Internal Messaging Versions + +## Versioning Strategies/Background (Literature Review) + +How do current systems handle versioning? Give a brief overview of the current space. +* Most best practices follow semantic versioning for APIs, this will be covered more in [#1198](https://github.com/mojaloop/project/issues/1198) + +### Demonstrates zero-downtime deployment approaches with Kubernetes [5] + +Key observations: +* in order to support rollbacks, the services must be both forward and backwards compatible. +consecutive app versions must be schema compatible +* 'Never deploy any breaking schema changes', separate into multiple deployments instead + +For example, start with a PERSON table: +``` +PK ID + NAME + ADDRESS_LINE_1 + ADDRESS_LINE_2 + ZIPCODE + COUNTRY +``` + +And we want to break this down (normalize) into 2 tables, PERSON and ADDRESS: + +``` +#person +PK ID + NAME + +#address +PK ID +FK PERSON_ID + ADDRESS_LINE_1 + ADDRESS_LINE_2 + ZIPCODE + COUNTRY +``` + +If this change were made in one migration, 2 different versions of our application won't be compatible. Instead, the schema changes must be broken down: +1. Create ADDRESS table + * App use the PERSON table data as previously + * Trigger a copy of data to the ADDRESS table +2. The ADDRESS now becomes the 'source of truth' + * App now uses the ADDRESS table data + * Trigger a copy of new added to address to the PERSON table +3. Stop copying data +4. Remove extra columns from PERSON table + +This means for any one change of the database schema, multiple application versions will need to be created, and multiple deployments must be made in succession for this change to be made. +* [5] also notes how simple Kubernetes makes deploying such a change + * rolling upgrade deployments + * Tip: make sure your health endpoint waits for the migrations to finish! +* Q: so how do we make big changes that touch both the database schema and the API? + * this seems really hard, and would need a lot of coordination + * If we don't design it correctly, it could mean that a single schema change could require all DFSPs to be on board + * This is why I think the API version and Service version should be unrelated. We should be able to + deploy a new version of a service (which runs a migration), and supports an old API version + + +### Using a schema registry for Kafka Messages [6] + +* [6] suggests some approaches, such as using a schema registry for kafka messages, such as [Apache Arvo](https://docs.confluent.io/current/schema-registry/index.html) +* This adds a certain level of 'strictness' to the messages we produce, and will help enforce versioning +* Adds a separate 'schema registry' component, which ensures messages conform to a given schema. This doesn't really + help enforce versioning, and leaves the work up to us still, but does give more guarantees about the message formats. + +### Backwards and Forwards Compatibility [3], [4] + +* "The Robustness principle states that you should be “liberal in what you accept and conservative in what you send +”. In terms of APIs this implies a certain tolerance in consuming services." [3] +* Backwards Compatibility vs Backwards Incompatibility [4]: + * Generally, additions are considered backwards compatible + * Removing or changing names is backwards incompatible + * It's more something to assess on a case-by-case basis, but [Google's API Design Doc](https://cloud.google.com/apis/design/compatibility) helps lay out the cases. + +## Mojaloop Ecosystem +When discussing versioning we need to be clear that we are versioning interfaces for various parties. + +# Proposal +The following section will outline the versioning proposal. + +## A “Mojaloop Version” +A Mojaloop Version **x.y**.z can be defined that can encompass the versions of all the three APIs included (detailed below). +In the version **x.y**.z, ‘x’ indicates the Major version and ‘y’ a minor version, similar to the Mojaloop FSPIOP API versioning standards; ‘z’ represents the ‘hotfix’ version or a version released with the same major, minor version x.y but to keep things simple, there is a need to bundle all the components included in the Mojaloop ecosystem indicating what all items are included there. + +In effect we may say Mojaloop version **x.y** includes +1. Mojaloop FSPIOP API + * Maintained by the CCB (Change Control Board) + * Uses x.y format + * Currently version v1.0, v1.1 and v2.0 are in the pipeline +2. Settlement API + * Maintained by the CCB + * To use x.y format + * Currently version v1.1 and v2.0 is in the pipeline +3. Admin / Operations API + * Maintained by the CCB + * To use x.y format + * Can use version v1.0 +4. Helm + * Maintained by the Design Authority + * Uses x.y.z format + * PI (Program Increment) + Sprint based versioning. + > *Note:* _PI + Sprint based versioning_ make sense in the context of the current Mojaloop Program Increments, but will need to be revised at a later date. + * Bundles compatible versions of individual services together +5. Internal Schemas + * Maintained by the Design Authority + * DB Schema x.y + * Internal messaging Schema (Kafka) x.y + +| **Mojaloop** | x.y | | | +|---|---|---|--- +| | Owner/Maintainer | Format | Meaning | +| **APIs** | | | | +| - FSPIOP API | CCB | *x.y* | Major.Minor | +| - Settlement API | CCB | *x.y* | Major.Minor | +| - Admin/Operations API | CCB | *x.y* | Major.Minor | +| Helm | Design Authority | *x.y.z* | PI.Sprint.Increment | +| **Internal Schemas** | | | | +| - DB Schema | Design Authority | *x.y* | Major.Minor | +| - Internal Messaging | Design Authority | *x.y* | Major.Minor | + + + +For example: Mojaloop 1.0 includes +1. APIs + * FSPIOP API v1.0 + * Settlements API v1.1 + * Admin API v1.0 +2. Helm v9.1.0 + * Individual services' versions + * Monitoring components versions +3. Internal Schemas + * DB Schema v1.0 + * Internal messaging version v1.0 + +| **Mojaloop** | v1.0 | | | +|---|---|---|--- +| | Owner/Maintainer | Version | +| **APIs** | | | | +| - FSPIOP API | CCB | *1.0* | +| - Settlement API | CCB | *1.1* | +| - Admin/Operations API | CCB | *1.0* | +| Helm | Design Authority | *9.1.0* | +| **Internal Schemas** | | | | +| - DB Schema | Design Authority | *1.0* | +| - Internal Messaging | Design Authority | *1.0* | + +### Advantages + +1. The advantage of this strategy is primarily simplicity. A given version say - Mojaloop v1.0 can just be used in + discussions which then refers to specific versions of the three APIs - FSPIOP, Settlements, Admin APIs, along with the Helm version that is a bundle of the individual services which are compatible with each other and can be deployed together. +Along with these, the Schema versions for the DB and Internal messaging to communicate whether any changes have been made to these or not since the previously released version. +2. The other advantage, obviously, is that it caters for everyone who may be interested in differing levels of details +, whether high level or detailed. Because of the nature of the major and minor versions, it should be easy for Users and adopters to understand compatibility issues as well. + +### Compatibility +As described in [section 3.3 of the API Definition v1.0](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#33-api-versioning), whether or not a version is backwards compatible is + indicated by the **Major** version. All versions with the same major version must be compatible while those having different major versions, will most likely not be compatible. + +_Important Note: Hub operators will likely need to support multiple versions of the FSPIOP API at the same time, in order to cater for different participants as they can't all be expected to upgrade at the same time._ + +## Breaking down the “Mojaloop Version” +This section aims to break down the above proposed mojaloop version into its constituent parts, and provide support for the above proposed versioning strategy + +### APIs + +The [Mojaloop Spec](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#33-api-versioning) already outlines many of the decisions made around versioning APIs. + +In terms of common best practices, there are many approaches for requesting different versions, including adding in a + version in the url, but let's not worry about this because the spec already lays this out for us, using the HTML vendor extension: [3.3.4.1 Http Accept Header](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#3341-http-accept-header) + +As for version negotiation, the spec also states that in the event of an unsupported version being requested by a + client, a HTTP status 406 can be returned, along with an error message which describes the supported versions. [3.3.4.3 Non-Acceptable Version Requested by Client](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#3343-non-acceptable-version-requested-by-client) + +Another best practice around versioning is specifying to what level clients may request specific apis. +* In a development environment, many APIs will allow specificy up to the BUGFIX version, i.e. vX.X.X +* In production however, this is limited to Major versions only, e.g. v1, v2 +* e.g. The Google API Platform supports only major versions, not minor and patch versions +* Given the new features that may become available with v1.1 of the Mojaloop API, we might want to allow participants + to specify MAJOR and MINOR versions, i.e. vX.X. This practice should be avoided however, since minor versions should be backwards compatible + +Participants using the same MAJOR version of the API should be able to interact. Participants on different MAJOR +versions are not able to interact. For example, a participant on API v1.1 can send transfers to another participant on v1.0, but not to a different participant on v2.0. + +### Helm +This section deals with how Mojaloop services interact within a given deployment. Here, we attempt to propose questions such as "should an instance of central-ledger:v10.0.1 be able to talk to ml-api-adapter:v10.1.0? How about ml-api-adapter:v11.0.0?"? or "how do we make sure both central-ledger:v10.0.1 and central-ledger:v10.1.0 talk to the database at the same time?" + +There are two places where this happens: +1. Where services interact with saved state - MySQL Percona Databases +2. Where services interact with each other - Apache Kakfa and (some) internal APIs + +This implies we need to version: +* the database schema +* messages within Apache kafka + * need to make sure the right services can appropriately read the right messages. E.g. Can mojaloop/ml-api-adapter:v10 +.1.0 publish messages to kafka that mojaloop/central-ledger:v10.0.1 can understand? + * Q: If we decide to make breaking changes to the message format, how can we ensure that messages in the kafka streams + don't get picked up by the wong services? + +### Internal Schemas + +#### Database + +todo: anything to be said here? + +#### Kafka/Messaging +Currently, we use the lime protocol for our kafka message formats: https://limeprotocol.org/ + +Also refer to the mojaloop/central-services-stream readme for more information about the message format. + +The lime protocol provides for a type, field, which supports MIME type declarations. So we could potentially handle messages in a manner similar to the API above (e.g. application/vnd.specific+json). Versioning messages in this manner means that consumers reading these messages would need to be backwards and fowards compatible (consecutive message versions must be schema compatible). +* Q. does it make sense to put the version in the Kafka topic? + * One example, ml-api-adapter publishes messages to the prepare topic + * If we add versioning to this, ml-api-adapter:v10.0.0 publishes messages to a prepare_v10.0 topic, and a new instance + of the ml-api-adapter:v10.1.0 will publish to the prepare_v10.1 topic. + * subscribers can subscribe to whichever prepare topic they want, or both, depending on their own tolerance to such + messages + * This may have some serious performance side effects +* Another potential option would be to allow for a message 'adapter' in the deployment. Say the ml-api-adapter:v10.1.0 is producing messages to a prepare_v10.1 topic, and there is no corresponding central-ledger in the deployment to read such messages, we could have an adapter, which subscribes to prepare_v10.1, reformats them to be backwards compatible, and publishes them to prepare_v10.0 in the old format. + +Such an approach would allow for incremental schema changes to the messaging format as services are gradually upgraded. + +All in all, I didn't see too much about this subject, so we'll likely need to return later down the line. + +## Version Negotiation +todo: @sam Discuss how to deal with version negotiation strategy + +## Long Term Support +todo: Discuss how long term support fits into the versioning proposal. I don’t think we want to get into too much detail, but more outline what it might look like + +Mention current (lack of) lts support, current PI cadence + +## Appendix A: Definitions + +* **service**: Mojaloop follows a microservices oriented approach, where a large application is broken down into smaller + micro services. In this instance, Service refers to a containerized application running as part of a Mojaloop deployment. At the moment, this takes the form of a Docker container running inside of a Kubernetes cluster. e.g. mojaloop/central-ledger is the central-ledger service +* **service version**: The version of the given service. This currently doesn't follow semantic versioning, but may in the + future e.g. mojaloop/central-ledger:v10.0.1. The current approach is described in more detail in the [standards + /Versioning doc](https://github.com/mojaloop/documentation/blob/master/contributors-guide/standards/versioning.md). +* **helm**: Helm is an application package manager that runs on top of Kubernetes. It may also be referred to as the + "deployment". A single helm deployment runs many different services, and MAY run multiple versions of the same service simultaneously. We also refer to the deployment as it's repo, mojaloop/helm interchangeably. +* **helm version**: A helm version is the version of the packaged helm charts, e.g.mojaloop/helm:v1.1.0 +* **interface**: An interface is the protocol by which a Mojaloop switch interacts with the outside world. This includes + interactions with Participants (DFSPs) who transfer funds through the switch, hub operators running a Mojaloop switch, and admins performing administrative functions. +* **api**: Application Programming Interface - in most cases referring to the FSPIOP-API a.k.a. Open API for FSP + Interoperability defined [here](https://github.com/mojaloop/mojaloop-specification). +* **api version**: The Version of the FSPIOP-API, e.g. FSPIOP-API v1. For the purposes of this document, it refers to the + contract between a Mojaloop Switch and Participants (DFSPs) who implement the FSPIOP-API + +## References + +[1] LTS versioning within nodejs. This is a great example of an LTS strategy, and how to clearly communicate such a strategy. +[2] Semantic Versioning Reference +[3] https://www.ben-morris.com/rest-apis-dont-need-a-versioning-strategy-they-need-a-change-strategy/ +[4] https://cloud.google.com/apis/design/compatibility +[5] Nicolas Frankel - Zero-downtime deployment with Kubernetes, Spring Boot and Flyway +[6] Stackoverflow - Kafka Topic Message Versioning + diff --git a/discussions/workbench.md b/docs/community/archive/discussion-docs/workbench.md similarity index 100% rename from discussions/workbench.md rename to docs/community/archive/discussion-docs/workbench.md diff --git a/docs/community/archive/notes/README.md b/docs/community/archive/notes/README.md new file mode 100644 index 000000000..8f7b7868c --- /dev/null +++ b/docs/community/archive/notes/README.md @@ -0,0 +1,5 @@ +# OSS Meeting Group Notes (Archive) + +- [Change Control Board](./ccb-notes.md) +- [Design Authority](./da-notes.md) +- [Scrum-of-scrum calls](./scrum-of-scrum-notes.md) diff --git a/docs/community/archive/notes/ccb-notes.md b/docs/community/archive/notes/ccb-notes.md new file mode 100644 index 000000000..b8c49a9df --- /dev/null +++ b/docs/community/archive/notes/ccb-notes.md @@ -0,0 +1,6 @@ +## CCB meetings: Overview +The Change Control Board meets every two weeks. + +The meetings are open for the public to participate, though discussions are usually limited to the Board members. However, attendees will be promoted to panelists in meetings if they have Change Requests or Solution Proposals to discuss. + +More details can be found here: https://github.com/mojaloop/mojaloop-specification/tree/master/ccb-meetings . \ No newline at end of file diff --git a/docs/community/archive/notes/da-notes.md b/docs/community/archive/notes/da-notes.md new file mode 100644 index 000000000..2e04a1be9 --- /dev/null +++ b/docs/community/archive/notes/da-notes.md @@ -0,0 +1,125 @@ +## DA meetings: Overview +The Design Authority meets every week for a weekly update and has ad-hoc or detailed sessions for Specific topics + +The meetings are open for the public to participate, though discussions are usually limited to the Board members. However, attendees will be promoted to panelists in meetings if they have designs to be reviewed or proposals for changes. + +More details can be found [here](https://github.com/mojaloop/design-authority/issues/42#workspaces/da-issue-log-5cdd507422733779191866e9/board?notFullScreen=false&repos=186592307) + +# DA Meeting - 30 September 2020 +Discussion around the topics mentioned started - the newly implemented "patch" in version 1.1 of the API spec was discussed and the majority of the meeting was spent on how to promote wider adoption of this new pattern. + +Concerns about the implementation and use of the "patch" command was raised, stating that further discussion is required to determine if we are not trying to patch a design flaw with another potential implementation flaw. + +See: https://github.com/mojaloop/design-authority/issues/68 + + +# DA Meeting - 2 September 2020 +First we discussed the topic about the "models" folder from being excluded from the unit test coverage checks. The decision taken was that if the folder contains business logic (which generally should not be the case), it must be refactored and moved out. Once at that "business logic isolated" state, coverage testing for that folder can be ignored. See: https://github.com/mojaloop/design-authority/issues/64 + +We concluded discussions on the separate scheme-adapter for a PISP - see issue on board: https://github.com/mojaloop/design-authority/issues/51 +Please have a look at the draft document at this location: https://github.com/mojaloop/pisp/blob/scratch/api-collision/docs/api-collision.md +The above link has a detailed discussion regarding the latest thinking and some examples of mitigations. +The decision has been taken to block this topic until further development on the PoC has been done, in order for the DA to assess if the designs are still aligned with the recommended approach. + +# DA Meeting - 26 August 2020 +We discussed https://github.com/mojaloop/design-authority/issues/51 further on our DA Meeting on 26/08/2020. + +Some of the key points were noted: + +In order to take advantage of Typescript, and to help speed up development, the PISP workstream has gone ahead and separated out the thirdparty-scheme-adapter already. + +One of the challenges identified with the "multi-scheme-adapter" approach was for cases where there are shared resources between the APIs, such as GET /parties/{type}/{id}. + +Our decision to break the Thirdparty API into it's own API (and not extend the FSPIOP-API) was predicated on the idea that "not all participants will want thirdparty functions", and therefore shouldn't have to worry about them. As a part of the decision to keep a separate Thirdparty API, we decided that some resources would be duplicated between the two. + +This could lead to problems down the line, where callbacks to some resources might not be able to reach their desired destination: for example if a DFSP needs to listen for PUT /parties/{type}/{id} callbacks for both the FSPIOP API and the Thirdparty API, it may not be possible for DFSPs to route such callbacks to the right place. + +Lewis Daly will spend more time working on some diagrams and design documents, and come back to the DA shortly + +# DA Meeting (Ad-Hoc) - 24 August 2020 +The topic for discussion was: https://github.com/mojaloop/design-authority/issues/65 +The Ad-Hoc meeting was conducted with a wider issue being addressed relating to recommendations required to be taken to the CCB for consideration to change/enhance the API spec. + +Many valid points were raised and discussed and Michael and Adrian suggested some collaboration on this platform to consolidate the ideas put forward in order to formulate a recommendation to the CCB. + +# DA Meeting - 19 August 2020 +The topic for discussion was: https://github.com/mojaloop/design-authority/issues/61 +The group agreed that there needs to be a balance between the need to eliminate reconciliation and liquidity management of (Payer) FSPs by not holding/reserving funds for longer than necessary. In addition, It was proposed to use 'grace time period' before timing out transfers to compensate for differences in clocks. It was also suggested that for risky transactions, the final notification in the form of a PATCH call that was introduced with FSPIOP API v1.1 can be used to mitigate risk to the Payee FSPs. + +One point made was that after the timeout period (plus the grace period to account for clock difference), a transfer status cannot be changed - it is either finalized or it isn't, but it cannot be changed. For example, if a timeout period (expressed as a time in future and not duration) is 10 seconds, then a Payer FSP (or Switch), may add a grace period of 1second and after waiting for 11seconds can query the downstream entity to find the transfer's status; At this point, if a transfer is finalized (Committed or Aborted), then the Payer FSP can take action accordingly; however if it is in an intermediate state, then the transfer has to be timed-out since the time-out period is done. + +The group agreed on the need to revisit the topic of implementing 'telescopic timeouts', which is not currently supported in favor of end-to-end encryption of (most) messages. + +# DA Meeting - 12 August 2020 +The topic for discussion was: https://github.com/mojaloop/design-authority/issues/63 +The DA discussed the topic of where and how to create and work on issue tickets. With over 50 repositories, it makes sense to create a ticket in the repo where it originated and keep working on it there until it is resolved. The Product Owner and Scrum Master would have context and should replicate a ticket in the Design Autority Repo with a link to the originating ticket. Please have a look at the DA Board for the decisions made here: https://github.com/mojaloop/design-authority#workspaces/da-issue-log-5cdd507422733779191866e9/board?repos=186592307 + +# DA Meeting - 5 August 2020 +The topic for discussion was: https://github.com/mojaloop/project/issues/852 +The "HSM Integration Approach" was touched on a few times, and the workgroup taking care of the design and implementation, tabled this for discussion at this week's DA meeting to answer a few questions arising from the last PI-Planning session where progress on this was again presented. + +As we have not completed the discussion, an ad-hoc DA meeting has been arranged for this Friday with a sub-section of the DA Members. The reason for that was because there were a few specific questions we did not have time to go into detail for, which will be clarified with the individuals who raised those questions. Please drop me a note if you would like to participate in that meeting. + +# DA Meeting - 29 July 2020 +Issue discussed: https://github.com/mojaloop/design-authority/issues/60 +Claudio noted three observations regarding usage of best practices in the Mojaloop Core codebase. One of the issues has an active issue and will be used for tracking it; the other two will be followed up as separate stories/bugs as well (standards). Claudio will provide examples and in some cases sample snippets that can be used. + +Istvan and Michael discussed the usage of a unique ID for lookup requests and proposed to have a follow-up meeting the upcoming week for those interested. The current trace headers (optional) usage for traceability (APM) was brought up as a solution, which after the DA review can be proposed to the CCB (if accepted by the DA). + +# DA Meeting - 22 July 2020 +Canceled as a result of the PI-11 Mojaloop Convening taking place + +# DA Meeting - 15 July 2020 +Sam walked through some of the high-level changes being introduced with Helm v10.4.0 release and various sections from the release notes: https://github.com/mojaloop/helm/releases/tag/v10.4.0 +Please have a look on the DA Topic board: https://github.com/mojaloop/design-authority/issues/56 + +Neal and Michael discussed the issue of shared DB, code between central-settlement and central-ledger; they’re going to continue with the current work on Continuous Gross Settlement but after the convening will get the inputs from the Perf/Arch PoC (Event sourcing / CQRS) and then align. https://github.com/mojaloop/design-authority/issues/58 + +# DA Meeting - 8 July 2020 +The TIPS team did a presentation of the design and implementation of a **Rules Engine** satisfying their requirements of interpretation in the **Settlements Portion**, to extend fees levied as part of a transfer. The implementation allows for rules to be interpreted at any stage during a transaction. A formal presentation will be made at the convening during the week of the 20th July 2020 after which more informed decisions as to the adaption of this implementation into the Core OSS codebase can be considered as a generic approach to implementation of a rules engine. +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/53 for a detailed problem statement, progression on meetings in the notes and remarks and also, if completed, the subsequent decision. + +# DA Meeting - 1 July 2020 +As part of the "Versioning" workstream, a "zero down-time deployment proposal" PoC is being conducted and feedback from that project has been presented in the form of a problem statement, solution and a demo. The team currently working on that is Lewis Daly, Mat de Haast and Sam Kummary. The feedback was well received and as this work is ongoing, the DA will follow up with any action items to come out of the upcoming presentation for this workstream at the PI 11 Meeting. +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/54 for a detailed problem statement, progression on meetings in the notes and remarks and also, if completed, the subsequent decision. + +# DA Meeting (Ad-Hoc) - 29 June 2020 +KNEX Discussion - continued. The KNEX discussion extended into talking about the possible use of third-party tools to assist in the generation of queries to help migration efforts. This has no direct bearing on the use of KNEX itself and after exploring a bit deeper, it was decided that there was no compelling reason to continue further investigation into the use of KNEX itself, but to keep an open mind and look out for alternative solutions out there as and when they are introduced. Those libraries will be measured against the current implementation to ensure we deploy the right tools for the right purpose. This issue is now closed. +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/27 for a detailed problem statement, progression on meetings in the notes and remarks and also, if completed, the subsequent decision. + +# DA Meeting (Ad-Hoc) - 25 June 2020 +KNEX Discussion - initiated +Conversations have been started, highlighting the problem statement of difficulty in generating or creating migration scripts when database changes occur, as well as the scenario of having to perform these upgrades on a database which is online at the time. +With this context in place, continued design sessions have been scheduled to determine if KNEX would be capable of handling the above scenario and if there are alternate libraries or tools out there to replace or supplement the current implementation, which may help alleviate this difficult task. +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/27 for a detailed problem statement, progression on meetings in the notes and remarks and also, if completed, the subsequent decision. + + +# DA Meeting - 24 June 2020 +Discussion today started with: Deprecation of Helm2 support - Issue #52, where it was agreed that migration to Helm3 should continue. Documentation to assist in the use of tools available to help in the migration should be provided. Find the link to this document at https://github.com/mojaloop/design-authority/issues/52 + +The topic of having a design approach of implementing a generic rules-based system was discussed with some specific reference first, to a requirement of having the capability to interrogate completed or in-flight transactions (either in the transfer stage or even as early in the quoting stage) in order to apply "interchange fees" for that transaction, depending on the transaction type, as interpreted by certain rules. +Various design decisions are going to be discussed around this topic as the requirement is the facility to attach rules at various points of the transaction path. +The current implementation of a Rules Engine in the TIPS project was discussed and a request to demonstrate the capabilities of that solution in order for the DA to see if it was generic anough to incorporate into the core Switch will be made in a follow-up discussion. +Please track the progression of the design decisions surrounding this issue on the board at https://github.com/mojaloop/design-authority/issues/53 + + +# DA Meeting - 17 June 2020 +Topic under discussion was: Understand and Define Mojaloop Roles for PISP, x-network, etc. use cases +The DA is happy for workstreams to go ahead and split out new APIs and Role definitions (e.g. Thirdparty API, CNP API etc.) +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/44 for a detailed problem statement and subsequent decision. + +# DA Meeting - 10 June 2020 +This week, the DA discussed: Discuss the PISP Simulator: https://github.com/mojaloop/design-authority/issues/46 +The decision was made that for the time being, the PISP workstream will work on it's own branch in the sdk-scheme-adapter, and such a division/abstraction of the sdk-scheme-adapter will be revisited at a later date (see #51) + +# DA Meeting - 3 June 2020 +We continued the discussion started last week regarding the separate API for PISP and decided to go with option 4: maximum API Separation, with common swagger/open api files for definition and data model reuse: +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/47 for a detailed problem statement and subsequent decision. + +# DA Meeting - 27 May 2020 +Consensus relating to the issue raised and discussed some time ago, as queried by Adrian, was reached amongst the attendees. The outcome is that the Switch development will not be restrictive and prescriptive but as far as recommendation for new contributions and modules are concerned, it will be preferred if those could be done in TypeScript. + +A new discussion topic was tabled: https://github.com/mojaloop/design-authority/issues/47 seeking to answer the question of whether to have a separate API for PISP, or simply extend the existing Open API. A position statement was prepared and added as a comment. All attendees were brought up to speed with the decision to be made and Issue-#47 will be the topic for the next DA meeting. + +Another, PISP related topic was tabled and will be scheduled for another DA meeting: https://github.com/mojaloop/design-authority/issues/48 - Answer the question of how to manage notifications so that a PISP can be registered as an interested party for notification of the success of a transfer + diff --git a/docs/community/archive/notes/scrum-of-scrum-notes.md b/docs/community/archive/notes/scrum-of-scrum-notes.md new file mode 100644 index 000000000..648d833d3 --- /dev/null +++ b/docs/community/archive/notes/scrum-of-scrum-notes.md @@ -0,0 +1,154 @@ +# Meeting Notes from Weekly Scrum-of-scrum meetings + +## OSS Scrum or scrum calls Thu **May 7th** 2020 + +1. Coil - Don: + a Performance: 'Big Gap' problem; changes to cs-stream; changed results; putting together a doc with changes for review; Joran's work on concurrent message processing on Kafka topics -> try to test it; seeing 40-50% throughput; + b LPS adapter: Working with Renjith (Applied Payments); putting together a lab / envt for partner teams to use it; Exploring collaboration with GSMA lab +2. Crosslake - Lewis: + a. Performance: Had report out with Confluent with Nakul, engagement wrapping up; Disseminating docs Nakul produced + b. PISP: Design discussions going on along with Implementation + c. Versioning: Figuring scope for ZDD deployments + d. Official launch related issues: DNS issues - worked on and were resolved +3. ModusBox - Sam: + a. Performance: Moving / standardizing Perf changes from PI-9 into master (not all PoCs); Working on goals, strategy for PI10 + b. Core-team: Bulk transfers - getting started by providing support in sdk-scheme-adapter + c. Maintenance (Bug Fixes): + i) Accents in names - Ongoing + ii) Mojaloop simulator on AWS deployments - almost done, working on QA scripts (on 'dev2' - second environment) + d. Testing toolkit: Currently available for testing - all resources in ML FSPIOP API Supported. Reports can be generated. Working on providing Command line options and more portability + e. CCB: Publishing v1.1 Spec this week - API Definition and corresponding Swagger (Open API) +4. Virtual / Mojaloop Foundation - Megan: + a. Launch of Mojaloop Foundation + b. Paula H - Executive Director of the Mojaloop Foundation. +5. Mojaloop Foundation - Simeon: + a. Provide feedback on the Community Survey + b. Hackathon possible in early June time-frame in collaboration with Google + c. Mojaloop Newsletter with interesting items such as ML FSPIOP v1.1 Spec, Helm v10.1.0 release, etc. to be launched next week. + +## OSS Scrum or scrum calls Thu **April 16th** 2020 + +1. Coil: + a. Don C: Perf - preliminary results - got some numbers - got individual handler numbers, to compare with individual handlers - focusing on DB - a thrid of time for one leg spent on perf + b. Don C: HSM: Renjit's team demo'ed the demo for next week - event prep +2. Crosslake: + a. Lewis D: PISP - Sprint planning - iterating designs + b. Lewis D: Hackathons - Discussed a few concepts with Innocent K (HiPiPo) + c. Lewis D: Has access to GSMA lab - will play around + d. Lewis D: Versioning: working on deck for PI10 + e. Kim W: Performance stream overall update - workshop with Confluent + f. Kim W: Performance stream update - Pedro putting together a proposal, presentation +3. Mifos: + a. Ed C: Demo Prep for PI10 meetings +4. Virtual: + a. Megan : Getting ready for the PI10 event and Logistics +5. DA: + a. Nico: Discussing PISP issue which Michael will be the owner of +6. Core team: + a. Sam K: Performance: Preparing Metrics; Doing performance runs to baseline master branches after moving some enhancements to master + b. Sam K: Accents in names issue - implementation ongoing + f. Sam K: Settlements V2 implementation being done by OSS-TIPS team ongoing - QA done for current iteration + g. Sam K: Testing toolkit: Improving unit test coverage. Assertions added for various endpoints + i. Sam K: CCB: V1.1 of the ML FSPIOP API Definition - First draft done, Reviews in progress +7. Mojaloop Community: + a. Community update by Simeon + +## OSS Scrum or scrum calls Thu **April 9th** 2020 + +1. Coil: + a. Don C: perf testing - Under utilization of resources - more tweaking to be done + b. Don C: HSM integration - demo prep + c. Don C: Legacy adapter - docs update - looking for feedback +2. Crosslake: + a. Kim W: FRMS meeting earlier today - proposals made + b. Kim W: PI10 meetings update, registrations - questions + c. Lewis D: PISP: more planning - working on stories, items, but discussing designs on Oauth, Fido + d. Lewis D: Performance: discussion with Pedro about PoC for arch changes, for Event Sourcing, CQRS, etc + e. Lewis D: Code standards - updated + f. Lewis D: Code quality & Security stream: HSM usage, demo, Security in the OSS community + g. Lewis D: Container scans working - will work with Victor, early benchmarks + h. Lewis D: Finally - versioning update +3. Mifos: + a. Ed C: Work on Payment Hub, integrating with Kafka, ML transactions going through, usiing Elastic Search, for backoffice ops moniring + b. Ed C: Demo Prep for PI10 meetings +4. Core team: + a. Sam K: Performance: Drafting reports, Moving metrics, other enhancements to master branches + b. Sam K: Performance: Wrapping-up final set of tests; Phase4 roadmap and kickoff planning + c. Sam K: Community Support: Fixing bugs (few major discussion items fixed), providing clarifications regarding implementation decisions, etc. + d. Sam K: Merchant Payment Support - Provide tests and validate Merchant "Request to Pay" use case, standardization on-going + e. Sam K: Accents in names issue - implementation ongoing + f. Sam K: Settlements V2 implementation being done by OSS-TIPS team ongoing + g. Sam K: Testing toolkit: Assertions being added for API resources, JWS done, mTLS being added + h. Sam K: Testing toolkit: Usage guide in progress along with adding Golden path related tests + i. Sam K: CCB: V1.1 of the ML FSPIOP API Definition - First draft done, waiting for review + +## OSS Scrum or scrum calls Thu **April 2nd** 2020 + +1. Mifos: + a. Ed C: Team continuing work on Payment Hub EE, Focus on Operational UI , capabilities for DFSP backends, Error event handling framework +2. Coil: + a. Don C: Performance - setup done and got started - on GCP - getting high latency times - need to troubleshoot and will probably get support from other contributors + b. Don C: ATM - OTP - Encryption +3. Crosslake: + a. Kim W: Agenda for PI10 drafted - email should good out soon + b. Kim W: Schedule for PI10: Tue - Fri; 11am - 4pm GMT - Remote / Virtual event + c. Lewis D: Perf meeting later today - architecture deep dive + d. Lewis D: Versioning - In progress + e. Lewis D: Code quality & Security - Overall Security architecture, HSM covered by Coil + f. Lewis D: Mojaloop in a Vagrant box - in progress +4. Core team: + a. Miguel dB: Performance: Wrapping up Perf work - nearing 900 TPS end-to-end; Currently attempting to identify / understand a single unit that needs this perf + b. Sam K: Performance: Wrapping-up final set of tests; Phase4 roadmap and kickoff planning + c. Sam K: Community Support: Fixing bugs (few major discussion items fixed), providing clarifications regarding implementation decisions, etc. + d. Sam K: Merchant Payment Support - Standardization on-going - Fixing issues in /authorizations + e. Sam K: Accents in names issue - implementation ongoing + f. Sam K: Settlements V2 implementation being done by OSS-TIPS team ongoing + g. Sam K: Testing toolkit: Assertions being added for API resources, JWS in progress + h. Sam K: CCB: V1.1 of the ML FSPIOP API Definition - drafting in progress + +## OSS Scrum of scrum call Thu **March 26th** 2020 + +1. DA: Nico - Versioning topic discussed by Lewis, Matt, Sam +2. Crosslake: + a. Kim W: Finalizing Agenda - Monday to Friday + b. Kim W: Reach out if you want to present / speak + c. Kim W: Preparing pre-reads + d. Kim W: Fraud & AML workshop: Justus to post summary and notes to GitHub after the workshops + e. Lewis D: Performance workshop / deep-dive possibly Monday + f. Lewis D: PISP Design discussions ongoing + g: Lewis D: Code quality and security stream: i. Docker container security recommendations. ii. GDPR Scope for Mojaloop +3. Mifos: + a. Ed C / Istvan M: Continue creating Lab + b. Ed C / Istvan M: Fineract , new instance of Payment Hub - good progress + c. Ed C / Istvan M: Working on operational monitoring of backend part (back-office debugging, monitoring, etc) +4. Simeon O - Community Manager in attendance +5. Core team: + a. Sam K: Performance: Finalized phase-3 work. Get to immediate goals for logical conclusion - still ongoing - Phase4 roadmap and kickoff + b. Sam K: Community Support: Fixing bugs, providing clarifications regarding implementation decisions, etc. + d. Sam K: Merchant Payment Support - Standardization on-going - Metrics being added, event framework added + e. Sam K: Accents in names issue - Discussing issue, designing solution + f. Sam K: Settlements V2 implementation being done by OSS-TIPS team ongoing + g. Sam K: Testing toolkit: Assertions being added for API resources, JWS in progress. Usage guide in progress + h. Sam K: CCB: V1.1 of the ML FSPIOP API Definition - drafting in progress + +## OSS Scrum or scrum call Thu **March 19th** 2020 + +1. Coil: + a. Don C: Looking at performance, network hops (avoid dup checks etc) + b. Adrian hB: Renjith & Matt working on translation ISO20022, (to JWEs, etc) - demo by the time we meet on how to use HSM +2. Crosslake: + a. Kim W: Finishing action items from the Mid-PI Workshop, follow-up items + b. Kim W: April Community event is happening but will be a Virtual event. Kim has a planning event and will confirm details: Suggestions welcome + c. Lewis D: Performance - to include Don in other discussions + d. Lewis D: Code quality - GDPR requirements proposal + e: Lewis D: Versioning - iinitial draft made as PR - will be presented to DA next week +3. Mifos: + a. Ed C, Istvan M: Payment Hub, envt in Azure, + b. Ed C, Istvan M: Transactions now going through + c. Ed C, Istvan M: Next phase: to implement back office screens to see screens for business users + d. Ed C, Istvan M: Workshop with Google on PISP +4. Core team: + a. Sam K: Perf - Combining prepare+position handler and fulfil+position handlers, characterization work ongoing + b. Sam K: Perf - Working on gaining an understanding of how 1 unit of Infrastructure looks like for a Mojaloop deployment + c. Sam K: Transaction requests service standardization: Added event framework, Adding metrics now + d. Sam K: Community Support: Fixing issues, upgrade issues, issue for allowing accents in names, etc,. diff --git a/docs/community/assets/cla/admin_configure.png b/docs/community/assets/cla/admin_configure.png new file mode 100644 index 000000000..1d8281bb4 Binary files /dev/null and b/docs/community/assets/cla/admin_configure.png differ diff --git a/docs/community/assets/cla/admin_sign_in.png b/docs/community/assets/cla/admin_sign_in.png new file mode 100644 index 000000000..a960e2dcd Binary files /dev/null and b/docs/community/assets/cla/admin_sign_in.png differ diff --git a/docs/community/assets/cla/cla_1.png b/docs/community/assets/cla/cla_1.png new file mode 100644 index 000000000..46718fc66 Binary files /dev/null and b/docs/community/assets/cla/cla_1.png differ diff --git a/docs/community/assets/cla/cla_2_1.png b/docs/community/assets/cla/cla_2_1.png new file mode 100644 index 000000000..18ae1809c Binary files /dev/null and b/docs/community/assets/cla/cla_2_1.png differ diff --git a/docs/community/assets/cla/cla_2_2.png b/docs/community/assets/cla/cla_2_2.png new file mode 100644 index 000000000..2e60fb762 Binary files /dev/null and b/docs/community/assets/cla/cla_2_2.png differ diff --git a/docs/community/assets/cla/cla_3.png b/docs/community/assets/cla/cla_3.png new file mode 100644 index 000000000..5e2ddc46d Binary files /dev/null and b/docs/community/assets/cla/cla_3.png differ diff --git a/docs/community/contributing/assets/consequential-change-process.jpg b/docs/community/contributing/assets/consequential-change-process.jpg new file mode 100644 index 000000000..dffd4091b Binary files /dev/null and b/docs/community/contributing/assets/consequential-change-process.jpg differ diff --git a/docs/community/contributing/assets/critical-change-process.jpg b/docs/community/contributing/assets/critical-change-process.jpg new file mode 100644 index 000000000..6f4ec733d Binary files /dev/null and b/docs/community/contributing/assets/critical-change-process.jpg differ diff --git a/docs/community/contributing/assets/mojaloop-product-engineering-process-overview.jpg b/docs/community/contributing/assets/mojaloop-product-engineering-process-overview.jpg new file mode 100644 index 000000000..9f21aefff Binary files /dev/null and b/docs/community/contributing/assets/mojaloop-product-engineering-process-overview.jpg differ diff --git a/docs/community/contributing/assets/mojaloop-product-feature-flow.jpg b/docs/community/contributing/assets/mojaloop-product-feature-flow.jpg new file mode 100644 index 000000000..464be410d Binary files /dev/null and b/docs/community/contributing/assets/mojaloop-product-feature-flow.jpg differ diff --git a/docs/community/contributing/assets/mojaloop-workstream-sprint-process.jpg b/docs/community/contributing/assets/mojaloop-workstream-sprint-process.jpg new file mode 100644 index 000000000..048b46dd7 Binary files /dev/null and b/docs/community/contributing/assets/mojaloop-workstream-sprint-process.jpg differ diff --git a/docs/community/contributing/assets/mojaloop-workstream-team-charter-template.pptx b/docs/community/contributing/assets/mojaloop-workstream-team-charter-template.pptx new file mode 100644 index 000000000..6f4226afb Binary files /dev/null and b/docs/community/contributing/assets/mojaloop-workstream-team-charter-template.pptx differ diff --git a/docs/community/contributing/code-of-conduct.md b/docs/community/contributing/code-of-conduct.md new file mode 100644 index 000000000..641649471 --- /dev/null +++ b/docs/community/contributing/code-of-conduct.md @@ -0,0 +1,94 @@ +# Mojaloop Code of Conduct + + +## Vision and Mission + +Mojaloop is a portmanteau derived from the Swahili word "Moja" meaning "one" and the English word loop. Mojaloop's vision is to loop digital financial providers and customers together in one inclusive ecosystem. + +The Mojaloop open source project mission is to increase financial inclusion by empowering organizations creating trusted and interoperable payments systems to enable digital financial services for all. We believe an economy that includes everyone, benefits everyone and we are building software that will accelerate full financial inclusion. Succeeding in our mission will require diverse opinions and contributions from people reflecting differing experiences and who come from culturally diverse backgrounds. + +## Community Foundation and Values + +Our goal is a strong and diverse community that welcomes new ideas in a complex field and fosters collaboration between groups and individuals with very different needs, interests, and skills. + +We build a strong and diverse community by actively seeking participation from those who add value to it. + +We treat each other openly and respectfully, we evaluate contributions with fairness and equity, and we seek to create a project that includes everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, and orientation. + +*This code of conduct exists to ensure that diverse groups collaborate to mutual advantage and enjoyment.* + +The Code of Conduct governs how we behave in public or in private, virtually or in person. We expect it to be honoured by everyone who represents the project officially or informally, claims affiliation with the project, or participates directly. + +### We strive to: + +- **Be Considerate**\ + Our work will be used by other people, and we in turn will depend on the work of others. Any decision we take will affect everyone involved in our ecosystem, and we should consider all relevant aspects when making decisions. + +- **Be Respectful**\ + We work together to resolve conflict, assume good intentions, and do our best to act in an empathic fashion. We believe a community where people are respected and feel comfortable is a productive one. + +- **Be Accountable**\ + We are accountable for our words and actions. We all can make mistakes; when we do, we take responsibility for them. If someone has been harmed or offended, we listen carefully and respectfully and work to right the wrong. + +- **Be Collaborative**\ + What we produce is a complex whole made of many parts. Collaboration between teams that each have their own goal and vision is essential; for the whole to be more than the sum of its parts, each part must make an effort to understand the whole.\ + Collaboration reduces redundancy and improves the quality of our work. Internally and externally, we celebrate good collaboration. Wherever possible, we work closely with upstream projects and others in the open-source software community to coordinate our efforts. We prefer to work transparently and involve interested parties as early as possible. + +- **Value Decisiveness, Clarity, and Consensus**\ + Disagreements, social and technical, are normal, but we do not allow them to persist and fester leaving others uncertain of the agreed direction.\ + We expect community members to resolve disagreements constructively. When they face obstacles in doing so, we escalate the matter to structures with designated leaders to arbitrate and provide clarity and direction. + +- **Ask for help when unsure**\ + Nobody is expected to be perfect in this community. Asking questions early avoids many problems later, so questions are encouraged, though they may be directed to the appropriate forum. Those who are asked should be responsive and helpful. + +- **Step Down Considerately**\ + When somebody leaves or disengages from the project, we ask that they do so in a way that minimises disruption to the project. They should tell people they are leaving and take the proper steps to ensure that others can pick up where they left off. + +- **Open Meritocracy**\ +We invite anybody, from any company or organization, to participate in any aspect of the project. Our community is open, and any responsibility can be carried by any contributor who demonstrates the required capacity and competence. + +- **Value Diversity and Inclusion**\ +This is a community that wants to make a real difference to people's lives across the globe; and, in particular, in developing societies and economies. We value our members, first of all, for themselves; and, second, for the help they can give each of us as we work together to transform the world. Each of us will strive never to allow any other considerations to weigh with us, either consciously or unconsciously. In particular, considerations of gender identity or expression, sexual orientation, religion, ethnicity, age, neurodiversity, disability status, language, and citizenship have no place in our collaboration and we will work to eradicate them where we find them: first of all, in ourselves; but after that, and with respect and affection, in those we work with. + +- **Be Transparent**\ +We believe community members will have personal and professional interests in the development of the Mojaloop Open Source Software. These interests will, directly and indirectly, influence perceptions about the best direction of the community. Community members should make every reasonable effort to be transparent about their interests within the limits of confidentiality.  Community members who hold permanent or temporary governance roles should not use those roles in the advancement of personal or professional interests but should base their influence on the best interests of the success of the community. + +This Code of Conduct is not exhaustive or complete. It is not a rulebook; it serves to distill our common understanding of a collaborative, shared environment, and goals. We expect it to be followed in spirit as much as in the letter. + +### Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +- Using welcoming and inclusive language + +- Being respectful of differing viewpoints and experiences + +- Gracefully accepting constructive criticism + +- Focusing on what is best for the community + +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and unwelcome sexual attention or advances + +- Trolling, insulting/derogatory comments, and personal or political attacks + +- Public or private harassment + +- Publishing others' private information, such as a physical or electronic address, without explicit permission + +- Other conduct which could reasonably be considered inappropriate in a professional setting + +### Reporting and Resolution + +If you see someone violating the code of conduct, you are encouraged to address the behavior directly with those involved. Many issues can be resolved quickly and easily, and this gives people more control over the outcome of their dispute. If you are unable to resolve the matter for any reason, or if the behavior is threatening or harassing, report it. We are dedicated to providing an environment where participants feel welcome and safe. + +Reports should be directed to the Community Leadership Committee via an email sent to . This email goes to the Mojaloop Foundation Community Manager whose duty it is to receive and address reported violations of the code of conduct. They will then work with the Community Leadership Committee to address and resolve the report. + +We will investigate every complaint, but you may not receive a direct response. Whether we respond to you directly or not, you will always be able to enquire after the status of a complaint by contacting a member of the Community Leadership Committee. We will use our discretion in determining when and how to follow up on reported incidents, which may range from not taking action to permanent expulsion from the community and foundation-sponsored spaces. We will notify the accused of the report and provide them an opportunity to discuss it before any action is taken. The identity of the reporter will be omitted from the details of the report supplied to the accused. In potentially harmful situations, such as ongoing harassment or threats to anyone's safety, we may take action without notice. + +### Attribution + +This Code of Conduct is adapted from the Ubuntu Code of Conduct v2.0, available at diff --git a/docs/community/contributing/consequential-change-process.md b/docs/community/contributing/consequential-change-process.md new file mode 100644 index 000000000..eafb3772f --- /dev/null +++ b/docs/community/contributing/consequential-change-process.md @@ -0,0 +1,72 @@ +# Consequential Change Process + +For changes which are covered by the [consequential change definition](./design-review.md#consequential-changes) the +following process must be followed: + +1. Propose a product change to the Mojaloop Product Council: + 1. Create a 'Product Change Proposal' in the GitHub 'product-council' project + repository [here](https://github.com/mojaloop/product-council-project/issues). + 1. Complete the template as thoroughly as possible to ensure a quick turnaround. + 2. Send a message on the [#product-council](https://mojaloop.slack.com/archives/C01FF8AQUAK) slack channel asking + for a review of your proposal. + 3. The Product Council will discuss your proposal with you in order to understand where it fits within the Mojaloop + product roadmap. +2. Propose code changes to the Mojaloop Design Authority: + 1. Create a 'Consequential Change Proposal' issue in the GitHub 'design-authority-project' + repository [here](https://github.com/mojaloop/design-authority-project/issues). + 1. Complete the template as thoroughly as possible to ensure a quick turnaround. + 2. Send a message on the [#design-authority](https://mojaloop.slack.com/archives/CARJFMH3Q) slack channel asking for + a review of your proposal. + 3. The design authority will assign one or more members to work with you on your proposal. +3. Take part in a design review: + 1. Your assigned design authority member(s) will guide you through an iterative design review process. + 2. Once the design review process is complete you may proceed with your change. +4. Implement and review your code changes: + 1. Create and work on github/zenhub work items in + your [workstream process](./product-engineering-process.md#mojaloop-workstreams) as necessary. Be sure to + reference the product council ticket and consequential change proposal ticket in your item descriptions to enable + future traceability. + 2. When you are ready to make pull requests on one or more code repositories, contact your assigned design authority + member(s) and ask them ro begin the code review phase. + 3. Be ready to respond to questions and make adjustments during this stage. + 4. Once your assigned design authority member(s) approve your pull request(s) your feature is ready for including in + the official Mojaloop release process. + 5. Any changes to the design made during implementation must be recorded on the proposal ticket. + +![Consequential Change Process](./assets/consequential-change-process.jpg) + +## What to expect during the design review process + +_The Mojaloop Design Authority has responsibility for ensuring risks are identified and mitigated appropriately and that +our established standards for tools, patterns and practices are upheld. Your assigned design authority member(s) are +there to help you achieve the best possible outcome for yourself and the entire Mojaloop community._ + +Your assigned design authority member(s) will help you identify and mitigate any risks your change may introduce as well +as discussing how your design aligns with established tools, patterns and practices. + +1. You will be asked to talk through the reason(s) for your proposed change and to explain what you wish to achieve and + how you intend to achieve it. + 1. You should be able to refer to an existing Mojaloop Product Council GitHub ticket showing that you have discussed + your work with them and they are happy for the change to be made. Note that the Product Council has a + responsibility to maintain a coherent roadmap for our technology and will guide you on the most appropriate way + to achieve your business objectives within the Mojaloop context. The Product Council may consult the Design + Authority as part of this process. + 2. You should be able to explain how your change will be implemented, which existing components will be affected, + how they need to change and your designs for any new components. You should present, as a minimum: + 1. UML sequence diagrams showing each significant component involved in your usecase(s) and how they interact to + achieve your desired outcome(s). You should make sure to include error cases as well as "normal" expected + behaviours. + 2. Full details of any third-party components you will use as part of your implementation. + 3. Full details of any changes to existing components highlighting the differences between current behaviours + and your desired changed and/or new behaviours. + 3. Your assigned Design Authority members will likely ask lots of questions in order to fully understand your + proposal and its context. +2. Your assigned design authority member(s) will help you identify any other potentially impacted contributors, teams or + stakeholders to bring them in to the review process. This is done to ensure up and downstream behaviours are not + adversely affected and also, to take into account any upcoming changes in other areas of the system. Mojaloop is a + large system and it is often helpful to bring in experts from other areas to assist. +3. The primary goal of your assigned Design Authority member(s) is to identify and mitigate risks that you may not have + spotted. + 1. Your assigned design authority member(s) may make suggestions to mitigate risk from your design and may ask you + to make specific changes to bring your proposal in line with any established Mojaloop constraints. + diff --git a/docs/community/contributing/contributors-guide.md b/docs/community/contributing/contributors-guide.md new file mode 100644 index 000000000..9e5dfc416 --- /dev/null +++ b/docs/community/contributing/contributors-guide.md @@ -0,0 +1,86 @@ +# Contributors' Guide + +We are glad that you are considering becoming a part of the Mojaloop community. + +Based on the current phase of the Mojaloop project, we are looking for the following types of contributors: + +## Types of contributors + +- #### Individual Contributors + +These individuals are those that want to start contributing to the Mojaloop community. This could be a software +developer or quality assurance person that wants to write new code or fix a bug. This could also be a business, +compliance or risk specialist that wants to help provide rules, write documentation or participate in requirements +gathering. + +- #### Hub Operators + +Typically these or organizations or individuals or government agencies that are interested in setting up their own +Mojaloop Switch to become part of the ecosystem. + +- #### Implementation Teams + +Implementation teams can assist banks, government offices, mobile operators or credit unions in deploying Mojaloop. + +## How do I contribute? + +* Read and familiarise yourself with our [product engineering processes](./product-engineering-process.md) + and [Mojaloop design and code review processes](./design-review.md). +* Review the [Mojaloop Deployment Guide](https://docs.mojaloop.io/documentation/deployment-guide/) and + the [Onboarding Guide](https://github.com/mojaloop/mojaloop/blob/master/onboarding.md). +* Browse through the [Repository Overview](https://docs.mojaloop.io/documentation/repositories/) to understand how the + Mojaloop code is managed across multiple Github Repositories. +* Get familiar with our [Standards](../standards/guide.md) for contributing to this project. +* Go through the [New Contributor Checklist](./new-contributor-checklist.md), and browse through the project board and + work on + your [good first issue](https://github.com/mojaloop/project/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) +* Review the [Roadmap](../mojaloop-roadmap.md) and contribute to future opportunities. +* Familiarize yourself with our Community [Code of Conduct](./code-of-conduct.md). + +## What work is needed? + +Mojaloop follows a structured [product engineering process](./product-engineering-process.md) and we actively maintain +a [roadmap](../mojaloop-roadmap.md) of new feature developments and maintenance work. You can find information about our +currently running official workstreams on +our [community central workstreams page](https://community.mojaloop.io/pi-24-workstreams). + +Each Mojaloop workstream maintains a work item backlog in GitHub and a ZenHub workspace, reach out to the workstream +lead or post a message on the workstream slack channel to introduce yourself and find a good ticket to start work on. +You will find contact details for the workstream leads and slack channel information on +our [community central workstreams page](https://community.mojaloop.io/pi-24-workstreams). + +## Where do I get help? + +Join +the [Mojaloop Slack Discussions](https://join.slack.com/t/mojaloop/shared_invite/zt-1qy6f3fs0-xYfqfIHJ6zFfNXb0XRpiHw) to +connect with other developers. + +Also checkout +the [FAQ](https://github.com/mojaloop/documentation/blob/master/contributors-guide/frequently-asked-questions.md) + +## What is the current release? + +See the [Mojaloop Slack Announcements channel](https://mojaloop.slack.com/messages/CG3MAJZ5J) to find out information on +the latest release. + +## What's here and what's not? + +This is free code provided under an [Apache 2.0 license](https://github.com/mojaloop/mojaloop/blob/master/LICENSE.md). + +The code is released with an Apache 2.0 license but the Specification documents under the 'mojaloop-specification' +documents are published with CC BY-ND 4.0 License + +We don't provide production servers to run it on. That's up to you. You are free \(and encouraged!\) to clone these +repositories, participate in the community of developers, and contribute back to the code. + +We are not trying to replace mobile wallets or financial service providers. We provide a platform to link together new +and existing +financial providers using a common scheme. There are central services for identifying a customer's provider, quoting, +fulfillment, deferred net settlement, and shared fraud management. Each provider can take advantage of these services to +send and receive money with others on the system and there's no cost to them to onboard new providers. We provide code +for a simple example mobile money provider to show how integration can be done, but our example DFSP is not meant to be +a production mobile money provider. + +## Where do I send bugs, questions, and feedback? + +For bugs, see [Reporting bugs](https://github.com/mojaloop/mojaloop/blob/master/contribute/Reporting-Bugs.md). \ No newline at end of file diff --git a/docs/community/contributing/critical-change-process.md b/docs/community/contributing/critical-change-process.md new file mode 100644 index 000000000..d3d41a73b --- /dev/null +++ b/docs/community/contributing/critical-change-process.md @@ -0,0 +1,78 @@ +# Critical Change Process + +_**In Mojaloop, the "critical change process" is similar to the "consequential change process" but with additional +oversight and a formal sign-off requirement, given the high risk nature of such changes in our operating environment.**_ + +For changes which are covered by the [critical change definition](./design-review.md#critical-changes) the +following process must be followed: + +1. Propose a product change to the Mojaloop Product Council: + 1. Create a 'Product Change Proposal' in the GitHub 'product-council' project + repository [here](https://github.com/mojaloop/product-council-project/issues). + 1. Complete the template as thoroughly as possible to ensure a quick turnaround. + 2. Send a message on the [#product-council](https://mojaloop.slack.com/archives/C01FF8AQUAK) slack channel asking + for a review of your proposal. + 3. The Product Council will discuss your proposal with you in order to understand where it fits within the Mojaloop + product roadmap. +2. Propose code changes to the Mojaloop Design Authority: + 1. Create a 'Critical Change Proposal' issue in the GitHub 'design-authority-project' + repository [here](https://github.com/mojaloop/design-authority-project/issues). + 1. Complete the template as thoroughly as possible to ensure a quick turnaround. + 2. Send a message on the [#design-authority](https://mojaloop.slack.com/archives/CARJFMH3Q) slack channel asking for + a review of your proposal. + 3. The design authority will assign two or more members to work with you on your proposal. +3. Take part in a design review: + 1. Your assigned design authority members will guide you through an iterative design review process. + 2. Once the design review process is complete your assigned design authority members will formally sign-off your + design for implementation to begin + 3. Once your design has been formally signed-off, you may proceed with your change. +4. Implement and review your code changes: + 1. Create and work on github/zenhub work items in + your [workstream process](./product-engineering-process.md#mojaloop-workstreams) as necessary. Be sure to + reference the product council ticket and critical change proposal ticket in your item descriptions to enable + future traceability. + 2. When you are ready to make pull requests on one or more code repositories, contact your assigned design authority + members and ask them ro begin the code review phase. + 3. Be ready to respond to questions and make adjustments during this stage. + 4. Once your assigned design authority members approve your pull request(s) your feature is ready for including in + the official Mojaloop release process. + 5. Your assigned design authority members will formally record their approving review of your pull request(s). + 6. Any changes to the design made during implementation must be recorded on the proposal ticket. + +![Critical Change Process](./assets/critical-change-process.jpg) + +## What to expect during the design review process + +_The Mojaloop Design Authority has responsibility for ensuring risks are identified and mitigated appropriately and that +our established standards for tools, patterns and practices are upheld. Your assigned design authority member(s) are +there to help you achieve the best possible outcome for yourself and the entire Mojaloop community._ + +Your assigned design authority members will help you identify and mitigate any risks your change may introduce as well +as discussing how your design aligns with established tools, patterns and practices. + +1. You will be asked to talk through the reason(s) for your proposed change and to explain what you wish to achieve and + how you intend to achieve it. + 1. You should be able to refer to an existing Mojaloop Product Council GitHub ticket showing that you have discussed + your work with them and they are happy for the change to be made. Note that the Product Council has a + responsibility to maintain a coherent roadmap for our technology and will guide you on the most appropriate way + to achieve your business objectives within the Mojaloop context. The Product Council may consult the Design + Authority as part of this process. + 2. You should be able to explain how your change will be implemented, which existing components will be affected, + how they need to change and your designs for any new components. You should present, as a minimum: + 1. UML sequence diagrams showing each significant component involved in your usecase(s) and how they interact to + achieve your desired outcome(s). You should make sure to include error cases as well as "normal" expected + behaviours. + 2. Full details of any third-party components you will use as part of your implementation. + 3. Full details of any changes to existing components highlighting the differences between current behaviours + and your desired changed and/or new behaviours. + 3. Your assigned Design Authority members will likely ask lots of questions in order to fully understand your + proposal and its context. +2. Your assigned design authority members will help you identify any other potentially impacted contributors, teams or + stakeholders to bring them in to the review process. This is done to ensure up and downstream behaviours are not + adversely affected and also, to take into account any upcoming changes in other areas of the system. Mojaloop is a + large system and it is often helpful to bring in experts from other areas to assist. +3. The primary goal of your assigned Design Authority members is to identify and mitigate risks that you may not have + spotted. + 1. Your assigned design authority members may make suggestions to mitigate risk from your design and may ask you + to make specific changes to bring your proposal in line with any established Mojaloop constraints. + diff --git a/docs/community/contributing/cvd.md b/docs/community/contributing/cvd.md new file mode 100644 index 000000000..025827a3c --- /dev/null +++ b/docs/community/contributing/cvd.md @@ -0,0 +1,304 @@ +# Disclosing and Receiving Information Regarding Security Vulnerabilities + +The Mojaloop Foundation and community take the security of Mojaloop software very seriously and operate a number of +processes intended to ensure Mojaloop is a secure platform for conducting business. Please see +our [documentation on cybersecurity architecture](../tools/cybersecurity.md) for more information. + +The Mojaloop Foundation operates +a ["Coordinated Vulnerability Disclose"](https://github.com/ossf/oss-vulnerability-guide/blob/main/finder-guide.md#what-is-coordinated-vulnerability-disclosure) +process which is a model whereby a discovered vulnerability or issue is disclosed publicly only after responsible and +effected parties have been given sufficient time to patch or remedy the problem. By operating this model, the Mojaloop +Foundation and community aim to minimise the potential impact of such issues on our adopters. + +## Mojaloop Foundation Coordinated Vulnerability Disclosure Policy + +The following sections define the requirements and expectations of various parties involved in the discovery and +remediation of security vulnerabilities in the Mojaloop software. All members of the Mojaloop community are expected to +comply with these policies regardless of which role they are playing in any particular scenario. Participation in the +Mojaloop community implies acceptance of and compliance with these policies. + +### Terminology + +The following definitions apply within the Mojaloop Foundation Coordinated Vulnerability Disclosure Policy: + +#### Terms from RFC 2119 + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and " +OPTIONAL" in this document are to be interpreted as described in RFC 2119. + +#### Terms from ISO, CERT + +The terms "Researcher" or "Reporter" in this document are intended to be consistent with the terms "Finder" and/or " +Reporter" as used in ISO/IEC 29147:2014(E) and the CERT® Guide to Coordinated Vulnerability Disclosure. + +### Reporters Policy + +Reporters MUST adhere to the following guidelines. + +#### General + +* Reporters MUST comply with all applicable local and international laws in connection with security research activities + or other participation in this vulnerability disclosure program. + +* Reporters SHOULD make a good faith effort to notify and work directly with the affected vendor(s) or service providers + prior to publicly disclosing vulnerability reports. + +#### Scope of Authorized Testing + +* Reporters MAY test The Mojaloop open-source software to detect a vulnerability for the sole purpose of providing The + Mojaloop Foundation information about that vulnerability. + +* Reporters SHOULD only test against test accounts owned by the Reporter or with explicit permission from the account + holder. + +* Reporters MUST avoid harm to the information systems and operations of The Mojaloop Foundation, its associates and + users of Mojaloop open-source software. + +* Reporters MUST make every effort to avoid privacy violations, degradation of user experience, disruption to production + systems, and destruction or manipulation of data. + +* Reporters MUST stop testing once that testing has established that a vulnerability exists, or sensitive data has been + encountered. Sensitive data includes personally identifiable information, financial information (e.g., account + numbers), proprietary information or trade secrets. + +* Reporters MUST NOT test any software or services not expressly contained in The Mojaloop open-source software Github + repositories, including any connected services. + +* Reporters MUST NOT exploit any vulnerability beyond the minimal amount of testing required to prove that the + vulnerability exists or to identify an indicator related to that vulnerability. + +* Reporters MUST NOT intentionally access the content of any communications, data, or information transiting or stored + on information systems belonging to The Mojaloop Foundation, its associates or users of Mojaloop open-source + software – except to the extent that the information is directly related to a vulnerability and the access is + necessary to prove that the vulnerability exists. + +* Reporters MUST NOT exfiltrate any data under any circumstances. + +* Reporters MUST NOT intentionally compromise the privacy or safety of The Mojaloop Foundation's personnel, customers, + the general public, users of the Mojaloop open-source software or any legitimate third parties. + +* Reporters MUST NOT use any exploit to compromise, alter, or exfiltrate data + +* Reporters SHOULD NOT establish command line access and/or persistence + +* Reporters MUST NOT exploit any vulnerabilities found to pivot to other systems. + +* Reporters MUST NOT intentionally compromise the intellectual property or other commercial or financial interests of + any The Mojaloop Foundation's personnel or entities, customers, the general public, users of the Mojaloop open-source + software or any legitimate third parties. + +* Reporters MUST NOT cause a denial of any legitimate services in the course of their testing. + +* Reporters MUST NOT perform physical access testing (e.g. office access, open doors, tailgating, or other trespass). + +* Reporters MUST NOT conduct social engineering in any form of The Mojaloop Foundation personnel its contractors, + associates, or user of the Mojaloop open-source software, their personnel, contractors or customers. + +* Reporters SHOULD contact The Mojaloop Foundation by email at [security@mojaloop.io](mailto:security@mojaloop.io) if at + any point you are uncertain of whether to proceed with testing. + +#### Coordination with The Mojaloop Foundation + +* Reporters SHOULD submit vulnerability reports to The Mojaloop Foundation via secure (encrypted) email + to [security@mojaloop.io](mailto:security@mojaloop.io). + +* Reporters SHOULD submit high quality reports. + +* Reporters SHOULD include sufficient descriptive details to permit The Mojaloop Foundation and/or the affected + vendor(s) to accurately reproduce the vulnerable behavior. + +* Reporters SHOULD NOT report unanalyzed crash dumps or fuzzer output unless accompanied by a sufficiently detailed + explanation of how they represent a security vulnerability. + +* Reporters SHOULD report other vulnerabilities found incidental to their in-scope testing even if those vulnerabilities + would be otherwise considered out-of-scope. For example, while testing an in-scope system the reporter finds it to be + exposing data from out-of-scope system. These are still reportable vulnerabilities. + +* Reporters MUST keep confidential any information about vulnerabilities discovered for 90 days after you have notified + The Mojaloop Foundation. Notwithstanding, this expectation does not preclude Reporters from simultaneously + coordinating the vulnerability report with other affected parties (vendors, service providers, coordinators, etc.) + +* Reporters MAY include a proof-of-concept exploit if available. + +* Reporters MAY request that their contact information be withheld from all affected vendor(s). + +* Reporters MAY request not to be named in the acknowledgements of The Mojaloop Foundation's public disclosures. + +* Reporters MUST NOT submit a high-volume of low-quality reports. + +* Reporters MUST NOT require The Mojaloop Foundation to enter into a customer relationship, non-disclosure agreement + (NDA) or any other contractual or financial obligation as a condition of receiving or coordinating vulnerability + reports. + +* Reporters MUST NOT demand compensation in return for reporting vulnerability information reported outside of an + explicit bug bounty program. + +#### Coordination with vendors + +* In the event that the Reporter finds a vulnerability in The Mojaloop Foundation open-source software consequent to a + vulnerability in a generally available product or service, the Reporter MAY report the vulnerability to the affected + vendor(s), service provider(s), or third party vulnerability coordination service(s) in order to enable the product or + service to be fixed. + +#### Coordination with others + +* Reporters MAY engage the services of a third party coordination service (e.g., CERT/CC, DHS CISA) to assist in + resolving any conflicts that cannot be resolved between the Reporter and The Mojaloop Foundation. + +* Reporters SHOULD NOT disclose any details of any extant Mojaloop Foundation open-source software vulnerability, or any + indicators of vulnerability to any party not already aware at the time the report is submitted to The Mojaloop + Foundation. + +#### Public disclosure + +* Reporters MAY disclose to the public the prior existence of vulnerabilities already fixed by The Mojaloop Foundation, + including potentially details of the vulnerability, indicators of vulnerability, or the nature (but not content) of + information rendered available by the vulnerability. + +* Reporters choosing to disclose to the public SHOULD do so in consultation with The Mojaloop Foundation. + +* Reporters MUST NOT disclose any incidental proprietary data revealed during testing or the content of information + rendered available by the vulnerability to any party not already aware at the time the report is submitted to + The Mojaloop Foundation. + +### Receivers Policy + +The Mojaloop Foundation SHALL deal in good faith with Reporters who discover, test, and report vulnerabilities or +indicators of vulnerabilities in accordance with these guidelines. + +#### General + +* The Mojaloop Foundation MAY modify the terms of this policy or terminate the policy at any time. + +* The Mojaloop Foundation SHALL use information reported to this program for defensive purposes only; to mitigate or + remediate vulnerabilities in the Mojaloop open-source software, Mojaloop Foundation networks, applications, the + applications of our vendors and those of users of Mojaloop open-source software. + +#### Case handling + +* The Mojaloop Foundation MAY, at our discretion, decline to coordinate or publish a vulnerability report. This decision + is generally based on the scope and severity of the vulnerability and our ability to add value to the coordination and + disclosure process. + +* In the event that The Mojaloop Foundation declines to coordinate a vulnerability report, the Reporter MAY proceed to + coordinate with any other affected vendor(s). Additionally, the Reporter MAY proceed with public disclosure at their + discretion. + +* The Mojaloop Foundation SHALL investigate every reported vulnerability and strive to ensure that appropriate steps are + taken to mitigate risk and remediate reported vulnerabilities. + +* The Mojaloop Foundation SHALL, to the best of our ability, validate the existence of the vulnerability + +* The Mojaloop Foundation SHALL determine an appropriate timeframe for mitigation development and deployment for + vulnerabilities reported in systems it controls. + +#### Coordination with reporters + +* The Mojaloop Foundation SHALL acknowledge receipt of vulnerability reports via email within 7 working days. + +* The Mojaloop Foundation MAY contact the Reporter for further information. + +* The Mojaloop Foundation SHALL inform the Reporter of the results of our validation, as appropriate, and accordingly + provide status updates as remediation of the vulnerability is underway. + +* The Mojaloop Foundation SHALL include credit to the reporter in any published vulnerability report unless otherwise + requested by the reporter. + +* In the event that The Mojaloop Foundation chooses to publicly disclose the reported vulnerability, The Mojaloop + Foundation SHALL recognize your contribution to improving our security if you are the first to report a unique + vulnerability, and your report triggers a code or configuration change. + +* The Mojaloop Foundation MAY forward the name and contact information of the Reporter to any affected vendors unless + otherwise requested by the reporter. + +* The Mojaloop Foundation SHALL forward the name and contact information of the reporter to the affected vendors unless + otherwise requested by the reporter. + +* The Mojaloop Foundation SHALL advise the reporter of significant changes in the status of any vulnerability he or she + reported to the extent possible without revealing information provided to us in confidence. + +* The Mojaloop Foundation MAY adjust its publication timeframe to accommodate reporter constraints if that timing is + otherwise compatible with this policy. In most cases such an adjustment would be expected to represent a delay rather + than an acceleration of the publication schedule. Examples include delaying publication to coincide with conference + presentations. + +* The Mojaloop Foundation SHALL NOT require Reporters to enter into a customer relationship, non-disclosure agreement + (NDA) or any other contractual or financial obligation as a condition of receiving or coordinating vulnerability + reports. + +#### Coordination with vendors + +* In the event that The Mojaloop Foundation determines the reported vulnerability is consequent to a vulnerability in a + generally available product or service, The Mojaloop Foundation MAY report the vulnerability to the affected + vendor(s), service provider(s), or third party vulnerability coordination service(s) in order to enable the product or + service to be fixed. + +* The Mojaloop Foundation SHALL make a good faith effort to inform vendors of reported vulnerabilities prior to public + disclosure. + +* The Mojaloop Foundation SHALL forward vulnerability reports to the affected vendor(s) as soon as practical after we + receive the report. + +* The Mojaloop Foundation SHALL apprise any affected vendors of our publication plans and negotiate alternate + publication schedules with the affected vendors when required. + +* The Mojaloop Foundation SHALL provide the vendor the opportunity to include a vendor statement within our public + disclosure document. + +* The Mojaloop Foundation SHALL NOT withhold vendor-supplied information simply because it disagrees with our assessment + of the problem. + +* The Mojaloop Foundation SHALL notify affected vendors of any public disclosure plans. + +* The Mojaloop Foundation SHALL NOT reveal information provided in confidence by any vendor. + +* The Mojaloop Foundation SHALL act in accordance with the expectations of Reporters set forth in this policy when + acting as a Reporter to other organizations (vendors, coordinators, etc.). + +#### Coordination with others + +* The Mojaloop Foundation MAY engage the services of a third party coordination service (e.g., CERT/CC, DHS CISA) to + assist in resolving any conflicts that cannot be resolved between the Reporter and The Mojaloop Foundation. + +* The Mojaloop Foundation MAY, at our discretion, provide reported vulnerability information to anyone who can + contribute to the solution and with whom we have a trusted relationship, including vendors (often including vendors + whose products are not vulnerable), service providers, community experts, sponsors, and sites that are part of a + national critical infrastructure, if we believe those sites to be at risk. + +#### Public disclosure + +* The Mojaloop Foundation SHALL determine the type and schedule of our public disclosure of the vulnerability. + +* The Mojaloop Foundation MAY disclose reported vulnerabilities to the public 7 days days after the initial + report, regardless of the existence or availability of patches or workarounds from affected vendors. + +* The Mojaloop Foundation MAY disclose vulnerabilities to the public earlier or later than 7 days due to extenuating + circumstances, including but not limited to active exploitation, threats of an especially serious (or trivial) nature, + or situations that require changes to an established standard. + +* The Mojaloop Foundation MAY consult with the Reporter and any affected vendor(s) to determine the appropriate public + disclosure timing and details. + +* The Mojaloop Foundation SHALL balance the need of the public to be informed of security vulnerabilities with vendors' + and users of Mojaloop open-source software need for time to respond effectively. + +* The Mojaloop Foundation's final determination of a publication schedule SHALL be based on the best interests of the + community overall. + +* The Mojaloop Foundation SHALL publish public disclosures via one or more of email, slack, and/or the Mojaloop + Community Central website. + +* The Mojaloop Foundation MAY disclose to the public the prior existence of vulnerabilities already fixed by The + Mojaloop Foundation, including potentially details of the vulnerability, indicators of vulnerability, or the nature ( + but not content) of information rendered available by the vulnerability. + +* The Mojaloop Foundation SHALL make our disclosure determinations based on relevant factors such as but not limited to: + whether the vulnerability has already been publicly disclosed, the severity of the vulnerability, potential impact to + critical infrastructure, possible threat to public health and safety, immediate mitigations available, vendor + responsiveness and feasibility for creating an upgrade or patch, and vendor estimate of time required for customers to + obtain, test, and apply the patch. Active exploitation, threats of an especially serious nature, or situations that + require changes to an established standard may result in earlier or later disclosure. + +* The Mojaloop Foundation MAY disclose product vulnerabilities 30 days after the initial contact is made, regardless of + the existence or availability of patches or workarounds from affected vendors in cases where a product is affected and + the vendor is unresponsive, or fails to establish a reasonable timeframe for remediation. diff --git a/docs/community/contributing/design-review.md b/docs/community/contributing/design-review.md new file mode 100644 index 000000000..06c9ac2dd --- /dev/null +++ b/docs/community/contributing/design-review.md @@ -0,0 +1,231 @@ +# Technical Design Review & Code Review + +Mojaloop software is intended to form the backbone of nation scale inclusive instant payments schemes. These schemes +are important pieces of national financial infrastructure which facilitate the life critical daily activities of a +great number of people, such as purchasing food and clean drinking water. Adopters and users of Mojaloop software demand +and deserve an extremely high level of quality, security, reliability and resilience from our products. + +In order to maintain these qualities and mitigate the many business and technical risks our adopters and their +stakeholders face, the Mojaloop Foundation implements a structured product engineering process based on best +demonstrated industry practices for regulated financial software which includes managed technical and process driven +change control and traceability, technical design and code reviews, high thresholds for testing and multiple levels of +quality assurance gates. + +Our processes are intended to help our contributors identity and mitigate risks while enhancing our products, for the +benefit of the entire Mojaloop community. + +Please read the following information carefully to make sure you understand our definitions and how these processes +apply to the work you want to accomplish **before you begin**. + +**Please note that if you do not follow these processes you may be asked to rework your contribution, or it may be +rejected outright if it does not meet our standards. This may lead to significant delays in getting your work into an +official Mojaloop release. Please read our statements on +the [external dontaion process](product-engineering-process.md#non-official-workstreams-and-external-contributions).** + +## What is Technical Design Review? + +"Technical design review" is a process whereby one or more senior domain expert engineers who are members of the +Mojaloop Design Authority, familiar with the area(s) of the system effected, discuss proposed changes with contributors +and product representatives **before implementation work is started**, for the following purposes: + +- Risk Management + - To help identify and mitigate technical and/or business risks to any of our stakeholders, users or other + contributors. +- Impact Assessment + - To help identify other areas of the system, teams and stakeholders who may be impacted by the change, and to + facilitate communication with them. +- Standards & Cohesion + - To guide on established Mojaloop standards for tooling, third party component choices and design patterns with a + view to maintaining cohesion across the entire Mojaloop codebase. + +For non-trivial changes, this process involves working collaboratively with the Mojaloop Design Authority to produce a +design document which captures the various elements of the proposed change in a sufficient level of detail. Once the +change is implemented, this document goes on to form part of our community documentation, helping others understand the +rationale behind the design decisions made historically as our software evolves. + +## What is Code Review + +"Code review" is a process whereby one or more other software engineers look over a set of proposed code changes +**before they are merged into the main branch of a repository**, for the following purposes: + +- Quality Assurance + - Code reviews help ensure the quality of the codebase by allowing other team members to identify potential issues, + bugs, or areas for improvement before the code is merged into the main branch. This can lead to higher-quality + software with fewer defects. +- Knowledge Sharing + - Code reviews provide an opportunity for team members to learn from each other. By reviewing code written by their + peers, contributors can gain insights into different approaches, best practices, and coding patterns. This helps + spread knowledge and expertise around the community. +- Consistency + - Code reviews help maintain consistency in coding style, standards, and conventions within the Mojaloop project. By + having multiple community members review each other's code, we hope to ensure that the codebase follows + established standards and remains cohesive. +- Risk Mitigation + - Code reviews can help mitigate risks associated with changes to the codebase. By having multiple sets of eyes + examine the code, potential risks, security vulnerabilities, and performance bottlenecks can be identified early + on and addressed before they cause problems in production deployments. +- Feedback and Improvement + - Code reviews provide an opportunity for constructive feedback and collaboration. Contributors can offer + suggestions for improvement, share alternative solutions, and discuss design decisions. This fosters a culture of + continuous improvement within the community. +- Code Ownership + - Code reviews encourage a sense of collective ownership of the codebase. When multiple community members are + involved in reviewing and contributing to the code, it becomes a shared responsibility rather than the sole + responsibility of individual contributors. + +## Types of Change + +As a Mojaloop contributor, the process you must follow depends on the nature of the change you are making and its +potential impact on various categories of users and the system as a whole. + +Use the definitions below to identify the category of change you are making and select the appropriate process to +follow. It is your responsibility as a contributor to apply the appropriate process and you will be required to sign a +contributors agreement stating that you will adhere to these requirements. + +If you are in any doubt about which of the following categories applies to you change, please consult the Mojaloop +Design Authority via slack here: [#design-authority](https://mojaloop.slack.com/archives/CARJFMH3Q). Please note that it +is important to engage in any required design review process before proceeding with any code changes to avoid wasting +your own efforts should re-work be requested by the Design Authority. + +### Non-consequential Changes + +#### Definition and Characteristics + +A non-consequential code change is a small, highly isolated modification made to an existing piece of code. These +changes do not affect the internal or external structure, or functionality of the local scope i.e. its inputs or +outputs, and are typically made for reasons such as improving readability, fixing coding style issues and/or minor +performance optimisations. Non-consequential code changes are straightforward and low-risk. + +A non-consequential code change does not alter the external interfaces, functionality or externally observable behaviour +of a component(s) in any way. + +A non-consequential code change does not alter the internal structure of one or more components in any way. + +_Important Note: If your change is an optimisation and involves altering the implementation of any algorithm, consider +carefully if it warrants design review or a more stringent code review than normal. It is far better to be cautious and +seek more eyes on your change than to inadvertently introduce a regression._ + +#### Examples + +Examples include: + +- Renaming variables +- Adjusting indentation +- Adding comments +- Removing unused imports +- Optimising smaller algorithms + +#### Required Design & Code Review Process + +1. No design review is required but can be understaken regardless should you be under any doubts about the consequences + of your changes. +2. At least one approving "code owner" review of all the source files being modified. + 1. Note that if no code owners are defined for any of the source files being modified you must raise an issue with + {contact details} to get code owners defined for you before proceeding. All code files in the Mojaloop GitHub + organisation should have code owners defined. +3. Additional peer code reviews as desired. The more eyes on your proposed change the better. + +### Consequential Changes + +#### Definition and Characteristics + +Consequential changes are modifications that have an impact on the behavior, functionality, operational characteristics +or performance of a sub-system or the system as a whole. These changes typically involve altering the logic of a +component or service, implementing new features, fixing bugs, changing or upgrading dependencies, or refactoring large +sections of code. Consequential changes require a considerable amount of up-front thinking and coordination with other +teams and stakeholders due to their potential system wide impact on stability and functionality of the software. They +typically carry a higher risk and require careful consideration and planning before implementation. + +_Important Note: If you think your change falls into the "Consequential Changes" category, you must also ensure it does +not fall under the ["Critical Changes"](#critical-changes) category. Please review the definition +for ["Critical Changes"](#critical-changes) before proceeding._ + +#### Examples + +Examples include: + +- Changing an existing internal API method implementation +- Adding a new internal API method implementation +- Changing the definition or behaviour of an internal interface +- Changing a backing service dependency such as swapping an existing DBMS type for another +- Changing a code dependency such as replacing one YAML parser package for another +- Refactorings across multiple code files +- Changes to deployment configurations e.g. in Infrastructure as Code. + +#### Required Design & Code Review Process + +Consequential changes must follow the defined [Consequential Change Process](consequential-change-process.md). + +### Critical Changes + +#### Definition and Characteristics + +_**In Mojaloop, "critical changes" have largely the same definition as consequential changes but apply specifically to +areas of the system considered critical to our core functionality and main use cases.**_ + +Critical changes are modifications that have an impact on the behavior, functionality, operational characteristics or +performance of any critical sub-system, system or other artefacts. These changes typically involve altering the logic of +a critical component or service e.g. for implementing new features, fixing bugs, changing or upgrading dependencies, or +refactoring code. Critical changes require a considerable amount of up-front thinking and coordination with other teams +and stakeholders due to their potential system wide impact on stability and functionality of critical aspects of the +software. They typically carry a very high risk and require careful consideration and planning before implementation. + +A change should be considered a critical change if it falls under one or more of the following code repositories, areas +and/or sub-systems: + +- External APIs: + - Any alteration to an external API specification, normal or error paths, including request validation and bug + fixes. + - Any alteration to an external API request handling implementation, normal or error paths, including request + validation and bug fixes. + - Note that "external API" in this case means any API exposed outside the switch boundary e.g. FSPIOP API etc... +- Administrative APIs: + - Any change to any administrative API specification. + - Any change to any administrative API request handling implementation, normal, or error paths, including request + validation and bug fixes. +- Transfer Flow Discovery Phase: + - Any change in discovery phase API request handling e.g.: + - Any change to account lookup API request handling implementation(s) and/or call flows to and from internal or + external "oracles". +- Transfer Flow Agreement Phase: + - Any change in agreement phase API request handling e.g.: + - Any change to the storage, retrieval, processing or display of agreement phase data or meta-data. + - Any change to agreement phase API request handling implementation(s) and/or call flows to and from internal or + external entities. +- Transfer Flow Transfer (clearing) Phase: + - Any change in transfer clearing phase API request handling, e.g.: + - Any change related to the process of deciding whether to clear a transfer of reject it based on the available + liquidity of a participant (liquidity check). + - Any change to the calculation, storage, retrieval, processing or display of participant net debit cap values. + - Any change to the calculation, storage, retrieval, processing or display of a participants available + liquidity. + - Any change to the calculation, storage, retrieval, processing or display of any monetary value. + - Any change to the calculation, storage, retrieval, processing or display of transfer data or meta-data. + - Any change within the transfer prepare request processing pipeline. + - Any change within the transfer fulfil request processing pipeline. +- Settlement: + - Any alteration to an external or internal settlement API specification, normal or error paths, including request + validation and bug fixes. + - Any alteration to an external or internal settlement API request handling implementation, normal or error paths, + including request validation and bug fixes. + - Any change related to the inclusion or exclusion of transfers for settlement batching. + - Any change related to the calculation, storage, retrieval, processing or display of settlement related data or + meta-data. + +#### Examples + +Examples include: + +- Fixing a bug in an FSPIOP API validation method +- Adding a new feature to an administrative API +- Changing the formatting of currency values displayed to users in a web portal +- Upgrading the version of an external code dependency e.g. npm package of a ledger related service +- Optimising calls to backing store services during processing of an external API request + +#### Required Design & Code Review Process + +Critical changes must follow the defined [Critical Change Process](critical-change-process.md). + + + + diff --git a/docs/community/contributing/new-contributor-checklist.md b/docs/community/contributing/new-contributor-checklist.md new file mode 100644 index 000000000..e438fc7ec --- /dev/null +++ b/docs/community/contributing/new-contributor-checklist.md @@ -0,0 +1,63 @@ +# New Contributor Checklist + +This guide summarizes the steps needed to get up and running as a contributor to Mojaloop. They needn't be completed all in one sitting, but by the end of the checklist, you should have learned a good deal about Mojaloop, and be prepared to contribute to the community. + + +## 1. Tools & Documentation + +- Make sure you have a GitHub account already, or sign up for an account [here](https://github.com/join) + +- Join the slack community at the [self-invite link](https://join.slack.com/t/mojaloop/shared_invite/zt-1qy6f3fs0-xYfqfIHJ6zFfNXb0XRpiHw), and join the following channels: + - `#announcements` - Announcements for new Releases and QA Status + - `#design-authority` - Questions + Discussion around Mojaloop Design + - `#general` - General discussion about Mojaloop + - `#help-mojaloop` - Ask for help with installing or running Mojaloop + - `#ml-oss-bug-triage` - Discussion and triage for new bugs and issues + +- Say hi! Feel free to give a short introduction of yourself to the community on the `#general` channel. + +- Review the [Git workflow guide](https://docs.mojaloop.io/community/standards/creating-new-features.html) and ensure you are familiar with git. + - Further reading: [Introduction to Github workflow](https://www.atlassian.com/git/tutorials/comparing-workflows) + +- Familiarize yourself with our standard coding style: https://standardjs.com/ + +- Browse through the [Mojaloop Documentation](https://mojaloop.io/documentation/) and get a basic understanding of how the technology works. + +- Go through the [Developer Tools Guide](https://github.com/mojaloop/mojaloop/blob/master/onboarding.md) to get the necessary developer tools up and running on your local environment. + +- (Optional) Get the Central-Ledger up and running on local machines: + - https://github.com/mojaloop/central-ledger/blob/master/Onboarding.md + - https://github.com/mojaloop/ml-api-adapter/blob/master/Onboarding.md + +- (Optional:) Run an entire switch yourself with Kubernetes https://mojaloop.io/documentation/deployment-guide/ _(note: if running locally, your Kubernetes cluster will need 8GB or more of RAM)_ + +## 2. Finding an Issue + +- Review the [good-first-issue](https://github.com/mojaloop/project/labels/good%20first%20issue) list on [`mojaloop/project`](https://github.com/mojaloop/project), to find a good issue to start working on. Alternatively, reach out to the community on Slack at `#general` to ask for help to find an issue. + +- Leave a comment on the issue asking for it to be assigned to you -- this helps make sure we don't duplicate work. As always, reach out to us on Slack if you have any questions or concerns. + +- Fork the relevant repos for the issue, clone and create a new branch for the issue + - Refer to our [Git User Guide](https://docs.mojaloop.io/community/standards/creating-new-features.html) if you get lost + + +## 3. Opening your First PR + +> Complete this part of the guide once you have been added to the Mojaloop GitHub organization. If you don't have access, reach out to us on the `#general` or `#help-mojaloop` + +- Sign up for [Zenhub](https://www.zenhub.com/), and connect it to the Mojaloop Organisation, Search for the _'project'_ workspace +- Install the [Zenhub Browser extension](https://www.zenhub.com/extension) for Chrome or Firefox, and browse the (Mojaloop Project Kanban board](https://github.com/mojaloop/project#zenhub) + +- When your branch is ready for review, open a new pull request from your repository back into the mojaloop project. + >_Note: if the CI/CD pipelines don't run, this may be because your Github account isn't added to the Mojaloop repo_ +- Ensure the following: + - A good description of the feature/bugfix you implemented + - The PR is _assigned_ to yourself + - You have assigned two or more _reviewers_. GitHub often has suggested reviewers, but if you don't know who to assign, feel free to ask whoever created the issue. + +- (Optional) Post a link to your PR on the `#ml-oss-devs` channel in Slack so everyone can share in the fun + + +## 4. Signing the CLA + +After you open your first PR, our CI/CD pipelines will ask you to sign the CLA. For more information on what the CLA is and how to sign it, see [Signing the CLA](./signing-the-cla.md) diff --git a/docs/community/contributing/product-engineering-process.md b/docs/community/contributing/product-engineering-process.md new file mode 100644 index 000000000..1818851e2 --- /dev/null +++ b/docs/community/contributing/product-engineering-process.md @@ -0,0 +1,194 @@ +# Mojaloop Product Engineering Process + +## Introduction + +Mojaloop software is intended to form the backbone of nation scale inclusive instant payments schemes. These schemes are +important pieces of regulated national financial infrastructure which facilitate the life critical daily activities of a +great number of people, such as purchasing food and clean drinking water. Our adopters, their regulators and the people +transacting through Mojaloop schemes demand and deserve an extremely high level of quality, security, reliability and +resilience from our products. + +In order to maintain these qualities and mitigate the many business and technical risks our adopters and their +stakeholders face, the Mojaloop Foundation implements a structured product engineering process based on best +demonstrated industry practices for regulated financial software which includes managed technical and process driven +change control and traceability, technical design and code reviews, high thresholds for testing and multiple levels of +quality assurance gates. + +Our process is intended to help our contributors identify and mitigate risks while enhancing our products, for the +benefit of the entire Mojaloop community. + +## Evolution of our process + +Since 2017 when the Mojaloop project cut its first code, our process model has evolved to cope with the +transition from a single engineering team to a number of community resourced workstreams, each focused on developing +specific areas of a large product suite. + +Our current model is based on the [Scaled Agile Framework](https://scaledagileframework.com/) which we use to facilitate +a number of teams working as independently as possible to deliver a coordinated set of roadmap outcomes across our +entire product space. + +Our model is a cycle of "[program increments](https://v5.scaledagileframework.com/program-increment/)", each lasting +approximately four calendar months. At the end of each increment, workstreams present their accomplishments at a +community meeting, new code is released and planning for the next increment begins. + +![Mojaloop Program Increments](./assets/mojaloop-product-engineering-process-overview.jpg) + +## Product Requirements Flow + +![Mojaloop Feature Flow](./assets/mojaloop-product-feature-flow.jpg) + +Feature requests and new requirements come from a variety of sources, for example: + +- Current Mojaloop adopters and Mojaloop scheme participants +- Payment scheme operators wishing to benefit from Mojaloop technology +- Government departments wishing to implement inclusive payment schemes in their countries +- Financial inclusion experts +- Mojaloop community members + +These new requirements and feature requests are gathered and analysed by the Mojaloop product council. If sufficient +demand and willingness to contribute is evident then these are fed into the Mojaloop Product Roadmap and allocated to an +official Mojaloop workstream. If no appropriate workstream exists then a new one may be created and resourced by the +community. + +Workstreams typically have a set of objectives defined at the beginning of each Mojaloop programme increment, but high +priority feature requests may be inserted during an increment. + +Workstreams deliver their output into a controlled process which periodically makes official releases of the +Mojaloop software. The Mojaloop release process tends to align with program increments; major releases, which +include new features, are typically made close to the end of an increment. Minor and patch releases are made more +frequently and may include high priority features, bug fixes or security patches for example. + +## Mojaloop Workstreams + +Official workstreams are the "production lines" of the Mojaloop community software factory, this is where the bulk of +product development work happens. Typically there are many workstreams running in parallel, each focused on specific +areas or features of the platform. + +### Governance Model & Operating Requirements + +Mojaloop workstreams have a clearly defined governance model and operating requirements to minimize risks to all +stakeholders: + +1. Workstreams must have a clear and concise name which reflects their purpose. +2. Workstreams must have a named individual as leader at all times; in some circumstances the workstream lead position + may be shared by two individuals if neither has sufficient time to contribute. +3. Workstreams must have a named individual as a liaison with the Mojaloop Design Authority. This may be the same + individual(s) as the workstream leader or a different nominated individual. +4. Workstreams must publish and maintain a description which explains their purpose, objectives and scope for each + program increment on community central. +5. Workstreams must have a minimum of two named, active contributors. +6. Workstreams must operate a minimum of one online meeting per week. + 1. Workstream meetings should be considered open for other community members to observe. + 2. Workstream meetings should be recorded and recordings should be published publicly. +7. Workstreams with more than two active contributors should operate a scrum style stand-up online meeting. + 1. Stand-up meetings should be daily, unless the volume of work is low, in which case a less frequent cadence may + be acceptable. +8. Workstreams must maintain a public github repository containing all related code, documentation and work items. +9. Workstreams must adhere to all [Mojaloop design and code review processes](./design-review.md) before, during + and after work has been completed. +10. Workstreams must obtain and use a specific hashtag on community central when making posts. +11. Workstreams must be reviewed by the Mojaloop Product Council before commencement of each program increment. + 1. Workstream objectives must be aligned with the Mojaloop product roadmap. + 2. Workstream objectives must be aligned with the mission of the Mojaloop Foundation. + +### Workstream Leadership Criteria and Responsibilities + +The Mojaloop Foundation appoints leads who are typically volunteers from the community with a high level of relevant +expertise or experience. + +To qualify as a workstream (co)lead, individuals should meet the following criteria: + +1. Commitment and ability to fulfil all workstream lead responsibilities (see below). +2. Demonstrable organizational ability. +3. Demonstrable leadership ability. +4. Demonstrable relevant technical ability. +5. Familiarity with Mojaloop ecosystem. +6. Commitment for the duration of the PI. +7. Commitment to and adherence to the Mojaloop Code of conduct + +Workstream (co)leads must accept the following responsibilities: + +1. To be a primary point of contact for queries. +2. To schedule, hold, record and publish recordings and minutes of workstream meetings. +3. To facilitate liaison between workstream contributors, other workstreams and the rest of the community. +4. To create, publish on community central and maintain a workstream team charter document. +5. Report Progress to... + 1. ...the community regularly on Community Central using assigned hashtag. + 2. ...the Product Manager/Product Council. +6. Ensure all work items adhere to all [Mojaloop design and code review processes](./design-review.md) before, during + and after work has completed. +7. Ensure all work adheres to Mojaloop quality standards such as style, test coverage and documentation. +8. Ensure all work is tracked in GitHub/Zenhub and timelines and progress are updated. +9. Ensure all technical output is tested by the core team before integration into the official release process. For + non-technical workstreams output should be reviewed by the Mojaloop Foundation Product Director. +10. Facilitate building new features and write code as necessary. +11. Triage/review contributions, issues, and respond to users. +12. File bug reports / fixes and resolve conflicts in the workstream. +13. Proactively manage technical debt and improve existing code, while adhering to + all [Mojaloop design and code review processes](./design-review.md). +14. Ensure documentation meets the required standards. +15. Guide the workstream strategic direction in collaboration with the Mojaloop Foundation Product Director and Product + Council. +16. Define SMART objectives at the beginning of each PI. + +### Defining Work + +Workstreams must define and record publicly, via github/zenhub issues, the work they plan to undertake and the +progress they make during implementation: + +1. Work items must be recorded in GitHub as project issues; use of zenhub is not mandatory but is highly encouraged. + 1. Each workstream has its own GitHub project and zenhub workspace for managing work items. +2. Work items, also known as "user stories", should be defined in + the “As a... I want to... So That...” + [behaviour driven development style](https://www.agilealliance.org/glossary/user-story-template/). +3. Work items should include detailed acceptance criteria defined in the "given, when, + then" [behaviour driven development style](https://www.agilealliance.org/glossary/given-when-then/). +4. Work items must be sized so the expected duration of any item or sub item does not exceed a single two week sprint. +5. Work items must adhere to all [Mojaloop design and code review processes](./design-review.md) before, during and + after work has completed. Where design review is required, "spike" tickets should be used to track the design process + before work item tickets are created. + 1. All required design documentation must be approved by the Mojaloop Design Authority before work commences. + +A github/zenhub ticket template is available here: [github-work-item-template.docx](github-work-item-template.docx) + +### Getting Work Done + +Mojaloop workstreams should follow a [scrum](https://www.scrum.org/resources/what-scrum-module)-like process model by +default, running over a two-week sprint cadence. Given the stringent risk management requirements of our users +regulatory environments and best demonstrated practice for financial software, our day-to-day process differs from some +typical agile methodologies in that we implement mandatory oversight functions and stricter change control mechanisms, +more typical of larger technical organisations building and operating critical infrastructure. + +Workstreams have flexibility to adjust working methods to suit their particular circumstances, within sensible +boundaries appropriate for our mission and regulatory domain. The Mojaloop Foundation provides guidance to workstreams +to ensure they remain within our required operating standards. + +Workstreams should operate regular scheduled standup, backlog refinement, sprint planning, sprint review and +retrospective activities. + +![Mojaloop Workstream Sprint Process](./assets/mojaloop-workstream-sprint-process.jpg) + +It is required that every workstream define and maintain a "team charter" document to clearly and unambiguously +communicate agreed ways of working for all contributors. + +A workstream team charter template is available for download +here: [mojaloop-workstream-team-charter-template.pptx](assets/mojaloop-workstream-team-charter-template.pptx) + +### Getting Support + +When things do not go to plan and a resolution cannot be found among workstream contributors, the Mojaloop Foundation +provides support mechanisms. Please contact the Mojaloop Foundation Director of Community who will guide you to find a +resolution. + +## Non-Official Workstreams and External Contributions + +When an appropriate existing workstream may not exist and support is not sufficient to warrant creation of a new +official workstream, contributors may decide to work on features or changes externally to the community processes. In +these circumstances +our [external donation process](../standards/guide.md#adopting-open-source-contributions-into-mojaloop) must be followed +before code, documentation or other artifacts can be adopted by the Mojaloop Foundation. + +Please note that all work done outside of official Mojaloop workstream processes is subject to +our [external donation process](../standards/guide.md#adopting-open-source-contributions-into-mojaloop). This is to +ensure an appropriate amount of rigorous review to ensure our standards are met before inclusion in any official +Mojaloop release. \ No newline at end of file diff --git a/docs/community/contributing/signing-the-cla.md b/docs/community/contributing/signing-the-cla.md new file mode 100644 index 000000000..a07b97826 --- /dev/null +++ b/docs/community/contributing/signing-the-cla.md @@ -0,0 +1,97 @@ +# Signing the CLA + +Mojaloop has a [Contributor License Agreement (CLA)](https://github.com/mojaloop/mojaloop/blob/master/CONTRIBUTOR_LICENSE_AGREEMENT.md) which clarifies the intellectual property rights for contributions from individuals or entities. + +To ensure every developer has signed the CLA, we use [CLA Assistant](https://cla-assistant.io/), a well maintained, open source tool which checks to make sure that a contributor has signed the CLA before allowing a pull request to be merged. + +## How to sign the CLA + +1. Open a pull request to any Mojaloop repository +2. When the pull request performs the standard checks, you will see the `license/cla` check has run, and requests users to sign the CLA: + + + +3. Click 'Details', and you will be directed to the CLA Assistant tool, where you can read the CLA, fill out some personal details, and sign it. + + +
+ + + +4. Once you have clicked "I agree", navigate back to the Pull request, and see that the CLA Assistant check has passed. + + + + + +### Signing For A Company + +Section 3 of the [Mojaloop CLA](https://github.com/mojaloop/mojaloop/blob/master/CONTRIBUTOR_LICENSE_AGREEMENT.md) covers contributions both from individuals and contributions made by individuals on behalf of their employer. If you are contributing to the Mojaloop Community on behalf of your employer, please enter your employer's name in the "Company or Organization" field. If not, feel free to write "OSS Contributor" and leave the "role" field blank. + + +## Administering the CLA tool + +The CLA Tool is easy to install, any GitHub admin can link it with the Mojaloop organization. + +1. Create a new GitHub Gist and enter in the text of the CLA in a new file. +> Since Github doesn't allow Gists to be owned my organizations, [our gist](https://gist.github.com/mojaloopci/9b7133e1ac153a097ae4ff893add8974) is owned by the 'mojaloopci' user. + +2. Go to [CLA Assistant](https://cla-assistant.io/) and click "Sign in with GitHub" + + + +3. You can add a CLA to either a Repo or Organization. Select "Mojaloop", and then select the gist you just created + + + +4. Hit "Link" and that's it! + + +### Requesting Additional Information: + +> Reference: [request-more-information-from-the-cla-signer](https://github.com/cla-assistant/cla-assistant#request-more-information-from-the-cla-signer) + +You can also add a `metadata` file to the CLA gist, to build a custom form for the CLA tool: + +```json +{ + "name": { + "title": "Full Name", + "type": "string", + "githubKey": "name" + }, + "email": { + "title": "E-Mail", + "type": "string", + "githubKey": "email", + "required": true + }, + "country": { + "title": "Country you are based in", + "type": "string", + "required": true + }, + "company": { + "title": "Company or Organization", + "description": "If you're not affiliated with any, please write 'OSS Contributor'", + "type": "string", + "required": true + }, + "role": { + "title": "Your Role", + "description": "What is your role in your company/organization? Skip this if you're not affiliated with any", + "type": "string", + "required": false + }, + "agreement": { + "title": "I have read and agree to the CLA", + "type": "boolean", + "required": true + } +} +``` + +Produces the following form: + + + diff --git a/contributors-guide/documentation/api-documentation.md b/docs/community/documentation/api-documentation.md similarity index 100% rename from contributors-guide/documentation/api-documentation.md rename to docs/community/documentation/api-documentation.md diff --git a/docs/community/documentation/standards.md b/docs/community/documentation/standards.md new file mode 100644 index 000000000..fdc339691 --- /dev/null +++ b/docs/community/documentation/standards.md @@ -0,0 +1,29 @@ +# Documentation + +### Overview + +Mojaloop has set forward several standards to ensure that documentation throughout the project is consistent and kept up to date. + +* All documentation that is relevant for contributors is kept on the "documentation" repository. +* The "documentation" repository is sync'ed with GitBook and all content is consumed in an easily readable format on: [https://www.gitbook.com/mojaloop](https://www.gitbook.com/mojaloop) +* All documentation should include: + * Overview: business overview to provide the value or reason for the documentation page + * Details: appropriate summary information to support the documentation + +### + +[Documentation standards](https://github.com/mojaloop/mojaloop/blob/master/contribute/Documentation-and-Template-Standards.md) + +### Documentation Style Guide + +All new documentation should confirm to the documentation and styles as discussed [here](style-guide.md). + +### Code Style Guide + +#### NodeJS + +We follow the [Standard style guidelines](https://github.com/feross/standard). Add `npm install standard` to you package.json. + +#### Java + +For Java we follow [Checkstyle](http://checkstyle.sourceforge.net/).Code Quality Metrics diff --git a/contributors-guide/documentation/documentation-style-guide.md b/docs/community/documentation/style-guide.md similarity index 100% rename from contributors-guide/documentation/documentation-style-guide.md rename to docs/community/documentation/style-guide.md diff --git a/docs/community/faqs.md b/docs/community/faqs.md new file mode 100644 index 000000000..71ac45b77 --- /dev/null +++ b/docs/community/faqs.md @@ -0,0 +1,9 @@ +# Using Vue in Markdown + +## Browser API Access Restrictions + +Because VuePress applications are server-rendered in Node.js when generating static builds, any Vue usage must conform to the [universal code requirements](https://ssr.vuejs.org/en/universal.html). In short, make sure to only access Browser / DOM APIs in `beforeMount` or `mounted` hooks. + +If you are using or demoing components that are not SSR friendly (for example containing custom directives), you can wrap them inside the built-in `` component: + +## diff --git a/mojaloop-publications.md b/docs/community/mojaloop-publications.md similarity index 100% rename from mojaloop-publications.md rename to docs/community/mojaloop-publications.md diff --git a/docs/community/mojaloop-roadmap.md b/docs/community/mojaloop-roadmap.md new file mode 100644 index 000000000..776706bf4 --- /dev/null +++ b/docs/community/mojaloop-roadmap.md @@ -0,0 +1,53 @@ +# The Mojaloop Roadmap + +The Mojaloop Roadmap is developed and maintained by the Mojaloop foundation, in collaboration with the wider Community. It is reviewed and updated at each Community Meeting, and was last updated at the PI 23 Community meeting in Lusaka, Zambia. + +The roadmap is built around the concept of three pillars.

+ +The Pillars are: + +1. **Make Adoption Easier** – create tools to allow developers and adopters to deploy Mojaloop with minimum fuss and complication, in an environment which meets their technical, operational or regulatory needs. +2. **Achieve Scale** – make available as many “value add” functions as possible, in order to support adopters as they seek to achieve their goals, be these financial profitability or support of social aims; or indeed both. +3. **Connect to Other Systems** – We recognise that Mojaloop is not the only payments interoperability solution, so under this pillar we seek to develop as many options as possible to both interconnect with other payment services and switches, and to ensure that the underlying Mojaloop engine is optimised to support those interconnections. + +The Pillars are themselves supported by a foundational **Quality Product** set of workstreams, which together support the continuing maintenance and enhancement of the Core Mojaloop solution. + +This is the full roadmap for PI-23: ![Mojaloop Roadmap](https://github.com/mojaloop/product-council/blob/main/PI%2023%20Mojaloop%20Roadmap.png?raw=true). + +This revision of the Roadmap extends from the release of Mojaloop 15.1 at the end of PI 21 (June 2023), to the end of PI 26 (February 2025). Mojaloop releases moved from numbering to names during PI 22, so we have Mojaloop Acacia about to be released; this will be followed by Mojaloop Zambezi, at the end of PI 23, building on Acacia and incorporating the outputs of workstreams including Merchant Payments and Foreign Exchange (international transfers). + +We currently anticipate releasing Mojaloop Baobab, based on the vNext development effort and the Reference architecture, at the end of PI 24, the end of June 2024 (though this remains subject to achieving the necessary level of quality and functionality, to be achieved through a transition process which has its own roadmap). In turn, this will be replaced by Mojaloop Meerkat at the end of October 2024, which builds on Baobab by adding the outputs of workstreams that are as yet undefined. Further releases will follow the same process. + +On the right of the Roadmap there are four tables. These list candidate workstreams for each pillar and the quality product foundation. These have been established as desirable features at various Community events, but they have not yet been adopted by the Community. + +All of the Pillars have their own workstreams. For PI 23, the following technical workstreams have been adopted. + +## Make Adoption Easier +* Support for On Premise Deployment + * Improve support for non-Cloud deployment of Mojaloop, where this is required due to regulatory or other reasons +* Participation Tools + * Ensure there is a range of options for Participating DFSPs to connect to a Mojaloop Hub, and that these options off comparable connectivity capabilities + +## Achieve Scale +* Merchant Payments + * Support for merchant payments using a Mojaloop Hub as the payments element for a merchant scheme that offers payments through either QR codes or USSD. This includes merchant registration and support for merchant acquiring. + +## Connect to Other Systems +* Next Generation Settlement + * Connecting to other payments systems and conducting cross-border transactions increases the complexity of settlement processes needed by a switch, and this workstream is updating Mojaloop’s settlement engine to provide the necessary flexibility. +* Foreign Exchange + * This workstream is enhancing the Mojaloop Hub to support multi-currency transactions, through integration with an external FX Provider (FXP). The initial version will support one model (sender converts) and one FXP; future versions will support multiple models, multiple FXPs, and the use of a reserve currency as intermediary. +* MOSIP Integration + * In order to better support social payments and national payments programs, this workstream is developing a solution which will allow payments to be routed to a MOSIP digital identity, instead of for example a mobile phone number. This workstream also works towards greater integration with other open source DPG projects, including Mifos, PHEE and OpenG2P, in support of using MOSIP IDs to generate payments lists for bulk delivery of social payments. +## Quality Product +* Performance Characterisation + * Identify and implement changes to the Mojaloop Hub core software that can improve performance, as we move towards a number of national deployments. +* Adopt Tigerbeetle + * Use Tigerbeetle for ledger updates during transaction processing to achieve even greater performance (we don’t expect his to be in place before the release of Mojaloop Baobab) +* Core Team + * Maintains the Mojaloop core through fixes to critical bugs, prioritized feature enhancements and upgrades in dependencies, and undertakes the Release process of the core services and some adjacent services or products that are part of the Mojaloop Platform. +* Platform Quality and Security + * Assessment, maintenance and enhancement of the cybersecurity of the Mojaloop platform, encompassing connectivity to participating DFSPs (including transactions) and the security of hub operator portals. + +In addition to these technical workstreams, we have a number of **Strategic Workstreams**, which are intended to address long term, strategic issues, such as a migration to supporting ISO 20022, or monitoring developments in cross-border transactions. It is expected that the outputs of strategic workstreams will include the periodic specification of candidate technical workstreams, for potential adoption in future PIs. + diff --git a/docs/community/standards/creating-new-features.md b/docs/community/standards/creating-new-features.md new file mode 100644 index 000000000..fbde9bc55 --- /dev/null +++ b/docs/community/standards/creating-new-features.md @@ -0,0 +1,205 @@ +# Creating new Features + +## Fork + +Fork the Mojaloop repository into your own personal space. Ensure that you keep the `master` branch in sync. + +Refer to the following documentation for more information: [https://help.github.com/articles/fork-a-repo/](https://help.github.com/articles/fork-a-repo/) + +1. Clone repo using Git Fork button \(refer to the above documentation for more information\) +2. Clone your forked repo: `git clone https://github.com//.git` +3. Synchronise your forked repo with Mojaloop + + Add a new upstream repo for Mojaloop `$ git remote add mojaloop https://github.com/mojaloop/.git` + + You should now see that you have two remotes: + + ```bash + git remote -v + origin https://github.com//.git (fetch) + origin https://github.com//.git (push) + mojaloop https://github.com/mojaloop/.git (fetch) + mojaloop https://github.com/mojaloop/.git (push) + ``` + +4. To sync to your current branch: `git pull mojaloop ` This will merge any changes from Mojaloop's repo into your forked repo. +5. Push the changes back to your remote fork: `git push origin ` + +## Creating a Branch + +Create a new branch from the `master` branch with the following format: `/` where `issue#` can be attained from the Github issue, and the `issueDescription` is the issue description formatted in CamelCase. + +1. Create and checkout the branch: `git checkout -b /` +2. Push the branch to your remote: `git push origin /` + +Where `` can be one of the following: + +| branchType | Description | +| :--- | :--- | +| hotfix | A `hotfix` branch is for any urgent fixes. | +| feature | A `development` branch for new or maintenance features that are in active development. | +| fix | A `development` branch that is used to fix a bug. | +| release | A release branch containing a snapshot of a release. | +| backup | A temporary backup branch. Used normally during repo maintenance. | +| major | A `pre-release` branch for major changes. | +| minor | A `pre-release` branch for minor changes. | +| patch | A `pre-release` branch for patch changes. | + +## Main branch + +The main branch must always contain code that is suitable for deployment. +Build automation tools will try to build and test code from this branch and +tag this branch with semver based version tags on success. The resulting +artifacts will be also published on respective repositories (npm, docker, etc.), +so that they can be used by other modules. + +## Hotfix branches + +These branches are created from a tag on main branch, when the corresponding +version has been deployed in production and an issue must be fixed and at the +same time main branch has newer published versions or undergoing development, +where this fix cannot be included in a timely and stable way. These branches are +named by using the pattern `hotfix/`. It is highly +recommended that the fix be first committed in main (or another branch that is +going to be merged to main) and then cherry-picked in the hotfix branch. Hot-fix +branches are usually not merged to main and not deleted, as they may be used +for subsequent fixes. On hot-fix branches build automation tools will create +tags and publish corresponding packages by increasing only the patch version number. + +## Prerelease branches + +Prerelease branches are used when the development process requires artifacts +to be available in the repository for either automated or manual testing of +in-progress features or fixes, that are not ready for a release. +These branches are used to avoid the manual work associated with publishing +in repositories. The published artifacts will have prerelease versions and tags, +as specified by semver. Build automation tools will create and publish these +prerelease versions in the package repository and tag the branch in the git +repository for each commit that is successfully built. Prerelease branches are +usually created from the main branch and later merged into it. The patterns +for prerelease branches are: + +- `major/` - when a branch is expected to include + breaking changes. +- `minor/` - when a branch is expected to include + only new features and no breaking changes. This is the most common kind of + branch, where all new development happens. +- `patch/` - when a branch is expected to include + only fixes and no new features or breaking changes. These can sometimes be + created from hotfix branches, when fixes need to be first published for tests, + before being merged in the hotfix branch. + +The build scripts will automatically publish a prerelease version and tag using +`` as the prerelease identifier, followed by a +sequential number, i.e. something like +`X.Y.Z-.sequence`, where X, Y or Z will be auto +increment once for the first build of the branch, depending on the +major/minor/patch prefix of the branch name and `sequence` will be incremented +on each successful build. For the prerelease branches it is important to ensure +`` complies with the prerelease identifier rules +specified by semver. Sometimes a minor prerelease branch can eventually +include a breaking change, in which case the developers must ensure that +there is no parallel active development happening on another major +branch, as this may end up with both branches trying to release the same major +version. In general, developers should be careful when multiple prerelease +branches are being developed and ensure the version being released in the end +does not conflict with other prerelease branches. In such cases a manual edit +of the version may be needed while resolving a merge conflict for the version property. + +## Development branches + +These branches are used primarily for development of new features, when no +artifacts need to be published to package repositories until the branch is +merged. They are created from the main or prerelease branches. Names of these +branches must not match any of the patterns described above. The frequently +used ones are `feature/` or +`fix/`. Development branches can later +be renamed to prerelease ones, if the development process requires it. Using a +development branch instead of a prerelease branch helps avoid excessive +publishing of artifacts and tags, which take more time and clutter the repository. + +## Working on your Feature + +Before you start working on your Feature, please run through following steps to help ensure Mojaloop's code-base is well maintained and protected against security issues, note that some of these steps will be required for your Pull-Request (*PR*) to pass CI validation checks (as indicated below). + +It is recommended that `npm test` is executed after each of these steps to ensure that no breaking-changes have been introduced. + +1. REQUIRED - Update dependencies + + ```bash + npm run dep:check + ``` + + > + > IMPORTANT + > + > Take note of any Dependencies that have Major Version upgrades, as they may introduce a BREAKING CHANGE. This may require some code-refactoring to accommodate the change. + > + > Refer to [Dependency Management](./guide#dependency-upgrades) on how dependency upgrades can be ignored if/when required. + > + + Run the following to update and install the dependencies + + ```bash + npm run dep:update && npm i + ``` + +2. REQUIRED - Vulnerability Checks + + ```bash + npm run audit:check + ``` + +[npm audit](https://docs.npmjs.com/cli/v8/commands/npm-audit) can be used to apply any known available fixes: + + ```bash + npm audit fix --package-lock-only + ``` + + > + > IMPORTANT + > + > Take note of any Dependencies that have Version changes, as they may introduce a BREAKING CHANGE. + > + > Refer to [Dependency Management](./guide#dependency-auditing) for more information. + > + + If there is no available working fix for the vulnerability issue, you will need to do one of the following: + + 1. If the repo is using [audit-ci](https://www.npmjs.com/package/audit-ci) - update `audit-ci.jsonc` with the issue by adding it to the `allowlist`, and ensure that you add a comment indicating the reason. + 2. If the repo is using [npm-audit-resolver](https://www.npmjs.com/package/npm-audit-resolver) - Run `npm run audit:resolve` and follow the CLI prompts to try fix or ignore the issue (if there is no fix available) + +3. OPTIONAL - Update NodeJS to `Active LTS` version + + Check the `Active LTS` version as per [Official NodeJS Releases](https://nodejs.org/en/about/releases). + + 1. Update `.nvmrc` + + 2. Update `Dockerfile` (for both the *builder* and *runtime* containers), ref [Runtime Environment - 2.Container (Docker) Operating System (*OS*)](./guide.md#runtime-environment). + + > + > IMPORTANT + > + > Take note that upgrading the NodeJS version may introduce a BREAKING CHANGE. This may require some code-refactoring to accommodate the change. + > + +## Open a Pull Request (PR) + +Once your feature is ready for review, create a Pull Request from you feature branch back into the `master` branch on the Mojaloop Repository. If you're new to GitHub or Pull Requests, take a look at [this guide](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests) for more information. + +### Pull Request Titles + +Mojaloop uses [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) to help our automated tooling manage releases and deployments. Your Pull Request title _must_conform to the conventional commits specification to pass the CI/CD checks in CircleCI. + +By adopting Conventional Commits + Semantic Versioning we can automatically release a new version for a given component and increment the `MAJOR`, `MINOR` and `BUGFIX` versions based soley on the PR titles, and auto generate rich changelogs. (See [this example](https://github.com/mojaloop/thirdparty-scheme-adapter/releases/tag/v11.20.0) of an auto generated changelog) + +> **Note**: +> When merging (and squashing) a PR, GitHub uses the *title* of the PR for the git commit message. This means that to specify a breaking change, you must use the `!` format: +> "If included in the type/scope prefix, breaking changes MUST be indicated by a ! immediately before the :. If ! is used, BREAKING CHANGE: MAY be omitted from the footer section, and the commit description SHALL be used to describe the breaking change." + +#### Examples of good PR titles + +- feat(api): add ability to handle `PUT /thirdpartyRequests/trasactions/{ID}` endpoint +- fix: update outdated node modules +- feat(models)!: change database schema +- chore: tidy up readme diff --git a/docs/community/standards/guide.md b/docs/community/standards/guide.md new file mode 100644 index 000000000..21b535515 --- /dev/null +++ b/docs/community/standards/guide.md @@ -0,0 +1,653 @@ +# Standards + +> *Note:* These standards are by no means set in stone, and as a community, we always want to be iterating and improving Mojaloop. If you want to propose a change to these standards, or suggest further improvements, please reach out to the Design Authority Channel on the Mojaloop Slack (#design-authority) + +## Mojaloop Invariants + +Mojaloop has some [invariants](./invariants.md) that are important to understand and adhere to when contributing to the codebase. + +These invariants are derived from [The Level One Principles](https://www.leveloneproject.org/wp-content/uploads/2020/07/L1P_Guide_2019_Final.pdf) and other business requirements as decided upon by the Mojaloop Technical Governance Board, API Change Control Board, Design Authority and Product Council. They are intended to ensure the platform retains certain characteristics important for national infrastructure grade operation. + +Please ensure you are familiar with the invariants before contributing to the codebase. + +## Runtime Environment + +The following runtime standards apply to Mojaloop. + +### Micro-services & Libraries + +1. Javascript + + NodeJS is the standard Runtime for all Mojaloop services and components for the execution of Javascript source-code files. + + Our goal is to ensure that all NodeJS based services run against the latest `Active LTS` (*Long Time Support*) version of NodeJS following the official [NodeJS Release Cycle](https://nodejs.org/en/about/releases/). + +2. Container (Docker) Operating System (*OS*) + + Mojaloop's Micro-services are built on top of the `node:-alpine` base image, where `NODE_ACTIVE_LTS_VERSION` is the current NodeJS LTS following the official [NodeJS Release Cycle](https://nodejs.org/en/about/releases/). Refer to [DockerHub](https://hub.docker.com/_/node?tab=tags&page=1&name=alpine) for a full list of official NodeJS Alpine Docker images. + + > NOTE: When specifying the `NODE_ACTIVE_LTS_VERSION`, use the full semantic version such as `--`. + > + > `node:16.15.0-alpine ` <-- This is OK + > + > `lts-alpine3.16` <-- This is NOT OK + > + + 1. Standard **Javascript** `Dockerfile` example: + + ```docker + FROM node:-alpine as builder + WORKDIR /opt/app + + RUN apk --no-cache add git + RUN apk add --no-cache -t build-dependencies make gcc g++ python3 libtool libressl-dev openssl-dev autoconf automake \ + && cd $(npm root -g)/npm \ + && npm config set unsafe-perm true \ + && npm install -g node-gyp + + COPY package*.json /opt/app/ + + RUN npm ci --production + + FROM node:-alpine + WORKDIR /opt/app + + # Create empty log file & link stdout to the application log file + RUN mkdir ./logs && touch ./logs/combined.log + RUN ln -sf /dev/stdout ./logs/combined.log + + # Create a non-root user: ml-user + RUN adduser -D ml-user + USER ml-user + + # Copy builder artefact + COPY --chown=ml-user --from=builder /opt/app . + + # Copy source files + COPY src /opt/app/src + + # Copy default config + COPY config /opt/app/config + + EXPOSE + CMD ["npm", "run", "start"] + ``` + + 2. Standard **Typescript** `Dockerfile` example: + + ```docker + FROM node:-alpine as builder + USER root + WORKDIR /opt/app + + RUN apk update \ + && apk add --no-cache -t build-dependencies git make gcc g++ python3 libtool autoconf automake openssh \ + && cd $(npm root -g)/npm \ + && npm config set unsafe-perm true \ + && npm install -g node-gyp + + COPY package.json package-lock.json* ./ + + RUN npm ci + + FROM node:-alpine + WORKDIR /opt/app + + # Create empty log file & link stdout to the application log file + RUN mkdir ./logs && touch ./logs/combined.log + RUN ln -sf /dev/stdout ./logs/combined.log + + # Create a non-root user: ml-user + RUN adduser -D ml-user + USER ml-user + + # Copy builder artefact + COPY --chown=ml-user --from=builder /opt/app ./ + + COPY src /opt/app/src + COPY config /opt/app/config + + # NPM script to build source (./src) to destination (./dist) + RUN npm run build + + # Prune devDependencies + RUN npm prune --production + + # Prune source files + RUN rm -rf src + + EXPOSE + CMD ["npm", "run", "start"] + ``` + +### CI (*Continuos Integration*) Pipelines + +Mojaloop's CI Jobs are executed against the current Ubuntu LTS version following the official [Ubuntu Release Cycle](https://ubuntu.com/about/release-cycle). + +### Kubernetes + +Mojaloop's Helm Charts ([mojaloop/helm](https://github.com/mojaloop/helm) [mojaloop/charts](https://github.com/mojaloop/charts)) are deployed and verified against the current Kubernetes LTS version following the official [Kubernetes Release Cycle](https://kubernetes.io/releases/). + +## Style Guide + +The Mojaloop Community provides a set of guidelines for the style of code we write. These standards help ensure that the Mojaloop codebase remains high quality, maintainable and consistent. + +These style guides are chosen because they can be easily enforced and checked using popular tools with minimal customization. While we recognise that developers will have personal preferences that may conflict with these guidelines we favour consistency over [bike-shedding](https://en.wikipedia.org/wiki/Law_of_triviality) these rules. + +The goal of these guides is to ensure an easy developer workflow and reduce code commits that contain changes for the sake of style over content. By reducing the noise in diffs we make the job of reviewers easier. + +## Code Style + +### Naming Conventions + +To avoid confusion and guarantee cross-language interpolation, follow these rules regarding naming conventions: + +- Do not use abbreviations or contractions as parts of identifier names. For example, use `SettlementWindow` instead of `SetWin`. +- Do not use acronyms that are not generally accepted in the computing field. +- Where appropriate, use well-known acronyms to replace lengthy phrase names. For example, use `UI` for `User Interface`. +- Use Pascal case or camel case for names more than two characters long depending on context (e.g. class names vs variable names). For example, use `SettlementWindow` (Class) or `settlementWindow` (Variable). +- You should capitalize abbreviations that consist of only two characters, such as `ID` instead of `Id` when isolated. For example, use `/transfer/{{ID}}` instead of `/transfer/{{Id}}` when representing `ID` as a URI parameter. +- Avoid abbreviations in identifiers or parameter names. If you must use abbreviations, use camel case for abbreviations that consist of more than two characters, even if this contradicts the standard abbreviation of the word. +- Use screaming (capitalized) Snake case for Enumerations. For example, use `RECORD_FUNDS_OUT_PREPARE_RESERVE`. + +Ref: [Microsoft - Design Guidelines for Class Library Developers](https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-1.1/141e06ef(v=vs.71)?redirectedfrom=MSDN) + +### Javascript + +Mojaloop uses the Javascript code style dictated by [StandardJS](https://standardjs.com/). For a full set of rules, refer to the [Standard Rules](https://standardjs.com/rules.html), but as a brief set of highlights: + +- Use *2 spaces* for indentation + +```js +function helloWorld (name) { + console.log('hi', name) +} +``` + +- Use *single quotes* for strings except to avoid escaping. + +```js +console.log('hello there') // ✓ ok +console.log("hello there") // ✗ avoid +console.log(`hello there`) // ✗ avoid +``` + +- No semicolons. (see: 1, 2, 3) + +```js +window.alert('hi') // ✓ ok +window.alert('hi'); // ✗ avoid +``` + +### Typescript + +> *Note: Standard and Typescript* +> +> As we start to introduce more Typescript into the codebase, Standard becomes less useful, and can even be detrimental +> to our development workflow if we try to run standard across the Javascript compiled from Typescript. +> We need to evaluate other options for Standard in Typescript, such as a combination of Prettier + ESLint. + +Refer to the [template-typescript-public](https://github.com/mojaloop/template-typescript-public) for the standard typescript configuration. + +### YAML + +While YAML deserializers can vary from one to another, we follow the following rules when writing YAML: +> Credit: these examples were taken from the [flathub style guide](https://github.com/flathub/flathub/wiki/YAML-Style-Guide) + +- 2 space indents +- Always indent child elements + +```yaml +# GOOD: +modules: + - name: foo + sources: + - type: bar + +# BAD: +modules: +- name: foo + sources: + - type: bar +``` + +- Do not align values + +```yaml +# BAD: +id: org.example.Foo +modules: + - name: foo + sources: + - type: git +``` + +### sh + bash + +- The Shebang should respect the user's local environment: + +```bash +#!/usr/bin/env bash +``` + +This ensures that the script will match the `bash` that is defined in the user's environment, instead of hardcoding to a specific bash at `/usr/bin/bash`. + +- When referring to other files, don't use relative paths: + +This is because your script will likely break if somebody runs it from a different directory from where the script is located + +```bash +# BAD: +cat ../Dockerfile | wc -l + +# GOOD: +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cat ${DIR}/../Dockerfile | wc -l +``` + +For other recommended bash conventions, refer to this blog post: [Best Practices for Writing Shell Scripts](https://kvz.io/bash-best-practices.html) + +## Documentation + +- Documentation should be written in Markdown format. +- Hand drawn diagrams should use an editable SVG format (example - architecture / component / block / state transition diagrams) exported from [diagrams.net](https://app.diagrams.net) + > NOTE: Please ensure that you have imbedded the editable diagram when exporting the SVG from [diagrams.net](https://app.diagrams.net)! +- Sequence diagrams should use PlantUML +- All discussion documents should be placed in /community/archive/discussion-docs. +- The use of Google Docs and other private tools is not advised for community wide collaboration + +## Directory Structure + +Along with guidelines for coding styles, the Mojaloop Community recommends the following directory structure. This ensures that developers can easily switch from one project to another, and also ensures that our tools and configs (such as `.circleci/config.yml` and `Dockerfile`s) can be ported easily from one project to another with minor changes. + +The directory structure guide requires: + +```bash +├── README.md # README containing general information about components such as pre-requisites, testing, etc. +├── LICENSE.md # Standard Mojaloop License descriptor. +├── package.json # Project package descriptor. +├── package-lock.json # Project package descriptor describing an exact dependency tree in time. +├── nvmrc.json # NVMRC containing NodeJS runtime. This should preferably reflect the current NodeJS Active LTS version. +├── .ncurc.yaml # Ignore file for dep:check script (npm-check-updates). +├── Dockerfile # Optional - Dockerfile descriptor. +├── docker-compose.yml # Optional - Docker Compose descriptor, inc containing backend dependencies. +├── .npmignore # Optional - NPM ignore file for publishing libraries. +├── .gitignore # Github ignore file. +├── src # Directory containing project source files. +│  ├── index. # Main entry point for component. +│  ├── . # Source file format. +│  └── ... # Other source files and sub-directories +├── dist # Directory containing compiled javascript files (see tsconfig below). +├── test # Directory for tests, containing at least: +│  ├── unit # Unit tests, matching the directory structure in `./src`. +│  │ ├── .test. # Tests file format. +│ │  └── ... # Other test files and sub-directories +│  ├── integration # Integration tests, matching the directory structure in `./src`. +│  ├── functional # Functional tests, matching the directory structure in `./src`. +│  └── util # Generic testing scripts and NodeJS helpers. +└── config + └── default.json # Default config file. +``` + +## Config Files + +The following Config files help to enforce the code styles outlined above: + +### EditorConfig + +> EditorConfig is supported out of the box in many IDEs and Text editors. For more information, refer to the [EditorConfig guide](https://editorconfig.org/). + +`.editorconfig` + +```ini +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 + +[{*.js,*.ts,package.json,*.yml,*.cjson}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false +``` + +### NYC (code coverage tool) + +`.nycrc.yml` + +```yml +temp-directory: "./.nyc_output" +check-coverage: true +per-file: true +lines: 90 +statements: 90 +functions: 90 +branches: 90 +all: true +include: [ + "src/**/*.js" +] +reporter: [ + "lcov", + "text-summary" +] +exclude: [ + "**/node_modules/**", + '**/migrations/**' +] +``` + +### Typescript + +`.tsconfig.json` + +```json +{ + "include": [ + "src" + ], + "exclude": [ + "node_modules", + "**/*.spec.ts", + "test", + "lib", + "coverage" + ], + "compilerOptions": { + "target": "es2018", + "module": "commonjs", + "lib": [ + "esnext" + ], + "importHelpers": true, + "declaration": true, + "sourceMap": true, + "rootDir": "./src", + "outDir": "./dist", + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "moduleResolution": "node", + "baseUrl": "./", + "paths": { + "*": [ + "src/*", + "node_modules/*" + ] + }, + "esModuleInterop": true + } +} +``` + +`.eslintrc.js` + +```js +module.exports = { + parser: '@typescript-eslint/parser', // Specifies the ESLint parser + extends: [ + 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin + 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier + 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. + // Enforces ES6+ import/export syntax + 'plugin:import/errors', + 'plugin:import/warnings', + 'plugin:import/typescript', + ], + parserOptions: { + ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features + sourceType: 'module', // Allows for the use of imports + }, + rules: { + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off' + }, + overrides: [ + { + // Disable some rules that we abuse in unit tests. + files: ['test/**/*.ts'], + rules: { + '@typescript-eslint/explicit-function-return-type': 'off', + }, + }, + ], +}; +``` + +For a more detailed list of the recommended typescript configuration, including `package.json`, `jest.config.js` and more, refer to the [Typescript Template Project](https://github.com/mojaloop/template-typescript-public). + +## Dependency Management + +### Dependency Upgrades + +It is important to ensure that the latest Dependencies are used to mitigate security issues. + +#### NodeJS + +NodeJS projects should install [npm-check-updates](https://www.npmjs.com/package/npm-check-updates) using the following command: + +```bash +npm install -D npm-check-updates +``` + +And add the following scripts to `package.json`: + +```json +"scripts": { + "dep:check": "npx ncu -e 2", + "dep:update": "npx ncu -u" +} +``` + +Run the following script to check for any dependencies that need upgrading: + +```bash +npm run dep:check +``` + +If required, one can execute the following command to install the latest dependencies: + +```bash +npm run dep:update && npm i +``` + +If a dependency cannot be upgraded for a valid reason, then `.ncurc.yaml` file should added to the project root with said dependency added to the `reject` list with an appropriate `comment` as follows: + +```yaml +## Add a TODO comment indicating the reason for each rejected dependency upgrade added to this list, and what should be done to resolve it (i.e. handle it through a story, etc). +reject: [ + # TODO: + "", +] +``` + +The following approaches are utilized to enforce that dependencies are kept up-to-date: + +##### Git Pre-Commit Hook + +This will ensure that a validation check will occur on a Developer's local machine when making any Git Commits. + +The `dep:check` should be added as a git commit pre-hook using [Husky](https://www.npmjs.com/package/husky) as follows: + +```bash +npx husky add .husky/pre-commit "npm run dep:check" +``` + +> Note: It is possible to circumvent this by using `-n` parameter when committing using `git commit -nm `. A CI (*Continuous Integration*) `test-dependencies` Validation Check (*see next section*) is thus required to ensure enforcement. + +##### Automated CI Validations + +This will ensure that a validation check occur during reviews and releases, and also ensure that Git Pre-Commit Hook are not circumvented. + +CI Configs (i.e. `.circleci/config.yml`) must contain a `test-dependencies` Validation Check CI Job (i.e. `npm run dep:check`) for all Pull-Request, merges to Main branch, and Tagged Releases. + +### Dependency Auditing + +#### NodeJS + +NodeJS projects should install [audit-ci](https://www.npmjs.com/package/audit-ci) using the following command: + +```bash +npm install -D audit-ci +``` + +And add the following scripts to `package.json`: + +```json +"scripts": { + "audit:check": "npx audit-ci --config ./audit-ci.jsonc" +} +``` + +Run the following script to check for any dependencies that need upgrading: + +```bash +npm run audit:check +``` + +If required, one can execute [npm audit](https://docs.npmjs.com/cli/v8/commands/npm-audit) to apply any known available fixes: + +```bash +npm audit fix --package-lock-only +``` + +> +> NOTES +> +> 1. Ensure to commit any fixes applied by the above command to the `package-lock.json`. +> 2. Ensure that all tests pass after applying any fixes as they may result in a dependency version change which could introduce breaking changes. +> + +If there is no fix, then `audit-ci.jsonc` file should added to the project root with said `vulnerability advisories ID` added to the `allowlist` with an appropriate `comment` as follows: + +```json +{ + "$schema": "https://github.com/IBM/audit-ci/raw/main/docs/schema.json", + // audit-ci supports reading JSON, JSONC, and JSON5 config files. + // Only use one of ["low": true, "moderate": true, "high": true, "critical": true] + "moderate": true, + "allowlist": [ // NOTE: Please add as much information as possible to any items added to the allowList + // Currently no fixes available for the following advisory ID + "" + ] +} +``` + +##### Git Pre-Commit Hook + +This will ensure that a vulnerability checks will occur on a Developer's local machine when making any Git Commits. + +The `audit:check` should be added as a git commit pre-hook using [Husky](https://www.npmjs.com/package/husky) as follows: + +```bash +npx husky add .husky/pre-commit "npm run audit:check" +``` + +> Note: It is possible to circumvent this by using `-n` parameter when committing using `git commit -nm `. A CI (*Continuous Integration*) `vulnerability-check` vulnerability Check (*see next section*) is thus required to ensure enforcement. + +##### Automated CI Validations + +This will ensure that auditing checks occur during reviews and releases, and also ensure that Git Pre-Commit Hook are not circumvented. + +CI Configs (i.e. `.circleci/config.yml`) must contain a `vulnerability-check` vulnerability Check CI Job (i.e. `npm run dep:check`) for all Pull-Request, merges to Main branch, and Tagged Releases. + +## Design + Implementation Guidelines + +These guidelines are meant as recommendations for writing code in the Mojaloop community (or code that will be adopted into the community). If you are writing code that you wish to donate code to the community, we ask that you follow these guidelines as much as possible to aid with the consistency and maintainability of the codebase. Donations that adhere to these guidelines will be adopted more easily and swiftly. + +For more information, refer to the FAQ [below](#faqs). + +## Tools + Frameworks + +In the Mojaloop OSS Community, we are prefer the following tools and frameworks: + +- **Web Server:** [`HapiJS`](https://github.com/hapijs/hapi) +- **Web UI Framework:** [`ReactJS`](https://reactjs.org/) +- **Runtime Configuration:** [`convict`](https://www.npmjs.com/package/convict), with [`rc`](https://www.npmjs.com/package/rc) for legacy. (both for env variables and config files) +- **Package Management:** `npm` +- **Logging:** [`@mojaloop/central-services-logger`](https://github.com/mojaloop/central-services-logger#readme) library, built on top of Winston +- **Containers and Orchestration:** [`docker`](https://www.docker.com/) and [`kubernetes`](https://kubernetes.io/) +- **Unit Testing:** For existing tests, [`Tape`](https://github.com/substack/tape), but we are currently moving over to [`Jest`](https://jestjs.io/) for new codebases. +- **Test Coverage:** [`nyc`](https://github.com/istanbuljs/nyc) +- **CI:** [`CircleCI`](https://circleci.com/) + +By using these tools and frameworks, we maintain a high level of consistency and maintainability across the codebase, which keeps our developers productive and happy. While we don't mandate that donated codebases use these same tools and frameworks, we would like to stress that adoptions that use different tools could create an undue maintenance burden on the Community. + +## Adopting Open Source Contributions into Mojaloop + +This section provides guidelines regarding the adoption of a contribution to the Mojaloop Open Source repositories. Adoption is the process where we as the community work with a contributor to bring a contribution into alignment with our standards and guidelines to be a part of the Mojaloop OSS Codebase. + +>*Note:* Code Contributions are evaluated on a **case-by-case** basis. Contributions that don't align to these guidelines will need to go through the incubation phase as described below. Other misalignments to these standards (for example, framework choices) may be added to a roadmap for further improvement and OSS Standardization in the future. + +### Step 0: Prerequisites + +Before a contribution is to be considered for adoption, it: + +1. Should be in-line with the [Level One Project Principles](https://leveloneproject.org/). +1. Should adhere to the above Style and Design + Implementation Guides. +1. Should contain documentation to get started: the more, the better. +1. Contain tests with a high level of coverage. At a minimum, a contribution should contain unit tests, but a test suite with unit, integration and functional tests is preferred. Refer to the [contributors guide](./tools-and-technologies/automated-testing) for more information. + +### Step 1: Incubation + +1. Create a private repo within the Mojaloop GitHub organization for the adopted code. +1. Have a sub-team of the DA take a look to make sure its portable \(to OSS\) - aligns with L1P principles, etc, and ensure design is in line with standards. +1. Check Licensing of the contribution and any new dependencies it requires, and add the standard Mojaloop License with attribution to donor/contributors. +1. Assess the current state of the codebase, including documentation, tests, code quality, and address any shortfalls. +1. Assess Performance impact. +1. Create action items \(stories\) to update naming, remove/sanitize any items that are not generic +1. Inspect and discuss any framework and tooling choices. + +- If a decision is made to make any changes, add them to the roadmap. + +### Step 2: Public Adoption + +1. Make the project public on Mojaloop GitHub. +1. Announce on the slack [`#announcements`](https://mojaloop.slack.com/archives/CG3MAJZ5J) channel. +1. Enable CI/CD Pipelines and publish any relevant artifacts, such as Docker Images or npm modules. +1. Review and recommend a module or course for the Mojaloop Training Program if needed and relevant for this contribution. + +## Versioning + +Review the information on [versioning](./versioning.md) for Mojaloop. + +## Creating new Features + +Process for creating new [features and branches](./creating-new-features.md) in Mojaloop. + +## Pull Request Process + +It's a good idea to ask about major changes on [Slack](https://mojaloop.slack.com). Submit pull requests which include both the change and the reason for the change. Feel free to use GitHub's "Draft Pull Request" feature to open up your changes for comments and review from the community. + +Pull requests will be denied if they violate the [Level One Principles](https://leveloneproject.org/wp-content/uploads/2016/03/L1P_Level-One-Principles-and-Perspective.pdf). + +## Code of conduct + +We use the [Mojaloop Foundation Code of Conduct](https://github.com/mojaloop/mojaloop/blob/master/CODE_OF_CONDUCT.md) + +## Licensing + +See [License](https://github.com/mojaloop/mojaloop/blob/master/contribute/License.md) policy. + +## FAQs + +**1. What if I want to contribute code, but it doesn't align with the code style and framework/tool recommendations in this guide?** + + Contributions are accepted on a *case by case* basis. If your contribution is not yet ready to be fully adopted, we can go through the incubation phase described above, where the code is refactored with our help and brought into alignment with the code and documentation requirements. + +**2. These standards are outdated, and a newer, cooler tool (or framework, method or language) has come along that will solve problem *x* for us. How can I update the standards?** + + Writing high quality, functional code is a moving target, and we always want to be on the lookout for new tools that will improve the Mojaloop OSS codebase. So please talk to us in the design authority slack channel (`#design-authority`) if you have a recommendation. diff --git a/docs/community/standards/invariants.md b/docs/community/standards/invariants.md new file mode 100644 index 000000000..2dea21176 --- /dev/null +++ b/docs/community/standards/invariants.md @@ -0,0 +1,230 @@ +# Mojaloop Invariants + +The following invariants have been established during the course of the platform’s development and based upon the technical requirements inferred from the [Level One Project Principles](https://www.leveloneproject.org/project_guide/level-one-project-design-principles/) and applicable industry best practices. +These invariants should guide any product and technical design discussions related to the architecture of the platform. + +## General Principles + +### 1. The primary function of the platform is to clear credit-push payments in real-time and facilitate regular settlement, by the end of the value day. +#### Notes: +1. The platform allows participants to clear funds immediately to their customers while keeping the risks and costs associated with this to a minimum. +2. The platform supports per-transfer checks on available liquidity where these are required in support of the first objective. +3. The hub is optimized for critical path. +4. Intra-day Automated Settlement; configured by scheme and implementation using recommended settlement models for financial market infrastructure. + + +### 2. The hub supports fully automatic straight-through processing. +#### Notes: +1. "Straight through processing" means that no manual interventions in the execution of payments or settlements should be required, except where acceptance of the terms of a payment is required from an end user in conformity with the Level One Principles +2. Straight through processing helps reduce human errors in the transfer process which ultimately reduces costs. +3. The automated nature of straight through processing leads to faster value transfers between end customers. + +More information here: [Straight Through Processing Definition](https://www.investopedia.com/terms/s/straightthroughprocessing.asp) + + +### 3. The hub requires no manual reconciliation as the protocol for interacting with the hub guarantees deterministic outcomes. +#### Notes: +1. When a transfer is finalized, there can be no doubt about the status of that transfer (alternatively, it is not finalized and active notice provided to participants. The notice provided to participants is on demand: if they enquire, they are informed that status is indeterminate). +2. The hub guarantees deterministic outcomes for transfers and is accepted by all participants as the final authority on the status of transfers. +3. Determinism means individual transfers are traceable, auditable (based on limits, constraints), with final result provided within guaranteed time limit. +4. For the avoidance of doubt, batch transfers are processed line-by-line with potentially differing deterministic outcomes for each. + + +### 4. Transaction setup logic, which is use case-specific, is separated from the policy-free transfer of money. +#### Notes: +1. Transaction details and business rules should be captured and applied between counterparties prior to the agreement of terms phase and is out of scope for Mojaloop. +2. The agreement phase establishes a signed use-case specific transaction object which incorporates all transaction-specific details. +3. The transfer phase orchestrates the transfer of retail value between institutions for the benefit of the counterparties (i.e only system limit checks are applied) and without reference to transaction details. +4. No additional transaction-specific processing during the transfer phase. + + +### 5. The hub doesn’t parse or act on end-to-end transaction details; transfer messages contain only the values required to complete clearing and settlement. +#### Notes: +1. Checks & validations during the transfer step are only for conformance to scheme rules, limit checks, signature authentication, and validation of payment condition and fulfillment. +2. Transfers that are committed for settlement are final and are guaranteed to settle under the scheme rules. + + +### 6. Credit-push transfer semantics are reduced to their simplest form and standardized for all transaction types. +#### Notes: +1. Simplifies implementation and participant integration as many transaction types and use-cases can reuse the same underlying value transfer message flow. +2. Abstracts use-case complexity away from the critical path. + + +### 7. Internet-based API service hub is not a “message switch.” +#### Notes: +1. The service hub provides real-time API services for participants to support retail credit-push instant transfers. + 1. API services such as address resolution, transaction agreement between participants, submission of prepared transfers, and submission of fulfillment advice. +2. Auxiliary API services for participants are provided to support onboarding, position management, reporting for reconciliation, and other non-realtime functions not associated with transfer processing. +3. All messages are validated for conformance to the API specification; non-conforming messages are actively rejected with a standardized machine-interpretable reason code. + + +### 8. The hub exposes asynchronous interfaces to participants +#### Notes: +1. To maximize system throughput. +2. To isolate leaf-node connectivity issues so they don't impact other end-users. +3. To enable the hub system to process requests in its own priority order and without holding an active connection-per-transfer. +4. To handle numerous concurrent long-running processes through internal batching and load balancing. +5. To have a single mechanism for handling requests (Examples are transactions such as bulk or those needing end user input or that span multiple hops). +6. To better support real world networking as issues with connection speed and reliability for one participant should have minimal impact on other participants or system availability more generally. + +### 9. The transfer API is [idempotent](https://docs.mojaloop.io/api/fspiop/v1.1/api-definition.html#idempotent-services-in-server) +#### Notes: +1. This ensures duplicate requests may be made safely by message originators in conditions of degraded network connectivity. + 1. Duplicate requests are recognized and result in the same outcome (valid duplicates) or are rejected as duplicate (when not allowed by specification) with reference to the original. + + +### 10. **_Finalized_** Transfer records are held for a scheme-configurable period to support scheme processes such as reconciliation, billing, and for forensic purposes +#### Notes: +1. It is not possible to query the "sub-status" of an in-process Transfer; the API provides a deterministic outcome with active notice provided within the guaranteed service time. + + +### 11. Transfer records for finalized transfers are held indefinitely in long-term storage to support business analysis by the scheme operator and by participants (through appropriate interfaces) +#### Notes: +1. Availability of Transfer records may lag online process finality to accommodate separation of record-keeping from real-time processing of Transfer requests. + + +### 12. The hub should do the minimum parsing, storing and processing of messages required to execute the services that it provides to the scheme as a whole. +#### Notes: +1. In some messaging flows e.g. party lookup, it may be desirable for participants to have a single point of contact for routing of scheme related messages, even when the messages are not intended for the hub, nor require any inspection or other processing. + + +## Security and Safety of APIs + +### 13. API messages are confidential, tamper-evident, and non-repudiable. +#### Notes: +1. Confidentiality is required to protect the privacy of the participants and their customers. + 1. There are legal requirements in many regulatory domains where Mojaloop is expected to operate and as such, the hub must employ best practices to ensure that the privacy of the participants and their customers is protected. +2. Tamper-evident integrity mechanisms are required to ensure that messages cannot be altered in transit. + 1. To ensure the integrity of the overall system, each recipient of a message should be able to independently tell, with a high degree of confidence, that the message was not altered in transit. + 2. Public key cryptography (digital signing) provides the current best known mechanism for tamper-evident messaging + 1. The security of the sender's private key is critical. + 2. Scheme rules must be established to clarify the responsibilities for key management and the potential for financial liability upon compromise of a private key. +3. Non-repudiation is required to ensure that the message was sent by the party which purported to send it and that provenance can not be repudiated by the sender. + 1. This is important for determining the liable party during audit and dispute resolution processes. + + +### 14. API messages are Authenticated upon receipt prior to acceptance or further processing +#### Notes: +1. Authentication gives a degree of confidence that the message was sent by the party which purported to send it. +2. Authentication gives a degree of confidence that the message was not sent by an unauthorized party. + + +### 15. Authenticated Messages are not acknowledged as accepted until safely recorded to permanent store. +#### Notes: +1. The Mojaloop API assigns significant scheme related business meaning to certain HTTP response codes at various points in transaction flows: + 1. Certain HTTP responses, e.g. "202 Accepted", are intended to provide financial guarantees to participants and as such must only be sent once the receiving entity is confident it has made safe, permanent record(s) in support of: + 1. Facilitating system wide recovery to a consistent state after failure(s) in one or more distributed components/entities. + 2. Accurate settlement processes + 3. Audit and dispute resolution processes + 2. For example a "200 OK" from the hub to the payee participant upon receipt of a transfer fulfilment message indicates a guarantee of transaction settlement to the payee pending validation checks. +2. The Mojaloop API is designed to operate safely under imperfect network conditions and as such has built in support for retries and state synchronisation between participants. + + +### 16. Three levels of communication security to ensure integrity, confidentiality, and non-repudiation of messages between an API server and API client. +#### Notes: +1. Secure Connections: mTLS required for all communications between the scheme and authorized participants. + 1. Ensures communications are confidential, between known correspondents, and communications are protected against tampering. +2. Secure Messages: JSON message content is cryptographically signed according to the JWS specification. + 1. Ensures recipients that messages were sent by the party which purported to send them and that provenance can not be repudiated by the sender. +3. Secure Terms of Transfer: Interledger Protocol (ILP) between Payer and Payee participants. + 1. Protects the integrity of the payment condition and its fulfillment. + 2. Limits the time within which a transfer instruction is valid. + + +### 17. To ensure system is arithmetically consistent, only fixed point arithmetic is used. +#### Notes: +1. For the avoidance of doubt, floating point calculations may lose accuracy and must not be used in any financial calculation. +2. See [Level One Decimal Type](https://docs.mojaloop.io/documentation/discussions/decimal.html) representation and forms. + 1. This specification enables seamless interchange with XML-based financial systems without loss of precision or accuracy + + +## Operational Characteristics + +Mojaloop is designed to function as part of a jurisdictional Instant Payments System. As such, it must demonstrably meet the standards of performance and resilience which are required for such systems. + + +### 1. Baseline system demonstrated on minimal hardware supports clearing 1,000 transfers per second, sustained for one hour, with not more than 1% (of transfer stage) taking more than 1 second through the hub. +#### Notes: +1. This measurement includes all necessary hardware and software components with production grade security and data persistence in place. +2. This measurement includes all three transfer stages: discovery, agreement, and transfer. +3. This measurement does not include any participant introduced latency. +4. A one hour period is a reasonable approximation of a demand peak for a national payment system. +5. The cost of scaling up capacity should be less per unit of capacity than the cost of initial provisioning. +6. 1000 transfers (clearing) per second is a reasonable starting point for a national payment system. +7. 1% of transfers (clearing) taking more than 1 second is a reasonable starting point for a national payment system. +8. Mojaloop schemes should be able to start at a reasonable cost point, for national financial infrastructure, and scale economically as demand grows. + + +### 2. The hub is highly available and resilient to failures. +#### Notes: +1. Definition of "highly available": + 1. In this instance we define the term "_highly available_" as meaning "_the ability to provide and maintain an acceptable level of service in the face of faults and challenges to normal operation._" + 2. Although schemes may determine their own definition of what constitutes an "_acceptable level of service_", Mojaloop makes certain contributing tradeoff choices: + 1. When fault modes permit, service is degraded across the entire participant population rather than individual participants suffering total outages while others remain serviceable. +2. The hub has no single point of failure; meaning that it continues to operate with minimum degradation of service in the event of a failure of any single component. + 1. Multiple active instances of each component are deployed in a distributed manner behind load balancers. + 2. Each active component instance can handle requests from any client/participant meaning no single participant loses the ability to transact in the event of a failure of any single component. +3. Given appropriate infrastructure to operate upon, the Mojaloop software can be deployed in active:active and/or active:passive multiple, geographically distributed data center configurations where both services and data are replicated across multiple physical nodes which are expected to fail independently. +4. Note that it is expected that nodes in replication groups (and/or clusters) will be located in diverse physical locations (racks and/or data centres) with independent power supplies and network interconnects. +5. Should multiple component failures occur which have not been mitigated either in the Mojaloop software, deployment configuration or infrastructure, the Mojaloop API provides mechanisms for each entity in the scheme to recover to a consistent state, with the hub being the ultimate source of truth upon full restoration of service. +6. _Also see further points relating to resistance to data loss in the event of failures._ +7. Given that Mojaloop schemes are intended to form parts of national financial infrastructure they must have as close to zero downtime as possible, given reasonable cost constraints. +8. Failures in hardware and software components are to be expected, even in the highest quality components available. Best practice suggests these failures should be anticipated and planned for as much as possible in the design of the hub with a view to minimising loss or degradation of service and/or data. +9. For the avoidance of doubt this means the tradeoffs chosen favour overall service availability and state consistency over performance. I.e: + 1. All participants can continue to transact at a reduced rate rather than some participants being unable to transact at all. + 2. Inconsistencies in state between scheme entities are resolvable post service restoration via the Mojaloop API, with minimal manual reconciliation necessary; the hub being the ultimate source of truth. +10. In situation where sufficient throughput to handle all incoming requests in a timely manner cannot be sustained, the hub will prioritise processing transfers which are in-flight over new incoming requests. + 1. Transfers which the hub cannot process before specified deadlines expire will be timed out gracefully. + + +### 3. The hub is resistant to loss of data in the event of failures. +#### Notes: +1. Given appropriate infrastructure to operate upon, the Mojaloop software can be deployed in configurations which reliably replicate data across multiple, redundant physical storage nodes prior to processing. + 1. Database engine components which are provided by the Mojaloop deployment mechanisms support the following: + 1. Primary:secondary asynchronous replication + 2. Primary:primary synchronous replication. + 3. Synchronous quorum consensus algorithm based replication. + 2. The replication mechanisms available are dependant on the particular storage layer and database technologies employed. +2. Should multiple component failures occur which have not been mitigated either in the Mojaloop software, deployment configuration or infrastructure, the Mojaloop API provides mechanisms for each entity in the scheme to recover to a consistent state with minimal financial exposure risk. + 1. Transfers become financially binding only when the hub has successfully responded to a transfer fulfilment message from the payee participant. This response is only sent when the hub has persisted the fulfilment message and its outcome to its ledger database. + 2. Expiration timestamps on all financially significant API messages facilitate timely and deterministic failure path outcomes for all participants via automated retry mechanisms. +3. Given that Mojaloop schemes are intended to form parts of national financial infrastructure they must do as much as possible, given reasonable cost constraints, to avoid loss of data in the event of a failure. +4. Failures in hardware and software components are to be expected, even in the highest quality components available. Best practice suggests these failures should be anticipated and planned for in the design of the hub with a view to avoiding data loss. +5. Participants need timely confidence in the status of financial transactions across the scheme in order to minimise exposure risk and deliver excellent customer experiences. + + +## Design Decisions +1. NodeJS is the primary execution environment with TypeScript the preferred language for development. + 1. This platform is free open source + 2. Is widely used and actively supported by the world's largest web-based institutions + 3. Has a massive global portfolio of libraries + 4. Utilizes only the ECMAScript family of architecture-neutral languages and libraries known by millions of skilled web programmers + + +2. Use a micro-service distributed architecture. + 1. [Law of Demeter](https://en.wikipedia.org/wiki/Law_of_Demeter) or Principle of Least Knowledge + 2. [Separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns) secured by inter-module contracts + 3. [Modular architecture](https://en.wikipedia.org/wiki/Modular_programming) enables distributed development in a community environment and improvement of components with minimal disruption to adjacent components + + +3. [Apache Kafka](https://kafka.apache.org/intro) distributed [Publish–Subscribe](https://en.wikipedia.org/wiki/Publish–subscribe_pattern) for inter-module [Command–Query Separation (CQS)](https://en.wikipedia.org/wiki/Command–query_separation) + + +4. [Apache Kafka](https://kafka.apache.org/intro) for persistent handling of participant API messages + + +5. Mojaloop uses APIs based on Open API 3.0. + 1. Exposes resources that are mapped to functionality to support the defined API use-cases. + 2. Common practice for web API specification + + +## Annexure A : Level One Principles Overview +The [Level One Project](https://www.leveloneproject.org) proposes a new low-cost payments system that supports inclusive, interoperable digital payments. The [Level One Project Guide](https://www.leveloneproject.org/project_guide/03-welcome-to-the-2019-guide/) outlines a vision of how an inclusive digital financial services system can work for the benefit of poor people. The underlying design principles of the Guide include: +* A credit push payment model with immediate funds transfer and same day settlement +* Open-loop interoperability between providers +* Adherence to well-defined and adopted international standards +* Adequate system-wide shared fraud and security protection +* Efficient and proportional identity and know-your-customer (KYC) requirements +* Meeting or exceeding the convenience, cost and utility of cash + +By utilizing an open, digital approach to transactions, and partnering with organizations across the public and private sectors, the Level One Project aims to provide access to a robust, low-cost shared digital financial services infrastructure, sparking innovation from new and existing participants, reducing risk, and generating substantial value for providers, individuals and economies in developing markets. Additional resources have been created to help governments, NGOs and financial service providers successfully implement these changes. diff --git a/docs/community/standards/triaging-bugs.md b/docs/community/standards/triaging-bugs.md new file mode 100644 index 000000000..ef7a23c84 --- /dev/null +++ b/docs/community/standards/triaging-bugs.md @@ -0,0 +1,22 @@ +# Triaging Mojaloop OSS bugs + +### Raising a bug / issue + +If there is a bug or issue in general an issue is logged as a bug or feature request on the [project](https://github.com/mojaloop/project/issues/new/choose) repository and in some cases linked to an issue logged on the repository for that specific component. + +There is a bug [template](https://github.com/mojaloop/project/issues/new?assignees=&labels=bug&template=bug_report.md&title=) that can be used and encourages use of details such as versions, expected results and other details, which help with triage and reproducing the issue. + +### Once a bug is logged + +1. Typically, the bug is initially triaged in the [#ml-oss-bug-triage](https://mojaloop.slack.com/messages/CMCVBHPUH) public channel on Mojaloop Slack +2. For Security and other sensitive issues, the bug is triaged on a private channel with current contributors, before information is made public at an appropriate time. Details for security issues are covered here: https://docs.mojaloop.io/community/contributing/cvd.html +3. During bug triage, priority and severity are assigned to the bug after majority consensus and consultation with reporter(s) +4. Based on the priority and severity the bug is taken up by the Core team or other contributors based on a collaborative effort. +5. Once it is taken up, conversation and updates happen on GitHub issue and slack channel. + +### Triage + +1. The discussion regarding the issue is open to a public for normal bugs / issues +2. Based on the discussions, a final call on the priority and severity of the issue is made by the Core team in consultation with the reporter(s). +3. The list and the process will be updated as it evolves. +4. Mojaloop bug triage slack channel #[ml-oss-bug-triage](https://mojaloop.slack.com/archives/CMCVBHPUH) diff --git a/docs/community/standards/versioning.md b/docs/community/standards/versioning.md new file mode 100644 index 000000000..d8d759985 --- /dev/null +++ b/docs/community/standards/versioning.md @@ -0,0 +1,126 @@ +# Versioning + +## Versioning of releases made for core Switch services + +This document provides guidelines regarding the versioning strategy used for the releases of Mojaloop Open Source repositories corresponding to the Switch services. + +### Versioning Strategy + + +#### Standard for PI-11 and beyond +1. Starting PI-11 (27th July, 2020) the Versioning guidance is to move to a versioning system that is closely aligned with Semantic versioning by removing the PI/Sprint dependency. So starting 11.x.x, the proposal is to move to pure [SemVer](https://semver.org/). +2. At a high-level, we will still follow the vX.Y.Z format, but X represents ‘Major’ version, Y represents ‘Minor’ version and Z represents ‘patch’ version. Minor fixes, patches affect increments to ‘Z’, whereas non-breaking functionality changes affect changes to ‘Y; breaking changes affect the ‘X’ version. +3. Along with these, suffixes such as “-snapshot”, “-patch”, “-hotfix” are used as relevant and on need basis (supported by CI config). +4. So starting with 11.0.0 (primarily for Helm, but for individual services as well) for PI-11, the proposal is to move to pure [SemVer](https://semver.org/). +5. This implies that for any new release of a package/service below X=11 (for existing repositories and not new ones) will first be baselined to v11.0.0 and from then on follow standard SemVer guidelines as discussed above. For new projects or repositories, versioning can start from v1.0.0 (after they reach release status) + + +#### Versioning Strategy used until PI-10 +1. The Mojaloop (up to PI-10) versioning system is inspired by the [Semantic Versioning](https://semver.org/) numbering system for releases. +2. However, this is customized to depict the timelines of the Mojaloop project, based on the Program Increment \(PI\) and Sprint numbers +3. For example, the release number v5.1.0 implies that this release was the first one made during a Sprint 5.1, where Sprint5.1 is the first Sprint in PI-5. So for a version vX.Y.Z, X.Y is the Sprint number where X is the PI number and Z represents the number of release for this specific repository. Example v4.4.4 implies that the current release is the fourth of four releases made in Sprint 4.4 \(of PI-4\) + + + +### Current Version + +The currrent version information for Mojaloop can be found [here](../../deployment-guide/releases.md). + +### Sprint schedule for PI-13 + +Below is the Sprint schedule for Program Increment 13 which ends with the PI-14 Community event in April 2021. + +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Phase-5 Kick-off On-site**|1/25/2021|1/29/2021|5 days| Virtual Zoom Webinars| +|**Sprint 13.1**|02/01/2021|02/14/2021|2 weeks | | +|**Sprint 13.2**|02/15/2021|02/28/2021|2 weeks | | +|**Sprint 13.3**|03/01/2021|03/14/2021|2 weeks | | +|**Sprint 13.4**|03/15/2021|03/28/2021|2 weeks | | +|**Sprint 13.5**|03/29/2021|04/11/2021|2 weeks | | +|**Sprint 13.6**|04/12/2021|04/25/2021|2 weeks | | +|**Phase-5 PI-14**|04/26/2021|04/30/2021|5 days| Virtual meetings | + +### Sprint schedule for PI-12 + +Below is the Sprint schedule for Program Increment 12 which ends with the PI-13 Community event in January 2021. + +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| +|**Phase-4 PI-10 Virtual**|4/21/2020|4/24/2020|4 days| Virtual Zoom Webinars| +|**Phase-4 PI-11 Virtual**|7/21/2020|7/24/2020|4 days| Virtual Zoom Webinars| +|**Phase-4 PI-12 Virtual**|10/19/2020|10/23/2020|5 days| Virtual Zoom Webinars| +|**Sprint 12.1**|10/26/2020|11/15/2020|3 weeks | | +|**Sprint 12.2**|11/16/2020|11/29/2020|2 weeks | | +|**Sprint 12.3**|11/30/2020|12/13/2020|2 weeks | | +|**Sprint 12.4**|12/14/2020|12/27/2020|2 weeks | | +|**Sprint 12.5**|12/28/2020|01/10/2021|2 weeks | | +|**Sprint 12.6**|01/11/2020|01/24/2020|2 weeks | | +|**Phase-5 Kick-off / PI-13**|01/25/2021|01/29/2021|5 days| TBD | + +### Previous Sprint Schedules: + +### Sprint schedule for PI-11 + +Below is the Sprint schedule for Program Increment 11 which ends with the PI 12 Event. + +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| +|**Phase-4 PI-10 Virtual**|4/21/2020|4/24/2020|4 days| Virtual Zoom Webinars | +|**Phase-4 PI-11 Virtual**|7/21/2020|7/24/2020|4 days| Virtual Zoom Webinars | +|**Sprint 11.1**|7/27/2020|8/9/2020|2 weeks| | +|**Sprint 11.2**|8/10/2020|8/23/2020|2 weeks| | +|**Sprint 11.3**|8/24/2020|9/6/2020|2 weeks| | +|**Sprint 11.4**|9/7/2020|9/20/2020|2 weeks| | +|**Sprint 11.5**|9/21/2020|10/4/2020|2 weeks| | +|**Sprint 11.6**|10/5/2020|10/18/2020|2 weeks | | +|**Phase-4 PI-12**|10/20/2020|10/23/2020|4 days| TBD | + +#### Sprint schedule for PI-10 + +Below is the Sprint schedule for Program Increment 10 which ends with the PI 11 Event. Please use this as guidance during the versioning and release processes. + +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Phase-3 PI6 On-site**|4/16/2019|4/18/2019|3 days| Johannesburg| +|**Phase-3 PI7 On-site**|6/25/2019|6/27/2019|3 days| Arusha| +|**Phase-3 PI8 On-site**|9/10/2019|9/12/2019|3 days| Abidjan| +|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| +|**Phase-4 PI 10 Virtual**|4/21/2020|4/24/2020|5 days| Virtual Zoom Webinars | +|**Sprint 10.1**|4/27/2020|5/10/2020|2 weeks| | +|**Sprint 10.2**|5/11/2020|5/24/2020|2 weeks| | +|**Sprint 10.3**|5/25/2020|6/7/2020|2 weeks| | +|**Sprint 10.4**|6/8/2020|6/21/2020|2 weeks| | +|**Sprint 10.5**|6/22/2020|7/5/2020|2 weeks| | +|**Sprint 10.6**|7/6/2020|7/19/2020|2 weeks | | +|**Phase-4 PI 11 On-Site**|7/21/2020|7/23/2020|3 days| Kenya (Tentative) | + +#### PI-9 +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Sprint 9.1**|2/3/2020|2/16/2020|2 weeks| | +|**Sprint 9.2**|2/17/2020|3/1/2020|2 weeks| | +|**Sprint 9.3**|3/2/2020|3/15/2020|2 weeks| | +|**Sprint 9.4**|3/16/2020|3/29/2020|2 weeks| | +|**Sprint 9.5**|3/30/2020|4/12/2020|2 weeks| | +|**Sprint 9.6**|3/13/2020|4/19/2020|1 week | | +|**Phase-4 PI 10 Virtual**|4/21/2020|4/23/2020|5 days| Virtual Zoom Webinars | + +#### PI-8 +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Sprint 8.1**|9/16/2019|9/29/2019|2 weeks| | +|**Sprint 8.2**|9/30/2019|10/13/2019|2 weeks| | +|**Sprint 8.3**|10/14/2019|10/27/2019|2 weeks| | +|**Sprint 8.4**|10/28/2019|11/10/2019|2 weeks| | +|**Sprint 8.5**|11/11/2019|11/24/2019|2 weeks| | +|**Sprint 8.6**|11/25/2019|12/8/2019|2 weeks| | +|**Sprint 8.7**|12/9/2019|1/5/2020|4 weeks| Christmas Break| +|**Sprint 8.8**|1/6/2020|1/26/2020|3 weeks| 1 week prep| +|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| + +### Notes + +1. A new release for **helm** repo is made based on the feature and configuration changes made to core services and requirements from thhe Community. \ No newline at end of file diff --git a/contributors-guide/tools-and-technologies/assets/diagrams/automated-testing/QARegressionTestingMojaloop-Complete.plantuml b/docs/community/tools/assets/automated-testing/QARegressionTestingMojaloop-Complete.plantuml similarity index 100% rename from contributors-guide/tools-and-technologies/assets/diagrams/automated-testing/QARegressionTestingMojaloop-Complete.plantuml rename to docs/community/tools/assets/automated-testing/QARegressionTestingMojaloop-Complete.plantuml diff --git a/docs/community/tools/assets/automated-testing/QARegressionTestingMojaloop-Complete.svg b/docs/community/tools/assets/automated-testing/QARegressionTestingMojaloop-Complete.svg new file mode 100644 index 000000000..1b0b9de1a --- /dev/null +++ b/docs/community/tools/assets/automated-testing/QARegressionTestingMojaloop-Complete.svg @@ -0,0 +1,164 @@ + + Regression Test Life Cycle + + + + Regression Test Life Cycle + (Self-contained Test Server on EC2) + + + + This could be a manual trigger, + scheduler timer or + an external action like a Pull Request + from the Source Control System + + Test is triggered + + Validate run parameters as expected? + yes + no + + + Set Timestamp + PostmanCollection to execute + List of email recipients + Environment Variables + Execution Timestamp + Output FileName + + Prepare environment for required run + + Abort run with Note stating incorrect Run Parameters + + + + Create Simulator Docker Container + + + This container has node + Newman\email SMTP Server + + Create Regression Test Docker Container + + + Set up any variables for + preparation of the request to follow + + Perform Pre-Request Script + + Execute Postman Request + + Perform Test + + + Inspect the response + against variables set previously during + the run to determine if expected results are obtained + + Log Results + + no + Run Parameter requested 'Abort at First Error'? + yes + + + + yes + Assertion Test Failed? + no + + + Yes + More Postman Requests to run? + No + + + + Destroy Simulator Docker Container + + Finalise Report + + Prepare Notification(s) + + Attach Reports + + + The Attachment (Generated Report) + is sent as an attachment + to the different notification channels. + + Send out Notification(s) + + Destroy Regression Test Docker Container + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/community/tools/assets/images/ci_cd_lib_master.png b/docs/community/tools/assets/images/ci_cd_lib_master.png new file mode 100644 index 000000000..331087be4 Binary files /dev/null and b/docs/community/tools/assets/images/ci_cd_lib_master.png differ diff --git a/docs/community/tools/assets/images/ci_cd_lib_pr.png b/docs/community/tools/assets/images/ci_cd_lib_pr.png new file mode 100644 index 000000000..1a64f791f Binary files /dev/null and b/docs/community/tools/assets/images/ci_cd_lib_pr.png differ diff --git a/docs/community/tools/assets/images/ci_cd_lib_tag.png b/docs/community/tools/assets/images/ci_cd_lib_tag.png new file mode 100644 index 000000000..13af7e59c Binary files /dev/null and b/docs/community/tools/assets/images/ci_cd_lib_tag.png differ diff --git a/docs/community/tools/assets/images/ci_cd_svc_master.png b/docs/community/tools/assets/images/ci_cd_svc_master.png new file mode 100644 index 000000000..6ab54d9d9 Binary files /dev/null and b/docs/community/tools/assets/images/ci_cd_svc_master.png differ diff --git a/docs/community/tools/assets/images/ci_cd_svc_pr.png b/docs/community/tools/assets/images/ci_cd_svc_pr.png new file mode 100644 index 000000000..389f5ccba Binary files /dev/null and b/docs/community/tools/assets/images/ci_cd_svc_pr.png differ diff --git a/docs/community/tools/assets/images/ci_cd_svc_tag.png b/docs/community/tools/assets/images/ci_cd_svc_tag.png new file mode 100644 index 000000000..934aee684 Binary files /dev/null and b/docs/community/tools/assets/images/ci_cd_svc_tag.png differ diff --git a/docs/community/tools/assets/images/mojaloop_cybersec_architecture.jpg b/docs/community/tools/assets/images/mojaloop_cybersec_architecture.jpg new file mode 100644 index 000000000..aaf8dcca4 Binary files /dev/null and b/docs/community/tools/assets/images/mojaloop_cybersec_architecture.jpg differ diff --git a/docs/community/tools/assets/images/mojaloop_security_layers.jpg b/docs/community/tools/assets/images/mojaloop_security_layers.jpg new file mode 100644 index 000000000..d70949b68 Binary files /dev/null and b/docs/community/tools/assets/images/mojaloop_security_layers.jpg differ diff --git a/docs/community/tools/automated-testing.md b/docs/community/tools/automated-testing.md new file mode 100644 index 000000000..39651c0ad --- /dev/null +++ b/docs/community/tools/automated-testing.md @@ -0,0 +1,144 @@ +# QA and Regression Testing in Mojaloop +An overview of the testing framework set up in Mojaloop + +Contents: +1. [Regression requirements](#regression-topics) +2. [Developer Testing](#developer-testing) +3. [Postman and Newman Testing](#postman-and-newman-testing) +4. [Executing regression test](#executing-regression-test) +5. [Process flow of a typical Scheduled Test](#process-flow-of-a-typical-scheduled-test) +6. [Newman Commands](#newman-commands) + +## Regression Topics + In order for a deployed system to be robust, one of the last checkpoints is to determine if the environment it is deployed in, is in a healthy state and all exposed functionality works exactly the way as intended. + + Prior to that though, there are quite a number of disciplines one must put in place to ensure maximum control. + + To illustrate how the Mojaloop project reaches this goal, we are going to show you the various checkpoints put in place. + +### Developer Testing + Looking at each component and module, inside the code base, you will find a folder named "*test*" which contain three types of tests. + + Firstly, the *coverage test* which alerts one if there are unreachable or redundant code + + Unit Tests, which determines if the intended functionality works as expected + + Integration Tests, which does not test end-to-end functionality, but the immediate neighbouring interaction + + Automated code-standard checks implemented by means of packages that form part of the code base + + These tests are executed by running the command line instructions, by the developer, during the coding process. Also, the tests are automatically executed every time a *check-in* is done and a Github Pull-Request issued for the code to be integrated into the project. + + The procedure described above, falls outside the realm of Quality Assurance (QA) and Regression testing, which this document addresses. + + Once a developer has written new functionality or extended existing functionality, by having to go through the above rigorous tests, one can assume the functionality in question is executing as intended. How does one then ensure that this new portion of code does not negatively affect the project or product as a whole? + + When the code has passed all of the above and is deployed as part of the CI/CD processes implemented by our workflow, the new component(s) are accepted onto the various hosts, cloud-based or on-premise implementations. These hosts ranges from development platforms through to production environments. + +### Postman and Newman Testing + Parallel to the deployment process is the upkeep and maintenance of the [Postman](https://github.com/mojaloop/postman.git "Postman") Collection testing Framework. When a new release is done, as part of the workflow, Release Notes are published listing all of the new and/or enhanced functionality implemented as part of the release. These notes are used by the QA team to extend and enhance the existing Postman Collections where tests are written behind the request/response scripts to test both positive as well as negative scenarios agains the intended behaviour. These tests are then run in the following manner: + + Manually to determine if the tests cover all aspects and angles of the functionality, positive to assert intended behaviour and negative tests to determine if the correct alternate flows work as intended when something unexpected goes wrong + + Scheduled - as part of the Regression regime, to do exactly the same as the manual intent, but fully automated (with the *Newman Package*) with reports and logs produced to highlight any unintended behaviour and to also warn where known behaviour changed from a previous run. + +In order to facilitate the automated and scheduled testing of a Postman Collection, there are various methods one can follow and the one implemented for Mojaloop use is explained further down in this document. + +There is a complete repository containing all of the scripts, setup procedures and anything required in order to set up an automated [QA and Regression Testing Framework](https://github.com/mojaloop/ml-qa-regression-testing.git "QA and Regression Testing Framework"). This framework allows one to target any Postman Collection, specifying your intended Environment to execute against, as well as a comma-separated list of intended email recipients to receive the generated report. This framework is in daily use by Mojaloop and exists on an EC2 instance on AWS, hosting the required components like Node, Docker, Email Server and Newman, as well as various Bash Scripts and Templates for use by the framework to automatically run the intended collections every day. Using this guide will allow anyone to set up their own Framework. + +#### Postman Collections + +There are a number of Postman collections in use throughout the different processes: + +For Mojaloop Simulator: + ++ [MojaloopHub_Setup](https://github.com/mojaloop/postman/blob/master/MojaloopHub_Setup.postman_collection.json) : This collection needs to be executed once after a new deployment, normally by the Release Manager. It sets up an empty Mojaloop hub, including things such as the Hub's currency, the settlement accounts. ++ [MojaloopSims_Onboarding](https://github.com/mojaloop/postman/blob/master/MojaloopSims_Onboarding.postman_collection.json) : MojaloopSims_Onboarding sets up the DFSP simulators, and configures things such as the endpoint urls so that the Mojaloop hub knows where to send request callbacks. ++ [Golden_Path_Mojaloop](https://github.com/mojaloop/postman/blob/master/Golden_Path_Mojaloop.postman_collection.json) : The Golden_Path_Mojaloop collection is an end-to-end regression test pack which does a complete test of all the deployed functionality. This test can be run manually but is actually designed to be run from the start, in an automated fashion, right through to the end, as response values are being passed from one request to the next. (The core team uses this set to validate various releases and deployments) + + Notes: In some cases, there is need for a delay of `250ms` - `500ms` if executed through Postman UI Test Runner. This will ensure that tests have enough time to validate requests against the simulator. However, this is not always required. ++ [Bulk_API_Transfers_MojaSims](https://github.com/mojaloop/postman/blob/master/Bulk_API_Transfers_MojaSims.postman_collection.json) : This collection can be used test the bulk transfers functionality that targets Mojaloop Simulator. + +For Legacy Simulator (encouraged to use Mojaloop Simulator, as this will not be supported starting PI-12 (Oct 2020) ): + ++ [ML_OSS_Setup_LegacySim](https://github.com/mojaloop/postman/blob/master/ML_OSS_Setup_LegacySim.postman_collection.json) : This collection needs to be executed once after a new deployment (if it uses Legacy Simulator), normally by the Release Manager. It sets up the Mojaloop hub, including things such as the Hub's currency, the settlement accounts along with the Legacy Simulator(s) as FSP(s). ++ [ML_OSS_Golden_Path_LegacySim](https://github.com/mojaloop/postman/blob/master/ML_OSS_Golden_Path_LegacySim.postman_collection.json) : The Golden_Path_Mojaloop collection is an end-to-end regression test pack which does a complete test of all the deployed functionality. This test can be run manually but is actually designed to be run from the start, in an automated fashion, right through to the end, as response values are being passed from one request to the next. (The core team uses this set to validate various releases and deployments) + + Notes: In some cases, there is need for a delay of `250ms` - `500ms` if executed through Postman UI Test Runner. This will ensure that tests have enough time to validate requests against the simulator. However, this is not always required. ++ [Bulk API Transfers.postman_collection](https://github.com/mojaloop/postman/blob/master/Bulk%20API%20Transfers.postman_collection.json) : This collection can be used test the bulk transfers functionality that targets Legacy Simulator. + +#### Environment Configuration + +You will need to customize the following environment config file to match your deployment environment: ++ [Local Environment Config](https://github.com/mojaloop/postman/blob/master/environments/Mojaloop-Local.postman_environment.json) + +_Tips:_ +- _The host configurations will be the most likely changes required to match your environment. e.g. `HOST_CENTRAL_LEDGER: http://central-ledger.local`_ +- _Refer to the ingress hosts that have been configured in your `values.yaml` as part of your Helm deployment._ + +### Executing regression test +For the Mojaloop QA and Regression Testing Framework specifically, Postman regression test can be executed by going into the EC2 instance via SSH, for which you need the PEM file, and then by running a script(s). + +Following the requirements and instructions as set out in the detail in [QA and Regression Testing Framework](https://github.com/mojaloop/ml-qa-regression-testing.git "QA and Regression Testing Framework"), everyone will be able to create their own Framework and gain access to their instance to execute tests against any Postman Collection targeting any Environment they have control over. + +##### Steps to execute the script via Postman UI ++ Import the desired collection into your Postman UI. You can either download the collection from the repo or alternatively use the `RAW` link and import it directly via the **import link** option. ++ Import the environment config into your Postman UI via the Environmental Config setup. Note that you will need to download the environmental config to your machine and customize it to your environment. ++ Ensure that you have pre-loaded all prerequisite test data before executing transactions (party, quotes, transfers) as per the example collection [OSS-New-Deployment-FSP-Setup](https://github.com/mojaloop/postman/blob/master/OSS-New-Deployment-FSP-Setup.postman_collection.json): + + Hub Accounts + + FSP onboarding + + Add any test data to Simulator (if applicable) + + Oracle onboarding ++ The `p2p_money_transfer` test cases from the [Golden_Path](https://github.com/mojaloop/postman/blob/master/Golden_Path.postman_collection.json) collection are a good place to start. + +##### Steps to execute the bash script to run the Newman / Postman test via CLI ++ To run a test via this method, you will have to be in posession of the PEM-file of the server on which the Mojaloop QA and Regression Framework was deployed on an EC2 instance on Amazon Cloud. + ++ SSH into the specific EC2 instance and when running the script, it will in turn run the commands via an instantiated Docker container. + ++ You will notice that by using this approach where both the URLs for the Postman-Collection and Environment File are required as input parameters (together with a comma-delimited email recipient list for the report) you have total freedom of executing any Postman Collection you choose. + ++ Also, by having an Environment File, the specific Mojaloop services targeted can be on any server. This means you can execute any Postman test against any Mojaloop installation on any server of your choice. + ++ The EC2 instance we execute these tests from are merely containing all the tools and processes in order to execute your required test and does not host any Mojaloop Services as such. + +``` +./testMojaloop.sh +``` + +## Process flow of a typical Scheduled Test + +![](./assets/automated-testing/QARegressionTestingMojaloop-Complete.svg) + + +## Newman Commands +The following section is a reference, obtained from the Newman Package site itself, highlighting the different commands that may be used in order to have access to the Postman environment by specifying some commands via the CLI. +``` +Example: ++ newman run -e -n 1 -- + +Usage: run [options] + + URL or path to a Postman Collection. + + Options: + + -e, --environment Specify a URL or Path to a Postman Environment. + -g, --globals Specify a URL or Path to a file containing Postman Globals. + --folder Specify folder to run from a collection. Can be specified multiple times to run multiple folders (default: ) + -r, --reporters [reporters] Specify the reporters to use for this run. (default: cli) + -n, --iteration-count Define the number of iterations to run. + -d, --iteration-data Specify a data file to use for iterations (either json or csv). + --export-environment Exports the environment to a file after completing the run. + --export-globals Specify an output file to dump Globals before exiting. + --export-collection Specify an output file to save the executed collection + --postman-api-key API Key used to load the resources from the Postman API. + --delay-request [n] Specify the extent of delay between requests (milliseconds) (default: 0) + --bail [modifiers] Specify whether or not to gracefully stop a collection run on encountering an errorand whether to end the run with an error based on the optional modifier. + -x , --suppress-exit-code Specify whether or not to override the default exit code for the current run. + --silent Prevents newman from showing output to CLI. + --disable-unicode Forces unicode compliant symbols to be replaced by their plain text equivalents + --global-var Allows the specification of global variables via the command line, in a key=value format (default: ) + --color Enable/Disable colored output. (auto|on|off) (default: auto) + --timeout [n] Specify a timeout for collection run (in milliseconds) (default: 0) + --timeout-request [n] Specify a timeout for requests (in milliseconds). (default: 0) + --timeout-script [n] Specify a timeout for script (in milliseconds). (default: 0) + --ignore-redirects If present, Newman will not follow HTTP Redirects. + -k, --insecure Disables SSL validations. + --ssl-client-cert Specify the path to the Client SSL certificate. Supports .cert and .pfx files. + --ssl-client-key Specify the path to the Client SSL key (not needed for .pfx files) + --ssl-client-passphrase Specify the Client SSL passphrase (optional, needed for passphrase protected keys). + -h, --help output usage information +``` \ No newline at end of file diff --git a/docs/community/tools/ci_cd_pipelines.md b/docs/community/tools/ci_cd_pipelines.md new file mode 100644 index 000000000..d0b25a50c --- /dev/null +++ b/docs/community/tools/ci_cd_pipelines.md @@ -0,0 +1,127 @@ +# CI/CD Pipelines + +The Mojaloop Community uses [CircleCI](https://circleci.com/) to automatically build, test and deploy our +software. This document describes how we use CI/CD in Mojaloop, the different checks we perform on the +software, and how we distribute the software. + +Broadly speaking, there are 2 types of workflow we use, depending on the type of project: +- Library: build node project -> test -> publish to [npm](https://www.npmjs.com/search?q=%40mojaloop) +- Service: build docker image -> test -> publish to [Docker Hub](https://hub.docker.com/u/mojaloop) + +Additionally, we also maintain a set of [Mojaloop Helm Charts](http://docs.mojaloop.io/helm/), which are +built from the [mojaloop/helm](https://github.com/mojaloop/helm) + +## Libraries + +> For a good example of this CI/CD pattern see [central-services-shared](https://github.com/mojaloop/central-services-shared/blob/master/.circleci/config.yml) + +### Pull Request (PR) Flow: + +The PR flow runs on pull requests, and during the [PR review process](https://github.com/mojaloop/documentation/blob/master/contributors-guide/standards/creating-new-features.md#creating-new-features), these checks must be satisfied +for the code to be merged in. + +![](./assets/images/ci_cd_lib_pr.png) + +| Step | Description | More Info | +| --- | ----------- | --------- | +| pr-title-check | Checks that the PR title conforms to the conventional commits specification | Defined in a CircleCI orb here: [mojaloop/ci-config](https://github.com/mojaloop/ci-config) | +| test-coverage | Runs the unit-tests and checks that code coverage is above the specified limit. | Typically this is 90% | +| test-unit | Runs the unit-tests. Fails if any unit test fails. | | +| vulnerability-check | Runs the `npm audit` tool to search for any vulnerabilities in dependencies | `npm audit` is full of false positives, or security issues that don't apply to our codebase. We use `npm-audit-resolver` to give us flexibility over vulnerabilities that may be ignored, e.g `devDependencies` | +| audit-licenses | Runs the mojaloop `license-scanner-tool` and fails if any license found doesn't match an allowlist specified in the `license-scanner-tool` | [license-scanner-tool repo](https://github.com/mojaloop/license-scanner-tool) | + + +### Master and Release Flow: + +This CI/CD pipeline runs on the master/main branch: + +![](./assets/images/ci_cd_lib_master.png) + +| Step | Description | More Info | +| --- | ----------- | --------- | +| pr-title-check | See above | | +| test-coverage | See above | | +| test-unit | See above | | +| vulnerability-check | See above | | +| audit-licenses | See above | | +| release | Runs a release which creates a git tag and pushes the git tag | | +| github-release | Adds the release metadata (e.g. changelog) to github, sends a slack alert to #announcements | | + + +### Tag Flow: + +Once a git tag is pushed to the repository, it triggers a workflow that ends +in publishing to `npm`. Importantly, the checks are all run again, to ensure +nothing has changed (e.g. dependencies) inbetween the main/master and the actual +artefact that is published to `npm`. + +![](./assets/images/ci_cd_lib_tag.png) + +| Step | Description | More Info | +| --- | ----------- | --------- | +| pr-title-check | See above | | +| test-coverage | See above | | +| test-unit | See above | | +| vulnerability-check | See above | | +| audit-licenses | See above | | +| publish | Publishes the latest version of the library based on the git tag | | + + +## Services + +> For a good example of this CI/CD pattern see [central-ledger](https://github.com/mojaloop/central-ledger/blob/master/.circleci/config.yml) + +### Pull Request (PR) Flow: + +The PR flow runs on pull requests, and during the PR review process, these checks must be satisfied +for the code to be merged in. + +![](./assets/images/ci_cd_svc_pr.png) + +| Step | Description | More Info | +| --- | ----------- | --------- | +| pr-title-check | Checks that the PR title conforms to the conventional commits specification | Defined in a CircleCI orb here: [mojaloop/ci-config](https://github.com/mojaloop/ci-config) | +| test-coverage | Runs the unit-tests and checks that code coverage is above the specified limit. | Typically this is 90% | +| test-unit | Runs the unit-tests. Fails if any unit test fails. | | +| test-integration | Runs the integration-tests. Typically by building a docker image locally | | +| vulnerability-check | Runs the `npm audit` tool to search for any vulnerabilities in dependencies | `npm audit` is full of false positives, or security issues that don't apply to our codebase. We use `npm-audit-resolver` to give us flexibility over vulnerabilities that may be ignored, e.g `devDependencies` | +| audit-licenses | Runs the mojaloop `license-scanner-tool` and fails if any license found doesn't match an allowlist specified in the `license-scanner-tool` | [license-scanner-tool repo](https://github.com/mojaloop/license-scanner-tool) | + + +### Master and Release Flow: + +This CI/CD pipeline runs on the master/main branch: + +![](./assets/images/ci_cd_svc_master.png) + +| Step | Description | More Info | +| --- | ----------- | --------- | +| pr-title-check | See above | | +| test-coverage | See above | | +| test-unit | See above | | +| test-integration | See above | | +| vulnerability-check | See above | | +| audit-licenses | See above | | +| release | Runs a release which creates a git tag and pushes the git tag | | +| github-release | Adds the release metadata (e.g. changelog) to github, sends a slack alert to #announcements | | + + +### Tag Flow: + +Once a git tag is pushed to the repository, it triggers a workflow that ends +in publishing a docker image to Docker Hub. Importantly, the checks are all run again, +and further scans are made on the docker image before the image is pushed. + +![](./assets/images/ci_cd_svc_tag.png) + +| Step | Description | More Info | +| --- | ----------- | --------- | +| pr-title-check | See above | | +| test-coverage | See above | | +| test-unit | See above | | +| vulnerability-check | See above | | +| audit-licenses | See above | | +| build | Builds the docker image | | +| image-scan | Runs `anchore/analyze_local_image` to scan the image | See [anchore-engine](https://circleci.com/developer/orbs/orb/anchore/anchore-engine) CircleCI Orb for more information. | +| license-scan | Runs the mojaloop `license-scanner-tool` on the licenses contained in the docker image | | +| publish | Publishes the latest version of the library based on the git tag | | diff --git a/docs/community/tools/code-quality-metrics.md b/docs/community/tools/code-quality-metrics.md new file mode 100644 index 000000000..f155be68f --- /dev/null +++ b/docs/community/tools/code-quality-metrics.md @@ -0,0 +1,30 @@ +# Code Quality Metrics + +## Functional quality metrics + +### Unit test metrics + +High coverage and low dependencies show that the code is testable and therefore well isolated and easy to maintain. Low complexity also makes code readable and maintainable and helps enforce single responsibility. Real unit tests run very fast as they don't call external components. + +| Code Quality Metrics | New and Project Code | +| :--- | :--- | +| Unit test coverage | >= 80% block coverage | +| Unit test speed | <= 10 seconds | +| Dependencies/method | <= 10 | +| Complexity/method | <= 7 | + +### Component + +Functional testing typically covers pair combinations of the system states. + +### Integration + +Functional tests have one test per message and error. Messages and errors that are handled the same way use the same test. + +### Contract + +Limited to what the consuming teams need that isn't covered by existing unit, component, and integration tests. Often added to over time. + +### End to End + +End to end tests cover acceptance tests from scenarios. \ No newline at end of file diff --git a/docs/community/tools/cybersecurity.md b/docs/community/tools/cybersecurity.md new file mode 100644 index 000000000..9ea975a43 --- /dev/null +++ b/docs/community/tools/cybersecurity.md @@ -0,0 +1,121 @@ +## Mojaloop Cybersecurity Architecture + +## Introduction + +Mojaloop takes both secure-by-design and risk based approaches to cybersecurity, meaning the open-source software provided by the Mojaloop Foundation have been designed to be foundationally secure and are continuously evaluated against possible risks by several processes. + +In addition to the cybersecurity initiatives managed by the Mojaloop Foundation, the wider Mojaloop community includes cybersecurity experts who are able to provide consultancy and services to further enhance adopters' own capabilities. + + + +![Figure 1 - Mojaloop Cybersecurity Architecture Layers](./assets/images/mojaloop_cybersec_architecture.jpg "Figure 1 - Mojaloop Cybersecurity Architecture Layers") + +Figure 1 - Mojaloop Cybersecurity Architecture Layers + +_Please note that although the Mojaloop Foundation and the Mojaloop community attempt to provide software that is secure by design and that can be operated in a secure manner, adopters bear the ultimate responsibility for ensuring the security of their operations. With this in mind the Mojaloop Foundation highly recommends that cybersecurity experts be engaged by adopters to ensure that cybersecurity best practice is followed and that all relevant and applicable standards and regulations are adhered to._ + + +## Secure-By-Design + + +### Design Review Processes + +The Mojaloop Foundation and community manage and operate several security aware design review processes which contribute to the secure-by-design and risk management approaches. + + + +1. The Mojaloop Technical Governing Board determines the high-level technical cybersecurity objectives for the Mojaloop project which are implemented by other community bodies and processes. +2. The Mojaloop community operates a design authority which is a managed group of elected subject matter experts from industry who convene weekly to review technical aspects of the platform software, including but not limited to cybersecurity. +3. The Mojaloop community operates an API change control board which is a managed group of elected subject matter experts from industry who convene weekly to review internal and external API related aspects of the platform software. This group has specific responsibility for ensuring all Mojaloop APIs are secure-by-design and support the latest and best industry standards for securing deployments of the Mojaloop platform. +4. The Mojaloop community operates a product council which is a managed group of elected subject matter experts from industry who convene weekly to review product feature designs. This group contributes to the overall cybersecurity architecture of the Mojaloop product(s) by reviewing existing and creating new requirements and specifications for Mojaloop platform and its security. +5. Mojaloop community standards require feature design and code reviews by community and foundation members who are expert in those areas of the system before code changes or new code is accepted from contributors into official releases. + + +## Technical Controls + +The Mojaloop platform employs several technical layers of security, detailed in the following sections, which contribute to an overall secure platform for conducting financial transactions. + + + +1. At network transport level, X.509 Mutually Authenticated Transport Layer Security (mTLS) is employed (best practice guidance is provided for appropriate cipher suites and hash algorithms) to secure connections between scheme participants and the Mojaloop hub. This mechanism, combined with best practice certificate and key management processes prevents eavesdropping and tampering across scheme network connections. Mojaloop provides best practice guidelines for PKI operations: [https://docs.mojaloop.io/api/fspiop/pki-best-practices.html](https://docs.mojaloop.io/api/fspiop/pki-best-practices.html). +2. Json Web Signatures (JWS) are used at the application message layer to ensure tamper evident messaging and non-repudiation. All scheme participants are provided with the means to tell if an incoming message has been tampered with during transmission. Scheme participants can also be confident of the identity of the message originator. Mojaloop services are able to use this same signature validation to ensure messages have not been tampered with before processing in the hub. +3. Mojaloop uses the [InterLedger protocol](https://docs.mojaloop.io/api/fspiop/v1.1/api-definition.html#interledger-payment-request) (aka ILP) during quotation and transfer phases, as a cryptographic key-lock mechanism, which uses asymmetric cryptography to prevent tampering with agreed transfer terms. +4. Mojaloop enforces request idempotency and transaction state transition controls which assist in mitigating replay type attacks. +5. The Mojaloop platform includes an API gateway layer, which facilitates "IP address filtering", OAuth2.0 identity and access management, and role based access controls which offer further protection against infiltration attacks. +6. Internal and external user interfaces e.g. for participants and hub operations users (technical / business), are secured with OAuth2.0 and Role Based Access Control (RBAC) mechanisms in combination with enforceable maker-checker processes (aka 4eyes). +7. Mojaloop supports a scheme wide Fraud and Risk Management Service (FRMS) model (shared between Financial service providers (FSPs) and the Mojaloop Switch / Hub). + + +![Figure 2 - Mojaloop Scheme Transactional Cybersecurity Architecture](./assets/images/mojaloop_security_layers.jpg "Figure 2 - Mojaloop Scheme Transactional Cybersecurity Architecture") + +Figure 2 - Mojaloop Scheme Transactional Cybersecurity Architecture + + +## Risk Management + + +### Security Testing + + +#### Automated Vulnerability Scanning + +Mojaloop employs a number of technical mechanisms to conduct automated vulnerability assessment against all Mojaloop platform source code repositories. These mechanisms scan code dependencies and container images for known vulnerabilities (from various continuously updated industry standard vulnerability databases) periodically and before code changes or additions are accepted to main branches. This reduces the likelihood of a known vulnerability in a Mojaloop dependency making its way into an official release. + + +#### Penetration Testing + +Members of the Mojaloop community periodically conduct penetration testing against their deployments using common security testing frameworks and share the results with the Mojaloop Foundation under a coordinated vulnerability disclosure process, whereby any newly identified risk may be mitigated by technical workstreams and/or adopters before vulnerabilities can be abused by third parties. + + +#### Community Expertise and Support + +The Mojaloop community, following the principles and processes detailed in this document, provides a software platform that embodies numerous cybersecurity features and capabilities. However, in order to realise the best possible secure operations, adopters of the Mojaloop technology are required to deploy and operate the software in a secure manner. This is often a difficult and daunting task with many applicable standards and regulations to adhere to. The Mojaloop community includes organisations with in-depth knowledge and experience in such matters who can be engaged to offer assistance. + + +## Coordinated Vulnerability Disclosure + +The Mojaloop Foundation operates a Coordinated Vulnerability Disclosure process. This process is a vulnerability disclosure model in which a vulnerability or an issue is disclosed to the public only after the responsible parties have been allowed sufficient time to patch or remedy the vulnerability or issue. + +This method is recommended by many governments and respected international organisations as the preferred process for managing software vulnerabilities as it provides protections against third-party exploitation of discovered issues beyond those provided by alternative models. + + +## Organisational Controls + +In addition to the technical cybersecurity controls described elsewhere, Mojaloop provides a range of tools to support organisational controls, reflecting the reality that although hacking attacks and fraud perpetrated by external agents generate the most media coverage, the most successful attacks in terms of the total value of money defrauded are inside jobs by a financial service’s own staff. + +In addition to the tools provided as part of Mojaloop, there are a number of recommendations that can be made regarding the business processes adopted by a hub operator which relate to the operation of the service. + + +### Control Points + +Mojaloop allows the hub operator to define control points, where the actions of an employee are subject to limitations imposed by the hub itself. Underpinning this is Mojaloop’s identity and access management capability, which implements a Role-Based Access Control (RBAC) model. Every employee action at the hub is only allowed if the employee holds a specific privilege; the hub owner defines a set of roles, each of which is a collection of privileges. An employee account is created and given a role (such as financial officer, administrator, operator etc), which then controls the functions they can perform. + +RBAC is then supplemented with maker/checker controls. Sensitive functions (such as funds movements) can be defined (“made”) by an operator, but will only be carried out when authorised (“checked”) by, for example, a financial operator. + +All employee actions are logged/recorded, in an audit log that cannot be tampered with. This allows forensic auditors to view all activity, and if necessary to “follow the money” when an issue arises due to, for example, employee/senior management collusion. + + +### Business Controls + +The operation of a Mojaloop Hub is a financial service, and the security of the service should be treated in the same way as any other financial service, such as that of a bank or an international payments switch. Business controls are the first line of defence, and limit the attack surface before the Control Points are even accessible. + +Business controls should include the following: + + + +* Cybersecurity can be undermined by malicious staff. Hub operators should conduct appropriate background checks when recruiting staff, including checks on police or criminal records and credit reference checks to identify excessive debt (vulnerability to bribery by outside attackers). +* Strict attention to the physical security of the hub operator’s premises (where access to the Mojaloop Hub is carried out - remote access, ie working from home, should **never** be allowed), including: + * There is only one, strictly controlled entrance to the hub operator’s premises. + * Other entrances are secured, and fire exits have alarms. + * All rooms are secured with biometric locks, require touch in **and** touch out to control tailgating, and access is restricted based on job function. + * Staff in customer-facing roles or in the finance department must not be allowed to have their mobile phones with them on the premises; phones should be stored in metal lockers (Faraday cages) during working hours. + * Video surveillance and 24-hour recording of all areas (cameras must face away from screens that might show sensitive information). + * Carefully check and log visitors’ identities. + * Do not permit visitors to bring any electronic equipment into operational areas. + * In non-operational areas **only**, mobile phones and laptops may be allowed. However, the serial numbers of laptops should be logged, and providers should **check to ensure visitors leave with the same equipment they brought**. Switching laptops is the fastest method of stealing data. + * Ensure visitors are accompanied by a staff member who is responsible for their conduct. + * Continually remain aware of visitors’ activity: + * Do not let visitors wander unaccompanied. + * Do not let visitors insert USB drives or other devices into company laptops, printers, etc. + +Note that this is just a subset of the controls we would expect in order to secure a Hub operator’s operations. A prospective Hub operator should seek specialist advice before launching a service. diff --git a/docs/community/tools/pragmatic-rest.md b/docs/community/tools/pragmatic-rest.md new file mode 100644 index 000000000..bb7db5ef3 --- /dev/null +++ b/docs/community/tools/pragmatic-rest.md @@ -0,0 +1,129 @@ +# Pragmatic REST + +## Pragmatic REST For the Mojaloop Project + +With the emergence of API strategy as a scaling tool for Internet service businesses, the focus on interconnect technology has shifted. Building on the principles that enabled the Web to form and scale, REST \(Representational State Transfer\) has become a design preference for Internet service APIs. But while the REST principles, proposed in Roy Fielding's dissertation that defined them, have academic value as a basis for research, a pure REST design is not at present practical for most applications. We are advocating a kind of Pragmatic REST-a design pattern that adopts the beneficial components of RESTful design without requiring strict adherence to academic purity. + +### The Richardson Maturity Model + +Martin Fowler has referenced a structured model of RESTful adoption developed by Leonard Richardson and [explained](http://www.crummy.com/writing/speaking/2008-QCon/act3.html) at a QCon talk. Fowler refers to this as the Richardson Maturity Model of RESTful design. + + + +Martin Fowler, referencing [Rest in Practice](https://www.amazon.com/gp/product/0596805829?ie=UTF8&tag=martinfowlerc-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0596805829),2 summarizes the genesis of RESTful design: + +> use Restful web services to handle many of the integration problems that enterprises face. At its heart . . . is the notion that the web is an existence proof of a massively scalable distributed system that works really well, and we can take ideas from that to build integrated systems more easily. + +A pragmatic approach to RESTful design uses the best parts of Fielding's conceptual framework to allow developers and integrators to understand what they can do with the API as rapidly as possible and without writing extraneous code. + +At its most fundamental, a RESTful design is resource-centric and uses HTTP verbs. At its most advanced, a design that follows pure academic REST utilizes the HATEOAS principle by implementing Hypermedia Controls. We are advocating a Level 2 RESTful design for Mojaloop. + +### Why not Hypermedia Controls? + +Although HATEOAS is a fascinating principle-it advocates that a server should respond to each client action with a list of all possible actions that can lead the client to its next application state. And further, clients _must not_ rely on out of band information \(like a written API spec\) for what actions can be performed on which resources or on the format of URIs. + +It is this final proscription that fails the test of Pragmatic REST: While HATEOAS is an interesting theoretical approach to limit coupling, it does not easily apply to Mojaloop \(or any other contract API design\). When we take into account our audience for the interconnect APIs, we find a group of commercial entities that will be operating under a set of highly specific scheme rules. Interactions between the participants, and between participant and central service hub, will be highly specified to assign acceptable commercial risk that can be priced at very low cost to end-users. This requires _ex-ante_ predictability of the API which is anathema to the HATEOAS principle defined by Fielding. + +### Pragmatic RESTful Principles + +#### URIs Define Resources + +A well-designed URI pattern makes an API easy to consume, discover, and extend, just as a carefully designed API does in a traditional programming language. Pure REST disdains this principle in favor of HATEOAS. But pragmatic REST follows a normal pattern for URI definitions to improve human understanding, even if HATEOAS principles are employed for discovery. + +URI paths that refer to a collection of objects should consist of a plural noun, e.g. /customers, to refer to a set of customers. When a collection can have only one instance, the singular noun should be used to avoid confusion. E.g. GET /transfers/:id/fulfillment is correct, since there is only one fulfillment object per identified transfer. + +URI paths that refer to a single object should consist of a plural noun \(representing the collection\), followed by a predefined unique identifier. E.g., /customers/123456 to refer to the specific customer with number 123456. The identifier must be unique within the containing collection and persist for the life of the object within that collection. IDs must not be ordinal values-ordinal retrieval of objects from a collection is possible using query parameters on the collection URI. + +URI paths may have a prefix to identify the environment, version, or other context of the resource. Nothing should follow the identifying path but collections and object references. + +URI path and query segment identifiers should be chosen from the Roman character set, \[0-9A-Za-z\]. Use _camelCase_ to define the elements of the URI path. Do not use snake\_case. + +For the avoidance of doubt, "\_" \(underscore\) and "-" \(hyphen\) should not be used in URI path or query segment identifiers. + +This probably seems a bit parochial. The purpose is to find a well-defined URI format that is consistent with wide-spread practice, easy to define, predictable, and that maps to native environments and conventions. It isn't going to satisfy everyone. Here is reasoning behind this constraint: + +CapitalCase and camelCase are the defacto standard for NodeJS and JavaScript and are a common constraint in URI definition: URI path segments are often mapped to JS internal resources and so conforming to JS naming conventions makes sense. + +Field names in JSON and SQL should also follow this convention since they are often automatically mapped into variable name space and can be referenced in URIs as path or query segment identifiers. + +We should also avoid the use of "$" unless it is required by a library \(e.g. JQuery\). IBM JCL has passed away; let it rest in peace. There are better scope control tools to separate name spaces than introducing non-roman symbols. + +We should avoid "-" \(hyphen\) in path segment and query parameter names as it does not map into variable names, SQL, or JSON field name identifiers. + +Underscore characters must be escaped in markdown source by prefixing each with a "\" character. + +Snake\_case has been reported to be slightly easier to read than camelCase in variable names, but it actually does not improve readability of URIs, as it visually interferes with path and query segment delimiters making it difficult to visually parse them. And when URIs are underlined in presentation, the underscores become illegible. + +#### URI Parameters + +Use a standard and predictable set of optional parameters in a consistent way. + +A set of standard query parameters should be used for collections to enable caller control over how much of the collection they see. E.g. "count" to determine how many objects to return, "start" to determine where to start counting in the result set, and "q" as a generic free-form search query. We will define the standard set of parameters as we go and will apply them consistently. + +#### Verbs + +Singular objects should support GET for read, PUT for complete replacement \(or creation when the primary key is specified by the client and is persistent, e.g. a payment card PAN\), and DELETE for delete. + +Collections should support GET to read back the whole or part of a collection, and POST to add a new object to the collection. + +Singular objects may support POST as a way to change their state in specified ways. Posting a JSON document to a singular object URI may allow selected field values to be updated or trigger a state change or action without replacing the whole object. + +GET must be implemented in a _nullipotent_ manner-that is, GET never causes side effects and never modifies client-visible system state \(other than logging events or updating instrumentation, e.g.\). + +PUT and DELETE must be implemented in an _idempotent_ manner-that is, changes are applied consistently to the system data in a way that is dependent only on the state of the resource and inputs but on nothing else. The action has no additional effect if it is executed more than once with the same input parameters and does not depend on the order of other operations on a containing collection or other resources held in the collection. For example, removing a resource from a collection can be considered an idempotent operation on the collection. Using PUT to fully replace \(or create\) a uniquely identified resource when the URI is fully known to the client is also idempotent. This implies that the system may reorder operations to improve efficiency, and the client does not need to know whether a resource exists before attempting to replace it. + +POST and PATCH3 are not idempotent operations. POST is used to create new resources where the resource identifier is assigned by the server or where a single identified internal resource is implied by the target URI \(e.g. POST /transfers, but PUT /transfers/:id/fulfillment\). + +#### Data Format + +We favor [JSON](http://json.org/)4 related data formats over XML. In some cases, data formats will be binary or XML, as defined by pre-existing standards, and these will be precisely specified. Binary formats should have a formal syntax to avoid ambiguous representational translations \(e.g. character set translations, big- or little-endian representations of numeric values, etc\). + +Date and time values used in APIs should comply to the ISO 8601 standard, and further profiled by the w3c Note on Date and Time Formats.5 This w3c note should lead to the reduction in complexity and error scope of communicating components that must exchange tangible dates and times. There will be cases where we use non-ISO format date or time as required by an external standard, e.g. ISO 7813 expiry dates. + +Existing standard XML formats should have an XSD schema for the acceptable subset profile used within the project. For particularly complex data formats, we may use a common format profile translator to map between our project subset of the standard format and the wire format used by a standardized protocol \(e.g.\). This will limit coupling to complex formats in a more maintainable way. + +When specifying the PATCH action for a resource, we will use a consistent patch document format \(e.g. [JSON Patch](http://jsonpatch.com/)6\). + +#### Return Codes + +Use HTTP return codes in a consistent way and according to their standard definitions. The standard codes are defined in RFC 2616.7 + +#### Machine Readable Error Format + +The API should provide a machine readable error result in a well-defined JSON format. {TBD whether to use a response envelope and how to format errors, faults, and success envelopes. RESTful design relies on headers to carry protocol-defined errors, debug info can also be carried in headers. We should be clear on why we are using an envelope and how this supports normal production communication between client and server. + +#### Versioning + +API URIs should include a version identifier in the format v_M_ as a leading path element \(where _"M"_ is the Major component of the multi-part version number\). The API and its version identifier element must conform to the [semantic versioning](http://semver.org/)8 2.0 specification for API versioning. + +A client must specify the Major version number in each request. It is not possible for a client to express a requirement for a specific minor version. + +The full API version number is specified in the response header \(TBD\) for all successful and error responses. + +While an API version contract will be influenced by Major, minor, _and_ patch levels, only the Major version number is a production API binding element-that is, a production client cannot request a particular minor version or patch level and a production server will not accept a URI request that specifies these extra elements. + +However, in pre-production environments, it is anticipated that some combination of minor, patch, pre-release, and metadata suffixes would be supported in client requests \(as defined in _semver_ \[3\]\) and _may_ be expressed in _pre-production_ URIs to assist with development and integration scenarios. + +### We May Need to Give REST a Rest + +As we design the interconnection APIs between components and between participating systems, we may find API requirements that don't precisely match the Pragmatic REST pattern defined here. We will evaluate these case-by-case and make the best choice to support the project goals. + +### Non-Functional Requirements + +As we develop the APIs, we will make consistent choices about non-functional requirements to reinforce the project goals. + +1: [http://martinfowler.com/articles/richardsonMaturityModel.html](Richardson%20Maturity%20Model), retrieved August 18, 2016. + +2: [https://www.amazon.com/gp/product/0596805829](https://www.amazon.com/gp/product/0596805829?ie=UTF8&tag=martinfowlerc-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0596805829), retrieved August 18, 2016. + +3: RFC 5789, _PATCH Method for HTTP_, [https://tools.ietf.org/html/rfc5789](https://tools.ietf.org/html/rfc5789), retrieved August 18, 2016. + +4: _Introducing JSON_, [http://json.org/](http://json.org/), retrieved August 18, 2016. + +5: [http://www.w3.org/TR/1998/NOTE-datetime-19980827](http://www.w3.org/TR/1998/NOTE-datetime-19980827), retrieved August 22, 2016. + +6: _JSON Patch_, [http://jsonpatch.com/](http://jsonpatch.com/), retrieved August 18, 2016. + +7: [https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) + +8: _Semantic Versioning 2.0.0_, [http://semver.org/](http://semver.org/), retrieved August 18, 2016. \ No newline at end of file diff --git a/docs/community/tools/test.md b/docs/community/tools/test.md new file mode 100644 index 000000000..0527e6bd2 --- /dev/null +++ b/docs/community/tools/test.md @@ -0,0 +1 @@ +This is a test diff --git a/docs/community/tools/tools-and-technologies.md b/docs/community/tools/tools-and-technologies.md new file mode 100644 index 000000000..36600635d --- /dev/null +++ b/docs/community/tools/tools-and-technologies.md @@ -0,0 +1,51 @@ +# Tools and Technologies + +Here we document the reasoning behind certain tools, technology and process choices for Mojaloop. We also have included the recommendation links/versions for each of these tools. + +**TOOL CHOICES** + +* **API Development** + * **Open API 3.0 ** is leveraged for API development (Swagger 2.0 earlier). + * ** ISTIO** as the API Gateway (WSO2 now outdated with Mojaloop v16.0.0 - Congo and IaC v5.0.0 onwards) offers an enterprise platform for integrating APIs, applications, and web services—locally and across the Internet. It also provides Mojaloop with a Security Layer, and Development Portal. +* **Circle-CI** - This tool is used for continuous build and continuous deployment. We needed an online continuous build and testing system that can work with many small projects and a distributed team. Jenkins was considered, but it requires hosting a server and a lot of configuration. CircleCI allowed for a no host solution that could be started with no cost and very limited configuration. We thought we might start with CircleCI and move off later if we outgrew it, but that hasn’t been needed. +* **Dactyl** – We need to be able to print the online documentation. While it’s possible to print markdown files directly one at a time, we’d like to put the files into set of final PDF documents, where one page might end up in more than one final manual. [Dactyl](https://github.com/ripple/dactyl) is a maintained open source conversion tool that converts between markdown and PDF. We originally tried Pandoc, but it had bugs with converting tables. Dactyl fixes that and is much more flexible. +* **DBeaver** - [DBeaver](https://dbeaver.io/) is a free multi-platform database tool for developers, SQL programmers, database administrators and analysts. Supports all popular databases: MySQL, PostgreSQL, MariaDB, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Derby, etc. +* **Docker** - The Docker container engine creates and runs the Docker container from the Docker image file. +* **Docker hub** is used to link, build, test and push the Mojaloop code repositories. We needed to support both local and cloud execution. We have many small microservices that have very simple specific configurations and requirements. The easiest way to guarantee that the service works the same way in every environment from local development, to cloud, to hosted production is to put each microservice in a Docker container along with all the prerequisites it needs to run. The container becomes a secure, closed, pre-configured, runnable unit. +* **Draw.io** – We need to create pictures for our documents and architecture diagrams using an \(ideally free\) open source friendly tool, that is platform agnostic, supports vector and raster formats, allows WYSIWYG drawing, works with markdown, and is easy to use. We looked at many tools including: Visio, Mermaid, PlantUML, Sketchboard.io, LucidChart, Cacoo, Archi, and Google Drawings. Draw.io scored at the top for our needs. It’s free, maintained, easy to use, produces our formats, integrates with DropBox and GitHub, and platform agnostic. In order to save our diagrams, we have to save two copies – one in SVG \(scalable vector\) format and the other in PNG \(raster\). We use the PNG format within the docs since it can be viewed directly in GitHub. The SVG is used as the master copy as it is editable. +* **ESLint** - Within JavaScript code, we use [ESLint](https://eslint.org/) as a code style guide and style enforcement tool. +* **GitHub** – [GitHub](https://github.com/Mojaloop) is a widely-used source code repository service, based on git, the standard source code version control system for open source projects. So the decision to use GitHub was straightforward. We create a story every time for integration work. Create bugs for any issues. Ensure all stories are tracked throughout the pipeline to ensure reliable metrics. +* **Helm** - The Helm package manager for Kubernetes provides templatized deployments and configurations and allow for overall complexity management. +* **IaC** - Infrascture as Code (IaC) is the tooling, scripts used to deploy a Mojaloop platform at the desired quality level, ranging from development, qa or sandboxes to pre-production or even extended for production quality deployments. This uses the Mojaloop releases as the core and deploys the entire supporting toolset needed to run the Mojaloop Platform for a Mojaloop Switch. +* **Kafka** - This technology is leveraged to support Mojaloop’s demand for a high velocity and high volume data messaging but keep our hardware requirements minimum. +* **JavaScript** - The Mojaloop application is primarily written in JavaScript. +* **Kubectl** - This is a command line interface for running commands against Kubernetes clusters. +* **Kubernetes** - This enterprise tool provides an extraction layer, infrastructure management and a container-orchestration system. +* **Markdown** – Documentation is a deliverable for this project, just like the code, and so we want to treat it like the code in terms of versioning, review, check in, and tracking changes. We also want the documentation to be easily viewable online without constantly opening a viewer. GitHub has a built-in format called Markdown which solves this well. The same files work for the Wiki and the documents. They can be reviewed with the check in using the same tools and viewed directly in GitHub. We considered Google Docs, Word and PDF, but these binary formats aren’t easily diff-able. A disadvantage is that markdown only allows simple formatting – no complex tables or font changes - but this should be fine when our main purpose is clarity. +* **Mojaloop Testing Toolkit (TTK)** – [Mojaloop Testing Toolkit](https://github.com/mojaloop/ml-testing-toolkit)) is a Swiss-knife tool for Mojaloop related activities, primarily used for end-to-end testing, demonstrations, mocking APIs and in several other extended scenarios. The Mojaloop test collections use the ML TTK and it is the tool of preference for end-to-end testing, which is also integrated into the scripts for automated testing (using TTK CLI in IaC and other dev/qa environments). +* **MySQLWorkbench** – [MySQL Workbench](https://www.mysql.com/products/workbench/) is a unified visual tool for database architects, developers, and DBAs. MySQL Workbench provides data modeling, SQL development, and comprehensive administration tools for server configuration, user administration, backup, and much more. MySQL Workbench is available on Windows, Linux and Mac OS X. +* **NodeJS** - This development tool is a JavaScript runtime built on Chrome's V8 JavaScript engine that runs Mojaloop. NodeJS is designed to create simple microservices and it has a huge set of open source libraries available. Node performance is fine and while Node components don’t scale vertically a great deal, but we plan to scale horizontally, which it does fine. The original Interledger code was written in NodeJS as was the level one prototype. Most teams used Node already, so this made sense as a language. Within NodeJS code, we use [Standard](https://www.npmjs.com/package/standard) as a code style guide and to enforce code style. +* **NPM** - NPM is the package manager for Mojaloop since JavaScript is the default programming language. +* **Percona** for **MySQL** - These tools are leveraged as a relational database management system to ensure high performance and enterprise-grade functionality for the Mojaloop system. We needed a SQL backend that is open source friendly and can scale in a production environment. Thus, we chose MySQL, an open-source relational database management system. +* **Postman** is a Google Chrome application for interacting with HTTP APIs. It presents you with a friendly GUI for constructing requests and reading responses. +* **Rancher 2.0** - The Infrastructure management, provisioning and monitoring is provided by Rancher 2.0 which is an enterprise Kubernetes platform that manage Kubernetes deployments, clusters, on cloud & on-prem. Rancher makes it easy for DevOps teams to test, deploy and manage the Mojaloop system no matter where it is running. +* **Slack** – Slack is used for internal team communication. This was largely picked because several team already used it and liked it as a lightweight approach compared to email. +* **SonarCloud** – We need an online dashboard of code quality \(size, complexity, issues, and coverage\) that can aggregate the code from all the repos. SonarCloud for Mojaloop is free, with some setup. This also offers quality checks on Pull Requests and offers ratings based on the quality gates applied. +* **SourceTree** – [Sourcetree](https://www.sourcetreeapp.com/) simplifies how you interact with your Git repositories so you can focus on coding. Visualize and manage your repositories through Sourcetree's simple Git GUI. But this is up to the developer to use their tool of choice following general GitHub recommendations. +* **Visual Studio Code** - [Visual Studio Code](https://code.visualstudio.com/) is a code editor redefined and optimized for building and debugging modern web and cloud applications. Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows. +* **ZenHub** – We needed a project management solution that was very light weight and cloud based to support distributed teams. It had to support epics, stories, and bugs and a basic project board. VS and Jira online offerings were both considered. For a small distributed development team an online service was better. For an open source project, we didn’t want ongoing maintenance costs of a server. Direct and strong GitHub integration was important. It was very useful to track work for each microservice with that microservice. Jira and VS both have more overhead than necessary for a project this size and don’t integrate as cleanly with GitHub as we’d want. ZenHub allowed us to start work immediately. A disadvantage is the lack of support for cumulative flow diagrams and support for tracking \# of stories instead of points, so we do these manually with a spreadsheet updated daily and the results published to the "Project Management" Slack channel. + +**TECHNOLOGY CHOICES** + +* **Agile development** - This methodology is used to track and run the project. The requirements need to be refined as the project is developed, therefore we picked agile development over waterfall or lean. +* **APIs** - In order to avoid confusion from too many changing microservices, we use strongly defined APIs that conform to our [Pragmatic REST](pragmatic-rest.md) design pattern. APIs will be defined using OpenAPI. Teams document their APIs with Swagger v2.0 or RAML v0.8 so they can automatically test, document, and share their work. Swagger is slightly preferred as there are free tools. Mule will make use of RAML 0.8. Swagger can be automatically converted to RAML v0.8, or manually to RAML v1.0 if additional readability is desired. +* **Automated Testing** - For the most part, most testing will be automated to allow for easy regression testing. See the [automated testing strategy](automated-testing.md) and [code quality metrics](code-quality-metrics.md) for standards. +* **Hosting** - Mojaloop has been designed to be infrastructure agnostic and as such is supported by AWS, Azure and On-Premise installations. +* **Interledger** – Mojaloop needed a lightweight, open, and secure transport protocol for funds. [Interledger.org](http://Interledger.org) provides all that. It also provides the ability to connect to other systems. We also considered block chain systems, but block chain systems send very large messages which will be harder to guarantee delivery of in third world infrastructure. Also, while blockchain systems provide good anonymity, that is not a project goal. To enable fraud detection, regulatory authorities need to be able to request records of transfers by account and person. +* **Open source** - The entire project has been released as open source in accordance with the [Level One Project principles](https://leveloneproject.org/wp-content/uploads/2016/03/L1P_Level-One-Principles-and-Perspective.pdf). All tools and processes must be open source friendly and support projects that use an Apache 2.0 license with no restrictive licenses requirements on developers. +* **Operating System** – Microsoft Windows is widely used in many target countries, but we need an operating system that is free of license fees and is open source compatible. We are using Linux. We don’t have a dependency on the particular flavor, but are using the basic Amazon Linux. In the Docker containers, [Alpine Linux](https://alpinelinux.org/) is used. +* **Microservices** - Because the architecture needs to easily deploy, scale, and have components be easily replaced or upgraded, it will be built as a set of microservices. +* **Scaled Agile Framework** - There were four initial development teams that are geographically separate. To keep the initial phase of the project on track, the [scaled agile framework \(SAFe\)](https://www.scaledagileframework.com/) was picked. This means work is divided into program increments \(PI\) that are typically four 2 week sprints long. As with the sprints, the PI has demo-able objective goals defined in each PI meeting. +* **Services** - Microservices are grouped and deployed in a few services such as the DFSP, Central Directory, etc. Each of these will have simple defined interfaces, configuration scripts, tests, and documentation. +* **Threat Modeling, Resilience Modeling, and Health Modeling** - Since the Mojaloop code needs to exchange money in an environment with very flaky infrastructure it must have good security, resilience, and easily report it's health state and automatically attempt to return to it. +* **USSD** - Smart phones are only 25% of the target market and not currently supported by most money transfer service, so we need a protocol that will work on simple feature phones. Like M-Pesa, we are using USSD between the phone and the digital financial service provider \(DFSP\). diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md new file mode 100644 index 000000000..29ea5c047 --- /dev/null +++ b/docs/getting-started/README.md @@ -0,0 +1,24 @@ +# Your First Action + +To help get you started with Mojaloop, select which of the options below best suits your needs: + + +1. [Frequently Asked Questions](./faqs) +2. [License](./license.md) +3. [Review Mojaloop APIs](/api/) +4. [Take a training program](https://mojaloop.io/mojaloop-training-program/) +5. [Contribute to Mojaloop](/community/) +6. [Install Mojaloop](./installation/installing-mojaloop.md) +7. [Demos](./demos/mojaloop-overview.md) + + 7.1. [Why Mojaloop?](./demos/why-mojaloop.md) + + 7.2. [Working with Mojaloop?](./demos/working-with-mojaloop.md) + + 7.3. [Financial inclusion 101 ](./demos/financial-inclusion-101.md) + + 7.4. [What is RTP?](./demos/what-is-rtp.md) + + 7.5. [What Makes a Successful Financial Ecosystem?](./demos/what-makes-a-successful-financial-ecosystem.md) + + 7.6. [Inside the Loop](./demos/inside-the-loop.md) diff --git a/docs/getting-started/demo-one.md b/docs/getting-started/demo-one.md new file mode 100644 index 000000000..e8071921d --- /dev/null +++ b/docs/getting-started/demo-one.md @@ -0,0 +1,3 @@ +# Demo One + +Details of Demo one goes here diff --git a/docs/getting-started/demo.md b/docs/getting-started/demo.md new file mode 100644 index 000000000..245a52d18 --- /dev/null +++ b/docs/getting-started/demo.md @@ -0,0 +1,6 @@ +# Demos + +## Demos List + +TODO: A list of demos + diff --git a/docs/getting-started/demos/financial-inclusion-101.md b/docs/getting-started/demos/financial-inclusion-101.md new file mode 100644 index 000000000..feaab07f2 --- /dev/null +++ b/docs/getting-started/demos/financial-inclusion-101.md @@ -0,0 +1,11 @@ +# Financial Inclusion 101 + + \ No newline at end of file diff --git a/docs/getting-started/demos/inside-the-loop.md b/docs/getting-started/demos/inside-the-loop.md new file mode 100644 index 000000000..8d7842c9e --- /dev/null +++ b/docs/getting-started/demos/inside-the-loop.md @@ -0,0 +1,26 @@ +# Inside the Loop + + +## Part 1 + + + +## Part 2 + + \ No newline at end of file diff --git a/docs/getting-started/demos/mojaloop-overview.md b/docs/getting-started/demos/mojaloop-overview.md new file mode 100644 index 000000000..46b479495 --- /dev/null +++ b/docs/getting-started/demos/mojaloop-overview.md @@ -0,0 +1,11 @@ +# Mojaloop Overview + + \ No newline at end of file diff --git a/docs/getting-started/demos/what-is-rtp.md b/docs/getting-started/demos/what-is-rtp.md new file mode 100644 index 000000000..394347196 --- /dev/null +++ b/docs/getting-started/demos/what-is-rtp.md @@ -0,0 +1,11 @@ +# What is RTP? + + \ No newline at end of file diff --git a/docs/getting-started/demos/what-makes-a-successful-financial-ecosystem.md b/docs/getting-started/demos/what-makes-a-successful-financial-ecosystem.md new file mode 100644 index 000000000..45c0b43fc --- /dev/null +++ b/docs/getting-started/demos/what-makes-a-successful-financial-ecosystem.md @@ -0,0 +1,11 @@ +# What Makes a Successful Financial Ecosystem? + + \ No newline at end of file diff --git a/docs/getting-started/demos/why-mojaloop.md b/docs/getting-started/demos/why-mojaloop.md new file mode 100644 index 000000000..5230c5e03 --- /dev/null +++ b/docs/getting-started/demos/why-mojaloop.md @@ -0,0 +1,11 @@ +# Why Mojaloop? + + \ No newline at end of file diff --git a/docs/getting-started/demos/working-with-mojaloop.md b/docs/getting-started/demos/working-with-mojaloop.md new file mode 100644 index 000000000..febc571b9 --- /dev/null +++ b/docs/getting-started/demos/working-with-mojaloop.md @@ -0,0 +1,11 @@ +# Working with Mojaloop + + \ No newline at end of file diff --git a/docs/getting-started/faqs.md b/docs/getting-started/faqs.md new file mode 100644 index 000000000..7193a2036 --- /dev/null +++ b/docs/getting-started/faqs.md @@ -0,0 +1,6 @@ +# Frequently Asked Questions + +This document contains some of the most frequently asked questions from the community. + +- [General FAQs](/getting-started/general-faqs) +- [Technical FAQs](/getting-started/technical-faqs) \ No newline at end of file diff --git a/docs/getting-started/general-faqs.md b/docs/getting-started/general-faqs.md new file mode 100644 index 000000000..5afab4b63 --- /dev/null +++ b/docs/getting-started/general-faqs.md @@ -0,0 +1,59 @@ +# General FAQs + +This document contains some of the most frequently asked questions from the community. + +## 1. What is Mojaloop? + +Mojaloop is open-source software for building interoperable digital payments platforms on a national scale. It makes it easy for different kinds of providers to link up their services and deploy low-cost financial services in new markets. + + +## 2. How does it work? + +Most digital financial providers run on their own networks, which prevents customers who use different services from transacting with each other. Mojaloop functions like a universal switchboard, routing payments securely between all customers, regardless of which network they're on. It consists of three primary layers, each with a specific function: an interoperability layer, which connects bank accounts, mobile money wallets, and merchants in an open loop; a directory service layer, which navigates the different methods that providers use to identify accounts on each side of a transaction; a transactions settlement layer, which makes payments instant and irrevocable; and components which protect against fraud. + +## 3. Who is it for? + +There are many components to the code, and everyone either directly or indirectly working with digital financial transactions-fintech developers, bankers, entrepreneurs, startups-is invited to explore and use whatever parts are useful or appealing. The software as a whole is meant to be implemented on a national scale, and so it will be most applicable to mobile money providers, payments associations, central banks, and country regulators. + +Developers at fintech and financial services companies can use the code in three ways: adapt the code to the financial services standards for a country, use the code to update their own products and services or create new ones, and improve the code by proposing updates and new versions of it for other users. + +For example: + +- A central bank may commission the use of the software by their commercial partners to speed up the deployment of a national payment gateway. +- A major payment processor can use the software to modernize their current offering, to achieve lower transaction costs without major R&D investments. +- A fintech startup can use the code to understand practically how to comply with interoperable payment APIs. +- A bank can use the code to modify their internal systems so that they easily interoperate with other payment providers. + +## 4. Why does it exist? + +Providers trying to reach developing markets with innovative, low-cost digital financial services have to build everything on their own. This raises costs and segregates services from each other. Mojaloop can be used as a foundation to help build interoperable platforms, lowering costs for providers and allowing them to integrate their services with others in the market. + +## 5. Who's behind it? + +Mojaloop was built in collaboration with a group of leading tech and fintech companies: [Ripple](https://github.com/ripple), [Dwolla](https://github.com/dwolla), [Software Group](http://www.softwaregroup-bg.com/), [ModusBox](http://www.modusbox.com/) and [Crosslake Technologies](http://www.crosslaketech.com/). Mojaloop was created by the Gates Foundation's Mojaloop, which is aimed at leveling the economic playing field by crowding in expertise and resources to build inclusive payment models to benefit the world's poor. It is free to the public as open-source software under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0). + +## 6. What platforms does Mojaloop run on? + +The Mojaloop platform was developed for modern cloud-computing environments. Open-source methods and widely used platforms, like Node.js, serve as the foundation layer for Mojaloop. The microservices are packaged in Docker and can be deployed to local hardware or to cloud computing environments like Amazon Web Services or Azure. + +## 7. Is it really open-source? + +Yes, it is really open-source. All core modules, documentation and white papers are available under a [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0). Mojaloop relies on commonly used open-source software, including node.js, MuleCE, Java and PostgreSQL. Mojaloop also uses the [Interledger Protocol](https://github.com/interledger) to choreograph secure money transfers. The licenses for all of these platforms and their imported dependencies allow for many viable uses of the software. + +## 8. How can I contribute to Mojaloop? + +You can contribute by helping us create new functionality on our roadmap or by helping us improve the platform. For our roadmap, go to the [Mojaloop Roadmap](../mojaloop-roadmap.md). We recommend starting with the onboarding guide and sample problem. This has been designed by the team to introduce the core ideas of the platform and software, the build methods, and our process for check-ins. + +## 9. Using Mojaloop to do payment using crypto-currency? + +Not with the current Specification and with this platform. Currently this is limited to currencies listed in the ISO 4217. Since the specification and platform is all about digital transfers, it should be possible to investigate a use-case for this possible requirement. Alternatively, I guess an FSP can provide that conversion (like many do already from crypto to one of the listed currencies). + +## 10. How is the Mojaloop source accessible? + +Here are some resources to start with: +1. Docs: https://github.com/mojaloop/documentation. +2. Look at the repos that have “CORE COMPONENT (Mojaloop)” in the description and these are core components. “CORE RELATED (Mojaloop)” repos are the ones that are needed to support the current Mojaloop Switch implementation/deployment. +3. As a generic point of note, for latest code, please use the ‘develop’ branch for the time-being. +4. Current architecture: https://github.com/mojaloop/docs/tree/master/Diagrams/ArchitectureDiagrams. Please note that these are currently being migrated to https://github.com/mojaloop/documents. +5. You may use this for current deployment architecture and deployment information: https://github.com/mojaloop/documentation/tree/master/deployment-guide. + diff --git a/docs/getting-started/installation/installing-mojaloop.md b/docs/getting-started/installation/installing-mojaloop.md new file mode 100644 index 000000000..3aaa4011b --- /dev/null +++ b/docs/getting-started/installation/installing-mojaloop.md @@ -0,0 +1,16 @@ +# Installing Mojaloop + +Mojaloop is packaged and released as a set of [Helm Charts](https://github.com/mojaloop/helm) with various options for deployment and customization. +Even if you are new to Mojaloop and unfamiliar with [Helm](https://helm.sh) / [Kubernetes](https://kubernetes.io) or if you just want to get the software up and running quickly, there are several options avaiable to deploy Mojaloop. + +1. **Manual Deployment** - The Mojaloop [Deployment Guide](../../technical/deployment-guide/) is intended for those familiar with [Kubernetes](https://kubernetes.io) and [Helm](https://helm.sh). This is a great place to start if you are thinking of deploying Mojaloop on an existing Kubernetes environment, or if you are interested in setting one up yourself. + +2. **IaC (Infrastructure as Code)** - A comprehensive Mojaloop deployment aimed at giving users a starting point for production. IaC is highly automated ([Terraform](https://www.terraform.io), [Ansible](https://www.ansible.com)) and is extensible. To learn more about an the IaC review the [IaC Deployment blog](https://infitx.com/deploying-mojaloop-using-iac). + + IaC currently supports the following modular configurations: + - [IaC AWS (Amazon Web Services) Platform](https://github.com/mojaloop/iac-aws-platform) + - On-Prem (Coming Soon) + +3. **Mini-Loop** - Install utilities for Mojaloop that offers an easy and efficient way to get started. The [mini-Loop](https://github.com/tdaly61/mini-loop) scripts enable you to deploy Mojaloop in the cloud or on your laptop / server with just a couple of commands. You can then easily run the [Mojaloop Testing Toolkit](https://github.com/mojaloop/ml-testing-toolkit#mojaloop-testing-toolkit) to interact and test your deployment. + +4. **Azure Marketplace** - This is an Azure AKS native deployment and aims to give users a starting point for POC or pilot testing. It is a simple deployment, with highly automated Microsoft ARM templates and deploys to managed Kubernetes for easier management. Run the [Mojaloop Testing Toolkit](https://github.com/mojaloop/ml-testing-toolkit#mojaloop-testing-toolkit) to interact and test your deployment. Refer to the [PI 21 Mojaloop Azure Presentation](https://github.com/mojaloop/documentation-artifacts/blob/master/presentations/pi_21_march_2023/presentations/Mojaloop%20Azure%20Deployment.pdf) for more information. diff --git a/docs/getting-started/license.md b/docs/getting-started/license.md new file mode 100644 index 000000000..65a7f20bf --- /dev/null +++ b/docs/getting-started/license.md @@ -0,0 +1,10 @@ +# LICENSE + +Copyright © 2020-2024 Mojaloop Foundation + +The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 +(the "License") and you may not use these files except in compliance with the [License](http://www.apache.org/licenses/LICENSE-2.0). + +You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) + +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the [License](http://www.apache.org/licenses/LICENSE-2.0). diff --git a/docs/getting-started/quickstart-one.md b/docs/getting-started/quickstart-one.md new file mode 100644 index 000000000..4148ea4d6 --- /dev/null +++ b/docs/getting-started/quickstart-one.md @@ -0,0 +1,3 @@ +# Quickstart One + +Quickstart goes here \ No newline at end of file diff --git a/docs/getting-started/quickstart-two.md b/docs/getting-started/quickstart-two.md new file mode 100644 index 000000000..ada2469e4 --- /dev/null +++ b/docs/getting-started/quickstart-two.md @@ -0,0 +1,3 @@ +# Quickstart Two + +Quickstart two goes here \ No newline at end of file diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md new file mode 100644 index 000000000..0ed1d5a64 --- /dev/null +++ b/docs/getting-started/quickstart.md @@ -0,0 +1,3 @@ +# Quickstarts + +View a list of quickstarts here \ No newline at end of file diff --git a/docs/getting-started/technical-faqs.md b/docs/getting-started/technical-faqs.md new file mode 100644 index 000000000..04674b55a --- /dev/null +++ b/docs/getting-started/technical-faqs.md @@ -0,0 +1,160 @@ +# Technical FAQs + +This document contains some of the frequently asked technical questions from the community. + +## 1. What is supported? + +Currently the Central ledger components are supported by the team. The DFSP components are outdated and thus the end-to-end environment and full setup is challenging to install. + +## 2. Can we connect directly to Pathfinder in a development environment? + +For the local and test environment, we recommend interfacing with the 'mock-pathfinder' service instead. Pathfinder is a 'paid by usage' service. + +Access the https://github.com/mojaloop/mock-pathfinder repository to download and install mock-pathfinder. Run command npm install in mock-pathfinder directory to install dependencies after this update Database_URI in mock-pathfinder/src/lib/config.js. + +## 3. Should i register DFSP via url http://central-directory/commands/register or i need to update configuration in default.json? + +You should register using the API provided, using postman or curl. Client is using LevelOne code. Needs to implement the current Mojaloop release with the current Postman scripts. + +## 4. Status of the pod pi3-kafka-0 is still on CrashLoopBackOff? + +- More background related to the question: + + When I tired to get logs of the container centralledger-handler-admin-transfer, I get the following error: + Error from server (BadRequest): container "centralledger-handler-admin-transfer" in pod "pi3-centralledger-handler-admin-transfer-6787b6dc8d-x68q9" is waiting to start: PodInitializing + And the status of the pod pi3-kafka-0 is still on CrashLoopBackOff. + I am using a vps on ubuntu 16.04 with RAM 12GB, 2vCores, 2.4GHz, Rom 50GB at OVH for the deployment. + +Increased RAM to 24 GB and CPU to 4 resolved the issues. Appears to be a timeout on Zookeeper due depletion of available resources, resulting in the services shutting down. + +## 5. Why am I getting an error when we try to create new DFSP using Admin? + +Please insure you are using the most current Postman scripts available on https://github.com/mojaloop/mock-pathfinder repository. + + +## 6. Can I spread Mojaloop components over different physical machines and VM's? + +You should be able to setup on different VM's or physical machines. The distribution pretty much depend on your requirements and would be implementation specific. We utilise Kubernetes to assist with the Container Orchestration. This enables us to schedule the deployments through the Kubernetes runtime to specific machines if required, and request specific resources if required. The helm charts in the helm repository could be used as guideline to how best allocate and group the components in your deployment. Naturally you would need to update the configurations to complement your custom implementation. + +## 7. Can we expect all the endpoints defined in the API document are implemented in Mojaloop? + +The Mojaloop Specification API for transfers and the Mojaloop Open Source Switch implementation are independent streams, though obviously the implementation is based on the Specification. Based on the use-cases prioritized for a time-frame and based on the end-points needed to support those use-cases, implementation will be done. If a few end-points are not prioritized then implementation for them may not be available. However, I think the goal is to eventually support all the end-points specified though it may take time. Thanks for the collection. We do have some of these on the ‘postman’ repo in the mojaloop GitHub org. + +## 8. Does Mojaloop store the payment initiator FSP’s quote/status info? + +At the moment, the Mojaloop Open source Switch implementation does *not* store Quotes related information. The onus is on the Payer, Payee involved in the process to store the relevant information. + +## 9. Does Mojaloop handle workflow validation? + +Not at the moment, but this may happen in the future. Regarding correlating requests that are related to a specific transfer, you may look at the ‘transaction’ end-point/resource in the Specification for more information on this. In addition to this, I can convey that some background work is ongoing regarding the specification to make this correlation more straight-forward and simpler i.e., to correlate quote and transfer requests that come under a single transaction. + + +## 10. How to register a new party in Mojaloop? + +There is no POST on /parties resource, as specified in section 6.1.1 of the API Defintion. Please refer to section: 6.2.2.3 `POST /participants//` in the API Defintion. + +” _The HTTP request `POST /participants//` (or `POST /participants///`) is used to create information on the server regarding the provided identity, defined by ``, ``, and optionally `` (for example, POST_ + _/participants/MSISDN/123456789 or POST /participants/BUSINESS/shoecompany/employee1). See Section 5.1.6.11 for more information regarding addressing of a Party._ ”. + +## 11. Does the participant represent an account of a customer in a bank? + +For more on this, please refer to this doc (Section 3..2): https://github.com/mojaloop/mojaloop-specification/blob/develop/Generic%20Transaction%20Patterns.pdf. + +” _In the API, a Participant is the same as an FSP that is participating in an Interoperability Scheme. The primary purpose of the logical API resource Participants is for FSPs to find out in which other FSP a counterparty in an interoperable financial transaction is located. There are also services defined for the FSPs to provision information to a common system._ ” + +In essence, a participant is any FSP participating in the Scheme (usually not a customer). For account lookup, a directory service such as *Pathfinder* can be used, which provides user lookup and the mapping. If such a directory service is not provided, an alternative is provided in the Specification, where the Switch hosts an Account Lookup Service (ALS) but to which the participants need to register parties. I addressed this earlier. But one thing to note here is that the Switch does not store the details, just the mapping between an ID and an FSP and then the calls to resolve the party are sent to that FSP. + +https://github.com/mojaloop/mojaloop-specification CORE RELATED (Mojaloop): + +This repo contains the specification document set of the Open API for FSP Interoperability - mojaloop/mojaloop-specification. + +## 12. How to register _trusted_ payee to a payer, to skip OTP? + +To skip the OTP, the initial request on the /transactionRequests from the Payee can be programmatically (or manually for that matter) made to be approved without the use of the /authorizations endpoint (that is need for OTP approval). Indeed the FSP needs to handle this, the Switch does not. This is discussed briefly in section 6.4 of the Specification. + +## 13. Receiving a 404 error when attempting to access or load kubernetes-dashboard.yaml file? + +From the official kubernetes github repository in the README.md, the latest link to use is "https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml". Be sure to always verify 3rd party links before implementing. Open source applications are always evolving. + +## 14. When installing nginx-ingress for load balancing & external access - Error: no available release name found? + +Please have a look at the following addressing a similar issue. To summarise - it is most likely an RBAC issue. Have a look at the documentation to set up Tiller with RBAC. https://docs.helm.sh/using_helm/#role-based-access-control goes into detail about this. The issue logged: helm/helm#3839. + +## 15. Received "ImportError: librdkafka.so.1: cannot open shared object file: No such file or directory" when running `npm start' command. + +Found a solution here https://github.com/confluentinc/confluent-kafka-python/issues/65#issuecomment-269964346 +GitHub +ImportError: librdkafka.so.1: cannot open shared object file: No such file or directory · Issue #65 · confluentinc/confluent-kafka-python +Ubuntu 14 here, pip==7.1.2, setuptools==18.3.2, virtualenv==13.1.2. First, I want to build latest stable (seems it's 0.9.2) librdkafka into /opt/librdkafka. curl https://codeload.github.com/ede... + +Here are the steps to rebuild librdkafka: + +git clone https://github.com/edenhill/librdkafka && cd librdkafka && git checkout ` + +cd librdkafka && ./configure && make && make install && ldconfig + +After that I'm able to import stuff without specifying LD_LIBRARY_PATH. +GitHub +edenhill/librdkafka +The Apache Kafka C/C++ library. Contribute to edenhill/librdkafka development by creating an account on GitHub. + +## 16. Can we use mojaloop as open-source mobile wallet software or mojaloop does interoperability only? + +We can use mojaloop for interoperability to support mobile wallet and other such money transfers. This is not a software for a DFSP (there are open source projects that cater for these such as Finserv etc). Mojaloop is for a Hub/Switch primarily and an API that needs to be implemented by a DFSP. But this is not for managing mobile wallets as such. + +## 17. Describe companies that helps to deploy & support for mojaloop? + +Mojaloop is an open source software and specification. + +## 18. Can you say something about mojaloop & security? + +The Specification is pretty standard and has good security standards. But these need to be implemented by the adopters and deployers. Along with this, the security measures need to be coupled with other Operational and Deployment based security measures. Moreover, the coming few months will focus on security perspective for the Open Source community. + +## 19. What are the benefit(s) from using mojaloop as interoperabilty platform? + +Benefits: Right now for example, an Airtel mobile money user can transfer to another Airtel mobile money user only. With this, he/she can transfer to any Financial service provider such as another mobile money provider or any other bank account or Merchant that is connected to the Hub, irrespective of their implementation. They just need to be connected to the same Switch. Also, this is designed for feature phones so everyone can use it. + +## 20. What are the main challenges that companies face using mojaloop? + +At this point, the main challenges are around expectations. Expectations of the adopters of mojaloop and what really mojaloop is. A lot of adopters have different understanding of what mojaloop is and about its capabilities. If they have a good understanding, a lot of current challenges are mitigated.. +Yes, forensic logging is a security measure as well for auditing purposes which will ensure there is audit-able log of actions and that everything that is a possible action of note is logged and rolled up, securely after encryption at a couple of levels. + +## 21. Is forensic logging/audit in mojaloop , is it related with securing the inter-operability platform? + +This also ensures all the services always run the code they’re meant to run and anything wrong/bad is stopped from even starting up. Also, for reporting and auditors, reports can have a forensic-log to follow. + +## 22. How do the financial service providers connect with mojaloop? + +There is an architecture diagram that presents a good view of the integration between the different entities. https://github.com/mojaloop/docs/blob/master/Diagrams/ArchitectureDiagrams/Arch-Flows.svg. + +## 23. Is there any open source ISO8583-OpenAPI converter/connector available? + +I don't believe a generic ISO8583 `<-> Mojaloop integration is available currently. We're working on some "traditional payment channel" to Mojaloop integrations (POS and ATM) which we hope to demo at the next convening. These would form the basis for an ISO8583 integration we might build and add to the OSS stack but bare in mind that these integrations will be very use case specific. + +## 24. How do I know the end points to setup postman for testing the deployment? + +On the Kubernetes dashboard, select the correct NAMESPACE. Go to Ingeresses. Depending on how you deployed the helm charts, look for 'moja-centralledger-service'. Click on edit, and find the tag ``. This would contain the endpoint for this service. + +If you use the CLI, find the 'Host' column in `kubectl describe ingress moja-centralledger-service` + +## 25. Why are there no reversals allowed on a Mojaloop? + +*Irrevocability* is a core Level One Principle (edited) and not allowing reversals is essential for that. Here is the section from the API Definition addressing this: + +_*6.7.1.2 Transaction Irrevocability*_ +_The API is designed to support irrevocable financial transactions only; this means that a financial transaction cannot be changed, cancelled, or reversed after it has been created. This is to simplify and reduce costs for FSPs using the API. A large percentage of the operating costs of a typical financial system is due to reversals of transactions._ +_As soon as a Payer FSP sends a financial transaction to a Payee FSP (that is, using POST /transfers including the end-to-end financial transaction), the transaction is irrevocable from the perspective of the Payer FSP. The transaction could still be rejected in the Payee FSP, but the Payer FSP can no longer reject or change the transaction. An exception to this would be if the transfer’s expiry time is exceeded before the Payee FSP responds (see Sections 6.7.1.3 and 6.7.1.5 for more information). As soon as the financial transaction has been accepted by the Payee FSP, the transaction is irrevocable for all parties._ + +However, *Refunds* is a use case supported by the API. + +## 26. ffg. error with microk8s installation "MountVolume.SetUp failed"? + +Would appear if it is a space issue, but more the 100GiB of EBS storage was allocated. +The issue resolved itself after 45 minutes. Initial implementation of the mojaloop project can take a while to stabilize. + +## 27. Why am I getting this error when trying to create a participant: "Hub reconciliation account for the specified currency does not exist"? + +You need to create the corresponding Hub accounts (HUB_MULTILATERAL_SETTLEMENT and HUB_RECONCILIATION) for the specified currency before setting up the participants. +In this Postman collection you can find the requests to perform the operation in the "Hub Account" folder: https://github.com/mojaloop/postman/blob/master/OSS-New-Deployment-FSP-Setup.postman_collection.json + +Find also the related environments in the Postman repo: https://github.com/mojaloop/postman diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..29dda5cd4 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,26 @@ +--- +home: true +heroImage: /mojaloop_logo_med.png +tagline: This is the official documentation of the Mojaloop project +# actionText: Getting Started → +# actionLink: /getting-started/ +# features: +# - title: Business +# details: Making the business case for Mojaloop +# - title: Community +# details: Learn about the community behind the tech +# - title: Technical +# details: See inside the different components, and deploy Mojaloop for yourself! +# - title: Product +# details: Mojaloop product features, requirements and roadmap +--- + +
+
+ +| | | | | +|:----:|:----:|:----:|:----:| +|

**[Adoption](/adoption/)**

|

**[Community](/community/)**

|

**[Product](/product/)**

|

**[Technical](/technical/)**

| +| Making the business case for Mojaloop | Learn about the community behind the tech | Mojaloop product features, requirements and roadmap | Look inside the different components and deploy Mojaloop for yourself! | + +
\ No newline at end of file diff --git a/docs/product/README.md b/docs/product/README.md new file mode 100644 index 000000000..b44b23e26 --- /dev/null +++ b/docs/product/README.md @@ -0,0 +1,5 @@ +# Welcome to Mojaloop the Product + +This section is devoted to Product-related documentation of Mojaloop, setting out from a business perspective its feature set, functionality, APIs, support for connecting DFSPs, the establishment of Mojaloop-based merchant payments schemes, cross-border transactions, ISO 20022, etc; in fact, all the features a potential adopter needs to know about when considering the shape of their scheme. It does not provide technical/engineering detail, which is available elsewhere on this site. + +It represents the outputs of the open source Mojaloop Community over a period of years. Should the reader wish to help shape the future of Mojaloop, then come and join the discussions held on the #product-council Slack channel and Community Central (https://community.mojaloop.io/). \ No newline at end of file diff --git a/docs/product/features/ComplexXB.svg b/docs/product/features/ComplexXB.svg new file mode 100644 index 000000000..4e87239dd --- /dev/null +++ b/docs/product/features/ComplexXB.svg @@ -0,0 +1,4 @@ + + + +
Jurisdiction B
Jurisdiction B
Jurisdiction A
Jurisdiction A
Scheme 1
Scheme 1
Scheme 2
Scheme 2
DFSP 2
DFSP 2
Proxy
Proxy
FXP 1
FXP 1
FXP 3
FXP 3
FXP 2
FXP 2
Proxy
Proxy
Existing Scheme 1.1
Existing Scheme 1.1
DFSP 1
DFSP 1
DFSP 3
DFSP 3
\ No newline at end of file diff --git a/docs/product/features/CrossBorder.md b/docs/product/features/CrossBorder.md new file mode 100644 index 000000000..c54b43a0e --- /dev/null +++ b/docs/product/features/CrossBorder.md @@ -0,0 +1,25 @@ +# Cross Border Transactions + +*This page assumes the reader is familiar with both Mojaloop's [**interscheme capabilities**](./InterconnectingSchemes.md) and the operation of [**foreign exchange**](./ForeignExchange.md).* + +The current version of Mojaloop treats a cross-border transaction as a transaction that leaves one payments scheme, and is passed to another in a different regulatory jurisdiction. It is therefore, in Mojaloop terms, an interscheme transaction that includes a foreign exchange. + +The following diagram illustrates how Mojaloop implements this functionality. + +![Cross Border Transactions](./XB.svg) + +In this context, a Proxy acts as the link between two Mojaloop schemes operating in different countries (regulatory jurisdictions), facilitating transactions and ensuring their end-to-end non-repudiation. Multiple FXPs are illustrated, two in jurisdiction A and one in jurisdiction B, so the various business models proposed for FX transactions can be supported. + +This model can be extended further, so that countries with existing domestic instant payment systems can be interconnected, as follows: + +![Interconnecting Domestic Schemes to Offer Cross Border transactions](./ComplexXB.svg) + +## Applicability + +This version of this document relates to Mojaloop Version [17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.1|22nd April 2025| Paul Makin|Added version history; clarified some wording| +|1.0|14th April 2025| Paul Makin|Initial version| \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Discovery.plantuml b/docs/product/features/CurrencyConversion/FXAPI_Discovery.plantuml new file mode 100644 index 000000000..2e20cd471 --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Discovery.plantuml @@ -0,0 +1,216 @@ +@startuml FXAPI_Discovery + +!$simplified = false +!$shortCutSingleFXP = false +!$hideSwitchDetail = false +!$advancedCoreConnectorFlow = false +!$senderName = "John" +!$senderLastName = "" +!$senderDOB = "1966-06-16" +!$receiverName = "Yaro" +!$receiverFirstName = "Yaro" +!$receiverMiddleName = "" +!$receiverLastName = "" +!$receiverDOB = "1966-06-16" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$fxpID = "FDH_FX" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "44000" +!$payerSendAmount = "300" +!$payeeFee = "4000" +!$targetAmount = "48000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "300" +!$fxpTargetAmount = "48000" +!$totalChargesSourceCurrency = "55" +!$totalChargesTargetCurrency = "10000" +!$conversionRequestId = "828cc75f1654415e8fcddf76cc" +!$conversionId = "581f68efb54f416f9161ac34e8" +!$homeTransactionId = "string" +!$quoteId = "382987a875ce4037b500c475e0" +!$transactionId = "d9ce59d4359843968630581bb0" +!$quotePayerExpiration = "2021-08-25T14:17:09.663+01:00" +!$quotePayeeExpiration = "2021-08-25T14:17:09.663+01:00" +!$commitRequestId = "77c9d78dc26a44748b3c99b96a" +!$determiningTransferId = "d9ce59d4359843968630581bb0" +!$transferId = "d9ce59d4359843968630581bb0" +!$fxCondition = "GRzLaTP7DJ9t4P-a_B..." +!$condition = "HOr22-H3AfTDHrSkP..." + +title Discovery - Mojaloop Connector Integration +actor "$senderName" as A1 + participant "Payer CBS" as PayerCBS +box "Payer DFSP" #LightBlue + participant "Core Connector" as PayerCC + participant "Payer\nMojaloop\nConnector" as D1 +end box + +participant "Mojaloop Switch" as S1 + +box "Discovery Service" #LightYellow + participant "ALS Oracle" as ALS +end box + +'box "FX provider" +' participant "FXP\nConnector" as FXP +' participant "Backend FX API" as FXPBackend +'end box + +box "Payee DFSP" #LightBlue + participant "Payee\nMojaloop\nConnector" as D2 + participant "Core Connector" as PayeeCC +end box + +'actor "$receiverName" as A2 +autonumber + +A1->PayerCBS:I'd like to pay $receiverName\n$payerSendAmount $payerCurrency, please +PayerCBS->PayerCC: Initiate remittance transfer +!if ($advancedCoreConnectorFlow != true) + PayerCC->D1: **POST /transfers** + !if ($simplified != true) + note left + { + "homeTransactionId": "$homeTransactionId", + "from": { + "dateOfBirth": "$senderDOB", + "displayName": "$senderName", + "firstName": "$senderFirstName", + "middleName": "$senderMiddleName", + "lastName": "$senderLastName" + "fspId": "$payerFSPID", + "idType": "MSISDN", + "idValue": "$payerMSISDN" + }, + "to": { + "idType": "MSISDN", + "idValue": "$payeeMSISDN" + }, + "amountType": "SEND", + "currency": "$payerCurrency", + "amount": "$payerSendAmount" + } + end note + !endif +!else +PayerCC->D1: **GET /parties/MSISDN/$payeeMSISDN** +!endif + +activate D1 +D1->>S1:I want to send to MSISDN $payeeMSISDN\n**GET /parties/MSISDN/$payeeMSISDN** +activate S1 +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif +S1->ALS:Who owns MSISDN $payeeMSISDN? +activate ALS +ALS-->S1:It's $payeeFSPID +deactivate ALS +S1->>D2:Do you own MSISDN $payeeMSISDN? +activate D2 +!if ($simplified != true) +D2-->>S1:202 I'll get back to you +deactivate S1 +!endif +D2->PayeeCC: **GET** /parties +PayeeCC->PayeeCC: Validate whether the party \n can receive the transfer +PayeeCC->PayeeCC: Check account and\n get currency type +!if ($simplified != true) +PayeeCC-->D2: Result +!endif +deactivate S1 +D2->>S1:Yes, it's $receiverName.\n He can receive in $payeeCurrency\n**PUT /parties/MSISDN/$payeeMSISDN** +!if ($simplified != true) +note right + PUT /parties + { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payeeMSISDN", + "fspId": "$payeeFSPID" + }, + "name": "$receiverName" + }, + "supportedCurrencies": [ "$payeeCurrency" ] + } +end note +!else +!endif +activate S1 +!if ($simplified != true) +S1-->>D2:200 Gotcha +!endif +deactivate D2 +S1->>D1:Yes, it's $receiverName. \nHe can receive in $payeeCurrency\n**PUT /parties/MSISDN/$payeeMSISDN** +!if ($simplified != true) +D1-->>S1:200 Gotcha +!endif +deactivate S1 + +!if ($advancedCoreConnectorFlow != true) + D1-->PayerCC: Here is the party information\nand supported currencies + note right + { + "transferId": "$transferId", + "homeTransactionId": "$homeTransactionId", + "from": { + "displayName": "$senderName", + "fspId": "$payerFSPID", + "idType": "MSISDN", + "idValue": "$payerMSISDN" + }, + "to": { + "type": "CONSUMER", + "idType": "MSISDN", + "idValue": "$payeeMSISDN", + "displayName": "$receiverName", + "fspId": "$payeeFSPID" + "supportedCurrencies": [ "$payeeCurrency" ] + }, + "amountType": "SEND", + "currency": "$payerCurrency", + "amount": "$payerSendAmount" + "currentState": "**WAITING_FOR_PARTY_ACCEPTANCE**", + "getPartiesResponse": { + "body": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payeeMSISDN", + "fspId": "$payeeFSPID" + }, + "name": "$receiverName", + "supportedCurrencies": [ "$payeeCurrency" ] + } + } + } + end note +!else + D1-->PayerCC: Here is the party information\nand supported currencies + !if ($simplified != true) + note right of PayerCC + { + "party": { + "body": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payeeMSISDN", + "fspId": "$payeeFSPID" + }, + "name": "$receiverName", + "supportedCurrencies": [ "$payeeCurrency" ] + } + }, + "currentState": "COMPLETED" + } + end note + !endif +!endif +deactivate D1 +PayerCC-->PayerCBS:Here's are the \nreceiver details +PayerCBS->A1:Hi, $senderName: \nThe number belongs to $receiverName \nLet me know if you want to\n go ahead +@enduml \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Discovery.svg b/docs/product/features/CurrencyConversion/FXAPI_Discovery.svg new file mode 100644 index 000000000..c1b690c59 --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Discovery.svg @@ -0,0 +1 @@ +Discovery - Mojaloop Connector IntegrationPayer DFSPDiscovery ServicePayee DFSPJohnJohnPayer CBSPayer CBSCore ConnectorCore ConnectorPayerMojaloopConnectorPayerMojaloopConnectorMojaloop SwitchMojaloop SwitchALS OracleALS OraclePayeeMojaloopConnectorPayeeMojaloopConnectorCore ConnectorCore Connector1I'd like to pay Yaro300 BWP, please2Initiate remittance transfer3POST /transfers{"homeTransactionId": "string","from": {"dateOfBirth": "1966-06-16","displayName": "John","firstName": "$senderFirstName","middleName": "$senderMiddleName","lastName": """fspId": "PayerFSP","idType": "MSISDN","idValue": "26787654321"},"to": {"idType": "MSISDN","idValue": "2551234567890"},"amountType": "SEND","currency": "BWP","amount": "300"}4I want to send to MSISDN 2551234567890GET /parties/MSISDN/25512345678905202 I'll get back to you6Who owns MSISDN 2551234567890?7It's PayeeFSP8Do you own MSISDN 2551234567890?9202 I'll get back to you10GET/parties11Validate whether the partycan receive the transfer12Check account andget currency type13Result14Yes, it's Yaro.He can receive in TZSPUT /parties/MSISDN/2551234567890PUT /parties{"partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "2551234567890","fspId": "PayeeFSP"},"name": "Yaro"},"supportedCurrencies": [ "TZS" ]}15200 Gotcha16Yes, it's Yaro.He can receive in TZSPUT /parties/MSISDN/255123456789017200 Gotcha18Here is the party informationand supported currencies{"transferId": "d9ce59d4359843968630581bb0","homeTransactionId": "string","from": {"displayName": "John","fspId": "PayerFSP","idType": "MSISDN","idValue": "26787654321"},"to": {"type": "CONSUMER","idType": "MSISDN","idValue": "2551234567890","displayName": "Yaro","fspId": "PayeeFSP""supportedCurrencies": [ "TZS" ]},"amountType": "SEND","currency": "BWP","amount": "300""currentState": "WAITING_FOR_PARTY_ACCEPTANCE","getPartiesResponse": {"body": {"partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "2551234567890","fspId": "PayeeFSP"},"name": "Yaro","supportedCurrencies": [ "TZS" ]}}}19Here's are thereceiver details20Hi, John:The number belongs to YaroLet me know if you want togo ahead \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_Agreement.plantuml b/docs/product/features/CurrencyConversion/FXAPI_Payer_Agreement.plantuml new file mode 100644 index 000000000..9f71b0acb --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_Agreement.plantuml @@ -0,0 +1,236 @@ +@startuml FXAPI_Payer_Agreement + +!$simplified = false +!$shortCutSingleFXP = false +!$hideSwitchDetail = false +!$advancedCoreConnectorFlow = false +!$senderName = "John" +!$senderLastName = "" +!$senderDOB = "1966-06-16" +!$receiverName = "Yaro" +!$receiverFirstName = "Yaro" +!$receiverMiddleName = "" +!$receiverLastName = "" +!$receiverDOB = "1966-06-16" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$fxpID = "FDH_FX" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "44000" +!$payerSendAmount = "300" +!$payeeFee = "4000" +!$targetAmount = "48000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "300" +!$fxpTargetAmount = "48000" +!$totalChargesSourceCurrency = "55" +!$totalChargesTargetCurrency = "10000" +!$conversionRequestId = "828cc75f1654415..." +!$conversionId = "581f68efb54f41..." +!$homeTransactionId = "string" +!$quoteId = "382987a875ce403..." +!$transactionId = "d9ce59d43598439..." +!$quotePayerExpiration = "2021-08-25T14:17:09.663+01:00" +!$quotePayeeExpiration = "2021-08-25T14:17:09.663+01:00" +!$commitRequestId = "77c9d78dc26a44748b3c99b96a" +!$determiningTransferId = "d9ce59d4359843..." +!$transferId = "d9ce59d43598439..." +!$fxCondition = "GRzLaTP7DJ9t4P-a_B..." +!$condition = "HOr22-H3AfTDHrSkP..." + +title Agreement Phase - Mojaloop Connector Integration +'actor "$senderName" as A1 +' participant "Payer CBS" as PayerCBS +box "Payer DFSP" #LightBlue + participant "Core Connector" as PayerCC + participant "Payer\nMojaloop\nConnector" as D1 +end box + +participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow +' participant "ALS Oracle" as ALS +'end box + +'box "FX provider" +' participant "FXP\nConnector" as FXP +' participant "Backend FX API" as FXPBackend +'end box + +box "Payee DFSP" #LightBlue + participant "Payee\nMojaloop\nConnector" as D2 + participant "Core Connector" as PayeeCC +end box + +'actor "$receiverName" as A2 +autonumber + +!if ($advancedCoreConnectorFlow != true) +PayerCC->D1: I want to get a quote from the FSP\n**PUT /transfers** +note left +{"acceptConversion": true} +end note +!else +PayerCC->D1: I want to get a quote from the FSP\n**POST /quotes** + !if ($simplified != true) + note right of PayerCC + { + "fspId": "$payeeFSPID", + "quotesPostRequest": { + "quoteId": "$quoteId", + "transactionId": "$transactionId", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payeeMSISDN", + "fspId": "$payeeFSPID" + }, + "name": "$receiverName", + "supportedCurrencies": [ "$payeeCurrency" ] + }, + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payerMSISDN", + "fspId": "$payerFSPID" + }, + "name": "$senderName", + }, + "amountType": "SEND", + "amount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount" + }, + "converter": "PAYER", + "expiration": "$quotePayerExpiration" + } + } + end note + !endif +!endif + + +D1->>S1:Please quote for a transfer which \nsends $fxpTargetAmount $payeeCurrency.\n**POST /quotes** +!if ($simplified != true) +note left +**POST /quotes** +{ + "quoteId": "$quoteId", + "transactionId": "$transactionId", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payeeMSISDN", + "fspId": "$payeeFSPID"}, + "name": "$receiverName", + "supportedCurrencies": [ "$payeeCurrency" ] }, + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payerMSISDN", + "fspId": "$payerFSPID"}, + "name": "$senderName"}, + "amountType": "SEND", + "amount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "converter": "PAYER", + "expiration": "$quotePayerExpiration" +} +end note +!endif +activate S1 +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif + +S1->>D2:**POST /quotes** +activate D2 +!if ($simplified != true) +D2-->>S1:202 I'll get back to you +!endif +deactivate S1 +D2->PayeeCC:**POST /quoterequests** +!if ($simplified != true) +note left +**POST /quoterequests** +{ + "quoteId": "$quoteId", + "transactionId": "$transactionId", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payeeMSISDN", + "fspId": "$payeeFSPID"}, + "name": "$receiverName", + "supportedCurrencies": [ "$payeeCurrency" ]}, + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payerMSISDN", + "fspId": "$payerFSPID"}, + "name": "$senderName"}, + "amountType": "SEND", + "amount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "converter": "PAYER", + "expiration": "$quotePayerExpiration" +} +end note +!endif +PayeeCC->PayeeCC:OK, so I will charge $payeeFee $payeeCurrency for this.\nNow I create terms of the transfer +PayeeCC-->D2:Here are the terms +!if ($simplified != true) +note right +**POST /quoterequests** response +{ + "quoteId": "$quoteId", + "transactionId": "$transactionId", + "payeeFspFeeAmount": "$payeeFee", + "payeeFspFeeAmountCurrency": "$payeeCurrency", + "payeeReceiveAmount": "$payeeReceiveAmount", + "payeeReceiveAmountCurrency": "$payeeCurrency", + "transferAmount": "$targetAmount", + "transferAmountCurrency": "$payeeCurrency" + "expiration": "$quotePayerExpiration" +} +end note +!endif +D2->D2:Now I will sign the transaction object +D2->>S1:Here's the signed quote +note right +**put /quotes/$quoteId** +{ + "transferAmount": { + "currency": "$payeeCurrency", + "amount": "$targetAmount"}, + "payeeReceiveAmount": { + "currency": "$payeeCurrency", + "amount": "$payeeReceiveAmount"}, + "payeeFspFee": { + "currency": "$payeeCurrency", + "amount": "$payeeFee"}, + "expiration": "$payeeQuoteExpiration", + "ilpPacket": "", + "condition": "$condition" +} + +end note +activate S1 +!if ($simplified != true) +S1-->>D2:200 Gotcha +!endif +deactivate D2 +S1->>D1:Here's the signed quote\n**PUT /quotes/$quoteId** +activate D1 +!if ($simplified != true) +D1-->>S1:200 Gotcha +!endif +deactivate S1 +D1->D1:OK, I can see that there \nare going to be $payeeFee $payeeCurrency in charges. +@enduml diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_Agreement.svg b/docs/product/features/CurrencyConversion/FXAPI_Payer_Agreement.svg new file mode 100644 index 000000000..b9d56798d --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_Agreement.svg @@ -0,0 +1 @@ +Agreement Phase - Mojaloop Connector IntegrationPayer DFSPPayee DFSPCore ConnectorCore ConnectorPayerMojaloopConnectorPayerMojaloopConnectorMojaloop SwitchMojaloop SwitchPayeeMojaloopConnectorPayeeMojaloopConnectorCore ConnectorCore Connector1I want to get a quote from the FSPPUT /transfers{"acceptConversion": true}2Please quote for a transfer whichsends 48000 TZS.POST /quotesPOST /quotes{"quoteId": "382987a875ce403...","transactionId": "d9ce59d43598439...","payee": {"partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "2551234567890","fspId": "PayeeFSP"},"name": "Yaro","supportedCurrencies": [ "TZS" ] },"payer": {"partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "26787654321","fspId": "PayerFSP"},"name": "John"},"amountType": "SEND","amount": {"currency": "TZS","amount": "48000"},"converter": "PAYER","expiration": "2021-08-25T14:17:09.663+01:00"}3202 I'll get back to you4POST /quotes5202 I'll get back to you6POST /quoterequestsPOST /quoterequests{"quoteId": "382987a875ce403...","transactionId": "d9ce59d43598439...","payee": {"partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "2551234567890","fspId": "PayeeFSP"},"name": "Yaro","supportedCurrencies": [ "TZS" ]},"payer": {"partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "26787654321","fspId": "PayerFSP"},"name": "John"},"amountType": "SEND","amount": {"currency": "TZS","amount": "48000"},"converter": "PAYER","expiration": "2021-08-25T14:17:09.663+01:00"}7OK, so I will charge 4000 TZS for this.Now I create terms of the transfer8Here are the termsPOST /quoterequestsresponse{"quoteId": "382987a875ce403...","transactionId": "d9ce59d43598439...","payeeFspFeeAmount": "4000","payeeFspFeeAmountCurrency": "TZS","payeeReceiveAmount": "44000","payeeReceiveAmountCurrency": "TZS","transferAmount": "48000","transferAmountCurrency": "TZS""expiration": "2021-08-25T14:17:09.663+01:00"}9Now I will sign the transaction object10Here's the signed quoteput /quotes/382987a875ce403...{"transferAmount": {"currency": "TZS","amount": "48000"},"payeeReceiveAmount": {"currency": "TZS","amount": "44000"},"payeeFspFee": {"currency": "TZS","amount": "4000"},"expiration": "$payeeQuoteExpiration","ilpPacket": "<This is encoded transaction object.>","condition": "HOr22-H3AfTDHrSkP..."} 11200 Gotcha12Here's the signed quotePUT /quotes/382987a875ce403...13200 Gotcha14OK, I can see that thereare going to be 4000 TZS in charges. \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_CurrencyConversion.plantuml b/docs/product/features/CurrencyConversion/FXAPI_Payer_CurrencyConversion.plantuml new file mode 100644 index 000000000..994fc0f2d --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_CurrencyConversion.plantuml @@ -0,0 +1,384 @@ +@startuml FXAPI_Payer_CurrencyConversion + +!$simplified = false +!$shortCutSingleFXP = false +!$hideSwitchDetail = false +!$advancedCoreConnectorFlow = false +!$senderName = "John" +!$senderLastName = "" +!$senderDOB = "1966-06-16" +!$receiverName = "Yaro" +!$receiverFirstName = "Yaro" +!$receiverMiddleName = "" +!$receiverLastName = "" +!$receiverDOB = "1966-06-16" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$fxpID = "FDH_FX" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "44000" +!$payerSendAmount = "300" +!$payeeFee = "4000" +!$targetAmount = "48000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "300" +!$fxpTargetAmount = "48000" +!$totalChargesSourceCurrency = "55" +!$totalChargesTargetCurrency = "10000" +!$conversionRequestId = "828cc75f1654415e8fcddf76cc" +!$conversionId = "581f68efb54f416f9161ac34e8" +!$homeTransactionId = "string" +!$quoteId = "382987a875ce4037b500c475e0" +!$transactionId = "d9ce59d4359843968630581bb0" +!$quotePayerExpiration = "2021-08-25T14:17:09.663+01:00" +!$quotePayeeExpiration = "2021-08-25T14:17:09.663+01:00" +!$commitRequestId = "77c9d78dc26a44748b3c99b96a" +!$determiningTransferId = "d9ce59d4359843968630581bb0" +!$transferId = "d9ce59d4359843968630581bb0" +!$fxCondition = "GRzLaTP7DJ9t4P-a_B..." +!$condition = "HOr22-H3AfTDHrSkP..." + +title Agreement Phase Currency Conversion - Mojaloop Connector Integration +actor "$senderName" as A1 +participant "Payer CBS" as PayerCBS +box "Payer DFSP" #LightBlue + participant "Core Connector" as PayerCC + participant "Payer\nMojaloop\nConnector" as D1 +end box + +participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow +' participant "ALS Oracle" as ALS +'end box + +box "FX provider" + participant "FXP\nConnector" as FXP + participant "Backend FX API \n(Core Connector)" as FXPBackend +end box + +'box "Payee DFSP" #LightBlue +' participant "Payee\nMojaloop\nConnector" as D2 +' participant "Core Connector" as PayeeCC +'end box + +'actor "$receiverName" as A2 +autonumber + +A1->PayerCBS:Yes please, go ahead +PayerCBS->PayerCC: Payer has accepted\n the party information + +!if ($shortCutSingleFXP != true) + +!if ($advancedCoreConnectorFlow != true) +PayerCC->>D1:Get quotation\n**PUT /transfers/$transferId** +note left +{ "acceptParty": true } +end note +D1->D1:Hmmm. I can only send in $payerCurrency.\nI need to get some currency conversion +!else +PayerCC->PayerCC:Hmmm. I can only send in $payerCurrency.\nI need to get some currency conversion +PayerCC->>PayerCC:Lookup the local cached FXPs\n that can provide the conversion +!endif + +D1->>D1:Lookup the local cached FXPs\n that can provide the conversion + + +!if ($advancedCoreConnectorFlow != true) +' TODO: We can pause the execution here if required to allow the core connector to select the FXP +D1->D1:I'll ask FDH FX to perform my conversion +!else +D1->>PayerCC:Here are the available FXPs +note right of PayerCC + { + "providers": [ + "$fxpID" + ] + } +end note + +PayerCC->PayerCC:I'll ask FDH FX to perform my conversion +PayerCC->D1: I want to get a quote from this FXP\n**POST /fxQuotes** + !if ($simplified != true) + note right of PayerCC + { + "homeTransactionId": "$homeTransactionId", + "conversionRequestId": "$conversionRequestId", + "conversionTerms": { + "conversionId": "$conversionId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$payerSendAmount" + }, + "targetAmount": { + "currency": "$payeeCurrency" + }, + "expiration": "2021-08-25T14:17:09.663+01:00" + } + } + end note + !endif +!endif +!endif + +deactivate S1 + +!if ($shortCutSingleFXP != true) +D1->>S1:Here is the initial version of the transfer.\nPlease quote me for the currency conversion. +!else +D1->>FXP:Here is the initial version of the transfer.\nPlease quote me for the currency conversion. +!endif +note left + **post /fxQuotes** + { + "conversionRequestId": "$conversionRequestId", + "conversionTerms": { + "conversionId": "$conversionId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$payerSendAmount"}, + "targetAmount": { + "currency": "$payeeCurrency"}, + "expiration": "2021-08-25T14:17:09.663+01:00" + } + } +end note +!if ($shortCutSingleFXP != true) +activate S1 +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif +deactivate D1 +S1->>FXP:Here is the initial version of the transfer.\nPlease quote me for the currency conversion.\n**POST /fxQuote** +activate FXP +!if ($simplified != true) +FXP-->>S1:202 I'll get back to you +!endif +deactivate S1 +!else +!if ($simplified != true) +FXP-->>D1:202 I'll get back to you +!endif +!endif +FXP->FXPBackend:Lookup FX rate +!if ($simplified != true) +note left + **post /fxQuotes** + { + "conversionRequestId": "$conversionRequestId", + "conversionTerms": { + "conversionId": "$conversionId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$payerSendAmount"}, + "targetAmount": { + "currency": "$payeeCurrency"}, + "expiration": "2021-08-25T14:17:09.663+01:00" + } + } +end note +!endif +note over FXPBackend + I will add a $fxpChargesSource $payerCurrency fee for undertaking the conversion. + Now I'll set an expiry time, sign the quotation object, +end note +FXPBackend-->FXP:Return FX rate +!if ($simplified != true) +note right + **post /fxQuotes** response + { + "conversionTerms": { + "conversionId": "$conversionId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "expiration": "2021-08-25T14:17:09.663+01:00" + "charges": [ + { + "chargeType": "string", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpChargesSource"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpChargesTarget"} + }]} + } +end note +!endif + +note over FXP + Now I'll sign the quotation object, + create an ILP prepare packet and return it in the intermediary object. + + **NOTE:** the ILP prepare packet contains the following items, all encoded: + - The amount being sent (i.e. in the source currency) + - An expiry time + - The condition + - The name of the FXP + - The content of the conversion terms +end note + +!if ($shortCutSingleFXP != true) +FXP->>S1:Here's the signed conversion object +note right + **PUT /fxQuotes/$conversionRequestId** + { + "condition": "$fxCondition", + "conversionTerms": { + "conversionId": "$conversionId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "expiration": "2021-08-25T14:17:09.663+01:00" + "charges": [ + { + "chargeType": "string", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpChargesSource"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpChargesTarget"} + }]} + } +end note +activate S1 +!if ($simplified != true) +S1-->>FXP:200 Gotcha +!endif +deactivate FXP +S1->>D1:Here's the signed conversion object\n**PUT /fxQuotes/$conversionRequestId** +activate D1 +!if ($simplified != true) +D1-->>S1:Gotcha +!endif +deactivate S1 +!else +FXP-->>D1:Here's the signed conversion object\n**PUT /fxQuotes/$conversionRequestId** +!if ($simplified != true) +D1-->>FXP:202 I'll get back to you +!endif +activate D1 +!endif + + +!if ($advancedCoreConnectorFlow != true) + D1-->PayerCC: Here are the conversion terms + note right + **POST/PUT /transfers** response + { + "transferId": "$transferId", + "homeTransactionId": "$homeTransactionId", + "from": { + "displayName": "$senderName", + "fspId": "$payerFSPID", + "idType": "MSISDN", + "idValue": "$payerMSISDN"}, + "to": { + "type": "CONSUMER", + "idType": "MSISDN", + "idValue": "$payeeMSISDN", + "displayName": "$receiverName", + "fspId": "$payeeFSPID" + "supportedCurrencies": [ "$payeeCurrency" ]}, + "amountType": "SEND", + "currency": "$payerCurrency", + "amount": "$payerSendAmount" + "currentState": "**WAITING_FOR_CONVERSION_ACCEPTANCE**", + "getPartiesResponse": {}, + "conversionRequestId": "$conversionRequestId", + "fxQuotesResponse": { + "body": { + "condition": "$fxCondition", + "conversionTerms": { + "conversionId": "$conversionId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "expiration": "2021-08-25T14:17:09.663+01:00" + "charges": [{ + "chargeType": "string", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpChargesSource"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpChargesTarget"} + }]}} + }, + "fxQuotesResponseSource": "$payeeFSPID", + } + end note +!else + D1->PayerCC: Here are the conversion terms + !if ($simplified != true) + note right of PayerCC + { + "homeTransactionId": "$homeTransactionId", + "condition": "$fxCondition", + "conversionTerms": { + "conversionId": "$conversionId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount" + }, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount" + }, + "expiration": "2021-08-25T14:17:09.663+01:00" + "charges": [ + { + "chargeType": "string", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpChargesSource" + }, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpChargesTarget" + } + } + ] + } + } + end note + !endif +!endif + +@enduml \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_CurrencyConversion.svg b/docs/product/features/CurrencyConversion/FXAPI_Payer_CurrencyConversion.svg new file mode 100644 index 000000000..8114a5163 --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_CurrencyConversion.svg @@ -0,0 +1 @@ +Agreement Phase Currency Conversion - Mojaloop Connector IntegrationPayer DFSPFX providerJohnJohnPayer CBSPayer CBSCore ConnectorCore ConnectorPayerMojaloopConnectorPayerMojaloopConnectorMojaloop SwitchMojaloop SwitchFXPConnectorFXPConnectorBackend FX API(Core Connector)Backend FX API(Core Connector)1Yes please, go ahead2Payer has acceptedthe party information3Get quotationPUT /transfers/d9ce59d4359843968630581bb0{ "acceptParty": true }4Hmmm. I can only send in BWP.I need to get some currency conversion5Lookup the local cached FXPsthat can provide the conversion6I'll ask FDH FX to perform my conversion7Here is the initial version of the transfer.Please quote me for the currency conversion.post /fxQuotes{"conversionRequestId": "828cc75f1654415e8fcddf76cc","conversionTerms": {"conversionId": "581f68efb54f416f9161ac34e8","initiatingFsp": "PayerFSP","counterPartyFsp": "FDH_FX","amountType": "SEND","sourceAmount": {"currency": "BWP","amount": "300"},"targetAmount": {"currency": "TZS"},"expiration": "2021-08-25T14:17:09.663+01:00"}}8202 I'll get back to you9Here is the initial version of the transfer.Please quote me for the currency conversion.POST /fxQuote10202 I'll get back to you11Lookup FX ratepost /fxQuotes{"conversionRequestId": "828cc75f1654415e8fcddf76cc","conversionTerms": {"conversionId": "581f68efb54f416f9161ac34e8","initiatingFsp": "PayerFSP","counterPartyFsp": "FDH_FX","amountType": "SEND","sourceAmount": {"currency": "BWP","amount": "300"},"targetAmount": {"currency": "TZS"},"expiration": "2021-08-25T14:17:09.663+01:00"}}I will add a 33 BWP fee for undertaking the conversion.Now I'll set an expiry time, sign the quotation object,12Return FX ratepost /fxQuotesresponse{"conversionTerms": {"conversionId": "581f68efb54f416f9161ac34e8","initiatingFsp": "PayerFSP","counterPartyFsp": "FDH_FX","amountType": "SEND","sourceAmount": {"currency": "BWP","amount": "300"},"targetAmount": {"currency": "TZS","amount": "48000"},"expiration": "2021-08-25T14:17:09.663+01:00""charges": [{"chargeType": "string","sourceAmount": {"currency": "BWP","amount": "33"},"targetAmount": {"currency": "TZS","amount": "6000"}}]}}Now I'll sign the quotation object,create an ILP prepare packet and return it in the intermediary object. NOTE:the ILP prepare packet contains the following items, all encoded:- The amount being sent (i.e. in the source currency)- An expiry time- The condition- The name of the FXP- The content of the conversion terms13Here's the signed conversion objectPUT /fxQuotes/828cc75f1654415e8fcddf76cc{"condition": "GRzLaTP7DJ9t4P-a_B...","conversionTerms": {"conversionId": "581f68efb54f416f9161ac34e8","initiatingFsp": "PayerFSP","counterPartyFsp": "FDH_FX","amountType": "SEND","sourceAmount": {"currency": "BWP","amount": "300"},"targetAmount": {"currency": "TZS","amount": "48000"},"expiration": "2021-08-25T14:17:09.663+01:00""charges": [{"chargeType": "string","sourceAmount": {"currency": "BWP","amount": "33"},"targetAmount": {"currency": "TZS","amount": "6000"}}]}}14200 Gotcha15Here's the signed conversion objectPUT /fxQuotes/828cc75f1654415e8fcddf76cc16Gotcha17Here are the conversion termsPOST/PUT /transfersresponse{"transferId": "d9ce59d4359843968630581bb0","homeTransactionId": "string","from": {"displayName": "John","fspId": "PayerFSP","idType": "MSISDN","idValue": "26787654321"},"to": {"type": "CONSUMER","idType": "MSISDN","idValue": "2551234567890","displayName": "Yaro","fspId": "PayeeFSP""supportedCurrencies": [ "TZS" ]},"amountType": "SEND","currency": "BWP","amount": "300""currentState": "WAITING_FOR_CONVERSION_ACCEPTANCE","getPartiesResponse": {<Same as the previous responses>},"conversionRequestId": "828cc75f1654415e8fcddf76cc","fxQuotesResponse": {"body": {"condition": "GRzLaTP7DJ9t4P-a_B...","conversionTerms": {"conversionId": "581f68efb54f416f9161ac34e8","initiatingFsp": "PayerFSP","counterPartyFsp": "FDH_FX","amountType": "SEND","sourceAmount": {"currency": "BWP","amount": "300"},"targetAmount": {"currency": "TZS","amount": "48000"},"expiration": "2021-08-25T14:17:09.663+01:00""charges": [{"chargeType": "string","sourceAmount": {"currency": "BWP","amount": "33"},"targetAmount": {"currency": "TZS","amount": "6000"}}]}}},"fxQuotesResponseSource": "PayeeFSP",} \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_Agreement.plantuml b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_Agreement.plantuml new file mode 100644 index 000000000..53bde892c --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_Agreement.plantuml @@ -0,0 +1,241 @@ +@startuml FXAPI_Payer_Receive_Agreement + +!$simplified = false +!$shortCutSingleFXP = false +!$hideSwitchDetail = false +!$senderName = "Keeya" +!$receiverName = "Yaro" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "50000" +!$payeeFee = "4000" +!$targetAmount = "54000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "330" +!$fxpTargetAmount = "54000" +!$totalChargesSourceCurrency = "55" + + +title Agreement - Currency Conversion with Amount Type RECEIVE +'actor "$senderName" as A1 +box "Payer DFSP" #LightBlue +' participant "Payer CBS" as PayerCBS + participant "Payer\nMojaloop\nConnector" as D1 +end box + +participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow +' participant "ALS Oracle" as ALS +'end box + +box "FX provider" + participant "FXP\nConnector" as FXP + participant "Backend FX API" as FXPBackend +end box + +box "Payee DFSP" #LightBlue + participant "Payee\nMojaloop\nConnector" as D2 +' participant "Payee CBS" as PayeeCBS +end box + +'actor "$receiverName" as A2 +autonumber + +D1->>S1:Please quote for a payment\n of $payeeReceiveAmount $payeeCurrency.\n**POST /quotes** +!if ($simplified != true) +note left + **POST /quotes** + { + "quoteId": "382987a875ce...", + "transactionId": "d9ce59d43598...", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payeeMSISDN" }} + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payerMSISDN"}}, + "amountType": **"RECEIVE"**, + "amount": { + "currency": "$payeeCurrency", + "amount": "$payeeReceiveAmount"} + "validity": "2021-08-25T14:17:09.663+01:00" + } +end note +!endif +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif +deactivate D1 +S1->>D2:**POST /quotes** +activate D2 +!if ($simplified != true) +D2-->>S1:202 I'll get back to you +deactivate S1 +!endif +D2->D2: Let me get a quote to do the conversion +!if ($shortCutSingleFXP != true) + + +D2->D2:OK, so I will charge $payeeFee $payeeCurrency for this.\nNow I create terms of the transfer \nand sign the transaction object +D2->>S1:Here's the signed quote +note right +**put /quotes/382987a875ce...** +{ + "transferAmount": { + "currency": "$payeeCurrency", + "amount": "$targetAmount" }, + "payeeReceiveAmount": { + "currency": "$payeeCurrency", + "amount": "$payeeReceiveAmount"}, + "payeeFspFee": { + "currency": "$payeeCurrency", + "amount": "$payeeFee"}, + "expiration": "2021-08-25T14:17:09.663+01:00, + "transaction": { + "transactionId": "d9ce59d43598...", + "quoteId": "382987a875ce...", + "payee": { + "fspId": "$payeeFSPID", + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payeeMSISDN"}}, + "payer": { + "fspId": "$payerFSPID", + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payerMSISDN"}}, + "amount": { + "currency": "$payeeCurrency", + "amount": "$targetAmount"}, + "payeeReceiveAmount": { + "currency": "$payeeCurrency", + "amount": "$payeeReceiveAmount"}, + "converter": "PAYER"}, + "condition": "BfNFPRgfKF8Ke9kpo..." +} +end note +activate S1 +!if ($simplified != true) +S1-->>D2:200 Gotcha +!endif +deactivate D2 +S1->>D1:Here's the signed quote\n**PUT /quotes/382987a875ce...** +activate D1 +!if ($simplified != true) +D1-->>S1:200 Gotcha +!endif +deactivate S1 +D1->D1:OK, I can see that there are going\n to be $payeeFee $payeeCurrency in charges and \nI need send $targetAmount $payeeCurrency to make \nthis transfer + +group Currency Conversion +D1->D1:Now I need to find out what the \nexchange rate is +deactivate S1 +D1->D1:I'll ask FDH FX to\n perform my conversion + +!if ($shortCutSingleFXP != true) +D1->>S1:Here is the initial version \nof the transfer.Please quote\n me for the currency conversion. +!else +D1->>FXP:Here is the initial version\n of the transfer.Please quote\n me for the currency conversion. +!endif +note left + **post /fxQuotes** + { + "conversionRequestId": "828cc75f1654...", + "conversionTerms": { + "conversionId": "581f68efb54f...", + "counterPartyFsp": "FDH_FX", + "amountType": "RECEIVE", + "sourceAmount": { + "currency": "$payerCurrency"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$targetAmount"}, + "validity": "2021-08-25T14:17:09.663+01:00"} + } +end note +!if ($shortCutSingleFXP != true) +activate S1 +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif +deactivate D1 +S1->>FXP:Here is the initial version\n of the transfer. Please quote\n me for the currency conversion.\n**POST /fxQuote** +activate FXP +!if ($simplified != true) +FXP-->>S1:202 I'll get back to you +!endif +deactivate S1 +!else +!endif +FXP->FXPBackend:Lookup FX rate +FXPBackend-->FXP:Return FX rate +' !if ($shortCutSingleFXP != true) + +note right + I will add a $fxpChargesSource $payerCurrency fee for + undertaking the conversion. Now I'll set an expiry time, + sign the quotation object, create an ILP prepare packet + and return it in the intermediary object. + + **NOTE:** the ILP prepare packet contains the following + items, all encoded: + - The amount being sent (i.e. in the source currency) + - An expiry time + - The condition + - The name of the FXP + - The content of the conversion terms + + **PUT /fxQuotes/828cc75f1654...** + { + "condition": "bdbcf517cfc7e...", + "conversionTerms": { + "conversionId": "581f68efb54f...", + "initiatingFsp": "$payerFSPID" + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount" + }, + "targetAmount": { + "currency": "$payeeCurrency"", + "amount": "$fxpTargetAmount" + }, + "charges": [{ + "chargeType": "Conversion fee", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpChargesSource"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpChargesTarget"}}], + "validity": "2021-08-25T14:17:09.663+01:00"} + } +end note +!if ($shortCutSingleFXP != true) +FXP->>S1:Here's the signed \nconversion object +activate S1 +!if ($simplified != true) +S1-->>FXP:200 Gotcha +!endif +deactivate FXP +S1->>D1:Here's the signed conversion object\n**PUT /fxQuotes/828cc75f1654...** +activate D1 +!if ($simplified != true) +D1-->>S1:Gotcha +!endif +deactivate S1 +!else +FXP-->>D1:Here's the signed conversion object\n**PUT /fxQuotes/828cc75f1654...** +activate D1 +!endif + +end group + +@enduml diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_Agreement.svg b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_Agreement.svg new file mode 100644 index 000000000..1d646e96c --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_Agreement.svg @@ -0,0 +1 @@ +Agreement - Currency Conversion with Amount Type RECEIVEPayer DFSPFX providerPayee DFSPPayerMojaloopConnectorPayerMojaloopConnectorMojaloop SwitchMojaloop SwitchFXPConnectorFXPConnectorBackend FX APIBackend FX APIPayeeMojaloopConnectorPayeeMojaloopConnector1Please quote for a paymentof 50000 TZS.POST /quotesPOST /quotes{"quoteId": "382987a875ce...","transactionId": "d9ce59d43598...","payee": {"partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "2551234567890" }}"payer": {"partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "26787654321"}},"amountType":"RECEIVE","amount": {"currency": "TZS","amount": "50000"}"validity": "2021-08-25T14:17:09.663+01:00"}2202 I'll get back to you3POST /quotes4202 I'll get back to you5Let me get a quote to do the conversion6OK, so I will charge 4000 TZS for this.Now I create terms of the transferand sign the transaction object7Here's the signed quoteput /quotes/382987a875ce...{"transferAmount": {"currency": "TZS","amount": "54000" },"payeeReceiveAmount": {"currency": "TZS","amount": "50000"},"payeeFspFee": {"currency": "TZS","amount": "4000"},"expiration": "2021-08-25T14:17:09.663+01:00,"transaction": {"transactionId": "d9ce59d43598...","quoteId": "382987a875ce...","payee": {"fspId": "PayeeFSP","partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "2551234567890"}},"payer": {"fspId": "PayerFSP","partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "26787654321"}},"amount": {"currency": "TZS","amount": "54000"},"payeeReceiveAmount": {"currency": "TZS","amount": "50000"},"converter": "PAYER"},"condition": "BfNFPRgfKF8Ke9kpo..."}8200 Gotcha9Here's the signed quotePUT /quotes/382987a875ce...10200 Gotcha11OK, I can see that there are goingto be 4000 TZS in charges andI need send 54000 TZS to makethis transferCurrency Conversion12Now I need to find out what theexchange rate is13I'll ask FDH FX toperform my conversion14Here is the initial versionof the transfer.Please quoteme for the currency conversion.post /fxQuotes{"conversionRequestId": "828cc75f1654...","conversionTerms": {"conversionId": "581f68efb54f...","counterPartyFsp": "FDH_FX","amountType": "RECEIVE","sourceAmount": {"currency": "BWP"},"targetAmount": {"currency": "TZS","amount": "54000"},"validity": "2021-08-25T14:17:09.663+01:00"}}15202 I'll get back to you16Here is the initial versionof the transfer. Please quoteme for the currency conversion.POST /fxQuote17202 I'll get back to you18Lookup FX rate19Return FX rateI will add a 33 BWP fee forundertaking the conversion. Now I'll set an expiry time,sign the quotation object, create an ILP prepare packetand return it in the intermediary object. NOTE:the ILP prepare packet contains the followingitems, all encoded:- The amount being sent (i.e. in the source currency)- An expiry time- The condition- The name of the FXP- The content of the conversion terms PUT /fxQuotes/828cc75f1654...{"condition": "bdbcf517cfc7e...","conversionTerms": {"conversionId": "581f68efb54f...","initiatingFsp": "PayerFSP""sourceAmount": {"currency": "BWP","amount": "330"},"targetAmount": {"currency": "TZS"","amount": "54000"},"charges": [{"chargeType": "Conversion fee","sourceAmount": {"currency": "BWP","amount": "33"},"targetAmount": {"currency": "TZS","amount": "6000"}}],"validity": "2021-08-25T14:17:09.663+01:00"}}20Here's the signedconversion object21200 Gotcha22Here's the signed conversion objectPUT /fxQuotes/828cc75f1654...23Gotcha \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_Discovery.plantuml b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_Discovery.plantuml new file mode 100644 index 000000000..ea6b0de21 --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_Discovery.plantuml @@ -0,0 +1,112 @@ +@startuml FXAPI_Payer_Receive_Discovery + +!$simplified = false +!$shortCutSingleFXP = false +!$hideSwitchDetail = false +!$senderName = "Keeya" +!$receiverName = "Yaro" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$payerMSISDN = "267876..." +!$payeeMSISDN = "255123..." +!$payeeReceiveAmount = "50000" +!$payeeFee = "4000" +!$targetAmount = "54000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "330" +!$fxpTargetAmount = "54000" +!$totalChargesSourceCurrency = "55" + + +title Discovery - Currency Conversion with Amount Type RECEIVE +actor "$senderName" as A1 +box "Payer DFSP" #LightBlue + participant "Payer CBS" as PayerCBS + participant "Payer\nMojaloop\nConnector" as D1 +end box + +participant "Mojaloop Switch" as S1 + +box "Discovery Service" #LightYellow + participant "ALS Oracle" as ALS +end box + +'box "FX provider" +' participant "FXP\nConnector" as FXP +' participant "Backend FX API" as FXPBackend +'end box + +box "Payee DFSP" #LightBlue + participant "Payee\nMojaloop\nConnector" as D2 + participant "Payee CBS" as PayeeCBS +end box + +'actor "$receiverName" as A2 +autonumber + +A1->PayerCBS:I'd like to pay $receiverName\n$payeeReceiveAmount $payeeCurrency for \nhis latest book, please +PayerCBS->D1: Initiate merchant payment +activate D1 +D1->>S1:I want to send to MSISDN $payeeMSISDN\n**GET /parties/MSISDN/$payeeMSISDN** +activate S1 +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif +deactivate D1 +S1->ALS:Who owns MSISDN $payeeMSISDN? +activate ALS +ALS-->S1:It's $payeeFSPID +deactivate ALS +S1->>D2:Do you own MSISDN $payeeMSISDN? +activate D2 +!if ($simplified != true) +D2-->>S1:202 I'll get back to you +!endif +deactivate S1 +D2->D2: Check Sanction list status \n& trigger a refresh of the status +D2->PayeeCBS: Check account and get\n currency type +!if ($simplified != true) +PayeeCBS-->D2: Result +!endif +D2->>S1:Yes, it's $receiverName. He can receive in $payeeCurrency,\n and I can convert from $payerCurrency\n**PUT /parties/MSISDN/$payeeMSISDN** +!if ($simplified != true) +note right + **PUT /parties** + { + "party": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payeeMSISDN"}, + "name": "$receiverName", + "supportedCurrencies":["$payeeCurrency"]} + } +end note +!else +note over D2 + Payee Info with Encrypted KYC Data +end note +!endif +activate S1 +!if ($simplified != true) +S1-->>D2:200 Gotcha +!endif +deactivate D2 +S1->>D1:Yes, it's $receiverName. He can receive in $payeeCurrency\n**PUT /parties/MSISDN/$payeeMSISDN** +activate D1 +!if ($simplified != true) +D1-->>S1:200 Gotcha +!endif +deactivate S1 + +D1->D1: I will need to perform currency conversion. +note left +I need to calculate +how much currency I need. +Let me find a currency +conversion provider before I start. +end note + +@enduml diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_Discovery.svg b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_Discovery.svg new file mode 100644 index 000000000..5177277c1 --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_Discovery.svg @@ -0,0 +1 @@ +Discovery - Currency Conversion with Amount Type RECEIVEPayer DFSPDiscovery ServicePayee DFSPKeeyaKeeyaPayer CBSPayer CBSPayerMojaloopConnectorPayerMojaloopConnectorMojaloop SwitchMojaloop SwitchALS OracleALS OraclePayeeMojaloopConnectorPayeeMojaloopConnectorPayee CBSPayee CBS1I'd like to pay Yaro50000 TZS forhis latest book, please2Initiate merchant payment3I want to send to MSISDN 255123...GET /parties/MSISDN/255123...4202 I'll get back to you5Who owns MSISDN 255123...?6It's PayeeFSP7Do you own MSISDN 255123...?8202 I'll get back to you9Check Sanction list status& trigger a refresh of the status10Check account and getcurrency type11Result12Yes, it's Yaro. He can receive in TZS,and I can convert from BWPPUT /parties/MSISDN/255123...PUT /parties{"party": {"partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "255123..."},"name": "Yaro","supportedCurrencies":["TZS"]}}13200 Gotcha14Yes, it's Yaro. He can receive in TZSPUT /parties/MSISDN/255123...15200 Gotcha16I will need to perform currency conversion.I need to calculatehow much currency I need.Let me find a currencyconversion provider before I start. \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_SenderConfirmation.plantuml b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_SenderConfirmation.plantuml new file mode 100644 index 000000000..8bffb60ec --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_SenderConfirmation.plantuml @@ -0,0 +1,57 @@ +@startuml FXAPI_Payer_Receive_SenderConfirmation + +!$simplified = false +!$shortCutSingleFXP = false +!$hideSwitchDetail = false +!$senderName = "Keeya" +!$receiverName = "Yaro" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "50000" +!$payeeFee = "4000" +!$targetAmount = "54000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "330" +!$fxpTargetAmount = "54000" +!$totalChargesSourceCurrency = "55" + + +title Currency Conversion with Amount Type RECEIVE +actor "$senderName" as A1 +box "Payer DFSP" #LightBlue + participant "Payer CBS" as PayerCBS + participant "Payer\nMojaloop\nConnector" as D1 +end box + +'participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow +' participant "ALS Oracle" as ALS +'end box + +'box "FX provider" +' participant "FXP\nConnector" as FXP +' participant "Backend FX API" as FXPBackend +'end box + +'box "Payee DFSP" #LightBlue +' participant "Payee\nMojaloop\nConnector" as D2 +' participant "Payee CBS" as PayeeCBS +'end box + +'actor "$receiverName" as A2 +autonumber + + +D1->PayerCBS:Here's the quote for the transfer\nIt expires at 2021-08-25T14:17:09.663+01:00 +PayerCBS->A1:Hi, $senderName: I can do the transfer.\nIt'll cost you $totalChargesSourceCurrency $payerCurrency in fees\n$fxpSourceAmount $payerCurrency will be deducted from your account,\nand $receiverName will receive\n$payeeReceiveAmount $payeeCurrency.\nLet me know if you want to go ahead +A1-->PayerCBS:Great! Yes please, go ahead + +PayerCBS-->D1: Payer has accepted the terms please proceed + +@enduml diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_SenderConfirmation.svg b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_SenderConfirmation.svg new file mode 100644 index 000000000..5c94fddac --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_SenderConfirmation.svg @@ -0,0 +1 @@ +Currency Conversion with Amount Type RECEIVEPayer DFSPKeeyaKeeyaPayer CBSPayer CBSPayerMojaloopConnectorPayerMojaloopConnectorSender Confirmation1Here's the quote for the transferIt expires at 2021-08-25T14:17:09.663+01:002Hi, Keeya: I can do the transfer.It'll cost you 55 BWP in fees330 BWP will be deducted from your account,and Yaro will receive50000 TZS.Let me know if you want to go ahead3Great! Yes please, go ahead4Payer has accepted the terms please proceed \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_TransferPhase.plantuml b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_TransferPhase.plantuml new file mode 100644 index 000000000..a5b9f2977 --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_TransferPhase.plantuml @@ -0,0 +1,254 @@ +@startuml FXAPI_Payer_Receive_TransferPhase + +!$simplified = false +!$shortCutSingleFXP = false +!$hideSwitchDetail = false +!$senderName = "Keeya" +!$receiverName = "Yaro" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "50000" +!$payeeFee = "4000" +!$targetAmount = "54000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "330" +!$fxpTargetAmount = "54000" +!$totalChargesSourceCurrency = "55" + + +title Transfer - Currency Conversion with Amount Type RECEIVE +actor "$senderName" as A1 +box "Payer DFSP" #LightBlue +' participant "Payer CBS" as PayerCBS + participant "Payer\nMojaloop\nConnector" as D1 +end box + +participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow +' participant "ALS Oracle" as ALS +'end box + +box "FX provider" + participant "FXP\nConnector" as FXP + participant "Backend FX API" as FXPBackend +end box + +box "Payee DFSP" #LightBlue + participant "Payee\nMojaloop\nConnector" as D2 +end box + participant "Payee CBS" as PayeeCBS + +'actor "$receiverName" as A2 +autonumber + +D1->D1:First, activate the conversion +D1->>S1:Please confirm your\n part of the transfer +note left +**POST /fxTransfers** +{ + "commitRequestId": "77c9d78dc26a4474...", + "determiningTransactionId": "d9ce59d435...", + "requestingFsp": "$payerFSPID", + "respondingFxp": "FDH_FX", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "condition": "bdbcf517cfc7..." +} +end note +activate S1 +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif +deactivate D1 +!if ($hideSwitchDetail != true) +S1->S1:OK, so this is an FX confirmation. +S1->S1: Does the sender have an account \nin this currency? Yes, it does. +!endif +S1->S1: Liquidity check and reserve on\n Payer DFSP's account +!if ($hideSwitchDetail != true) +note over S1 +Reservations: + +**$payerFSPID has a reservation of $fxpSourceAmount $payerCurrency** +end note +!endif +S1->>FXP:Please confirm the currency \nconversion part of the transfer\n **POST /fxTransfers** +activate FXP +!if ($simplified != true) +FXP-->>S1:202 I'll get back to you +!endif +deactivate S1 +FXP->FXPBackend:Reserve funds for\n FX conversion +FXPBackend->FXP:Success +FXP->>S1:Confirmed. Here's the fulfilment +note right +**PUT /fxTransfers/77c9d78dc26a...** +{ + "fulfilment": "188909ceb6cd5c...", + "completedTimeStamp": "2021-08-25T14:17:08.175+01:00" + "conversionState": "RESERVED" +} +end note +activate S1 +!if ($simplified != true) +S1-->>FXP:200 Gotcha +!endif +deactivate FXP +!if ($simplified != true) +S1->S1:Check fulfilment \nmatches and cancel if not. +alt Conversion failed +S1->FXP:Sorry. Conversion failed +note left +**PATCH /fxTransfers/77c9d78dc26a...** +{ + "fulfilment": "188909ceb6cd5c35...", + "completedTimeStamp": "2021-08-25T14:17:08.175+01:00", + "conversionState": "ABORTED" +} +end note +activate FXP +FXP-->S1:Acknowledged +FXP->FXP:Remove any reservations\nor obligations +deactivate FXP + +S1->>D1:Sorry. Conversion failed +note right +**PUT /fxTransfers/77c9d78dc26a.../error** +{ + "errorCode": "9999", + "errorDescription": "Whatever the error was" +} +end note +activate D1 +else Conversion succeeded +S1->D1:Conversion succeeded subject\n to transfer success\n**PUT /fxTransfers/77c9d78dc26a...** + +end +!else +S1->D1:Conversion succeeded subject\n to transfer success\n**PUT /fxTransfers/77c9d78dc26a...** +!endif +activate D1 +!if ($simplified != true) +D1-->S1:200 Gotcha +!endif +deactivate S1 +D1->D1:OK, so that's all right\nNow I can send the transfer itself + +D1->S1:Please do the transfer \n**POST /transfers** +!if ($simplified != true) +note left +**POST /transfers** +{ + "transferId": "c720ae14fc72...", + "payeeFsp": "$payeeFSPID", + "payerFsp": "$payerFSPID", + "amount": { + "currency": "$payeeCurrency", + "amount": "$targetAmount"}, + "transaction": { + "transactionId": "d9ce59d43598...", + "quoteId": "382987a875ce...", + "payee": { + "fspId": "$payeeFSPID", + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payeeMSISDN"}}, + "payer": { + "fspId": "$payerFSPID", + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payerMSISDN"}} + } +} +end note +!endif +activate S1 +!if ($simplified != true) +S1-->D1:202 I'll get back to you +!endif +deactivate D1 +!if ($hideSwitchDetail != true) +S1->S1:Is there a dependent transfer? Yes +!endif +S1->S1:Perform liquidity check and\n reserve funds against creditor\n party to dependent transfer +note over S1 +**Reservations:** + +$payerFSPID has a reservation of $fxpSourceAmount $payerCurrency +**FDH_FX has a reservation of $targetAmount $payeeCurrency** +end note + +S1->D2:Please do the transfer\n**POST /transfers** +activate D2 +!if ($simplified != true) +D2-->S1:202 I'll get back to you +!endif +deactivate S1 +D2->D2:Let me check that the terms \nof the dependent transfer are\n the same as the ones I agreed\n to and that the fulfilment\n and condition match +D2->D2:Yes, they do. \nI approve the transfer +D2->PayeeCBS:Please credit $receiverName's account\n with $payeeReceiveAmount $payeeCurrency +D2->S1:Transfer is confirmed, here's the fulfilment +note right +**PUT /transfers/c720ae14fc72...** +{ + "fulfilment": "mhPUT9ZAwdXLfe...", + "completedTimestamp": "2021-08-25T14:17:08.227+01:00", + "transferState": "COMMITTED" +} +end note +activate S1 +!if ($simplified != true) +S1-->D2:200 Gotcha +!endif +deactivate D2 +!if ($hideSwitchDetail != true) +S1->S1:Is there a dependent transfer?\nYes, there is. +S1->S1:Is this dependency against the\n debtor party to the transfer?\nYes, it is. +S1->S1:Create an obligation from the\n debtor party to the party named\n in the dependency (the FXP) +S1->S1:Is the transfer denominated in\n the currency of the payee \nreceive amount? Yes, it is. +S1->S1:Create an obligation from the\n party named in the dependency\nto the creditor party for the transfer +!else +S1->S1:Create obligations from the\n payer to the FXP and from \nFXP to the payee +!endif +S1->FXP:The transfer succeeded.\nYou can clear it in your ledgers +note left +**PATCH /fxTransfers/77c9d78dc26a...** +{ + "fulfilment": "2e6870fb4ed...", + "completedTimeStamp": "2021-08-25T14:17:08.175+01:00", + "conversionState": "COMMITTED" +} +end note +activate FXP +FXP->FXP:Let's just check: does \nthis match the stuff I sent? +FXP->FXP:It does. Great. \nI'll clear the conversion +FXP-->S1:200 Gotcha +deactivate FXP +note over S1 + **Ledger positions:** + $payerFSPID has a debit of $fxpSourceAmount $payerCurrency + FDH_FX has a credit of $fxpSourceAmount $payerCurrency + FDH_FX has a debit of $fxpTargetAmount $payeeCurrency + $payeeFSPID has a credit of $targetAmount $payeeCurrency +end note +S1->D1:Transfer is complete\n**PUT /transfers/c720ae14fc72...** +activate D1 +!if ($simplified != true) +D1-->S1:200 Gotcha +!endif +deactivate S1 +D1->D1:Commit the funds in my ledgers +D1->A1:Transfer was completed successfully +deactivate D1 + +@enduml diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_TransferPhase.svg b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_TransferPhase.svg new file mode 100644 index 000000000..0ca638f9b --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_Receive_TransferPhase.svg @@ -0,0 +1 @@ +Transfer - Currency Conversion with Amount Type RECEIVEPayer DFSPFX providerPayee DFSPKeeyaKeeyaPayerMojaloopConnectorPayerMojaloopConnectorMojaloop SwitchMojaloop SwitchFXPConnectorFXPConnectorBackend FX APIBackend FX APIPayeeMojaloopConnectorPayeeMojaloopConnectorPayee CBSPayee CBS1First, activate the conversion2Please confirm yourpart of the transferPOST /fxTransfers{"commitRequestId": "77c9d78dc26a4474...","determiningTransactionId": "d9ce59d435...","requestingFsp": "PayerFSP","respondingFxp": "FDH_FX","sourceAmount": {"currency": "BWP","amount": "330"},"targetAmount": {"currency": "TZS","amount": "54000"},"condition": "bdbcf517cfc7..."}3202 I'll get back to you4OK, so this is an FX confirmation.5Does the sender have an accountin this currency? Yes, it does.6Liquidity check and reserve onPayer DFSP's accountReservations: PayerFSP has a reservation of 330 BWP7Please confirm the currencyconversion part of the transfer POST /fxTransfers8202 I'll get back to you9Reserve funds forFX conversion10Success11Confirmed. Here's the fulfilmentPUT /fxTransfers/77c9d78dc26a...{"fulfilment": "188909ceb6cd5c...","completedTimeStamp": "2021-08-25T14:17:08.175+01:00""conversionState": "RESERVED"}12200 Gotcha13Check fulfilmentmatches and cancel if not.alt[Conversion failed]14Sorry. Conversion failedPATCH /fxTransfers/77c9d78dc26a...{"fulfilment": "188909ceb6cd5c35...","completedTimeStamp": "2021-08-25T14:17:08.175+01:00","conversionState": "ABORTED"}15Acknowledged16Remove any reservationsor obligations17Sorry. Conversion failedPUT /fxTransfers/77c9d78dc26a.../error{"errorCode": "9999","errorDescription": "Whatever the error was"}[Conversion succeeded]18Conversion succeeded subjectto transfer successPUT /fxTransfers/77c9d78dc26a...19200 Gotcha20OK, so that's all rightNow I can send the transfer itself21Please do the transferPOST /transfersPOST /transfers{"transferId": "c720ae14fc72...","payeeFsp": "PayeeFSP","payerFsp": "PayerFSP","amount": {"currency": "TZS","amount": "54000"},"transaction": {"transactionId": "d9ce59d43598...","quoteId": "382987a875ce...","payee": {"fspId": "PayeeFSP","partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "2551234567890"}},"payer": {"fspId": "PayerFSP","partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "26787654321"}}}}22202 I'll get back to you23Is there a dependent transfer? Yes24Perform liquidity check andreserve funds against creditorparty to dependent transferReservations: PayerFSP has a reservation of 330 BWPFDH_FX has a reservation of 54000 TZS25Please do the transferPOST /transfers26202 I'll get back to you27Let me check that the termsof the dependent transfer arethe same as the ones I agreedto and that the fulfilmentand condition match28Yes, they do.I approve the transfer29Please credit Yaro's accountwith 50000 TZS30Transfer is confirmed, here's the fulfilmentPUT /transfers/c720ae14fc72...{"fulfilment": "mhPUT9ZAwdXLfe...","completedTimestamp": "2021-08-25T14:17:08.227+01:00","transferState": "COMMITTED"}31200 Gotcha32Is there a dependent transfer?Yes, there is.33Is this dependency against thedebtor party to the transfer?Yes, it is.34Create an obligation from thedebtor party to the party namedin the dependency (the FXP)35Is the transfer denominated inthe currency of the payeereceive amount? Yes, it is.36Create an obligation from theparty named in the dependencyto the creditor party for the transfer37The transfer succeeded.You can clear it in your ledgersPATCH /fxTransfers/77c9d78dc26a...{"fulfilment": "2e6870fb4ed...","completedTimeStamp": "2021-08-25T14:17:08.175+01:00","conversionState": "COMMITTED"}38Let's just check: doesthis match the stuff I sent?39It does. Great.I'll clear the conversion40200 GotchaLedger positions:PayerFSP has a debit of 330 BWPFDH_FX has a credit of 330 BWPFDH_FX has a debit of 54000 TZSPayeeFSP has a credit of 54000 TZS41Transfer is completePUT /transfers/c720ae14fc72...42200 Gotcha43Commit the funds in my ledgers44Transfer was completed successfully \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_SenderConfirmation.plantuml b/docs/product/features/CurrencyConversion/FXAPI_Payer_SenderConfirmation.plantuml new file mode 100644 index 000000000..5b0d81e16 --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_SenderConfirmation.plantuml @@ -0,0 +1,157 @@ +@startuml FXAPI_Payer_SenderConfirmation + +!$simplified = false +!$shortCutSingleFXP = false +!$hideSwitchDetail = false +!$advancedCoreConnectorFlow = false +!$senderName = "John" +!$senderLastName = "" +!$senderDOB = "1966-06-16" +!$receiverName = "Yaro" +!$receiverFirstName = "Yaro" +!$receiverMiddleName = "" +!$receiverLastName = "" +!$receiverDOB = "1966-06-16" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$fxpID = "FDH_FX" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "44000" +!$payerSendAmount = "300" +!$payeeFee = "4000" +!$targetAmount = "48000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "300" +!$fxpTargetAmount = "48000" +!$totalChargesSourceCurrency = "55" +!$totalChargesTargetCurrency = "10000" +!$conversionRequestId = "828cc75f1654415e8fcddf76cc" +!$conversionId = "581f68efb54f416f9161ac34e8" +!$homeTransactionId = "string" +!$quoteId = "382987a875ce4037b500c475e0" +!$transactionId = "d9ce59d4359843968630581bb0" +!$quotePayerExpiration = "2021-08-25T14:17:09.663+01:00" +!$quotePayeeExpiration = "2021-08-25T14:17:09.663+01:00" +!$commitRequestId = "77c9d78dc26a44748b3c99b96a" +!$determiningTransferId = "d9ce59d4359843968630581bb0" +!$transferId = "d9ce59d4359843968630581bb0" +!$fxCondition = "GRzLaTP7DJ9t4P-a_B..." +!$condition = "HOr22-H3AfTDHrSkP..." + +title Payer DFSP requests conversion with SEND amount +actor "$senderName" as A1 +participant "Payer CBS" as PayerCBS + +box "Payer DFSP" #LightBlue + participant "Core Connector" as PayerCC + participant "Payer\nMojaloop\nConnector" as D1 +end box + +'participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow + 'participant "ALS Oracle" as ALS +'end box + +'box "FX provider" +' participant "FXP\nConnector" as FXP +' participant "Backend FX API" as FXPBackend +'end box + +'box "Payee DFSP" #LightBlue +' participant "Payee\nMojaloop\nConnector" as D2 +' participant "Core Connector" as PayeeCC +'end box + +'actor "$receiverName" as A2 +autonumber + + +!if ($advancedCoreConnectorFlow != true) + D1-->PayerCC:Here's the quote for the transfer\nIt expires at $quotePayeeExpiration + note right + **POST/PUT /transfers** response + { + "transferId": "$transferId", + "homeTransactionId": "$homeTransactionId", + "from": { + "displayName": "$senderName", + "fspId": "$payerFSPID", + "idType": "MSISDN", + "idValue": "$payerMSISDN" }, + "to": { + "type": "CONSUMER", + "idType": "MSISDN", + "idValue": "$payeeMSISDN", + "displayName": "$receiverName", + "fspId": "$payeeFSPID" + "supportedCurrencies": [ "$payeeCurrency" ] }, + "amountType": "SEND", + "currency": "$payerCurrency", + "amount": "$payerSendAmount" + "currentState": "**WAITING_FOR_QUOTE_ACCEPTANCE**", + "getPartiesResponse": {}, + "conversionRequestId": "$conversionRequestId", + "fxQuotesResponse": {}, + "fxQuotesResponseSource": "$payeeFSPID", + "quoteId": "$quoteId", + "quoteResponse": { + "body": { + "transferAmount": { + "currency": "$payeeCurrency", + "amount": "$targetAmount"}, + "payeeReceiveAmount": { + "currency": "$payeeCurrency", + "amount": "$payeeReceiveAmount"}, + "payeeFspFee": { + "currency": "$payeeCurrency", + "amount": "$payeeFee"}, + "expiration": "$payeeQuoteExpiration", + "ilpPacket": "", + "condition": "$condition"},}, + "quoteResponseSource": "$payeeFSPID", + } + end note +!else + D1-->PayerCC:Here's the quote for the transfer\nIt expires at $quotePayeeExpiration + !if ($simplified != true) + note right of PayerCC + { + "quotes": { + "body": { + "transferAmount": { + "currency": "$payeeCurrency", + "amount": "$targetAmount" + }, + "payeeReceiveAmount": { + "currency": "$payeeCurrency", + "amount": "$payeeReceiveAmount" + }, + "payeeFspFee": { + "currency": "$payeeCurrency", + "amount": "$payeeFee" + }, + "expiration": "$payeeQuoteExpiration", + "ilpPacket": " + + ", + "condition": "$condition" + }, + "headers": {} + }, + "currentState": "COMPLETED" + } + end note + !endif +!endif +PayerCC->PayerCBS:Here's the quote +PayerCBS->A1:Hi, $senderName: I can do the transfer.\nIt'll cost you $totalChargesSourceCurrency $payerCurrency($totalChargesTargetCurrency $payeeCurrency) in fees\nand $receiverName will receive\n$payeeReceiveAmount $payeeCurrency.\nLet me know if you want to go ahead +A1->PayerCBS:Great! Yes please, go ahead + +PayerCBS->PayerCC: Payer has accepted the terms please proceed + +@enduml \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_SenderConfirmation.svg b/docs/product/features/CurrencyConversion/FXAPI_Payer_SenderConfirmation.svg new file mode 100644 index 000000000..1f3622fef --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_SenderConfirmation.svg @@ -0,0 +1 @@ +Payer DFSP requests conversion with SEND amountPayer DFSPJohnJohnPayer CBSPayer CBSCore ConnectorCore ConnectorPayerMojaloopConnectorPayerMojaloopConnector1Here's the quote for the transferIt expires at 2021-08-25T14:17:09.663+01:00POST/PUT /transfersresponse{"transferId": "d9ce59d4359843968630581bb0","homeTransactionId": "string","from": {"displayName": "John","fspId": "PayerFSP","idType": "MSISDN","idValue": "26787654321" },"to": {"type": "CONSUMER","idType": "MSISDN","idValue": "2551234567890","displayName": "Yaro","fspId": "PayeeFSP""supportedCurrencies": [ "TZS" ] },"amountType": "SEND","currency": "BWP","amount": "300""currentState": "WAITING_FOR_QUOTE_ACCEPTANCE","getPartiesResponse": {<Same as the previous responses>},"conversionRequestId": "828cc75f1654415e8fcddf76cc","fxQuotesResponse": {<Same as the previous responses>},"fxQuotesResponseSource": "PayeeFSP","quoteId": "382987a875ce4037b500c475e0","quoteResponse": {"body": {"transferAmount": {"currency": "TZS","amount": "48000"},"payeeReceiveAmount": {"currency": "TZS","amount": "44000"},"payeeFspFee": {"currency": "TZS","amount": "4000"},"expiration": "$payeeQuoteExpiration","ilpPacket": "<This is encoded transaction object.>","condition": "HOr22-H3AfTDHrSkP..."},},"quoteResponseSource": "PayeeFSP",}2Here's the quote3Hi, John: I can do the transfer.It'll cost you 55 BWP(10000 TZS) in feesand Yaro will receive44000 TZS.Let me know if you want to go ahead4Great! Yes please, go ahead5Payer has accepted the terms please proceed \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_Transfer.plantuml b/docs/product/features/CurrencyConversion/FXAPI_Payer_Transfer.plantuml new file mode 100644 index 000000000..4cf1da01c --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_Transfer.plantuml @@ -0,0 +1,466 @@ +@startuml FXAPI_Payer_Transfer + +!$simplified = false +!$shortCutSingleFXP = false +!$hideSwitchDetail = false +!$advancedCoreConnectorFlow = false +!$senderName = "John" +!$senderLastName = "" +!$senderDOB = "1966-06-16" +!$receiverName = "Yaro" +!$receiverFirstName = "Yaro" +!$receiverMiddleName = "" +!$receiverLastName = "" +!$receiverDOB = "1966-06-16" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$fxpID = "FDH_FX" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "44000" +!$payerSendAmount = "300" +!$payeeFee = "4000" +!$targetAmount = "48000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "300" +!$fxpTargetAmount = "48000" +!$totalChargesSourceCurrency = "55" +!$totalChargesTargetCurrency = "10000" +!$conversionRequestId = "828cc75f1654415e8fcddf76cc" +!$conversionId = "581f68efb54f416f9161ac34e8" +!$homeTransactionId = "string" +!$quoteId = "382987a875ce4037b500c475e0" +!$transactionId = "d9ce59d4359843968630581bb0" +!$quotePayerExpiration = "2021-08-25T14:17:09.663+01:00" +!$quotePayeeExpiration = "2021-08-25T14:17:09.663+01:00" +!$commitRequestId = "77c9d78dc26a44748b3c99b96a" +!$determiningTransferId = "d9ce59d4359843968630581bb0" +!$transferId = "d9ce59d4359843968630581bb0" +!$fxCondition = "GRzLaTP7DJ9t4P-a_B..." +!$condition = "HOr22-H3AfTDHrSkP..." + +title Transfer Phase - Mojaloop Connector +actor "$senderName" as A1 + participant "Payer CBS" as PayerCBS +box "Payer DFSP" #LightBlue + participant "Core Connector" as PayerCC + participant "Payer\nMojaloop\nConnector" as D1 +end box + +participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow +' participant "ALS Oracle" as ALS +'end box + +box "FX provider" + participant "FXP\nConnector" as FXP + participant "Backend FX API" as FXPBackend +end box + +box "Payee DFSP" #LightBlue + participant "Payee\nMojaloop\nConnector" as D2 + participant "Core Connector" as PayeeCC +end box + +actor "$receiverName" as A2 +autonumber + +!if ($advancedCoreConnectorFlow != true) +PayerCC->D1: Proceed with the transfer\nPUT /transfers +note left +{"acceptQuote": true} +end note +!else +PayerCC->D1: Proceed with the transfer\n**POST /fxTransfers** + !if ($simplified != true) + note left + { + "homeTransactionId": "$homeTransactionId", + "commitRequestId": "$commitRequestId", + "determiningTransferId": "$determiningTransferId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "condition": "$fxCondition" + } + end note + !endif +!endif + +!if ($advancedCoreConnectorFlow != true) +D1->D1:First, activate the conversion +!endif +D1->>S1:Please confirm your part of the transfer +note left +**POST /fxTransfers** +{ + "commitRequestId": "$commitRequestId", + "determiningTransferId": "$determiningTransferId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "condition": "$fxCondition" +} +end note +activate S1 +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif +deactivate D2 +!if ($hideSwitchDetail != true) +S1->S1:OK, so this is an FX confirmation. +S1->S1: Is there any transfer with determiningTransactionId?\nNo, it does'nt. +!endif +S1->S1: Liquidity check and reserve on Payer DFSP's account +!if ($hideSwitchDetail != true) +note over S1 +Reservations: + +**$payerFSPID has a reservation of $fxpSourceAmount $payerCurrency** +end note +!endif +S1->>FXP:Please confirm the currency conversion part of the transfer\n** POST /fxTransfers** +activate FXP +!if ($simplified != true) +FXP-->>S1:202 I'll get back to you +!endif +deactivate S1 +FXP->FXPBackend:Reserve funds for FX conversion +note left +**POST /fxTransfers** +{ + "homeTransactionId": "$homeTransactionId", + "commitRequestId": "$commitRequestId", + "determiningTransferId": "$determiningTransferId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "condition": "$fxCondition" +} +end note +FXPBackend-->FXP:Success +note right +{ + "homeTransactionId": "$homeTransactionId", + "completedTimestamp": "2021-08-25T14:17:08.175+01:00", + "conversionState": "RESERVED" +} +end note +FXP->>S1:Confirmed. Here's the fulfilment +note right +**PUT /fxTransfers/$commitRequestId** +{ + "fulfilment": "188909ceb6cd5c35d5c6b394f0a9e5a0571199c332fbd013dc1e6b8a2d5fff42", + "completedTimestamp": "2021-08-25T14:17:08.175+01:00", + "conversionState": "RESERVED" +} +end note +activate S1 +!if ($simplified != true) +S1-->>FXP:200 Gotcha +!endif +deactivate FXP +!if ($simplified != true) +S1->S1:Check fulfilment matches and cancel if not. +alt Conversion failed +S1->FXP:Sorry. Conversion failed +note right +**PATCH /fxTransfers/$commitRequestId** +{ + "completedTimestamp": "2021-08-25T14:17:08.175+01:00", + "conversionState": "ABORTED" +} +end note +activate FXP +FXP-->S1:Acknowledged +FXP->FXPBackend:Remove any reservations or obligations +note left +**PUT /fxTransfers/$commitRequestId** +{ + "completedTimestamp": "2021-08-25T14:17:08.175+01:00", + "conversionState": "ABORTED" +} +end note +FXPBackend-->FXP:Ok +deactivate FXP + +S1->>D1:Sorry. Conversion failed +note right +**PUT /fxTransfers/$commitRequestId/error** +{ + "errorCode": "9999", + "errorDescription": "Whatever the error was" +} +end note +else Conversion succeeded +S1->D1:Conversion succeeded subject to transfer success\n**PUT /fxTransfers/77c9d78d-c26a-4474-8b3c-99b96a814bfc** + +end +!else +S1->D1:Conversion succeeded subject to transfer success\n**PUT /fxTransfers/77c9d78d-c26a-4474-8b3c-99b96a814bfc** +!endif +activate D1 +!if ($simplified != true) +D1-->S1:200 Gotcha +!endif +deactivate S1 + +!if ($advancedCoreConnectorFlow != true) + D1->D1:OK, so that's all right\nNow I can send the transfer itself + ' TODO: Need to add PUT /transfers response here +!else + D1-->PayerCC:Confirmed. You can proceed with the transfer. + note right of PayerCC + **PUT /fxTransfers/$commitRequestId** + { + "fulfilment": "188909ceb6cd5c35d5c6b394f0a9e5a0571199c332fbd013dc1e6b8a2d5fff42", + "completedTimestamp": "2021-08-25T14:17:08.175+01:00", + "conversionState": "RESERVED" + } + end note + + PayerCC-->D1:Please do the transfer **POST /simpleTransfers** + !if ($simplified != true) + note right of PayerCC + { + "fspId": "$payeeFSPID", + "transfersPostRequest": { + "transferId": "$transferId", + "payeeFsp": "$payeeFSPID", + "payerFsp": "$payerFSPID", + "amount": { + "currency": "$payeeCurrency", + "amount": "$targetAmount" + }, + "ilpPacket": "", + "condition": "$condition", + "expiration": "2016-05-24T08:38:08.699-04:00" + } + } + end note + !endif +!endif + +D1->S1:Please do the transfer **POST /transfers** +!if ($simplified != true) +note over D1 +**POST /transfers** +{ + "transferId": "$transferId", + "payeeFsp": "$payeeFSPID", + "payerFsp": "$payerFSPID", + "amount": { + "currency": "$payeeCurrency", + "amount": "$targetAmount"}, + "ilpPacket": "", + "condition": "$condition", + "expiration": "2016-05-24T08:38:08.699-04:00" +} +end note +!endif +activate S1 +!if ($simplified != true) +S1-->D1:202 I'll get back to you +!endif +deactivate D1 +!if ($hideSwitchDetail != true) +S1->S1:Is there a dependent transfer? Yes +!endif +S1->S1:Perform liquidity check and reserve funds\nagainst creditor party to dependent transfer +note over S1 +Reservations: + +$payerFSPID has a reservation of $fxpSourceAmount $payerCurrency +**$fxpID has a reservation of $targetAmount $payeeCurrency** +end note + +S1->D2:Please do the transfer\n**POST /transfers** +activate D2 +!if ($simplified != true) +D2-->S1:202 I'll get back to you +!endif +deactivate S1 +D2->D2:Let me check that the terms of the dependent transfer\nare the same as the ones I agreed to\nand that the fulfilment and condition match + +D2->PayeeCC:Please credit $receiverName's account with $payeeReceiveAmount $payeeCurrency +!if ($simplified != true) +note left +**POST /transfers** +{ + "transferId": "$transferId", + "amount": "$targetAmount", + "currency": "$payeeCurrency", + "amountType": "SEND", + "from": { + "displayName": "$senderName", + "fspId": "$payerFSPID", + "idType": "MSISDN", + "idValue": "$payerMSISDN"}, + "to": { + "displayName": "$receiverName", + "fspId": "$payeeFSPID", + "idType": "MSISDN", + "idValue": "$payeeMSISDN"}, + "quote": { + "quoteId": "$quoteId", + "transactionId": "$transactionId", + "payeeFspFeeAmount": "$payeeFee", + "payeeFspFeeAmountCurrency": "$payeeCurrency", + "payeeReceiveAmount": "$payeeReceiveAmount", + "payeeReceiveAmountCurrency": "$payeeCurrency", + "transferAmount": "$targetAmount", + "transferAmountCurrency": "$payeeCurrency" + "expiration": "$quotePayeeExpiration"}, + "transactionType": "TRANSFER", + "ilpPacket": {"data": } +} +end note +!endif + +PayeeCC-->D2:Done +PayeeCC->A2:You have received $payeeReceiveAmount $payeeCurrency +!if ($simplified != true) +note right of D2 +{ + "homeTransactionId": "string", + "completedTimestamp": "2021-08-25T14:17:08.227+01:00", + "fulfilment": "mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s", + **Note: fulfilment is optional: SDK will create if not found** + "transferState": "COMMITTED" +} +end note +!endif + +D2->>S1:Transfer is confirmed, here's the fulfilment +note over D2 +**PUT /transfers/$commitRequestId** +{ + "completedTimestamp": "2021-08-25T14:17:08.227+01:00", + "fulfilment": "mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s", + "transferState": "COMMITTED" +} +end note +activate S1 +!if ($simplified != true) +S1-->>D2:200 Gotcha +!endif +deactivate D2 +!if ($hideSwitchDetail != true) +S1->S1:Is there a dependent transfer?\nYes, there is. +S1->S1:Is this dependency against \nthe debtor party to the transfer?\nYes, it is. +S1->S1:Create an obligation from the\n debtor party to the party named in the dependency (the FXP) +S1->S1:Is the transfer denominated in\n the currency of the payee receive amount?\nYes, it is. +S1->S1:Create an obligation from the \nparty named in the dependency\nto the creditor party for the transfer +!else +S1->S1:Create obligations from the payer to the FXP and from FXP to the payee +!endif +S1->>FXP:The transfer succeeded.\nYou can clear it in your ledgers +note over S1 +**PATCH /fxTransfers/$commitRequestId** +{ + "completedTimestamp": "2021-08-25T14:17:08.227+01:00", + "fulfilment": "mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s", + "transferState": "COMMITTED" +} +end note +activate FXP +FXP->FXP:Let's just check: does this match the stuff I sent? +FXP->FXP:It does. Great. I'll clear the conversion +FXP-->>S1:200 Gotcha +deactivate FXP +note over S1 + Ledger positions: + $payerFSPID has a debit of $fxpSourceAmount $payerCurrency + $fxpID has a credit of $fxpSourceAmount $payerCurrency + $fxpID has a debit of $fxpTargetAmount $payeeCurrency + $payeeFSPID has a credit of $targetAmount $payeeCurrency +end note +S1->>D1:Transfer is complete\n**PUT /transfers/$commitRequestId** +activate D1 +!if ($simplified != true) +D1-->S1:200 Gotcha +!endif +deactivate S1 +!if ($advancedCoreConnectorFlow != true) + D1-->PayerCC:Transfer was completed successfully + note right of PayerCC + **POST/PUT /transfers/** response + { + "transferId": "$transferId", + "homeTransactionId": "$homeTransactionId", + "from": { + "displayName": "$senderName", + "fspId": "$payerFSPID", + "idType": "MSISDN", + "idValue": "$payerMSISDN"}, + "to": { + "type": "CONSUMER", + "idType": "MSISDN", + "idValue": "$payeeMSISDN", + "displayName": "$receiverName", + "fspId": "$payeeFSPID" + "supportedCurrencies": [ "$payeeCurrency" ]}, + "amountType": "SEND", + "currency": "$payerCurrency", + "amount": "$payerSendAmount" + "currentState": "**COMPLETED**", + "getPartiesResponse": {}, + "conversionRequestId": "$conversionRequestId", + "fxQuotesResponse": {}, + "fxQuotesResponseSource": "$payeeFSPID", + "quoteId": "$quoteId", + "quoteResponse": {}, + "quoteResponseSource": "$payeeFSPID", + "fulfil": { + "body": { + "completedTimestamp": "2021-08-25T14:17:08.227+01:00", + "fulfilment": "mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s", + "transferState": "COMMITTED"},}, + } + end note +!else + D1-->PayerCC:Transfer was completed successfully + !if ($simplified != true) + note right of PayerCC + { + "transfer": { + "body": { + "completedTimestamp": "2021-08-25T14:17:08.227+01:00", + "fulfilment": "mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s", + "transferState": "COMMITTED" + }, + "headers": {} + }, + "currentState": "COMPLETED" + } + end note + !endif +!endif + +PayerCC->PayerCBS:Transfer was completed successfully +PayerCBS->PayerCBS:Commit the funds in my ledgers +PayerCBS->A1:Your transfer is successful +deactivate D1 +@enduml \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/FXAPI_Payer_Transfer.svg b/docs/product/features/CurrencyConversion/FXAPI_Payer_Transfer.svg new file mode 100644 index 000000000..1cb78ebdb --- /dev/null +++ b/docs/product/features/CurrencyConversion/FXAPI_Payer_Transfer.svg @@ -0,0 +1 @@ +Transfer Phase - Mojaloop ConnectorPayer DFSPFX providerPayee DFSPJohnJohnPayer CBSPayer CBSCore ConnectorCore ConnectorPayerMojaloopConnectorPayerMojaloopConnectorMojaloop SwitchMojaloop SwitchFXPConnectorFXPConnectorBackend FX APIBackend FX APIPayeeMojaloopConnectorPayeeMojaloopConnectorCore ConnectorCore ConnectorYaroYaro1Proceed with the transferPUT /transfers{"acceptQuote": true}2First, activate the conversion3Please confirm your part of the transferPOST /fxTransfers{"commitRequestId": "77c9d78dc26a44748b3c99b96a","determiningTransferId": "d9ce59d4359843968630581bb0","initiatingFsp": "PayerFSP","counterPartyFsp": "FDH_FX","amountType": "SEND","sourceAmount": {"currency": "BWP","amount": "300"},"targetAmount": {"currency": "TZS","amount": "48000"},"condition": "GRzLaTP7DJ9t4P-a_B..."}4202 I'll get back to you5OK, so this is an FX confirmation.6Is there any transfer with determiningTransactionId?No, it does'nt.7Liquidity check and reserve on Payer DFSP's accountReservations: PayerFSP has a reservation of 300 BWP8Please confirm the currency conversion part of the transferPOST /fxTransfers**9202 I'll get back to you10Reserve funds for FX conversionPOST /fxTransfers{"homeTransactionId": "string","commitRequestId": "77c9d78dc26a44748b3c99b96a","determiningTransferId": "d9ce59d4359843968630581bb0","initiatingFsp": "PayerFSP","counterPartyFsp": "FDH_FX","amountType": "SEND","sourceAmount": {"currency": "BWP","amount": "300"},"targetAmount": {"currency": "TZS","amount": "48000"},"condition": "GRzLaTP7DJ9t4P-a_B..."}11Success{"homeTransactionId": "string","completedTimestamp": "2021-08-25T14:17:08.175+01:00","conversionState": "RESERVED"}12Confirmed. Here's the fulfilmentPUT /fxTransfers/77c9d78dc26a44748b3c99b96a{"fulfilment": "188909ceb6cd5c35d5c6b394f0a9e5a0571199c332fbd013dc1e6b8a2d5fff42","completedTimestamp": "2021-08-25T14:17:08.175+01:00","conversionState": "RESERVED"}13200 Gotcha14Check fulfilment matches and cancel if not.alt[Conversion failed]15Sorry. Conversion failedPATCH /fxTransfers/77c9d78dc26a44748b3c99b96a{"completedTimestamp": "2021-08-25T14:17:08.175+01:00","conversionState": "ABORTED"}16Acknowledged17Remove any reservations or obligationsPUT /fxTransfers/77c9d78dc26a44748b3c99b96a{"completedTimestamp": "2021-08-25T14:17:08.175+01:00","conversionState": "ABORTED"}18Ok19Sorry. Conversion failedPUT /fxTransfers/77c9d78dc26a44748b3c99b96a/error{"errorCode": "9999","errorDescription": "Whatever the error was"}[Conversion succeeded]20Conversion succeeded subject to transfer successPUT /fxTransfers/77c9d78d-c26a-4474-8b3c-99b96a814bfc21200 Gotcha22OK, so that's all rightNow I can send the transfer itself23Please do the transferPOST /transfersPOST /transfers{"transferId": "d9ce59d4359843968630581bb0","payeeFsp": "PayeeFSP","payerFsp": "PayerFSP","amount": {"currency": "TZS","amount": "48000"},"ilpPacket": "<Encoded transaction object>","condition": "HOr22-H3AfTDHrSkP...","expiration": "2016-05-24T08:38:08.699-04:00"}24202 I'll get back to you25Is there a dependent transfer? Yes26Perform liquidity check and reserve fundsagainst creditor party to dependent transferReservations: PayerFSP has a reservation of 300 BWPFDH_FX has a reservation of 48000 TZS27Please do the transferPOST /transfers28202 I'll get back to you29Let me check that the terms of the dependent transferare the same as the ones I agreed toand that the fulfilment and condition match30Please credit Yaro's account with 44000 TZSPOST /transfers{"transferId": "d9ce59d4359843968630581bb0","amount": "48000","currency": "TZS","amountType": "SEND","from": {"displayName": "John","fspId": "PayerFSP","idType": "MSISDN","idValue": "26787654321"},"to": {"displayName": "Yaro","fspId": "PayeeFSP","idType": "MSISDN","idValue": "2551234567890"},"quote": {"quoteId": "382987a875ce4037b500c475e0","transactionId": "d9ce59d4359843968630581bb0","payeeFspFeeAmount": "4000","payeeFspFeeAmountCurrency": "TZS","payeeReceiveAmount": "44000","payeeReceiveAmountCurrency": "TZS","transferAmount": "48000","transferAmountCurrency": "TZS""expiration": "2021-08-25T14:17:09.663+01:00"},"transactionType": "TRANSFER","ilpPacket": {"data": <decoded ilpPacket>}}31Done32You have received 44000 TZS{"homeTransactionId": "string","completedTimestamp": "2021-08-25T14:17:08.227+01:00","fulfilment": "mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s",    Note: fulfilment is optional: SDK will create if not found"transferState": "COMMITTED"}33Transfer is confirmed, here's the fulfilmentPUT /transfers/77c9d78dc26a44748b3c99b96a{"completedTimestamp": "2021-08-25T14:17:08.227+01:00","fulfilment": "mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s","transferState": "COMMITTED"}34200 Gotcha35Is there a dependent transfer?Yes, there is.36Is this dependency againstthe debtor party to the transfer?Yes, it is.37Create an obligation from thedebtor party to the partynamed in the dependency (the FXP)38Is the transfer denominated inthe currency of the payee receive amount?Yes, it is.39Create an obligation from theparty named in the dependencyto the creditor party for the transfer40The transfer succeeded.You can clear it in your ledgersPATCH /fxTransfers/77c9d78dc26a44748b3c99b96a{"completedTimestamp": "2021-08-25T14:17:08.227+01:00","fulfilment": "mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s","transferState": "COMMITTED"}41Let's just check: does this match the stuff I sent?42It does. Great. I'll clear the conversion43200 GotchaLedger positions:PayerFSP has a debit of 300 BWPFDH_FX has a credit of 300 BWPFDH_FX has a debit of 48000 TZSPayeeFSP has a credit of 48000 TZS44Transfer is completePUT /transfers/77c9d78dc26a44748b3c99b96a45200 Gotcha46Transfer was completed successfullyPOST/PUT /transfers/response{"transferId": "d9ce59d4359843968630581bb0","homeTransactionId": "string","from": {"displayName": "John","fspId": "PayerFSP","idType": "MSISDN","idValue": "26787654321"},"to": {"type": "CONSUMER","idType": "MSISDN","idValue": "2551234567890","displayName": "Yaro","fspId": "PayeeFSP""supportedCurrencies": [ "TZS" ]},"amountType": "SEND","currency": "BWP","amount": "300""currentState": "COMPLETED","getPartiesResponse": {<Same as the previous responses>},"conversionRequestId": "828cc75f1654415e8fcddf76cc","fxQuotesResponse": {<Same as the previous responses>},"fxQuotesResponseSource": "PayeeFSP","quoteId": "382987a875ce4037b500c475e0","quoteResponse": {<Same as the previous responses>},"quoteResponseSource": "PayeeFSP","fulfil": {"body": {"completedTimestamp": "2021-08-25T14:17:08.227+01:00","fulfilment": "mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s","transferState": "COMMITTED"},},}47Transfer was completed successfully48Commit the funds in my ledgers49Your transfer is successful \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/PAYER_SEND_Agreement.plantuml b/docs/product/features/CurrencyConversion/PAYER_SEND_Agreement.plantuml new file mode 100644 index 000000000..c50bf7548 --- /dev/null +++ b/docs/product/features/CurrencyConversion/PAYER_SEND_Agreement.plantuml @@ -0,0 +1,182 @@ +@startuml PAYER_SEND_Agreement + +!$simplified = true +!$hideSwitchDetail = false +!$advancedCoreConnectorFlow = true +!$senderName = "John" +!$senderLastName = "" +!$senderDOB = "1966-06-16" +!$receiverName = "Yaro" +!$receiverFirstName = "Yaro" +!$receiverMiddleName = "" +!$receiverLastName = "" +!$receiverDOB = "1966-06-16" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$fxpID = "FDH_FX" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "44000" +!$payerSendAmount = "300" +!$payeeFee = "4000" +!$targetAmount = "48000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "300" +!$fxpTargetAmount = "48000" +!$totalChargesSourceCurrency = "55" +!$totalChargesTargetCurrency = "10000" +!$conversionRequestId = "828cc75f1654415e8fcddf76cc" +!$conversionId = "581f68efb54f416f9161ac34e8" +!$homeTransactionId = "string" +!$quoteId = "382987a875ce4037b500c475e0" +!$transactionId = "d9ce59d4359843968630581bb0" +!$quotePayerExpiration = "2021-08-25T14:17:09.663+01:00" +!$quotePayeeExpiration = "2021-08-25T14:17:09.663+01:00" +!$commitRequestId = "77c9d78dc26a44748b3c99b96a" +!$determiningTransferId = "d9ce59d4359843968630581bb0" +!$transferId = "d9ce59d4359843968630581bb0" +!$fxCondition = "GRzLaTP7DJ9t4P-a_B..." +!$condition = "HOr22-H3AfTDHrSkP..." + + +title Payer DFSP requests quote from Payee DFSP +'actor "$senderName" as A1 +box "Payer DFSP" #LightBlue + participant "Payer DFSP" as D1 +end box + +participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow +' participant "ALS Oracle" as ALS +'end box + +'box "FX provider" +' participant "FXP\nConnector" as FXP +'end box + +box "Payee DFSP" #LightBlue + participant "Payee\nMojaloop\nConnector" as D2 +end box + +'actor "$receiverName" as A2 +autonumber + + +D1->>S1:Please quote for a transfer which sends $fxpTargetAmount $payeeCurrency.\n**POST /quotes** +deactivate D1 +!if ($simplified != true) +note left +POST /quotes + + { + "quoteId": "$quoteId", + "transactionId": "$transactionId", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payeeMSISDN", + "fspId": "$payeeFSPID" + }, + "name": "$receiverName", + "personalInfo": { + "complexName": { + "firstName": "$receiverFirstName", + "middleName": "$receiverMiddleName", + "lastName": "$receiverLastName" + }, + "dateOfBirth": "$receiverDOB", + "kycInformation": "" + }, + "supportedCurrencies": [ "$payeeCurrency" ] + }, + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payerMSISDN", + "fspId": "$payerFSPID" + }, + "name": "$senderName", + "personalInfo": { + "complexName": { + "firstName": "$senderFirstName", + "middleName": "$senderMiddleName", + "lastName": "$senderLastName" + }, + "dateOfBirth": "$senderDOB" + } + }, + "amountType": "SEND", + "amount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount" + }, + "converter": "PAYER", + "expiration": "$quotePayerExpiration" + } +end note +!endif +activate S1 +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif + +S1->>D2:**POST /quotes** +deactivate S1 +activate D2 +!if ($simplified != true) +D2-->>S1:202 I'll get back to you +!endif + +D2->D2:OK, so I will charge $payeeFee $payeeCurrency for this.\nNow I create terms of the transfer +!if ($simplified != true) +note right of D2 +{ + "quoteId": "$quoteId", + "transactionId": "$transactionId", + "payeeFspFeeAmount": "$payeeFee", + "payeeFspFeeAmountCurrency": "$payeeCurrency", + "payeeReceiveAmount": "$payeeReceiveAmount", + "payeeReceiveAmountCurrency": "$payeeCurrency", + "transferAmount": "$targetAmount", + "transferAmountCurrency": "$payeeCurrency" + "expiration": "$quotePayerExpiration" +} +end note +!endif +D2->D2:Now I will sign the transaction object +D2->>S1:Here's the signed quote +note right + **put /quotes/$quoteId** + { + "transferAmount": { + "currency": "$payeeCurrency", + "amount": "$targetAmount"}, + "payeeReceiveAmount": { + "currency": "$payeeCurrency", + "amount": "$payeeReceiveAmount"}, + "payeeFspFee": { + "currency": "$payeeCurrency", + "amount": "$payeeFee"}, + "expiration": "$payeeQuoteExpiration", + "ilpPacket": "", + "condition": "$condition" + } +end note +deactivate D2 +activate S1 +!if ($simplified != true) +S1-->>D2:200 Gotcha +!endif +S1->>D1:Here's the signed quote\n**PUT /quotes/$quoteId** +deactivate S1 +activate D1 +!if ($simplified != true) +D1-->>S1:200 Gotcha +!endif +D1->D1:OK, I can see that there are going to be $payeeFee $payeeCurrency in charges. + +@enduml \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/PAYER_SEND_Agreement.svg b/docs/product/features/CurrencyConversion/PAYER_SEND_Agreement.svg new file mode 100644 index 000000000..02cc3a5b4 --- /dev/null +++ b/docs/product/features/CurrencyConversion/PAYER_SEND_Agreement.svg @@ -0,0 +1 @@ +Payer DFSP requests quote from Payee DFSPPayer DFSPPayee DFSPPayer DFSPPayer DFSPMojaloop SwitchMojaloop SwitchPayeeMojaloopConnectorPayeeMojaloopConnector1Please quote for a transfer which sends 48000 TZS.POST /quotes2POST /quotes3OK, so I will charge 4000 TZS for this.Now I create terms of the transfer4Now I will sign the transaction object5Here's the signed quoteput /quotes/382987a875ce4037b500c475e0{"transferAmount": {"currency": "TZS","amount": "48000"},"payeeReceiveAmount": {"currency": "TZS","amount": "44000"},"payeeFspFee": {"currency": "TZS","amount": "4000"},"expiration": "$payeeQuoteExpiration","ilpPacket": "<This is encoded transaction object.>","condition": "HOr22-H3AfTDHrSkP..."}6Here's the signed quotePUT /quotes/382987a875ce4037b500c475e07OK, I can see that there are going to be 4000 TZS in charges. \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/PAYER_SEND_Confirmation.plantuml b/docs/product/features/CurrencyConversion/PAYER_SEND_Confirmation.plantuml new file mode 100644 index 000000000..2ebc792ac --- /dev/null +++ b/docs/product/features/CurrencyConversion/PAYER_SEND_Confirmation.plantuml @@ -0,0 +1,78 @@ +@startuml PAYER_SEND_Confirmation +!$simplified = true +!$hideSwitchDetail = false +!$advancedCoreConnectorFlow = true +!$senderName = "John" +!$senderLastName = "" +!$senderDOB = "1966-06-16" +!$receiverName = "Yaro" +!$receiverFirstName = "Yaro" +!$receiverMiddleName = "" +!$receiverLastName = "" +!$receiverDOB = "1966-06-16" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$fxpID = "FDH_FX" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "44000" +!$payerSendAmount = "300" +!$payeeFee = "4000" +!$targetAmount = "48000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "300" +!$fxpTargetAmount = "48000" +!$totalChargesSourceCurrency = "55" +!$totalChargesTargetCurrency = "10000" +!$conversionRequestId = "828cc75f1654415e8fcddf76cc" +!$conversionId = "581f68efb54f416f9161ac34e8" +!$homeTransactionId = "string" +!$quoteId = "382987a875ce4037b500c475e0" +!$transactionId = "d9ce59d4359843968630581bb0" +!$quotePayerExpiration = "2021-08-25T14:17:09.663+01:00" +!$quotePayeeExpiration = "2021-08-25T14:17:09.663+01:00" +!$commitRequestId = "77c9d78dc26a44748b3c99b96a" +!$determiningTransferId = "d9ce59d4359843968630581bb0" +!$transferId = "d9ce59d4359843968630581bb0" +!$fxCondition = "GRzLaTP7DJ9t4P-a_B..." +!$condition = "HOr22-H3AfTDHrSkP..." + + +title Payer DFSP presents the terms to the Payer +actor "$senderName" as A1 +box "Payer DFSP" #LightBlue + participant "Payer DFSP" as D1 +end box + +'participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow +' participant "ALS Oracle" as ALS +'end box + +'box "FX provider" +' participant "FXP\nConnector" as FXP +'end box + +'box "Payee DFSP" #LightBlue +' participant "Payee\nMojaloop\nConnector" as D2 +'end box + +'actor "$receiverName" as A2 +autonumber + +D1->A1: Present the terms of the transfer to the Payer +note right +Hi, $senderName: +I can do the transfer. +It'll cost you $totalChargesSourceCurrency $payerCurrency($totalChargesTargetCurrency $payeeCurrency) in fees +and $receiverName will receive $payeeReceiveAmount $payeeCurrency. +**Let me know if you want to go ahead?** +end note +A1->D1: Great! Yes please, go ahead + +D1->D1: Payer has accepted the terms please proceed +@enduml \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/PAYER_SEND_Confirmation.svg b/docs/product/features/CurrencyConversion/PAYER_SEND_Confirmation.svg new file mode 100644 index 000000000..b9161ef46 --- /dev/null +++ b/docs/product/features/CurrencyConversion/PAYER_SEND_Confirmation.svg @@ -0,0 +1 @@ +Payer DFSP presents the terms to the PayerPayer DFSPJohnJohnPayer DFSPPayer DFSP1Present the terms of the transfer to the PayerHi, John:I can do the transfer.It'll cost you 55 BWP(10000 TZS) in feesand Yaro will receive 44000 TZS.Let me know if you want to go ahead?2Great! Yes please, go ahead3Payer has accepted the terms please proceed \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/PAYER_SEND_CurrencyConversion.plantuml b/docs/product/features/CurrencyConversion/PAYER_SEND_CurrencyConversion.plantuml new file mode 100644 index 000000000..14b49b3e9 --- /dev/null +++ b/docs/product/features/CurrencyConversion/PAYER_SEND_CurrencyConversion.plantuml @@ -0,0 +1,193 @@ +@startuml PAYER_SEND_CurrencyConversion + +!$simplified = true +!$hideSwitchDetail = false +!$advancedCoreConnectorFlow = true +!$senderName = "John" +!$senderLastName = "" +!$senderDOB = "1966-06-16" +!$receiverName = "Yaro" +!$receiverFirstName = "Yaro" +!$receiverMiddleName = "" +!$receiverLastName = "" +!$receiverDOB = "1966-06-16" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$fxpID = "FDH_FX" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "44000" +!$payerSendAmount = "300" +!$payeeFee = "4000" +!$targetAmount = "48000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "300" +!$fxpTargetAmount = "48000" +!$totalChargesSourceCurrency = "55" +!$totalChargesTargetCurrency = "10000" +!$conversionRequestId = "828cc75f1654415e8fcddf76cc" +!$conversionId = "581f68efb54f416f9161ac34e8" +!$homeTransactionId = "string" +!$quoteId = "382987a875ce4037b500c475e0" +!$transactionId = "d9ce59d4359843968630581bb0" +!$quotePayerExpiration = "2021-08-25T14:17:09.663+01:00" +!$quotePayeeExpiration = "2021-08-25T14:17:09.663+01:00" +!$commitRequestId = "77c9d78dc26a44748b3c99b96a" +!$determiningTransferId = "d9ce59d4359843968630581bb0" +!$transferId = "d9ce59d4359843968630581bb0" +!$fxCondition = "GRzLaTP7DJ9t4P-a_B..." +!$condition = "HOr22-H3AfTDHrSkP..." + + +title Payer DFSP requests conversion with SEND amount +' actor "$senderName" as A1 +box "Payer DFSP" #LightBlue + participant "Payer DFSP" as D1 +end box + +participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow +' participant "ALS Oracle" as ALS +'end box + +box "FX provider" + participant "FXP\nConnector" as FXP +end box + +'box "Payee DFSP" #LightBlue +' participant "Payee\nMojaloop\nConnector" as D2 +'end box + +'actor "$receiverName" as A2 +autonumber + + +D1->D1:Hmmm. I can only send in $payerCurrency.\nI need to get some currency conversion +D1->D1: Look up the local cached FXPs\n that can provide the conversion +D1->D1:I'll ask FDH FX to perform my conversion + + +D1->>S1:Here is the initial version of the transfer.\nPlease quote me for the currency conversion. + +note left + **post /fxQuotes** + { + "conversionRequestId": "$conversionRequestId", + "conversionTerms": { + "conversionId": "$conversionId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$payerSendAmount"}, + "targetAmount": { + "currency": "$payeeCurrency"}, + "expiration": "2021-08-25T14:17:09.663+01:00" + } + } +end note + +deactivate D1 +activate S1 +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif +S1->>FXP:Here is the initial version of the transfer.\nPlease quote me for the currency conversion.\n**POST /fxQuote** +deactivate S1 +activate FXP +!if ($simplified != true) +FXP-->>S1:202 I'll get back to you +!endif + +note over FXP + I will add a $fxpChargesSource $payerCurrency fee for undertaking the conversion. + Now I'll set an expiry time, sign the quotation object, +end note +!if ($simplified != true) +note right of FXP + { + "conversionTerms": { + "conversionId": "$conversionId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "expiration": "2021-08-25T14:17:09.663+01:00" + "charges": [ + { + "chargeType": "string", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpChargesSource"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpChargesTarget"} + }]} + } +end note +!endif + +note over FXP + Now I'll sign the quotation object, + create an ILP prepare packet and return it in the intermediary object. + + **NOTE:** the ILP prepare packet contains the following items, all encoded: + - The amount being sent (i.e. in the source currency) + - An expiry time + - The condition + - The name of the FXP + - The content of the conversion terms +end note + + +FXP->>S1:Here's the signed conversion object +note right + **PUT /fxQuotes/$conversionRequestId** + { + "condition": "$fxCondition", + "conversionTerms": { + "conversionId": "$conversionId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "expiration": "2021-08-25T14:17:09.663+01:00" + "charges": [ + { + "chargeType": "string", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpChargesSource"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpChargesTarget"} + }]} + } +end note +deactivate FXP +activate S1 +!if ($simplified != true) +S1-->>FXP:200 Gotcha +!endif +S1->>D1:Here's the signed conversion object\n**PUT /fxQuotes/$conversionRequestId** +deactivate S1 +activate D1 +!if ($simplified != true) +D1-->>S1:Gotcha +!endif +@enduml \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/PAYER_SEND_CurrencyConversion.svg b/docs/product/features/CurrencyConversion/PAYER_SEND_CurrencyConversion.svg new file mode 100644 index 000000000..8078364ed --- /dev/null +++ b/docs/product/features/CurrencyConversion/PAYER_SEND_CurrencyConversion.svg @@ -0,0 +1 @@ +Payer DFSP requests conversion with SEND amountPayer DFSPFX providerPayer DFSPPayer DFSPMojaloop SwitchMojaloop SwitchFXPConnectorFXPConnector1Hmmm. I can only send in BWP.I need to get some currency conversion2Look up the local cached FXPsthat can provide the conversion3I'll ask FDH FX to perform my conversion4Here is the initial version of the transfer.Please quote me for the currency conversion.post /fxQuotes{"conversionRequestId": "828cc75f1654415e8fcddf76cc","conversionTerms": {"conversionId": "581f68efb54f416f9161ac34e8","initiatingFsp": "PayerFSP","counterPartyFsp": "FDH_FX","amountType": "SEND","sourceAmount": {"currency": "BWP","amount": "300"},"targetAmount": {"currency": "TZS"},"expiration": "2021-08-25T14:17:09.663+01:00"}}5Here is the initial version of the transfer.Please quote me for the currency conversion.POST /fxQuoteI will add a 33 BWP fee for undertaking the conversion.Now I'll set an expiry time, sign the quotation object,Now I'll sign the quotation object,create an ILP prepare packet and return it in the intermediary object. NOTE:the ILP prepare packet contains the following items, all encoded:- The amount being sent (i.e. in the source currency)- An expiry time- The condition- The name of the FXP- The content of the conversion terms6Here's the signed conversion objectPUT /fxQuotes/828cc75f1654415e8fcddf76cc{"condition": "GRzLaTP7DJ9t4P-a_B...","conversionTerms": {"conversionId": "581f68efb54f416f9161ac34e8","initiatingFsp": "PayerFSP","counterPartyFsp": "FDH_FX","amountType": "SEND","sourceAmount": {"currency": "BWP","amount": "300"},"targetAmount": {"currency": "TZS","amount": "48000"},"expiration": "2021-08-25T14:17:09.663+01:00""charges": [{"chargeType": "string","sourceAmount": {"currency": "BWP","amount": "33"},"targetAmount": {"currency": "TZS","amount": "6000"}}]}}7Here's the signed conversion objectPUT /fxQuotes/828cc75f1654415e8fcddf76cc \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/PAYER_SEND_Transfer.plantuml b/docs/product/features/CurrencyConversion/PAYER_SEND_Transfer.plantuml new file mode 100644 index 000000000..bd3cb95f5 --- /dev/null +++ b/docs/product/features/CurrencyConversion/PAYER_SEND_Transfer.plantuml @@ -0,0 +1,259 @@ +@startuml PAYER_SEND_Transfer + +!$simplified = true +!$hideSwitchDetail = false +!$advancedCoreConnectorFlow = true +!$senderName = "John" +!$senderLastName = "" +!$senderDOB = "1966-06-16" +!$receiverName = "Yaro" +!$receiverFirstName = "Yaro" +!$receiverMiddleName = "" +!$receiverLastName = "" +!$receiverDOB = "1966-06-16" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$fxpID = "FDH_FX" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "44000" +!$payerSendAmount = "300" +!$payeeFee = "4000" +!$targetAmount = "48000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "300" +!$fxpTargetAmount = "48000" +!$totalChargesSourceCurrency = "55" +!$totalChargesTargetCurrency = "10000" +!$conversionRequestId = "828cc75f165441..." +!$conversionId = "581f68efb5..." +!$homeTransactionId = "string" +!$quoteId = "382987a875ce..." +!$transactionId = "d9ce59d4359843..." +!$quotePayerExpiration = "2021-08-25T14:17:09.663+01:00" +!$quotePayeeExpiration = "2021-08-25T14:17:09.663+01:00" +!$commitRequestId = "77c9d78dc26..." +!$determiningTransferId = "d9ce59d4359843..." +!$transferId = "d9ce59d4359843..." +!$fxCondition = "GRzLaTP7DJ9t4P-a_B..." +!$condition = "HOr22-H3AfTDHrSkP..." + +title Remittance Transfer using Mojaloop FX APIs POC\nPayer DFSP requests conversion with SEND amount +actor "$senderName" as A1 +box "Payer DFSP" #LightBlue + participant "Payer DFSP" as D1 +end box + +participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow +' participant "ALS Oracle" as ALS +'end box + +box "FX provider" + participant "FXP\nConnector" as FXP +end box + +box "Payee DFSP" #LightBlue + participant "Payee\nMojaloop\nConnector" as D2 +end box + +actor "$receiverName" as A2 +autonumber + +D1->>S1:Please confirm your part\n of the transfer +deactivate D1 +note left +**POST /fxTransfers** +{ + "commitRequestId": "$commitRequestId", + "determiningTransferId": "$determiningTransferId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "condition": "$fxCondition" +} +end note +deactivate D2 +activate S1 +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif +!if ($hideSwitchDetail != true) +S1->S1:OK, so this is an FX confirmation. +S1->S1: Is there any transfer with \ndeterminingTransactionId?\nNo, it does'nt. +!endif +S1->S1: Liquidity check and reserve\n on Payer DFSP's account +!if ($hideSwitchDetail != true) +note over S1 +**Reservations:** + +**$payerFSPID has a reservation of $fxpSourceAmount $payerCurrency** +end note +!endif +S1->>FXP:Please confirm the currency \nconversion part of the transfer\n **POST /fxTransfers** +deactivate S1 +activate FXP +!if ($simplified != true) +FXP-->>S1:202 I'll get back to you +!endif +FXP->FXP:Reserve funds for FX conversion +FXP->>S1:Confirmed. Here's the fulfilment +note right +**PUT /fxTransfers/$commitRequestId** +{ + "fulfilment": "188909ceb6cd5c35d..", + "completedTimestamp": "2021-08-25T14:17:08.175+01:00", + "conversionState": "RESERVED" +} +end note +deactivate FXP +activate S1 +!if ($simplified != true) +S1-->>FXP:200 Gotcha +!endif +!if ($simplified != true) +S1->S1:Check fulfilment matches and cancel if not. +alt Conversion failed +S1->FXP:Sorry. Conversion failed +note left +**PATCH /fxTransfers/$commitRequestId** +{ + "completedTimestamp": "2021-08-25T14:17:08.175+01:00", + "conversionState": "ABORTED" +} +end note +activate FXP +FXP-->S1:Acknowledged +FXP->FXP:Remove any reservations or obligations +deactivate FXP + +S1->>D1:Sorry. Conversion failed +note right +**PUT /fxTransfers/$commitRequestId/error** +{ + "errorCode": "9999", + "errorDescription": "Whatever the error was" +} +end note +else Conversion succeeded +S1->D1:Conversion succeeded subject \nto transfer success\n**PUT /fxTransfers/$commitRequestId** + +end +!else +S1->D1:Conversion succeeded subject \nto transfer success\n**PUT /fxTransfers/$commitRequestId** +!endif +deactivate S1 +activate D1 +!if ($simplified != true) +D1-->S1:200 Gotcha +!endif + +D1->D1:OK, so that's all right\nNow I can send the transfer itself + +D1->S1:Please do the transfer\n **POST /transfers** +!if ($simplified != true) +note left +**POST /transfers** +{ + "transferId": "$transferId", + "payeeFsp": "$payeeFSPID", + "payerFsp": "$payerFSPID", + "amount": { + "currency": "$payeeCurrency", + "amount": "$targetAmount"}, + "ilpPacket": "", + "condition": "$condition", + "expiration": "2016-05-24T08:38:08.699-04:00" +} +end note +!endif +deactivate D1 +activate S1 +!if ($simplified != true) +S1-->D1:202 I'll get back to you +!endif +!if ($hideSwitchDetail != true) +S1->S1:Is there a dependent transfer? \nYes +!endif +S1->S1:Perform liquidity check and \nreserve funds against creditor\n party to dependent transfer +note over S1 +**Reservations:** + +$payerFSPID has a reservation of $fxpSourceAmount $payerCurrency +**$fxpID has a reservation of $targetAmount $payeeCurrency** +end note + +S1->D2:Please do the transfer\n**POST /transfers** +deactivate S1 +activate D2 +!if ($simplified != true) +D2-->S1:202 I'll get back to you +!endif +D2->D2:Let me check that the terms\n of the dependent transfer\nare the same as the ones I \nagreed to and that the \nfulfilment and condition match + +D2->A2: Hi $receiverName's, you got inbound \ntransfer $payeeReceiveAmount $payeeCurrency + +D2->>S1:Transfer is confirmed, here's the fulfilment +note right +**PUT /transfers/$commitRequestId** +{ + "completedTimestamp": "2021-08-25T14:17:08...", + "fulfilment": "mhPUT9ZAwd-BXLfeSd...", + "transferState": "COMMITTED" +} +end note +deactivate D2 +activate S1 +!if ($simplified != true) +S1-->>D2:200 Gotcha +!endif +!if ($hideSwitchDetail != true) +S1->S1:Is there a dependent transfer?\nYes, there is. +S1->S1:Is this dependency against the\n debtor party to the transfer?\nYes, it is. +S1->S1:Create an obligation from the\n debtor party to the party named \nin the dependency (the FXP) +S1->S1:Is the transfer denominated in\n the currency of the payee \nreceive amount? Yes, it is. +S1->S1:Create an obligation from the\n party named in the\n dependency to the creditor \nparty for the transfer +!else +S1->S1:Create obligations from the payer to the FXP and from FXP to the payee +!endif +note over S1 + **Ledger positions:** + $payerFSPID has a debit of $fxpSourceAmount $payerCurrency + $fxpID has a credit of $fxpSourceAmount $payerCurrency + $fxpID has a debit of $fxpTargetAmount $payeeCurrency + $payeeFSPID has a credit of $targetAmount $payeeCurrency +end note +S1->>FXP:The transfer succeeded.\nYou can clear it in your ledgers +note left +**PATCH /fxTransfers/$commitRequestId** +{ + "completedTimestamp": "2021-08-25T14:17:08.227+01:00", + "transferState": "COMMITTED" +} +end note +activate FXP +FXP->FXP:Let's just check: does this match the stuff I sent? +FXP->FXP:It does. Great. I'll clear the conversion +FXP-->>S1:200 Gotcha +deactivate FXP +S1->>D1:Transfer is complete\n**PUT /transfers/$commitRequestId** +deactivate S1 +activate D1 +!if ($simplified != true) +D1-->S1:200 Gotcha +!endif + +D1->A1:Your transfer is successful +deactivate D1 + +@enduml \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/PAYER_SEND_Transfer.svg b/docs/product/features/CurrencyConversion/PAYER_SEND_Transfer.svg new file mode 100644 index 000000000..e0b71bc2d --- /dev/null +++ b/docs/product/features/CurrencyConversion/PAYER_SEND_Transfer.svg @@ -0,0 +1 @@ +Remittance Transfer using Mojaloop FX APIs POCPayer DFSP requests conversion with SEND amountPayer DFSPFX providerPayee DFSPJohnJohnPayer DFSPPayer DFSPMojaloop SwitchMojaloop SwitchFXPConnectorFXPConnectorPayeeMojaloopConnectorPayeeMojaloopConnectorYaroYaro1Please confirm your partof the transferPOST /fxTransfers{"commitRequestId": "77c9d78dc26...","determiningTransferId": "d9ce59d4359843...","initiatingFsp": "PayerFSP","counterPartyFsp": "FDH_FX","amountType": "SEND","sourceAmount": {"currency": "BWP","amount": "300"},"targetAmount": {"currency": "TZS","amount": "48000"},"condition": "GRzLaTP7DJ9t4P-a_B..."}2OK, so this is an FX confirmation.3Is there any transfer withdeterminingTransactionId?No, it does'nt.4Liquidity check and reserveon Payer DFSP's accountReservations: PayerFSP has a reservation of 300 BWP5Please confirm the currencyconversion part of the transfer POST /fxTransfers6Reserve funds for FX conversion7Confirmed. Here's the fulfilmentPUT /fxTransfers/77c9d78dc26...{"fulfilment": "188909ceb6cd5c35d..","completedTimestamp": "2021-08-25T14:17:08.175+01:00","conversionState": "RESERVED"}8Conversion succeeded subjectto transfer successPUT /fxTransfers/77c9d78dc26...9OK, so that's all rightNow I can send the transfer itself10Please do the transfer POST /transfers11Is there a dependent transfer?Yes12Perform liquidity check andreserve funds against creditorparty to dependent transferReservations: PayerFSP has a reservation of 300 BWPFDH_FX has a reservation of 48000 TZS13Please do the transferPOST /transfers14Let me check that the termsof the dependent transferare the same as the ones Iagreed to and that thefulfilment and condition match15Hi Yaro's, you got inboundtransfer 44000 TZS16Transfer is confirmed, here's the fulfilmentPUT /transfers/77c9d78dc26...{"completedTimestamp": "2021-08-25T14:17:08...","fulfilment": "mhPUT9ZAwd-BXLfeSd...","transferState": "COMMITTED"}17Is there a dependent transfer?Yes, there is.18Is this dependency against thedebtor party to the transfer?Yes, it is.19Create an obligation from thedebtor party to the party namedin the dependency (the FXP)20Is the transfer denominated inthe currency of the payeereceive amount? Yes, it is.21Create an obligation from theparty named in thedependency to the creditorparty for the transferLedger positions:PayerFSP has a debit of 300 BWPFDH_FX has a credit of 300 BWPFDH_FX has a debit of 48000 TZSPayeeFSP has a credit of 48000 TZS22The transfer succeeded.You can clear it in your ledgersPATCH /fxTransfers/77c9d78dc26...{"completedTimestamp": "2021-08-25T14:17:08.227+01:00","transferState": "COMMITTED"}23Let's just check: does this match the stuff I sent?24It does. Great. I'll clear the conversion25200 Gotcha26Transfer is completePUT /transfers/77c9d78dc26...27Your transfer is successful \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/Payer_SEND_ABORT_TransferPhase.plantuml b/docs/product/features/CurrencyConversion/Payer_SEND_ABORT_TransferPhase.plantuml new file mode 100644 index 000000000..d1fe241fd --- /dev/null +++ b/docs/product/features/CurrencyConversion/Payer_SEND_ABORT_TransferPhase.plantuml @@ -0,0 +1,337 @@ +@startuml Payer_SEND_ABORT_TransferPhase + +!$simplified = true +!$hideSwitchDetail = false +!$advancedCoreConnectorFlow = true +!$senderName = "John" +!$senderLastName = "" +!$senderDOB = "1966-06-16" +!$receiverName = "Yaro" +!$receiverFirstName = "Yaro" +!$receiverMiddleName = "" +!$receiverLastName = "" +!$receiverDOB = "1966-06-16" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$fxpID = "FDH_FX" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "44000" +!$payerSendAmount = "300" +!$payeeFee = "4000" +!$targetAmount = "48000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "300" +!$fxpTargetAmount = "48000" +!$totalChargesSourceCurrency = "55" +!$totalChargesTargetCurrency = "10000" +!$conversionRequestId = "828cc75f16..." +!$conversionId = "581f68efb..." +!$homeTransactionId = "string" +!$quoteId = "382987a875..." +!$transactionId = "d9ce59d435..." +!$quotePayerExpiration = "2021-08-25T14:17:09.663+01:00" +!$quotePayeeExpiration = "2021-08-25T14:17:09.663+01:00" +!$commitRequestId = "77c9d78dc2..." +!$determiningTransferId = "d9ce59d43..." +!$transferId = "d9ce59d435..." +!$fxCondition = "GRzLaTP7DJ9t4P-a_B..." +!$condition = "HOr22-H3AfTDHrSkP..." + + +title Currency Conversion Transfer Phase ABORT flows +actor "$senderName" as A1 +box "Payer DFSP" #LightBlue + participant "Payer DFSP" as D1 +end box + +participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow +' participant "ALS Oracle" as ALS +'end box + +box "FX provider" + participant "FXP\nConnector" as FXP +end box + +box "Payee DFSP" #LightBlue + participant "Payee\nMojaloop\nConnector" as D2 +end box + +actor "$receiverName" as A2 +autonumber + +D1->>S1:Please confirm your part of the transfer +note left +**POST /fxTransfers** +{ + "commitRequestId": "$commitRequestId", + "determiningTransferId": "$determiningTransferId", + "initiatingFsp": "$payerFSPID", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount"}, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount"}, + "condition": "$fxCondition" +} +end note +activate S1 +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif +deactivate D2 +!if ($hideSwitchDetail != true) +S1->S1:OK, so this is an FX confirmation. +S1->S1: Is there any transfer with determiningTransactionId?\nNo, it does'nt. +!endif +S1->S1: Liquidity check and reserve on Payer DFSP's account +!if ($hideSwitchDetail != true) +note over S1 +Reservations: + +**$payerFSPID has a reservation of $fxpSourceAmount $payerCurrency** +end note +!endif +S1->>FXP:Please confirm the currency\n conversion part of the transfer\n **POST /fxTransfers** +deactivate S1 +activate FXP +!if ($simplified != true) +FXP-->>S1:202 I'll get back to you +!endif +alt conversion failed + FXP->>S1:Failed. + note right + **PUT /fxTransfers/$commitRequestId**/error + { + "errorInformation": { + "errorCode": "5100", + "errorDescription": "error message"} + } + ( **or** ) + **PUT /fxTransfers/$commitRequestId** + { + "conversionState": "ABORTED", + "extensionList": {"extension": [{"key": "reason","value": "some reason"}]} + } + end note +else conversion success + FXP->FXP:Reserve funds for FX conversion + FXP->>S1:Confirmed. Here's the fulfilment + note right + **PUT /fxTransfers/$commitRequestId** + { + "fulfilment": "188909ceb6cd5...", + "completedTimestamp": "2021-08-25T14:17:08.175+01:00", + "conversionState": "RESERVED" + } + end note + deactivate FXP + S1->S1:Check fulfilment matches and cancel if not. + alt Conversion failed + S1->FXP:Sorry. Conversion failed + note left + **PATCH /fxTransfers/$commitRequestId** + { + "completedTimestamp": "2021-08-25T14:17:08.175+01:00", + "conversionState": "ABORTED" + } + end note + activate FXP + FXP-->S1:Acknowledged + FXP->FXP:Remove any reservations or obligations + deactivate FXP + end +end +!if ($simplified != true) +S1-->>FXP:200 Gotcha +!endif +deactivate FXP + +alt Conversion failed + S1->S1: Abort the fxTransfer. Revert \nthe position changes involved in this\n fxTransfer. + note over S1 + **Note:** + Incase of payee side conversion, there will be dependent transfer. + But do not cancel that transfer as DFSP can try currency conversion with + another FXP. But make sure that while processing the fulfilment of the original + transfer, it shouldn't pickup this fxTransfer as the dependent transfer. + (Maybe by removing the entry from watchlist) + end note + S1->>D1:Sorry. Conversion failed + note right + **PUT /fxTransfers/$commitRequestId/error** + { + "errorInformation": { + "errorCode": "5100", + "errorDescription": "error message"} + } + ( **or** ) + **PUT /fxTransfers/$commitRequestId** + { + "conversionState": "ABORTED", + "extensionList": {"extension": [{"key": "reason","value": "some reason"}]} + } + end note +else Conversion succeeded + S1->D1:Conversion succeeded subject to\n transfer success\n**PUT /fxTransfers/77c9d78dc26a...** + activate D1 +end + +!if ($simplified != true) +D1-->S1:200 Gotcha +!endif +D1->D1:OK, so that's all right\nNow I can send the transfer itself + +D1->S1:Please do the transfer\n **POST /transfers** +deactivate D1 +!if ($simplified != true) +note over D1 +**POST /transfers** +{ + "transferId": "$transferId", + "payeeFsp": "$payeeFSPID", + "payerFsp": "$payerFSPID", + "amount": { + "currency": "$payeeCurrency", + "amount": "$targetAmount"}, + "ilpPacket": "", + "condition": "$condition", + "expiration": "2016-05-24T08:38:08.699-04:00" +} +end note +!endif +activate S1 +!if ($simplified != true) +S1-->D1:202 I'll get back to you +!endif +deactivate D1 +!if ($hideSwitchDetail != true) +S1->S1:Is there a dependent transfer? Yes +!endif +S1->S1:Perform liquidity check and reserve funds\nagainst creditor party to dependent transfer +note over S1 +Reservations: + +$payerFSPID has a reservation of $fxpSourceAmount $payerCurrency +**$fxpID has a reservation of $targetAmount $payeeCurrency** +end note + +S1->D2:Please do the transfer\n**POST /transfers** +deactivate S1 +activate D2 +!if ($simplified != true) +D2-->S1:202 I'll get back to you +!endif +D2->D2:Let me check that the terms \nof the dependent transfer are \nthe same as the ones I agreed\n to and that the fulfilment and \ncondition match + +D2->A2: Hi $receiverName's, you got inbound \ntransfer $payeeReceiveAmount $payeeCurrency +deactivate D2 + +alt transfer failed + D2->>S1:Transfer is rejected + note right + **PUT /transfers/$commitRequestId**/error + { + "errorInformation": { + "errorCode": "5100", + "errorDescription": "error message"} + } + ( **or** ) + { + "transferState": "ABORETED" + } + end note + + activate S1 + !if ($simplified != true) + S1-->>D2:200 Gotcha + !endif + + S1->S1: Revert the position changes \ninvolved in this transfer + S1->S1: If there are dependency fxTransfers,\n abort the fxTransfers as well and \nrevert the position changes involved \nin those fxTransfers + + S1->>FXP: The linked transfer is failed.\nRemove any reservations or obligations + note left + **PATCH /fxTransfers/$commitRequestId** + { + "completedTimestamp": "2021-08-25T14:17:08.227+01:00", + "transferState": "ABORTED" + } + end note + activate FXP + FXP->FXP: Oops! + FXP-->>S1:200 Gotcha + deactivate FXP + S1->>D1:Transfer is complete\n**PUT /transfers/$commitRequestId/error** + activate D1 + !if ($simplified != true) + D1-->S1:200 Gotcha + !endif + deactivate S1 + D1->A1:Your transfer is failed + deactivate D1 +else transfer success + D2->>S1:Transfer is confirmed, here's the fulfilment + note right + **PUT /transfers/$commitRequestId** + { + "completedTimestamp": "2021-08-25T14:17:08.227+01:00", + "fulfilment": "mhPUT9ZAwd...", + "transferState": "COMMITTED" + } + end note + activate S1 + !if ($simplified != true) + S1-->>D2:200 Gotcha + !endif + + !if ($hideSwitchDetail != true) + S1->S1:Is there a dependent transfer?\nYes, there is. + S1->S1:Is this dependency against the\n debtor party to the transfer?\nYes, it is. + S1->S1:Create an obligation from the \ndebtor party to the party named \nin the dependency (the FXP) + S1->S1:Is the transfer denominated in \nthe currency of the payee receive\n amount?\nYes, it is. + S1->S1:Create an obligation from the \nparty named in the dependency\nto the creditor party for the transfer + !else + S1->S1:Create obligations from the payer to the FXP and from FXP to the payee + !endif + S1->>FXP:The transfer succeeded.\nYou can clear it in your ledgers + note left + **PATCH /fxTransfers/$commitRequestId** + { + "completedTimestamp": "2021-08-25T14:17:08.227+01:00", + "fulfilment": "mhPUT9ZAwd...", + "transferState": "COMMITTED" + } + end note + activate FXP + FXP->FXP:Let's just check: does this match the stuff I sent? + FXP->FXP:It does. Great. I'll clear the conversion + FXP-->>S1:200 Gotcha + deactivate FXP + note over S1 + **Ledger positions:** + $payerFSPID has a debit of $fxpSourceAmount $payerCurrency + $fxpID has a credit of $fxpSourceAmount $payerCurrency + $fxpID has a debit of $fxpTargetAmount $payeeCurrency + $payeeFSPID has a credit of $targetAmount $payeeCurrency + end note + S1->>D1:Transfer is complete\n**PUT /transfers/$commitRequestId** + activate D1 + !if ($simplified != true) + D1-->S1:200 Gotcha + !endif + deactivate S1 + + D1->A1:Your transfer is successful + deactivate D1 +end + +@enduml \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/Payer_SEND_ABORT_TransferPhase.svg b/docs/product/features/CurrencyConversion/Payer_SEND_ABORT_TransferPhase.svg new file mode 100644 index 000000000..5cc482459 --- /dev/null +++ b/docs/product/features/CurrencyConversion/Payer_SEND_ABORT_TransferPhase.svg @@ -0,0 +1 @@ +Remittance Transfer using Mojaloop FX APIs POCPayer DFSP requests conversion with SEND amountPayer DFSPFX providerPayee DFSPJohnJohnPayer DFSPPayer DFSPMojaloop SwitchMojaloop SwitchFXPConnectorFXPConnectorPayeeMojaloopConnectorPayeeMojaloopConnectorYaroYaro1Please confirm your part of the transferPOST /fxTransfers{"commitRequestId": "77c9d78dc2...","determiningTransferId": "d9ce59d43...","initiatingFsp": "PayerFSP","counterPartyFsp": "FDH_FX","amountType": "SEND","sourceAmount": {"currency": "BWP","amount": "300"},"targetAmount": {"currency": "TZS","amount": "48000"},"condition": "GRzLaTP7DJ9t4P-a_B..."}2OK, so this is an FX confirmation.3Is there any transfer with determiningTransactionId?No, it does'nt.4Liquidity check and reserve on Payer DFSP's accountReservations: PayerFSP has a reservation of 300 BWP5Please confirm the currencyconversion part of the transfer POST /fxTransfersalt[conversion failed]6Failed.PUT /fxTransfers/77c9d78dc2.../error{"errorInformation": {"errorCode": "5100","errorDescription": "error message"}}(or)PUT /fxTransfers/77c9d78dc2...{"conversionState": "ABORTED","extensionList": {"extension": [{"key": "reason","value": "some reason"}]}}[conversion success]7Reserve funds for FX conversion8Confirmed. Here's the fulfilmentPUT /fxTransfers/77c9d78dc2...{"fulfilment": "188909ceb6cd5...","completedTimestamp": "2021-08-25T14:17:08.175+01:00","conversionState": "RESERVED"}9Check fulfilment matches and cancel if not.alt[Conversion failed]10Sorry. Conversion failedPATCH /fxTransfers/77c9d78dc2...{"completedTimestamp": "2021-08-25T14:17:08.175+01:00","conversionState": "ABORTED"}11Acknowledged12Remove any reservations or obligationsalt[Conversion failed]13Abort the fxTransfer. Revertthe position changes involved in thisfxTransfer.Note:Incase of payee side conversion, there will be dependent transfer.But do not cancel that transfer as DFSP can try currency conversion withanother FXP. But make sure that while processing the fulfilment of the originaltransfer, it shouldn't pickup this fxTransfer as the dependent transfer.(Maybe by removing the entry from watchlist)14Sorry. Conversion failedPUT /fxTransfers/77c9d78dc2.../error{"errorInformation": {"errorCode": "5100","errorDescription": "error message"}}(or)PUT /fxTransfers/77c9d78dc2...{"conversionState": "ABORTED","extensionList": {"extension": [{"key": "reason","value": "some reason"}]}}[Conversion succeeded]15Conversion succeeded subject totransfer successPUT /fxTransfers/77c9d78dc26a...16OK, so that's all rightNow I can send the transfer itself17Please do the transfer POST /transfers18Is there a dependent transfer? Yes19Perform liquidity check and reserve fundsagainst creditor party to dependent transferReservations: PayerFSP has a reservation of 300 BWPFDH_FX has a reservation of 48000 TZS20Please do the transferPOST /transfers21Let me check that the termsof the dependent transfer arethe same as the ones I agreedto and that the fulfilment andcondition match22Hi Yaro's, you got inboundtransfer 44000 TZSalt[transfer failed]23Transfer is rejectedPUT /transfers/77c9d78dc2.../error{"errorInformation": {"errorCode": "5100","errorDescription": "error message"}}(or){"transferState": "ABORETED"}24Revert the position changesinvolved in this transfer25If there are dependency fxTransfers,abort the fxTransfers as well andrevert the position changes involvedin those fxTransfers26The linked transfer is failed.Remove any reservations or obligationsPATCH /fxTransfers/77c9d78dc2...{"completedTimestamp": "2021-08-25T14:17:08.227+01:00","transferState": "ABORTED"}27Oops!28200 Gotcha29Transfer is completePUT /transfers/77c9d78dc2.../error30Your transfer is failed[transfer success]31Transfer is confirmed, here's the fulfilmentPUT /transfers/77c9d78dc2...{"completedTimestamp": "2021-08-25T14:17:08.227+01:00","fulfilment": "mhPUT9ZAwd...","transferState": "COMMITTED"}32Is there a dependent transfer?Yes, there is.33Is this dependency against thedebtor party to the transfer?Yes, it is.34Create an obligation from thedebtor party to the party namedin the dependency (the FXP)35Is the transfer denominated inthe currency of the payee receiveamount?Yes, it is.36Create an obligation from theparty named in the dependencyto the creditor party for the transfer37The transfer succeeded.You can clear it in your ledgersPATCH /fxTransfers/77c9d78dc2...{"completedTimestamp": "2021-08-25T14:17:08.227+01:00","fulfilment": "mhPUT9ZAwd...","transferState": "COMMITTED"}38Let's just check: does this match the stuff I sent?39It does. Great. I'll clear the conversion40200 GotchaLedger positions:PayerFSP has a debit of 300 BWPFDH_FX has a credit of 300 BWPFDH_FX has a debit of 48000 TZSPayeeFSP has a credit of 48000 TZS41Transfer is completePUT /transfers/77c9d78dc2...42Your transfer is successful \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/Payer_SEND_Discovery.plantuml b/docs/product/features/CurrencyConversion/Payer_SEND_Discovery.plantuml new file mode 100644 index 000000000..d997b7c62 --- /dev/null +++ b/docs/product/features/CurrencyConversion/Payer_SEND_Discovery.plantuml @@ -0,0 +1,113 @@ +@startuml Payer_SEND_Discovery +!$simplified = true +!$hideSwitchDetail = false +!$advancedCoreConnectorFlow = true +!$senderName = "John" +!$senderLastName = "" +!$senderDOB = "1966-06-16" +!$receiverName = "Yaro" +!$receiverFirstName = "Yaro" +!$receiverMiddleName = "" +!$receiverLastName = "" +!$receiverDOB = "1966-06-16" +!$payerCurrency = "BWP" +!$payeeCurrency = "TZS" +!$payerFSPID = "PayerFSP" +!$payeeFSPID = "PayeeFSP" +!$fxpID = "FDH_FX" +!$payerMSISDN = "26787654321" +!$payeeMSISDN = "2551234567890" +!$payeeReceiveAmount = "44000" +!$payerSendAmount = "300" +!$payeeFee = "4000" +!$targetAmount = "48000" +!$fxpChargesSource = "33" +!$fxpChargesTarget = "6000" +!$fxpSourceAmount = "300" +!$fxpTargetAmount = "48000" +!$totalChargesSourceCurrency = "55" +!$totalChargesTargetCurrency = "10000" +!$conversionRequestId = "828cc75f1654415e8fcddf76cc" +!$conversionId = "581f68efb54f416f9161ac34e8" +!$homeTransactionId = "string" +!$quoteId = "382987a875ce4037b500c475e0" +!$transactionId = "d9ce59d4359843968630581bb0" +!$quotePayerExpiration = "2021-08-25T14:17:09.663+01:00" +!$quotePayeeExpiration = "2021-08-25T14:17:09.663+01:00" +!$commitRequestId = "77c9d78dc26a44748b3c99b96a" +!$determiningTransferId = "d9ce59d4359843968630581bb0" +!$transferId = "d9ce59d4359843968630581bb0" +!$fxCondition = "GRzLaTP7DJ9t4P-a_B..." +!$condition = "HOr22-H3AfTDHrSkP..." + + +title Currency Conversion Discovery +actor "$senderName" as A1 +box "Payer DFSP" #LightBlue + participant "Payer DFSP" as D1 +end box + +participant "Mojaloop Switch" as S1 + +'box "Discovery Service" #LightYellow +' participant "ALS Oracle" as ALS +'end box + +'box "FX provider" +' participant "FXP\nConnector" as FXP +'end box + +box "Payee DFSP" #LightBlue + participant "Payee\nMojaloop\nConnector" as D2 +end box + +'actor "$receiverName" as A2 +autonumber + +A1->D1:I'd like to pay $receiverName\n$payerSendAmount $payerCurrency, please + +activate D1 +D1->>S1:I want to send to MSISDN $payeeMSISDN\n**GET /parties/MSISDN/$payeeMSISDN** +deactivate D1 +activate S1 +!if ($simplified != true) +S1-->>D1:202 I'll get back to you +!endif +S1->S1:Who owns MSISDN $payeeMSISDN?\nIt's $payeeFSPID +S1->>D2:Do you own MSISDN $payeeMSISDN? +deactivate S1 +activate D2 +!if ($simplified != true) +D2-->>S1:202 I'll get back to you +!endif +D2->D2: Check Sanction list status & trigger a refresh of the status +D2->>S1:Yes, it's $receiverName. He can receive in $payeeCurrency\n**PUT /parties/MSISDN/$payeeMSISDN** +note right + **PUT /parties** + { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "$payeeMSISDN", + "fspId": "$payeeFSPID"}, + "name": "$receiverName", + "supportedCurrencies": [ "$payeeCurrency" ] + } +end note + +deactivate D2 +activate S1 +!if ($simplified != true) +S1-->>D2:200 Gotcha +!endif +S1->>D1:Yes, it's $receiverName. He can receive in $payeeCurrency\n**PUT /parties/MSISDN/$payeeMSISDN** +deactivate S1 +activate D1 +!if ($simplified != true) +D1-->>S1:200 Gotcha +!endif + +D1->A1: Hi, $senderName: The number belongs to $receiverName \nLet me know if you want to go ahead +deactivate D1 +A1->D1: Payer has accepted the party information + +@enduml \ No newline at end of file diff --git a/docs/product/features/CurrencyConversion/Payer_SEND_Discovery.svg b/docs/product/features/CurrencyConversion/Payer_SEND_Discovery.svg new file mode 100644 index 000000000..a4cc63b7f --- /dev/null +++ b/docs/product/features/CurrencyConversion/Payer_SEND_Discovery.svg @@ -0,0 +1 @@ +Currency Conversion DiscoveryPayer DFSPPayee DFSPJohnJohnPayer DFSPPayer DFSPMojaloop SwitchMojaloop SwitchPayeeMojaloopConnectorPayeeMojaloopConnector1I'd like to pay Yaro300 BWP, please2I want to send to MSISDN 2551234567890GET /parties/MSISDN/25512345678903Who owns MSISDN 2551234567890?It's PayeeFSP4Do you own MSISDN 2551234567890?5Check Sanction list status & trigger a refresh of the status6Yes, it's Yaro. He can receive in TZSPUT /parties/MSISDN/2551234567890PUT /parties{"partyIdInfo": {"partyIdType": "MSISDN","partyIdentifier": "2551234567890","fspId": "PayeeFSP"},"name": "Yaro","supportedCurrencies": [ "TZS" ]}7Yes, it's Yaro. He can receive in TZSPUT /parties/MSISDN/25512345678908Hi, John: The number belongs to YaroLet me know if you want to go ahead9Payer has accepted the party information \ No newline at end of file diff --git a/docs/product/features/FXP.svg b/docs/product/features/FXP.svg new file mode 100644 index 000000000..396e2ff2a --- /dev/null +++ b/docs/product/features/FXP.svg @@ -0,0 +1,4 @@ + + + +
Scheme
Scheme
DFSP 1
DFSP 1
DFSP 2
DFSP 2
FXP
FXP
\ No newline at end of file diff --git a/docs/product/features/ForeignExchange.md b/docs/product/features/ForeignExchange.md new file mode 100644 index 000000000..139534f39 --- /dev/null +++ b/docs/product/features/ForeignExchange.md @@ -0,0 +1,51 @@ +# Foreign Exchange + +An important aspect of a modern payment system is the ability to support transactions in more than one currency; and Mojaloop is no different, with support for multiple transaction currencies built-in. It is an important precept that these currencies operate independently, so that a transaction debited from the debtor in currency X will always be credited to the creditor in currency X. + +Sometimes, however, it is necessary to provide a "bridge" between these currencies. This is facilitated by a function typically known as foreign exchange, and involves a third party called, in Mojaloop parlance, a Foreign Exchange Provider (FXP). + +Note that this function is not necessarily related to sending funds cross border, since there are legitimate reasons why a person in a single jurisdiction might wish to hold funds denominated in multiple currencies, not least because there are countries where multiple currencies are commonly in circulation. + +The following diagram shows how Mojaloop implements this functionality. + +![Foreign Exchange](./FXP.svg) + +Currently, Mojaloop only supports a single business model for the implementation of a foreign exchange transaction. This model implements the following "Payer Decides" model. + +### Payer Decides + +1. A customer of DFSP1 wishes to send 10 of currency X to the payee. +2. Discovery shows that the payee's account is hosted by DFSP 2. +3. DFSP 1 proposes the transaction to DFSP 2, who notes that the payment must be forwarded in currency Y. +4. DFSP 1 sends 10 X to the FXP, who forwards the equivalent value in currency Y to DFSP 2, and pays out to the payee (less fees, currency spread, etc). + +Further details of the implementation of this FX capability can be found in the [**FX documentation**](./fx.md). + +Other, more complex business models will be supported in an upcoming release. These are currently planned to include: + +### Multiple FXPs + +1. A customer of DFSP1 wishes to send 10 of currency X to the payee. +2. Discovery shows that the payee's account is hosted by DFSP 2. +3. DFSP 1 proposes the transaction to DFSP 2, who notes that the payment must be forwarded in currency Y. +4. DFSP 1 proposes the transaction to multiple FXPs, selects the one with the most beneficial terms and sends 10 X to that FXP, who forwards the equivalent value in currency Y to DFSP 2, pays out to the payee (less fees, currency spread, etc). + +### Payee Decides + +1. A customer of DFSP1 wishes to send 10 of currency X to the payee. +2. Discovery shows that the payee's account is hosted by DFSP 2. +3. DFSP 1 proposes the transaction to DFSP 2, who notes that the payment should be forwarded in the payer's currency, X. +4. DFSP 1 sends 10 X to DFSP 2 +5. DFSP 2 proposes the transaction to multiple FXPs, selects the one with the most beneficial terms and sends 10 X to that FXP, who returns the equivalent value in currency Y back to DFSP 2, who then pays out to the payee (less fees, currency spread, etc). + +The following page will be of interest to those who wish to review how interscheme and foreign exchange capabilities relate to [**cross border transactions**](./CrossBorder.md). + +## Applicability + +This version of this document relates to Mojaloop Version [17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.1|22nd April 2025| Paul Makin|Added version history| +|1.0|13th March 2025| Paul Makin|Initial version| \ No newline at end of file diff --git a/docs/product/features/InterconnectingSchemes.md b/docs/product/features/InterconnectingSchemes.md new file mode 100644 index 000000000..dd32fd695 --- /dev/null +++ b/docs/product/features/InterconnectingSchemes.md @@ -0,0 +1,32 @@ +# Interconnecting Payment Schemes + +Mojaloop, as a single deployment, is intended to be used to operate one (or more) payment schemes, operating on a single platform. Of course, it is quite common for a country to host multiple payment schemes operating on separate platforms, built around differing requirements for different sectors. + +Ultimately, though, as a payment scheme grows, then the need to be interconnected or interoperable with other payment schemes in a country grows. Mojaloop accommodates this, through a mechanism we call "Interscheme". + +Mojaloop's Interscheme approach uses a specialised type of DFSP Participant, which we call a Proxy. A Proxy is a lightweight DFSP that exists in both interconnecting schemes, and has the following characteristics: +- The Proxy does no message processing; all it does is pass messages (transactions) between the connected schemes; +- Ensuring non-repudiation across schemes means that the proxy is not involved in the agreement of terms, which helps reduce costs; +- It plays no part in the clearing of transactions. + +The consequence of this is that a Proxy preserves the three phases of a Mojaloop transfer, as well as ensuring end-to-end non-repudiation. Consequently, the agreement reached during a transfer remains between the originating and receiving DFSPs, whichever scheme they are connected to. + +![Simple Interscheme Connection](./SimpleInterscheme.svg) + +Further, the Mojaloop scheme interconnection model supports cross-scheme discovery; in other words, an alias used in one scheme can be used to route a payment from another. + +The current version of Mojaloop only supports the interconnection of Mojaloop-based schemes. Work continues to extend this to support other payment schemes, connected to a Mojaloop-based scheme. + +Further details of the implementation of this scheme interconnection capability can be found in the [**interscheme documentation**](./interscheme.md). + +The following pages will be of interest to those who wish to review how interscheme capabilities relate to [**foreign exchange**](./ForeignExchange.md) and [**cross border transactions**](./CrossBorder.md). + +## Applicability + +This version of this document relates to Mojaloop Version [17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.1|22nd April 2025| Paul Makin|Added version history; clarified some wording| +|1.0|14th April 2025| Paul Makin|Initial version| \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-Agreement.plantuml b/docs/product/features/Interscheme/Interscheme-Agreement.plantuml new file mode 100644 index 000000000..96faa68f5 --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-Agreement.plantuml @@ -0,0 +1,72 @@ +@startuml Interscheme-Agreement + +title Interscheme - Agreement + + +participant "Payer DFSP" as payerDFSP +box Scheme A #LightBlue + participant "Mojaloop\nScheme A" as schemeA + participant "Proxy Cache\nScheme A" as pc_A +end box +participant "Proxy AB" as xnp +box Scheme B #d1e0c3 + participant "Mojaloop\nScheme B" as schemeB + participant "Proxy Cache\nScheme B" as pc_B +end box +participant "Payee DFS" as payeeDFSP + +autonumber 1 "[0]" + +payerDFSP ->> schemeA: POST /quotes +schemeA -->> payerDFSP: 202 OK +note left +header + source: payerDFSP + destination: payeeDFSP +JWS signed by payerDFSP +end note +schemeA -> pc_A: Destination not in Scheme\n Lookup proxy for payeeDFSP = Proxy AB +schemeA ->> xnp: POST /quotes +xnp ->> schemeB: POST /quotes\nmessage unmodified +note left +header + source: payerDFSP + destination: payeeDFSP + fxpiop-proxy: proxyAB +JWS signed by payerDFSP +end note +schemeB -->> xnp: 202 OK +xnp -->> schemeA: 202 OK +schemeB->>payeeDFSP: POST /quotes +payeeDFSP-->>schemeB: 202 OK +note right +Checks JWS signed by payerDFSP +end note +payeeDFSP->>schemeB: PUT /quotes +note right +header + source: payeeDFSP + destination: payerDFSP +JWS signed by payeeDFSP +end note +schemeB-->>payeeDFSP: 200 OK +schemeB -> pc_B: Destination not in Scheme\n Lookup proxy for payerDFSP = Proxy AB +schemeB->>xnp: PUT /quotes +xnp->>schemeA: PUT /quotes\nmessage unmodified +note right +header + source: payeeDFSP + destination: payerDFSP + fxpiop-proxy: proxyAB +JWS signed by payeeDFSP +end note +schemeA-->>xnp: 200 OK +xnp-->>schemeB: 200 OK +schemeA->>payerDFSP: PUT /quotes +note left +Checks JWS signed by payeeDFSP +end note +payerDFSP -->> schemeA: 200 OK + + +@enduml \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-Agreement.svg b/docs/product/features/Interscheme/Interscheme-Agreement.svg new file mode 100644 index 000000000..73a3e83e4 --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-Agreement.svg @@ -0,0 +1 @@ +Interscheme - AgreementScheme AScheme BPayer DFSPPayer DFSPMojaloopScheme AMojaloopScheme AProxy CacheScheme AProxy CacheScheme AProxy ABProxy ABMojaloopScheme BMojaloopScheme BProxy CacheScheme BProxy CacheScheme BPayee DFSPayee DFS[1]POST /quotes[2]202 OKheadersource: payerDFSPdestination: payeeDFSPJWS signed by payerDFSP[3]Destination not in SchemeLookup proxy for payeeDFSP = Proxy AB[4]POST /quotes[5]POST /quotesmessage unmodifiedheadersource: payerDFSPdestination: payeeDFSPfxpiop-proxy: proxyABJWS signed by payerDFSP[6]202 OK[7]202 OK[8]POST /quotes[9]202 OKChecks JWS signed by payerDFSP[10]PUT /quotesheadersource: payeeDFSPdestination: payerDFSPJWS signed by payeeDFSP[11]200 OK[12]Destination not in SchemeLookup proxy for payerDFSP = Proxy AB[13]PUT /quotes[14]PUT /quotesmessage unmodifiedheadersource: payeeDFSPdestination: payerDFSPfxpiop-proxy: proxyABJWS signed by payeeDFSP[15]200 OK[16]200 OK[17]PUT /quotesChecks JWS signed by payeeDFSP[18]200 OK \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-ErrorCases.plantuml b/docs/product/features/Interscheme/Interscheme-ErrorCases.plantuml new file mode 100644 index 000000000..d77655558 --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-ErrorCases.plantuml @@ -0,0 +1,114 @@ +@startuml Interscheme-ErrorCases + +title Interscheme - Error Cases + +participant "Payer DFSP" as payerDFSP +box "Scheme A" #LightBlue + participant "ALS\nScheme A" as schemeA + participant "Proxy Cache\nScheme A" as pc_A +end box +participant "Proxy AB" as xnp +box "Scheme B" #d1e0c3 + participant "ALS\nScheme B" as schemeB + participant "Proxy Cache\nScheme B" as pc_B +end box +participant "Payee DFS" as payeeDFSP + +autonumber 1 "[0]" + +== POST == +payerDFSP ->> schemeA: POST/GET/PATCH/PUT /xxx +note left +header + source: payerDFSP + destination: payeeDFSP +end note + +alt if OpenAPI Error + schemeA -->> payerDFSP: 400 Bad Request +end +schemeA-->>payerDFSP: 202 OK + + alt if error in schemeA + schemeA ->> payerDFSP: PUT /xxx/{ID}/error + note right + Error Codes: 2xxx, 3xxx, 4xxx, 5xxx + end note + payerDFSP -->> schemeA: 200 OK + end + + schemeA -> pc_A: lookup proxy for payeeDFSP = Proxy AB + alt if not in proxy cache + schemeA ->> payerDFSP: PUT /xxx/{ID}/error + note right + Error Code: 3201 + end note + payerDFSP -->> schemeA: 200 OK + end + schemeA ->> xnp: POST/GET/PATCH/PUT /xxx + + alt if error in xnp + xnp -->> schemeA: 503 { ErrorCode: 3100} + + xnp ->> schemeA: PUT /xxx/{ID}/error + note right + header + source: Proxy AB + destination: payerDFSP + JWS Signed by Proxy AB + Error Codes: 3100 + end note + schemeA -->> xnp: 200 OK + schemeA ->> payerDFSP: PUT /xxx/{ID}/error + payerDFSP -->> schemeA: 200 OK + end + + xnp->xnp: Add header + note left + fxpiop-proxy = "Proxy AB" + end note + + xnp ->> schemeB: POST/GET/PATCH/PUT /xxx + schemeB -->> xnp: 202 OK + xnp -->> schemeA: 202 OK + + alt if error in schemeB + schemeB ->> xnp: PUT /xxx/{ID}/error + note right + Error Codes: 2xxx, 3xxx, 4xxx, 5xxx + end note + xnp->xnp: Add header + note left + fxpiop-proxy = "Proxy AB" + end note + xnp ->> schemeA: PUT /xxx/{ID}/error + schemeA -->> xnp: 200 OK + xnp -->> schemeB: 200 OK + schemeA ->> payerDFSP: PUT /xxx/{ID}/error + payerDFSP -->> schemeA: 200 OK + end + + schemeB ->> payeeDFSP: POST/GET/PATCH/PUT /xxx + payeeDFSP -->> schemeB: 200 OK + + alt if error in payeeDFSP + payeeDFSP->> schemeB: PUT /xxx/{ID}/error + note right + header destination: PayerDFSP + Error Codes: 5xxx + end note + schemeB -->> payeeDFSP: 200 OK + schemeB -> schemeB: Lookup proxy for payerDFSP = Proxy AB + schemeB ->> xnp: PUT /xxx/{ID}/error + xnp->xnp: Add header + note left + fxpiop-proxy = "Proxy AB" + end note + xnp ->> schemeA: PUT /xxx/{ID}/error + schemeA -->> xnp: 200 OK + xnp -->> schemeB: 200 OK + schemeA ->> payerDFSP: PUT /xxx/{ID}/error + payerDFSP -->> schemeA: 200 OK + end + +@enduml \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-ErrorCases.svg b/docs/product/features/Interscheme/Interscheme-ErrorCases.svg new file mode 100644 index 000000000..8c6b3db2c --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-ErrorCases.svg @@ -0,0 +1 @@ +Interscheme - Error CasesScheme AScheme BPayer DFSPPayer DFSPALSScheme AALSScheme AProxy CacheScheme AProxy CacheScheme AProxy ABProxy ABALSScheme BALSScheme BProxy CacheScheme BProxy CacheScheme BPayee DFSPayee DFSPOST[1]POST/GET/PATCH/PUT /xxxheadersource: payerDFSPdestination: payeeDFSPalt[if OpenAPI Error][2]400 Bad Request[3]202 OKalt[if error in schemeA][4]PUT /xxx/{ID}/errorError Codes: 2xxx, 3xxx, 4xxx, 5xxx[5]200 OK[6]lookup proxy for payeeDFSP = Proxy ABalt[if not in proxy cache][7]PUT /xxx/{ID}/errorError Code: 3201[8]200 OK[9]POST/GET/PATCH/PUT /xxxalt[if error in xnp][10]503 { ErrorCode: 3100}[11]PUT /xxx/{ID}/errorheadersource: Proxy ABdestination: payerDFSPJWS Signed by Proxy ABError Codes: 3100[12]200 OK[13]PUT /xxx/{ID}/error[14]200 OK[15]Add headerfxpiop-proxy = "Proxy AB"[16]POST/GET/PATCH/PUT /xxx[17]202 OK[18]202 OKalt[if error in schemeB][19]PUT /xxx/{ID}/errorError Codes: 2xxx, 3xxx, 4xxx, 5xxx[20]Add headerfxpiop-proxy = "Proxy AB"[21]PUT /xxx/{ID}/error[22]200 OK[23]200 OK[24]PUT /xxx/{ID}/error[25]200 OK[26]POST/GET/PATCH/PUT /xxx[27]200 OKalt[if error in payeeDFSP][28]PUT /xxx/{ID}/errorheader destination: PayerDFSPError Codes: 5xxx[29]200 OK[30]Lookup proxy for payerDFSP = Proxy AB[31]PUT /xxx/{ID}/error[32]Add headerfxpiop-proxy = "Proxy AB"[33]PUT /xxx/{ID}/error[34]200 OK[35]200 OK[36]PUT /xxx/{ID}/error[37]200 OK \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-GETTransfer.plantuml b/docs/product/features/Interscheme/Interscheme-GETTransfer.plantuml new file mode 100644 index 000000000..f29ce2212 --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-GETTransfer.plantuml @@ -0,0 +1,57 @@ +@startuml Interscheme-GETTransfer + +title Interscheme - GET Transfers + +participant "Payer DFSP" as payerDFSP +box Scheme A #LightBlue + participant "Mojaloop\nScheme A" as schemeA + participant "Proxy Cache\nScheme A" as pc_A +end box +participant "Proxy AB" as xnp +box Scheme B #d1e0c3 + participant "Mojaloop\nScheme B" as schemeB + participant "Proxy Cache\nScheme B" as pc_B +end box +participant "Payee DFS" as payeeDFSP + +autonumber 1 "[0]" + +payerDFSP ->> schemeA: GET /transfers/1234 +note left +header + source: payerDFSP + destination: payeeDFSP +JWS signed by payerDFSP +end note +schemeA -->> payerDFSP: 202 OK +schemeA -> schemeA: Load transfer information + + +schemeA->>payerDFSP: PUT /transfers/1234 +note right +header + source: schemeB + destination: payerDFSP +JWS signed by schemeB +end note +payerDFSP -->> schemeA: 200 OK + +payeeDFSP->>schemeB: GET /transfers/1234 +note right +header + source: scheme A +JWS signed by schemeA +end note +schemeB -->> payeeDFSP: 202 OK +schemeB -> schemeB: Load transfer informtaion\nand check if payeeDFSP is in scheme +schemeB->>payeeDFSP: Yes; return information\nPUT /transfers/1234 +note left +header + source: schemeB + destination: payeeDFSP +JWS signed by schemeB +end note +schemeB -->> payeeDFSP: 200 OK + + +@enduml \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-GETTransfer.svg b/docs/product/features/Interscheme/Interscheme-GETTransfer.svg new file mode 100644 index 000000000..d332a1cc5 --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-GETTransfer.svg @@ -0,0 +1 @@ +Interscheme - GET TransfersScheme AScheme BPayer DFSPPayer DFSPMojaloopScheme AMojaloopScheme AProxy CacheScheme AProxy CacheScheme AProxy ABProxy ABMojaloopScheme BMojaloopScheme BProxy CacheScheme BProxy CacheScheme BPayee DFSPayee DFS[1]GET /transfers/1234headersource: payerDFSPdestination: payeeDFSPJWS signed by payerDFSP[2]202 OK[3]Load transfer information[4]PUT /transfers/1234headersource: schemeBdestination: payerDFSPJWS signed by schemeB[5]200 OK[6]GET /transfers/1234headersource: scheme AJWS signed by schemeA[7]202 OK[8]Load transfer informtaionand check if payeeDFSP is in scheme[9]Yes; return informationPUT /transfers/1234headersource: schemeBdestination: payeeDFSPJWS signed by schemeB[10]200 OK \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-Happypath.plantuml b/docs/product/features/Interscheme/Interscheme-Happypath.plantuml new file mode 100644 index 000000000..84e0b4ebe --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-Happypath.plantuml @@ -0,0 +1,106 @@ +@startuml Interscheme-Happypath + +title Interscheme - General Pattern + +participant "Payer DFSP" as payerDFSP +box "Scheme A" #LightBlue + participant "Handler\nScheme A" as schemeA + participant "Proxy Cache\nScheme A" as pc_A +end box +participant "Proxy AB" as xnp +box "Scheme B" #d1e0c3 + participant "Handler\nScheme B" as schemeB + participant "Proxy Cache\nScheme B" as pc_B +end box +participant "Payee DFS" as payeeDFSP + +autonumber 1 "[0]" + +== POST == +payerDFSP ->> schemeA: POST /xxx +note left +header + source: payerDFSP + destination: payeeDFSP +body + {ID: 1234} +end note +schemeA-->>payerDFSP: http 202 response +schemeA -> pc_A: Destination not in scheme:\n payeeDFSP has a proxy mapped\n need to send to 'Proxy AB' +schemeA ->> xnp: POST /xxx +xnp->xnp: Add header + note left + fxpiop-proxy = "Proxy AB" + end note +xnp ->> schemeB: POST /xxx +note left +Message if forwarded to schemeB unmodified +end note + +schemeB -->> xnp: 202 OK +xnp -->> schemeA: 202 OK + +schemeB ->> payeeDFSP: POST /xxx +payeeDFSP-->>schemeB: http 202 response + +== GET == +payerDFSP -> schemeA: GET /xxx/{ID} \nwithout destination +note left + source: payerDFSP +end note +schemeA-->>payerDFSP: http 202 response + +schemeA->schemeA: lookup if ID result and triggers put + +payerDFSP -> schemeA: GET /xxx/{ID} \nwith destination +note left + source: payerDFSP + destination: payeeDFSP +end note +schemeA-->>payerDFSP: http 202 response + +schemeA -> pc_A: Destination not in scheme:\n payeeDFSP has a proxy mapped\n need to send to 'Proxy AB' +schemeA ->> xnp: GET /xxx +xnp->xnp: Add header + note left + fxpiop-proxy = "Proxy AB" + end note +xnp ->> schemeB: GET /xxx +note left +Message if forwarded to schemeB unmodified +end note +schemeB -->> xnp: 202 OK +xnp -->> schemeA: 202 OK + +schemeB ->> payeeDFSP: GET /xxx +payeeDFSP-->>schemeB: http 202 response + + + +== PUT == + + +payeeDFSP -> schemeB: PUT /xxx +note right + source: payeeDFSP + destination: payerDFSP +end note +schemeB-->>payeeDFSP: http 200 response + +schemeB -> pc_B: Destination not in scheme:\n payerDFSP has a proxy mapped\n need to send to 'Proxy AB' +schemeB -> xnp: PUT /xxx +xnp->xnp: Add header + note left + fxpiop-proxy = "Proxy AB" + end note +xnp -> schemeA: PUT /xxx +note right +Message if forwarded to schemeA unmodified +end note +schemeA -->> xnp: 200 OK +xnp -->> schemeB: 200 OK + +schemeA -> payerDFSP: PUT /xxx +payerDFSP-->>schemeA: http 200 response + +@enduml \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-Happypath.svg b/docs/product/features/Interscheme/Interscheme-Happypath.svg new file mode 100644 index 000000000..2af53e645 --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-Happypath.svg @@ -0,0 +1 @@ +Interscheme - General PatternScheme AScheme BPayer DFSPPayer DFSPHandlerScheme AHandlerScheme AProxy CacheScheme AProxy CacheScheme AProxy ABProxy ABHandlerScheme BHandlerScheme BProxy CacheScheme BProxy CacheScheme BPayee DFSPayee DFSPOST[1]POST /xxxheadersource: payerDFSPdestination: payeeDFSPbody{ID: 1234}[2]http 202 response[3]Destination not in scheme:payeeDFSP has a proxy mappedneed to send to 'Proxy AB'[4]POST /xxx[5]Add headerfxpiop-proxy = "Proxy AB"[6]POST /xxxMessage if forwarded to schemeB unmodified[7]202 OK[8]202 OK[9]POST /xxx[10]http 202 responseGET[11]GET /xxx/{ID}without destinationsource: payerDFSP[12]http 202 response[13]lookup if ID result and triggers put[14]GET /xxx/{ID}with destinationsource: payerDFSPdestination: payeeDFSP[15]http 202 response[16]Destination not in scheme:payeeDFSP has a proxy mappedneed to send to 'Proxy AB'[17]GET /xxx[18]Add headerfxpiop-proxy = "Proxy AB"[19]GET /xxxMessage if forwarded to schemeB unmodified[20]202 OK[21]202 OK[22]GET /xxx[23]http 202 responsePUT[24]PUT /xxxsource: payeeDFSPdestination: payerDFSP[25]http 200 response[26]Destination not in scheme:payerDFSP has a proxy mappedneed to send to 'Proxy AB'[27]PUT /xxx[28]Add headerfxpiop-proxy = "Proxy AB"[29]PUT /xxxMessage if forwarded to schemeA unmodified[30]200 OK[31]200 OK[32]PUT /xxx[33]http 200 response \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-OnDemandDiscovery.plantuml b/docs/product/features/Interscheme/Interscheme-OnDemandDiscovery.plantuml new file mode 100644 index 000000000..43daf9c05 --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-OnDemandDiscovery.plantuml @@ -0,0 +1,140 @@ +@startuml Interscheme-OnDemandDiscovery + +title Interscheme - On Demand Discovery + +participant "Payer DFSP" as payerDFSP +box "Scheme A" #LightBlue + participant "ALS\nScheme A" as ALS_A + participant "Proxy Cache\nScheme A" as pc_A + participant "Oracle\nScheme A" as Oracle_A +end box +participant "other Proxies" as dfspsA +participant "Proxy AB" as xnp +box "Scheme B" #d1e0c3 + participant "ALS\nScheme B" as ALS_B + participant "Proxy Cache\nScheme B" as pc_B + participant "Oracle\nScheme B" as Oracle_B +end box +participant "Payee DFS" as payeeDFSP + +autonumber 1 "[0]" + +payerDFSP ->> ALS_A: GET /parties/{Type}/{ID} +note left + header source = payerDFSP +end note +ALS_A -->> payerDFSP: 202 OK +ALS_A-> Oracle_A: GET /participant/{ID} +alt if not found in Oracle + +Oracle_A--> ALS_A: no dfsp found +ALS_A ->> ALS_A: Are there any proxies\n in Scheme A? + ALS_A ->> ALS_A: Cache Proxies that \nwill receive messages + note left + SentToProxies[{ID}] = + {['Proxy AB', 'Proxy CD', 'Proxy EF']} + end note + + loop for all Proxys in Scheme A and not source + alt if Proxy AB + ALS_A ->> xnp: GET /parties/{Type}/{ID} + xnp->xnp: Add header + note left + fxpiop-proxy = "Proxy AB" + end note + + xnp ->> ALS_B: GET /parties/{Type}/{ID} + ALS_B -->> xnp: 202 OK + xnp -->> ALS_A: 202 OK + ALS_B -> pc_B: Source not in Scheme: \nfxpiop-proxy = "Proxy AB"\nAdd 'Payer DFSP' to\n 'Proxy AB' mapping + pc_B -> pc_B: Add new mapping \nto cache + note left + Payer DFSP : Proxy AB + end note + + ALS_B-> Oracle_B: GET /participant/{ID} + Oracle_B--> ALS_B: dfps = payeeDFSP + ALS_B ->> payeeDFSP: GET /parties/{Type}/{ID} + payeeDFSP -->> ALS_B: 202 OK + payeeDFSP ->> ALS_B: PUT /parties/{ID} + note right + header destination = payerDFSP + source = payeeDFSP + end note + ALS_B -->> payeeDFSP: 200 Ok + ALS_B -> pc_B: Lookup payerDFSP proxy + ALS_B ->> xnp: PUT /parties/{ID} + xnp->xnp: Add header + note left + fxpiop-proxy = "Proxy AB" + end note + + xnp ->> ALS_A: PUT /parties/{ID} + ALS_A -->> xnp: 200 OK + xnp -->> ALS_B: 200 OK + ALS_A -> pc_A: Source not in Scheme: \nfxpiop-proxy = "Proxy AB"\nAdd 'Payee DFSP' to \n'Proxy AB' mapping + pc_A -> pc_A: New mapping\nCheck JWS \nsignature &\n Add to cache + note left + Payee DFSP : Proxy AB + end note + ALS_A -> Oracle_A: Update Oracle with mapping\n**POST /participants/{Type}/{ID}** \n{{"fspId": "Payee DFSP"}} + Oracle_A--> ALS_A: return + ALS_A ->> payerDFSP: PUT /parties/{ID} + payerDFSP -->> ALS_A: 200 OK + else if other Proxy in Scheme A + ALS_A ->> dfspsA: GET /parties/{Type}/{ID} + dfspsA -->> ALS_A: 202 OK + dfspsA ->> ALS_A: PUT /parties/{ID}/error + ALS_A -->> dfspsA: 200 OK + ALS_A ->> ALS_A: Mark message as \nreceived from proxy + note left + remove other Proxy from + list SentToProxies[{ID}] + end note + + alt if SentToProxies[{ID}] is empty + ALS_A ->> payerDFSP: PUT /parties/{ID}/error + note right + SentToProxies[{ID}] is empty + end note + payerDFSP -->> ALS_A: 200 OK + end + end +end loop +else if found in Oracle + Oracle_A--> ALS_A: dfsp = payeeDFSP + + ALS_A->ALS_A: Payee DFSP is \nnot in scheme A + ALS_A-> pc_A: Lookup proxy for\n Payee DFSP + alt if header source is a member of Scheme A + ALS_A->ALS_A: Add destination to header + note left + destination dfsp: Payee DFSP + end note + + ALS_A ->> xnp: GET /parties/{Type}/{ID} + xnp ->> ALS_B: GET /parties/{Type}/{ID} + ALS_B -->> xnp: 202 OK + xnp -->> ALS_A: 202 OK + end + ALS_B->ALS_B: Forward to destination + ALS_B ->> payeeDFSP: GET /parties/{Type}/{ID} + payeeDFSP -->> ALS_B: 202 OK + payeeDFSP ->> ALS_B: PUT /parties/{ID} + note right + header destination = payerDFSP + end note + ALS_B -->> payeeDFSP: 200 Ok + ALS_B -> pc_B: Lookup payerDFSP proxy + ALS_B ->> xnp: PUT /parties/{ID} + xnp ->> ALS_A: PUT /parties/{ID} + ALS_A -->> xnp: 200 OK + xnp -->> ALS_B: 200 OK + ALS_A -> pc_A: Source not in Scheme: \nAdd 'Payee DFSP' to\n 'Proxy AB' mapping + pc_A -> pc_A: Got Mapping + ALS_A ->> payerDFSP: PUT /parties/{ID} + payerDFSP -->> ALS_A: 200 OK +end + + +@enduml \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-OnDemandDiscovery.svg b/docs/product/features/Interscheme/Interscheme-OnDemandDiscovery.svg new file mode 100644 index 000000000..a73a08b38 --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-OnDemandDiscovery.svg @@ -0,0 +1 @@ +Interscheme - On Demand DiscoveryScheme AScheme BPayer DFSPPayer DFSPALSScheme AALSScheme AProxy CacheScheme AProxy CacheScheme AOracleScheme AOracleScheme Aother Proxiesother ProxiesProxy ABProxy ABALSScheme BALSScheme BProxy CacheScheme BProxy CacheScheme BOracleScheme BOracleScheme BPayee DFSPayee DFS[1]GET /parties/{Type}/{ID}header source = payerDFSP[2]202 OK[3]GET /participant/{ID}alt[if not found in Oracle][4]no dfsp found[5]Are there any proxiesin Scheme A?[6]Cache Proxies thatwill receive messagesSentToProxies[{ID}] ={['Proxy AB', 'Proxy CD', 'Proxy EF']}loop[for all Proxys in Scheme A and not source]alt[if Proxy AB][7]GET /parties/{Type}/{ID}[8]Add headerfxpiop-proxy = "Proxy AB"[9]GET /parties/{Type}/{ID}[10]202 OK[11]202 OK[12]Source not in Scheme:fxpiop-proxy = "Proxy AB"Add 'Payer DFSP' to'Proxy AB' mapping[13]Add new mappingto cachePayer DFSP : Proxy AB[14]GET /participant/{ID}[15]dfps = payeeDFSP[16]GET /parties/{Type}/{ID}[17]202 OK[18]PUT /parties/{ID}header destination = payerDFSPsource = payeeDFSP[19]200 Ok[20]Lookup payerDFSP proxy[21]PUT /parties/{ID}[22]Add headerfxpiop-proxy = "Proxy AB"[23]PUT /parties/{ID}[24]200 OK[25]200 OK[26]Source not in Scheme:fxpiop-proxy = "Proxy AB"Add 'Payee DFSP' to'Proxy AB' mapping[27]New mappingCheck JWSsignature &Add to cachePayee DFSP : Proxy AB[28]Update Oracle with mappingPOST /participants/{Type}/{ID} {{"fspId": "Payee DFSP"}}[29]return[30]PUT /parties/{ID}[31]200 OK[if other Proxy in Scheme A][32]GET /parties/{Type}/{ID}[33]202 OK[34]PUT /parties/{ID}/error[35]200 OK[36]Mark message asreceived from proxyremove other Proxy fromlist SentToProxies[{ID}]alt[if SentToProxies[{ID}] is empty][37]PUT /parties/{ID}/errorSentToProxies[{ID}] is empty[38]200 OK[if found in Oracle][39]dfsp = payeeDFSP[40]Payee DFSP isnot in scheme A[41]Lookup proxy forPayee DFSPalt[if header source is a member of Scheme A][42]Add destination to headerdestination dfsp: Payee DFSP[43]GET /parties/{Type}/{ID}[44]GET /parties/{Type}/{ID}[45]202 OK[46]202 OK[47]Forward to destination[48]GET /parties/{Type}/{ID}[49]202 OK[50]PUT /parties/{ID}header destination = payerDFSP[51]200 Ok[52]Lookup payerDFSP proxy[53]PUT /parties/{ID}[54]PUT /parties/{ID}[55]200 OK[56]200 OK[57]Source not in Scheme:Add 'Payee DFSP' to'Proxy AB' mapping[58]Got Mapping[59]PUT /parties/{ID}[60]200 OK \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-StalePartyIdentifierCache.plantuml b/docs/product/features/Interscheme/Interscheme-StalePartyIdentifierCache.plantuml new file mode 100644 index 000000000..934c98a7d --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-StalePartyIdentifierCache.plantuml @@ -0,0 +1,90 @@ +@startuml Interscheme-StalePartyIdentifierCache + +title Stale Party Identifier Cache + +participant "Payer DFSP" as payerDFSP +box "Scheme A" #LightBlue + participant "ALS\nScheme A" as ALS_A + participant "Oracle\nScheme A" as Oracle_A + participant "Proxy Cache\nScheme A" as pc_A +end box +participant "Proxy AB" as xnp +box "Scheme B" #d1e0c3 + participant "ALS\nScheme B" as ALS_B + participant "Oracle\nScheme A" as Oracle_B + participant "Proxy Cache\nScheme B" as pc_B +end box +participant "Payee DFS" as payeeDFSP + +autonumber 1 "[0]" + +payerDFSP ->> ALS_A: **GET** /parties/{Type}/{ID} +note left + header source = payerDFSP +end note + + ALS_A-> Oracle_A: **GET** /participant/{ID} + Oracle_A--> ALS_A: found DFSP = payeeDFSP + ALS_A ->> ALS_A: DFSP not in scheme + ALS_A -> pc_A: Who is payee DFSP's proxy? + alt proxy representative not found + pc_A --> ALS_A: Proxy not found + ALS_A -> Oracle_A: Remove mapping in Oracle\n **DELETE** \participants\{Type}\{ID} + note left + **Self heal** if proxy + reference is not found + end note + ALS_A ->> ALS_A: Restart the ALS get parties process + else + pc_A --> ALS_A: forward to Proxy AB + end + + ALS_A ->> xnp: **GET** /parties/{Type}/{ID} + xnp->xnp: Add header + note left + fxpiop-proxy = "Proxy AB" + end note + + xnp ->> ALS_B: **GET** /parties/{Type}/{ID} + ALS_B ->> pc_B: Source not in Scheme: \nfxpiop-proxy = "Proxy AB"\nAdd 'Payer DFSP' to 'Proxy AB' mapping +alt not MVP + pc_B -> pc_B: Check JWS signature +end + pc_B -> pc_B: Add new mapping to cache +note left +Payer DFSP : Proxy AB +end note +ALS_B-> Oracle_B: **GET** /participant/{ID} + Oracle_B--> ALS_B: dfps = payeeDFSP + alt if dfsp is a member of Scheme B + ALS_B ->> payeeDFSP: **GET** /parties/{Type}/{ID} + payeeDFSP ->> ALS_B: **PUT** /parties/{ID}/error + note right + header desitination = payerDFSP + end note + end + ALS_B -> pc_B: Lookup payerDFSP proxy + ALS_B ->> xnp: **PUT** /parties/{ID}/error + xnp->xnp: Add header + note left + fxpiop-proxy = "Proxy AB" + end note + xnp ->> ALS_A: **PUT** /parties/{ID}/error + alt message from proxy & error & no proxy message cache + note left ALS_A + **Self heal** if error in routing + fxpiop-proxy = "Proxy AB" + PUT /parties error + SentToProxies[{ID}] list undefined + end note + ALS_A -> Oracle_A: Remove mapping in Oracle\n **DELETE** \participants\{Type}\{ID} + ALS_A ->> payerDFSP: **PUT** /parties/{ID}/error + note right + {ErrorCode: "2003"} + (Service Unavailable) + end note + else + ALS_A->>payerDFSP: **PUT** /parties/{ID}/error +end + +@enduml \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-StalePartyIdentifierCache.svg b/docs/product/features/Interscheme/Interscheme-StalePartyIdentifierCache.svg new file mode 100644 index 000000000..cd5ae6924 --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-StalePartyIdentifierCache.svg @@ -0,0 +1 @@ +Stale Party Identifier CacheScheme AScheme BPayer DFSPPayer DFSPALSScheme AALSScheme AOracleScheme AOracleScheme AProxy CacheScheme AProxy CacheScheme AProxy ABProxy ABALSScheme BALSScheme BOracleScheme AOracleScheme AProxy CacheScheme BProxy CacheScheme BPayee DFSPayee DFS[1]GET/parties/{Type}/{ID}header source = payerDFSP[2]GET/participant/{ID}[3]found DFSP = payeeDFSP[4]DFSP not in scheme[5]Who is payee DFSP's proxy?alt[proxy representative not found][6]Proxy not found[7]Remove mapping in Oracle DELETE\participants\{Type}\{ID}Self healif proxyreference is not found[8]Restart the ALS get parties process[9]forward to Proxy AB[10]GET/parties/{Type}/{ID}[11]Add headerfxpiop-proxy = "Proxy AB"[12]GET/parties/{Type}/{ID}[13]Source not in Scheme:fxpiop-proxy = "Proxy AB"Add 'Payer DFSP' to 'Proxy AB' mappingalt[not MVP][14]Check JWS signature[15]Add new mapping to cachePayer DFSP : Proxy AB[16]GET/participant/{ID}[17]dfps = payeeDFSPalt[if dfsp is a member of Scheme B][18]GET/parties/{Type}/{ID}[19]PUT/parties/{ID}/errorheader desitination = payerDFSP[20]Lookup payerDFSP proxy[21]PUT/parties/{ID}/error[22]Add headerfxpiop-proxy = "Proxy AB"[23]PUT/parties/{ID}/erroralt[message from proxy & error & no proxy message cache]Self healif error in routingfxpiop-proxy = "Proxy AB"PUT /parties errorSentToProxies[{ID}] list undefined[24]Remove mapping in Oracle DELETE\participants\{Type}\{ID}[25]PUT/parties/{ID}/error{ErrorCode: "2003"}(Service Unavailable)[26]PUT/parties/{ID}/error \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-Transfer.plantuml b/docs/product/features/Interscheme/Interscheme-Transfer.plantuml new file mode 100644 index 000000000..9fda3da00 --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-Transfer.plantuml @@ -0,0 +1,80 @@ +@startuml Interscheme-Transfer + +title Interscheme - Transfer + +participant "Payer DFSP" as payerDFSP +box Scheme A #LightBlue + participant "Mojaloop\nScheme A" as schemeA + participant "Proxy Cache\nScheme A" as pc_A +end box +participant "Proxy AB" as xnp +box Scheme B #d1e0c3 + participant "Mojaloop\nScheme B" as schemeB + participant "Proxy Cache\nScheme B" as pc_B +end box +participant "Payee DFS" as payeeDFSP + +autonumber 1 "[0]" + +payerDFSP ->> schemeA: POST /transfers +note left +header + source: payerDFSP + destination: payeeDFSP +JWS signed by payerDFSP +body + transferId: 1234 +end note +schemeA -->> payerDFSP: 202 OK +schemeA -> schemeA: Payer DFSP\n - Checks limits\n - Updates position +schemeA -> pc_A: Destination not in Scheme\nLookup proxy for payeeDFSP = Proxy AB +schemeA ->> xnp: POST /transfers +xnp ->> schemeB: POST /transfers +note left +header + source: payerDFSP + destination: payeeDFSP + fxpiop-proxy: proxyAB +JWS signed by payerDFSP +body + transferId: 1234 +end note +schemeB -->> xnp: 202 OK +xnp -->> schemeA: 202 OK +schemeA -> schemeA: Disable timeout + +schemeB -> schemeB: Proxy AB\n **- No limit check**\n - Updates position +schemeB->>payeeDFSP: POST /transfers +note right +Checks JWS signed by payerDFSP +end note +payeeDFSP->>schemeB: PUT /transfers \n{fulfilment: "xyz", transferState: "RESERVED"} +note right +header + source: payeeDFSP + destination: payerDFSP +JWS signed by payeeDFSP +end note +schemeB -> schemeB: Payer DFSP\n - Updates position +schemeB -> pc_B: Lookup proxy for payerDFSP = Proxy AB +schemeB->>xnp: PUT /transfers +xnp->>schemeA: PUT /transfers +note right +header + source: payeeDFSP + destination: payerDFSP + fxpiop-proxy: proxyAB +JWS signed by payeeDFSP +end note +schemeA-->>xnp: 200 OK +xnp-->>schemeB: 200 OK +schemeB->>payeeDFSP: PATCH /transfers \n{transferState: "COMMITTED"} +payeeDFSP-->>schemeB: 200 OK +schemeA -> schemeA: NX Proxy\n - Updates position +schemeA->>payerDFSP: PUT /transfers +note left +Checks JWS signed by payeeDFSP +end note +payerDFSP -->> schemeA: 200 OK + +@enduml \ No newline at end of file diff --git a/docs/product/features/Interscheme/Interscheme-Transfer.svg b/docs/product/features/Interscheme/Interscheme-Transfer.svg new file mode 100644 index 000000000..65bb79a94 --- /dev/null +++ b/docs/product/features/Interscheme/Interscheme-Transfer.svg @@ -0,0 +1 @@ +Interscheme - TransferScheme AScheme BPayer DFSPPayer DFSPMojaloopScheme AMojaloopScheme AProxy CacheScheme AProxy CacheScheme AProxy ABProxy ABMojaloopScheme BMojaloopScheme BProxy CacheScheme BProxy CacheScheme BPayee DFSPayee DFS[1]POST /transfersheadersource: payerDFSPdestination: payeeDFSPJWS signed by payerDFSPbodytransferId: 1234[2]202 OK[3]Payer DFSP- Checks limits- Updates position[4]Destination not in SchemeLookup proxy for payeeDFSP = Proxy AB[5]POST /transfers[6]POST /transfersheadersource: payerDFSPdestination: payeeDFSPfxpiop-proxy: proxyABJWS signed by payerDFSPbodytransferId: 1234[7]202 OK[8]202 OK[9]Disable timeout[10]Proxy AB - No limit check- Updates position[11]POST /transfersChecks JWS signed by payerDFSP[12]PUT /transfers{fulfilment: "xyz", transferState: "RESERVED"}headersource: payeeDFSPdestination: payerDFSPJWS signed by payeeDFSP[13]Payer DFSP- Updates position[14]Lookup proxy for payerDFSP = Proxy AB[15]PUT /transfers[16]PUT /transfersheadersource: payeeDFSPdestination: payerDFSPfxpiop-proxy: proxyABJWS signed by payeeDFSP[17]200 OK[18]200 OK[19]PATCH /transfers{transferState: "COMMITTED"}[20]200 OK[21]NX Proxy- Updates position[22]PUT /transfersChecks JWS signed by payeeDFSP[23]200 OK \ No newline at end of file diff --git a/docs/product/features/Interscheme/InterschemeAccounts-Clearing.png b/docs/product/features/Interscheme/InterschemeAccounts-Clearing.png new file mode 100644 index 000000000..a219b4c67 Binary files /dev/null and b/docs/product/features/Interscheme/InterschemeAccounts-Clearing.png differ diff --git a/docs/product/features/Interscheme/SettingUpProxys.plantuml b/docs/product/features/Interscheme/SettingUpProxys.plantuml new file mode 100644 index 000000000..4d1ddb131 --- /dev/null +++ b/docs/product/features/Interscheme/SettingUpProxys.plantuml @@ -0,0 +1,31 @@ +@startuml SettingUpProxys +title Central Ledger API / Admin API + +participant "Onboarding Script" as script +participant "Mojaloop\nScheme A" as schemeA +participant "XN Proxy" as xnp +participant "Mojaloop\nScheme B" as schemeB + +autonumber 1 "[0]" + +== Create Participant Types == + +script -> schemeA: POST /participants +note left +{ + "name": "XN Proxy", + "currency": "USD", + "isProxy": true +} +end note + +script -> schemeB: POST /participants +note left +{ + "name": "XN Proxy", + "currency": "USD", + "isProxy": true +} +end note + +@enduml \ No newline at end of file diff --git a/docs/product/features/Interscheme/SettingUpProxys.svg b/docs/product/features/Interscheme/SettingUpProxys.svg new file mode 100644 index 000000000..f29814093 --- /dev/null +++ b/docs/product/features/Interscheme/SettingUpProxys.svg @@ -0,0 +1 @@ +Central Ledger API / Admin APIOnboarding ScriptOnboarding ScriptMojaloopScheme AMojaloopScheme AXN ProxyXN ProxyMojaloopScheme BMojaloopScheme BCreate Participant Types[1]POST /participants{"name": "XN Proxy","currency": "USD",  "isProxy": true}[2]POST /participants{"name": "XN Proxy","currency": "USD",  "isProxy": true} \ No newline at end of file diff --git a/docs/product/features/Iso20022/Appendix.md b/docs/product/features/Iso20022/Appendix.md new file mode 100644 index 000000000..7e0c862cd --- /dev/null +++ b/docs/product/features/Iso20022/Appendix.md @@ -0,0 +1,50 @@ +# 8. Appendix A: Payment Identifier Type Codes +## 8.1 FSPIOP Identifier types +|Code|Description| +| -- | -- | +|MSISDN|An MSISDN (Mobile Station International Subscriber Directory Number, that is, the phone number) is used as reference to a participant. The MSISDN identifier should be in international format according to the ITU-T E.164 standard. Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix.| +|EMAIL|An email is used as reference to a participant. The format of the email should be according to the informational RFC 3696.| +|PERSONAL_ID|A personal identifier is used as reference to a participant. Examples of personal identification are passport number, birth certificate number, and national registration number. The identifier number is added in the PartyIdentifier element. The personal identifier type is added in the PartySubIdOrType element.| +|BUSINESS|A specific Business (for example, an organization or a company) is used as reference to a participant. The BUSINESS identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the PartySubIdOrType element should be used.| +|DEVICE|A specific device (for example, a POS or ATM) ID connected to a specific business or organization is used as reference to a Party. For referencing a specific device under a specific business or organization, use the PartySubIdOrType element.| +|ACCOUNT_ID|A bank account number or FSP account ID should be used as reference to a participant. The ACCOUNT_ID identifier can be in any format, as formats can greatly differ depending on country and FSP.| +|IBAN|A bank account number or FSP account ID is used as reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without whitespace.| +|ALIAS| alias is used as reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias is a username in the FSP system. The ALIAS identifier can be in any format. It is also possible to use the PartySubIdOrType element for identifying an account under an Alias defined by the PartyIdentifier.| + + +## 8.2 Personal Identifier Code Table +These type are not yet supported. + +|Code|Description| +| -- | -- | +|ARNU|AlienRegistrationNumber| +|CCPT|PassportNumber| +|CUST|CustomerIdentificationNumber| +|DRLC|DriversLicenseNumber| +|EMPL|EmployeeIdentificationNumber| +|NIDN|NationalIdentityNumber| +|SOSE|SocialSecurityNumber| +|TELE|TelephoneNumber| +|TXID|TaxIdentificationNumber| +|POID|PersonCommercialIdentification| + + +## 8.3 Organisation Identifier Code Table +These type are not yet supported. + +|Code|Description +| -- | -- | +|BANK|BankPartyIdentification| +|CBID|CentralBankIdentificationNumber| +|CHID|ClearingIdentificationNumber| +|CINC|CertificateOfIncorporationNumber| +|COID|CountryIdentificationCode| +|CUST|CustomerNumber| +|DUNS|DataUniversalNumberingSystem| +|EMPL|EmployerIdentificationNumber| +|GS1G|GS1GLNIdentifier| +|SREN|SIREN| +|SRET|SIRET| +|TXID|TaxIdentificationNumber| +|BDID|BusinessDomainIdentifier| +|BOID|BusinessOtherIdentification| diff --git a/docs/product/features/Iso20022/MarketPracticeDocument.md b/docs/product/features/Iso20022/MarketPracticeDocument.md new file mode 100644 index 000000000..f5a02f1ca --- /dev/null +++ b/docs/product/features/Iso20022/MarketPracticeDocument.md @@ -0,0 +1,237 @@ +# Mojaloop ISO 20022 Market Practice Document + + + +- [1. Mojaloop ISO 20022 Market Practice Document](#_1-mojaloop-iso-20022-market-practice-document) +- [2. Introduction](#_2-introduction) + - [2.1. How to Use This Document?](#_2-1-how-to-use-this-document) + - [2.1.1. Relationship with Scheme-Specific Rules Documents](#_2-1-1-relationship-with-scheme-specific-rules-documents) + - [2.1.2. Distinction Between Generic Practices and Scheme-Specific Requirements](#_2-1-2-distinction-between-generic-practices-and-scheme-specific-requirements) +- [3. Message Expectations, Obligations, and Rules](#_3-message-expectations-obligations-and-rules) + - [3.1. Currency Conversion](#_3-1-currency-conversion) + - [3.2. JSON Messages](#_3-2-json-messages) + - [3.3. APIs](#_3-3-apis) + - [3.3.1. Header Details](#_3-3-1-header-details) + - [3.3.2. Supported HTTP Responses](#_3-3-2-supported-http-responses) + - [3.3.3. Common Error Payload](#_3-3-3-common-error-payload) + - [3.4. ULIDs as Unique Identifiers](#_3-4-ulids-as-unique-identifiers) + - [3.5. Inter-ledger Protocol v4 to represent the Cryptographic Terms](#_3-5-inter-ledger-protocol-v4-to-represent-the-cryptographic-terms) + - [3.6. ISO 20022 Supplementary Data Fields](#_3-6-iso-20022-supplementary-data-fields) +- [4. Discovery Phase](#_4-discovery-phase) + - [4.1. Message flow](#_4-1-message-flow) + - [4.2. Parties Resource](#_4-2-parties-resource) +- [5. Agreement Phase](#_5-agreement-phase) + - [5.1. Currency Conversion Agreement Sub-Phase](#_5-1-currency-conversion-agreement-sub-phase) + - [5.1.1. Message flow](#_5-1-1-message-flow) + - [5.1.2. fxQuotes Resource](#_5-1-2-fxquotes-resource) + - [5.2. Transfer Terms Agreement Sub-Phase](#_5-2-transfer-terms-agreement-sub-phase) + - [5.2.1. Message flow](#_5-2-1-message-flow) + - [5.2.2. Quotes Resource](#_5-2-2-quotes-resource) +- [6. Transfer Phase](#_6-transfer-phase) + - [6.1. Accepting Currency Conversion terms](#_6-1-accepting-currency-conversion-terms) + - [6.1.1. Message flow](#_6-1-1-message-flow) + - [6.1.2. fxTransfers Resource](#_6-1-2-fxtransfers-resource) + - [6.2. Transfer Execution and Clearing](#_6-2-transfer-execution-and-clearing) + - [6.2.1. Message flow](#_6-2-1-message-flow) + - [6.2.2. Transfers Resource](#_6-2-2-transfers-resource) + + +# 2. Introduction + +By combining the principles of financial inclusion with the robust capabilities of ISO 20022, Mojaloop ensures that DFSPs and other stakeholders can deliver real-time payment solutions that are cost-effective, secure, and scalable to meet the demands of inclusive financial ecosystems. + +## 2.1 How to Use This Document? +This document provides a foundational reference for implementing ISO 20022 messaging for IIPS within Mojaloop-based schemes. It outlines general guidelines and practices that apply universally across Mojaloop schemes, focusing on the base-level requirements. However, it is designed to be supplemented by scheme-specific rules documents, which can define additional message fields, validations, and rules necessary to meet the unique regulations and requirements of individual schemes. This layered approach enables each scheme to tailor its implementation details while maintaining consistency with the broader Mojaloop framework. + +### 2.1.1 Relationship with Scheme-Specific Rules Documents +This document serves as a foundation for understanding how ISO 20022 is applied in Mojaloop, focusing on core principles and practices. However, it does not prescribe the detailed business requirements, validations, and governance frameworks that are specific to individual schemes. Scheme-specific rules address these details, including mandatory and optional field specifications, tailored compliance protocols, and defined procedures for error handling. They also encompass business rules governing message flows, participant roles, and responsibilities within the scheme. The flexibility of this document allows scheme administrators to adapt and extend its guidance to meet their unique operational needs. + +### 2.1.2 Distinction Between Generic Practices and Scheme-Specific Requirements +This document distinctly separates generic practices from scheme-specific requirements to achieve a balance between consistency and adaptability in ISO 20022 implementations within Mojaloop. The generic practices outlined here establish foundational principles, including expectations for message structures, required fields to meet switch requirements, supported fields, and transactional flows. Additionally, they provide a high-level overview of the Mojaloop P2P FX transfer lifecycle. + +Scheme-specific requirements, documented separately, delve into additional field mappings, enhanced validations, and precise rules for settlement, reconciliation, and dispute resolution. These requirements also encompass governance policies and compliance obligations tailored to the unique needs of individual schemes. + +This distinction enables DFSPs to implement a consistent core messaging framework while granting scheme administrators the flexibility to define operational specifics. The generic practices presented in this document are purposefully designed to be extensible, ensuring seamless integration with scheme-specific rules and supporting adherence to Mojaloop’s ISO 20022 for IIPS standards. + +# 3 Message Expectations, Obligations, and Rules +The Mojaloop transfer process is divided into three key phases, each essential to ensuring secure and efficient transactions. These phases use specific resources to enable participant interactions, ensuring clear communication, agreement, and execution. While some phases and resources are optional, the ultimate goal is to ensure every transfer is accurate, secure, and aligns with agreed terms. +1. [Discovery](#_4-discovery-phase) +2. [Agreement](#_5-agreement-phase) +3. [Transfer](#_6-transfer-phase) + +## 3.1 Currency Conversion +Currency conversion is included to support cross-currency transactions. As it is not always required, the associated messages and flows are only used when needed, ensuring flexibility for both single-currency and multi-currency scenarios. + +## 3.2 JSON Messages +Mojaloop adopts a JSON variant of ISO 20022 messages, moving away from the traditional XML format to enhance efficiency and compatibility with modern APIs. The ISO 20022 organization is actively developing a canonical JSON representation of its messages, and Mojaloop aims to align with this standard as it evolves. + +## 3.3 APIs +ISO 20022 messages are exchanged in Mojaloop via REST-like API calls. This approach enhances interoperability, reduces data overhead through lightweight JSON messages, and supports scalable and modular implementations. By integrating ISO 20022 with REST APIs, Mojaloop delivers a robust, adaptable framework that balances global standards with practical implementation needs. + +### 3.3.1 Header Details +The API message header should contain the following details. Required headers are specified with an `*` asterisks. + +| Name                                | Description | +|--|--| +|**Content-Length**
*integer*
(header)|The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body.**Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes).| +| * **Type**
*string*
(path)|The type of the party identifier. For example, `MSISDN`, `PERSONAL_ID`.| +| * **ID**
*string*
(path)| The identifier value.| +| * **Content-Type**
*string*
(header)|The `Content-Type` header indicates the specific version of the API used to send the payload body.| +| * **Date**
*string*
(header)|The `Date` header field indicates the date when the request was sent.| +| **X-Forwarded-For**
*string*
(header)|The `X-Forwarded-For` header field is an unofficially accepted standard used for informational purposes of the originating client IP address, as a request might pass multiple proxies, firewalls, and so on. Multiple `X-Forwarded-For` values should be expected and supported by implementers of the API.**Note:** An alternative to `X-Forwarded-For` is defined in [RFC 7239](https://tools.ietf.org/html/rfc7239). However, to this point RFC 7239 is less-used and supported than `X-Forwarded-For`.| +| * **FSPIOP-Source**
*string*
(header)|The `FSPIOP-Source` header field is a non-HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing and signature verification (see header field `FSPIOP-Signature`).| +| **FSPIOP-Destination**
*string*
(header)|The `FSPIOP-Destination` header field is a non-HTTP standard field used by the API for HTTP header based routing of requests and responses to the destination. The field must be set by the original sender of the request if the destination is known (valid for all services except GET /parties) so that any entities between the client and the server do not need to parse the payload for routing purposes. If the destination is not known (valid for service GET /parties), the field should be left empty.| +| **FSPIOP-Encryption**
*string*
(header) | The `FSPIOP-Encryption` header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request.| +| **FSPIOP-Signature**
*string*
(header)| The `FSPIOP-Signature` header field is a non-HTTP standard field used by the API for applying an end-to-end request signature.| +| **FSPIOP-URI**
*string*
(header) | The `FSPIOP-URI` header field is a non-HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information, see [the API Signature document](https://docs.mojaloop.io/technical/api/fspiop/).| +| **FSPIOP-HTTP-Method**
*string*
(header) | The `FSPIOP-HTTP-Method` header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information, see [the API Signature document](https://docs.mojaloop.io/technical/api/fspiop/).| + +### 3.3.2 Supported HTTP Responses + +| **HTTP Error Code** | **Description and Common Causes** | +|---|----| +|**400 Bad Request** | **Description**: The server could not understand the request due to invalid syntax. This response indicates that the request was malformed or contained invalid parameters.
**Common Causes**: Missing required fields, invalid field values, or incorrect request format. | +|**401 Unauthorized** | **Description**: The client must authenticate itself to get the requested response. This response indicates that the request lacks valid authentication credentials.
**Common Causes**: Missing or invalid authentication token. | +|**403 Forbidden** | **Description**: The client does not have access rights to the content. This response indicates that the server understood the request but refuses to authorize it.
**Common Causes**: Insufficient permissions to access the resource. | +|**404 Not Found** | **Description**: The server can not find the requested resource. This response indicates that the specified resource does not exist.
**Common Causes**: Incorrect resource identifier or the resource has been deleted. | +|**405 Method Not Allowed** | **Description**: The request method is known by the server but is not supported by the target resource. This response indicates that the HTTP method used is not allowed for the endpoint.
**Common Causes**: Using an unsupported HTTP method (e.g., POST instead of PUT). | +|**406 Not Acceptable** | **Description**: The server cannot produce a response matching the list of acceptable values defined in the request's proactive content negotiation headers. This response indicates that the server cannot generate a response that is acceptable according to the Accept headers sent in the request.
**Common Causes**: Unsupported media type or format specified in the Accept header. | +|**501 Not Implemented** | **Description**: The server does not support the functionality required to fulfill the request. This response indicates that the server does not recognize the request method or lacks the ability to fulfill the request.
**Common Causes**: The requested functionality is not implemented on the server. | +|**503 Service Unavailable** | **Description**: The server is not ready to handle the request. This response indicates that the server is temporarily unable to handle the request due to maintenance or overload.
**Common Causes**: Server maintenance, temporary overload, or server downtime. | + +### 3.3.3 Common Error Payload + +All error responses return a common payload structure that includes a specific message. The payload typically contains the following fields: + +- **errorCode**: A code representing the specific error. +- **errorDescription**: A description of the error. +- **extensionList**: An optional list of key-value pairs providing additional information about the error. + +This common error payload helps clients understand the nature of the error and take appropriate actions. + + + +## 3.4 ULIDs as Unique Identifiers +Mojaloop employs Universally Unique Lexicographically Sortable Identifiers (ULIDs) as the standard for unique identifiers across its messaging system. ULIDs offer a robust alternative to traditional UUIDs, ensuring globally unique identifiers while also enabling natural ordering by time of creation. This lexicographical sorting simplifies traceability, troubleshooting, and operational analytics. + +## 3.5 Inter-ledger Protocol (v4) to represent the Cryptographic Terms +Mojaloop leverages the Inter-ledger Protocol (ILP) version 4 to define and represent cryptographic terms in its transfer processes. ILP v4 provides a standardized framework for secure and interoperable exchange of payment instructions, ensuring integrity and non-repudiation of transactions. By integrating ILP's cryptographic capabilities, Mojaloop supports precise and tamper-proof agreements between participants, enabling secure end-to-end transfer execution while maintaining compatibility with global payment ecosystems. + +## 3.6 ISO 20022 Supplementary Data Fields + +It is not expected that ISO 20022 supplementary data fields will be required for any of the messages used. If supplementary data is provided, the switch will not reject the message; however, it will ignore its contents and behave as if the supplementary data was not present. + +
+ +# 4. Discovery Phase +The Discovery Phase is an optional step in the transfer process, necessary only when the payee (end party) must be identified and confirmed before initiating an agreement. This phase utilizes the parties resource, which facilitates the retrieval and validation of the payee’s information to ensure they are eligible to receive the transfer. Key checks performed during this phase include verifying that the payee's account is active, identifying the currencies that can be transferred into the account, and confirming the account owner’s details. This information allows the payer to verify the payee's details accurately, reducing the risk of errors and ensuring a secure foundation for the subsequent phases of the transfer process. + +## 4.1 Message flow + +The sequence diagram shows the discovery example messages in a Payer initiated P2P transfer. +![Discovery Flow](./SequenceDiagrams/Discovery.svg) + +## 4.2 Parties Resource +The Parties resource provides all the necessary functionality in the discovery phase of a transfer. The functionality is always initiated with a GET /parties call, and responses to this are returned to the originator through a PUT /parties callback. Error messages are returned through the PUT /parties/.../error callback. These endpoints support an optional sub id type. + + +| Endpoint | Message | +|--- | --- | +|[GET /parties/{type}/{partyIdentifier}[/{subId}]](./script/parties_GET.md) | | +|[PUT /parties/{type}/{partyIdentifier}[/{subId}]](./script/parties_PUT.md) | acmt.024.001.04 | +|[PUT /parties/{type}/{partyIdentifier}[/{subId}]/error](./script/parties_error_PUT.md) | acmt.024.001.04 | + +
+ +# 5. Agreement Phase +The **Agreement Phase** is a critical step in the Mojaloop transfer process, ensuring that all parties involved have a shared understanding of the transfer terms before any funds are committed. This phase serves several essential purposes: +1. **Calculation and Agreement of Fees**
+The Agreement Phase provides an opportunity for the calculation and mutual agreement on any applicable fees. This ensures transparency and prevents disputes related to charges after the transfer is initiated. +1. **Pre-Commitment Validation**
+It allows each participating organization to verify whether the transfer can proceed. This step helps identify and address potential issues early, reducing errors during the transfer and minimizing reconciliation discrepancies. +1. **Cryptographic Signing of Terms**
+The terms of the transfer are cryptographically signed during this phase. This mechanism ensures non-repudiation, meaning that parties cannot deny their involvement in or agreement to the transaction. The Interledger Protocol is used to perform this cryptographic signing. Details on how to produce an ILP packet are defined here: [Mojaloop FSPIOP API Documentation](https://docs.mojaloop.io/technical/api/fspiop/). +1. **Promoting Financial Inclusion**
+By presenting all parties with the complete terms of the transfer upfront, the Agreement Phase ensures that participants are fully informed before making any commitments. This transparency supports financial inclusively by enabling fair and informed decision-making for all stakeholders. + +The Agreement Phase not only improves the reliability and efficiency of Mojaloop transfers but also aligns with its broader goal of fostering trust and inclusively in digital financial ecosystems. + +The agreement phase is further divided into two phases. + +## 5.1 Currency Conversion Agreement Sub-Phase +The Currency Conversion Agreement Sub-Phase is an optional step within the Agreement Phase, activated only when the transfer involves a currency conversion. During this sub-phase, the payer DFSP (Digital Financial Services Provider) coordinates with a foreign exchange (FX) provider to secure cross-currency liquidity required to complete the transaction. This step establishes the FX rates and associated fees, ensuring that both the DFSP and the FXP can rely on transparent and agreed-upon conversion terms. By addressing currency conversion needs before committing to the transfer, this sub-phase helps prevent delays and discrepancies, supporting a seamless cross-border transaction experience. + +### 5.1.1 Message flow + + +The sequence diagram shows the discovery example messages in a Payer initiated P2P transfer. +![Agreement Conversion Flow](./SequenceDiagrams/AgreementConversion.svg) + +### 5.1.2 fxQuotes Resource + +| Endpoint | Message | +|--- | --- | +|[POST /fxQuotes/{ID}](./script/fxquotes_POST.md) | **pacs.091.001** | +|[PUT /fxQuotes/{ID}](./script/fxquotes_PUT.md) | **pacs.092.001** | +|[PUT /fxQuotes/{ID}/error](./script/fxquotes_error_PUT.md) | **pacs.002.001.15** | + +## 5.2 Transfer Terms Agreement Sub-Phase +The End-to-End Terms Agreement Sub-Phase involves the collaborative establishment of the transfer terms between the payer DFSP and the payee DFSP. This process ensures both parties are aligned on critical details such as the amount to be transferred, fees, and timing requirements. This sub-phase also facilitates the cryptographic signing of these terms, providing a robust framework for non-repudiation and accountability. By finalizing the transfer terms in a transparent manner, this sub-phase minimizes the risk of errors or disputes, enhancing the efficiency and trustworthiness of the overall Mojaloop transfer process. + +### 5.2.1 Message flow + +The sequence diagram shows the discovery example messages in a Payer initiated P2P transfer. +![Agreement Flow](./SequenceDiagrams/Agreement.svg) + +### 5.2.2 Quotes Resource + +| Endpoint | Message | +| ------------- | --- | +|[POST /quotes/{ID}](./script/quotes_POST.md) | **pacs.081.001** | +|[PUT /quotes/{ID}](./script/quotes_PUT.md) | **pacs.082.001** | +|[PUT /quotes/{ID}/error](./script/quotes_error_PUT.md) | **pacs.002.001.15** | + +
+ +# 6. Transfer Phase +Once the agreements have been successfully established during the Agreement Phase, accepting these terms triggers the Transfer Phase, where the actual movement of funds occurs. This phase is executed with precision to ensure that the agreed terms are honored, and all participants fulfill their commitments. The Transfer Phase is divided into two sub-phases: the Currency Conversion Execution Sub-Phase and the Transfer Clearing Sub-Phase, each corresponding to its respective sub-phase in the Agreement Phase. + +## 6.1 Accepting Currency Conversion terms +The Currency Conversion Execution Sub-Phase occurs if the transfer involves a currency exchange. In this step, the foreign exchange provider, as agreed during the Agreement Phase, executes the currency conversion. The liquidity required for the cross-currency transfer is provided, and the converted funds are prepared for onward movement to the payee DFSP. This sub-phase is an opportunity for the FXP to ensure that the FX rates and fees agreed upon earlier are adhered to, safeguarding the transaction's financial integrity and transparency. + +### 6.1.1 Message flow + + +The sequence diagram shows the transfer example messages in a Payer initiated P2P transfer. +![Conversion Transfer Flow](./SequenceDiagrams/ConversionTransfer.svg) + +### 6.1.2 fxTransfers Resource + +| Endpoint | Message | +| -------- | --- | +|[POST /fxTransfers/{ID}](./script/fxtransfers_POST.md) | **pacs.009.001** | +|[PUT /fxTransfers/{ID}](./script/fxtransfers_PUT.md) | **pacs.002.001.15** | +|[PUT /fxTransfers/{ID}/error](./script/fxtransfers_error_PUT.md) | **pacs.002.001.15** | +|[PATCH /fxTransfers/{ID}/error](./script/fxtransfers_PATCH.md) | **pacs.002.001.15** | + +## 6.2 Transfer Execution and Clearing +The Funds Settlement Sub-Phase involves the actual transfer of funds between the payer DFSP and the payee DFSP. This step ensures that the amount agreed upon, including any associated fees, is accurately cleared in the appropriate accounts. This sub-phase completes the financial transaction, fulfilling the commitments made during the Agreement Phase. Through secure and efficient fund movement mechanisms, this sub-phase ensures that the transfer is completed smoothly and in compliance with the agreed terms. + +### 6.2.1 Message flow + + +The sequence diagram shows the discovery example messages in a Payer initiated P2P transfer. +![Transfer Flow](./SequenceDiagrams/Transfer.svg) + +### 6.2.2 Transfers Resource + +| Endpoint | Message | +| --------- | --- | +|[POST /transfers/{ID}](./script/transfers_POST.md) | **pacs.008.001** | +|[PUT /transfers/{ID}](./script/quotes_PUT.md) | **pacs.002.001.15** | +|[PUT /transfers/{ID}/error](./script/quotes_error_PUT.md) | **pacs.002.001.15** | +|[PATCH /transfers/{ID}/error](./script/transfers_PATCH.md) | **pacs.002.001.15** | + + + + diff --git a/docs/product/features/Iso20022/SequenceDiagrams/Agreement.plantuml b/docs/product/features/Iso20022/SequenceDiagrams/Agreement.plantuml new file mode 100644 index 000000000..175ce5d06 --- /dev/null +++ b/docs/product/features/Iso20022/SequenceDiagrams/Agreement.plantuml @@ -0,0 +1,96 @@ +@startuml + +Title Discovery ISO 20022 Message Flow +participant PayerDFSP as "Payer DFSP" +participant Mojaloop as "Mojaloop" +participant PayeeDFSP as "Payee DFSP" + +autonumber + +PayerDFSP -> Mojaloop: POST /quotes +note left +**pacs.081.001.01** +**Financial Institution to Financial Institution** +**Customer Credit Transfer Quote Request** +{ +"GrpHdr": { + "MsgId": "01JBVM19DJQ96BS9X6VA5AMW2Y", + "CreDtTm": "2024-11-04T12:57:42.066Z", + "NbOfTxs": "1", + "PmtInstrXpryDtTm": "2024-11-04T12:58:42.063Z", + "SttlmInf": { "SttlmMtd": "CLRG" } + }, +"CdtTrfTxInf": { + "PmtId": { + "TxId": "01JBVM19DFKNRWC21FGJNTHRAT", + "EndToEndId": "01JBVM13SQYP507JB1DYBZVCMF"}, + "Cdtr": { "Id": { "PrvtId": { "Othr": { "SchmeNm": { "Prtry": "MSISDN" }, + "Id": "16665551002" }}}}, + "CdtrAgt": { "FinInstnId": { "Othr": { "Id": "test-mwk-dfsp" }}}, + "Dbtr": { "Id": { "PrvtId": { "Othr": { "SchmeNm": { "Prtry": "MSISDN" }, + "Id": "16135551001" }}}, + "Name": "Joe Blogs"}, + "DbtrAgt": { "FinInstnId": { "Othr": { "Id": "payer-dfsp" }}}, + "IntrBkSttlmAmt": { + "Ccy": "MWK", + "ActiveCurrencyAndAmount": "1080"}, + "Purp": { "Prtry": "TRANSFER"}, + "ChrgBr": "CRED"} +} +end note +Mojaloop -> PayeeDFSP: POST /quotes +PayeeDFSP -> PayeeDFSP: Check to see if Payee can receive the payment. +alt if Payee can receive the payment +PayeeDFSP -> Mojaloop: PUT /quotes/{ID} +note right +**pacs.082.001.01** +**Financial Institution to Financial Institution** +**Customer Credit Transfer Quote Response** +"GrpHdr": { + "MsgId": "01JBVM19SPQAQV9EEP0QC1RNAD", + "CreDtTm": "2024-11-04T12:57:42.455Z", + "NbOfTxs": "1", + "SttlmInf": { "SttlmMtd": "CLRG" }, + "PmtInstrXpryDtTm": "2024-11-04T12:58:42.450Z" +}, +"CdtTrfTxInf": { "PmtId": { "TxId": "01JBVM19DFKNRWC21FGJNTHRAT" }, + "Dbtr": { "Id": { "PrvtId": { "Othr": { "SchmeNm": { "Prtry": "MSISDN" }, + "Id": "16135551001"} } }, + "Name": "Payer Joe" }, + "DbtrAgt": { "FinInstnId": { "Othr": { "Id": "payer-dfsp"} } }, + "Cdtr": { "Id": { "PrvtId": { "Othr": { "SchmeNm": { "Prtry": "MSISDN" }, + "Id": "16665551002"} } }, + "CdtrAgt": { "FinInstnId": { "Othr": { "Id": "payee-dfsp"} } }, + "ChrgBr": "CRED", + "IntrBkSttlmAmt": { + "Ccy": "MWK", + "ActiveCurrencyAndAmount": "1080" }, + "InstdAmt": { + "Ccy": "MWK", + "ActiveOrHistoricCurrencyAndAmount": "1080" }, + "ChrgsInf": { + "Amt": { "Ccy": "MWK", + "ActiveOrHistoricCurrencyAndAmount": "0" }, + "Agt": { "FinInstnId": { "Othr": { "Id": "payee-dfsp"} } } }, + "VrfctnOfTerms": { "IlpV4PrepPacket": "DIICzQAAAA..." } } +} +end note +Mojaloop -> PayerDFSP: PUT/quotes/{ID} + +else + +PayeeDFSP -> Mojaloop: PUT/quotes/{ID}/error +note right +**pacs.002.001.15** +**Financial Institution to Financial Institution** +**Payment Status Report** +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{"StsRsnInf":{"Rsn": {"Prtry":"ErrorCode"}}} +end note +Mojaloop -> PayerDFSP: PUT/quotes/{ID}/error + +end + +@enduml \ No newline at end of file diff --git a/docs/product/features/Iso20022/SequenceDiagrams/Agreement.svg b/docs/product/features/Iso20022/SequenceDiagrams/Agreement.svg new file mode 100644 index 000000000..bce7b2a4e --- /dev/null +++ b/docs/product/features/Iso20022/SequenceDiagrams/Agreement.svg @@ -0,0 +1 @@ +Discovery ISO 20022 Message FlowPayer DFSPPayer DFSPMojaloopMojaloopPayee DFSPPayee DFSP1POST /quotespacs.081.001.01Financial Institution to Financial Institution Customer Credit Transfer Quote Request{"GrpHdr": {"MsgId": "01JBVM19DJQ96BS9X6VA5AMW2Y","CreDtTm": "2024-11-04T12:57:42.066Z","NbOfTxs": "1","PmtInstrXpryDtTm": "2024-11-04T12:58:42.063Z","SttlmInf": { "SttlmMtd": "CLRG" }},"CdtTrfTxInf": {"PmtId": {"TxId": "01JBVM19DFKNRWC21FGJNTHRAT","EndToEndId": "01JBVM13SQYP507JB1DYBZVCMF"},"Cdtr": { "Id": { "PrvtId": { "Othr": { "SchmeNm": { "Prtry": "MSISDN" },"Id": "16665551002" }}}},"CdtrAgt": { "FinInstnId": { "Othr": { "Id": "test-mwk-dfsp" }}},"Dbtr": { "Id": { "PrvtId": { "Othr": { "SchmeNm": { "Prtry": "MSISDN" },"Id": "16135551001" }}},"Name": "Joe Blogs"},"DbtrAgt": { "FinInstnId": { "Othr": { "Id": "payer-dfsp" }}},"IntrBkSttlmAmt": {"Ccy": "MWK","ActiveCurrencyAndAmount": "1080"},"Purp": { "Prtry": "TRANSFER"},"ChrgBr": "CRED"}}2POST /quotes3Check to see if Payee can receive the payment.alt[if Payee can receive the payment]4PUT /quotes/{ID}pacs.082.001.01Financial Institution to Financial Institution Customer Credit Transfer Quote Response"GrpHdr": {"MsgId": "01JBVM19SPQAQV9EEP0QC1RNAD","CreDtTm": "2024-11-04T12:57:42.455Z","NbOfTxs": "1","SttlmInf": { "SttlmMtd": "CLRG" },"PmtInstrXpryDtTm": "2024-11-04T12:58:42.450Z"},"CdtTrfTxInf": { "PmtId": { "TxId": "01JBVM19DFKNRWC21FGJNTHRAT" },"Dbtr": { "Id": { "PrvtId": { "Othr": { "SchmeNm": { "Prtry": "MSISDN" },"Id": "16135551001"} } },"Name": "Payer Joe" },"DbtrAgt": { "FinInstnId": { "Othr": { "Id": "payer-dfsp"} } },"Cdtr": { "Id": { "PrvtId": { "Othr": { "SchmeNm": { "Prtry": "MSISDN" },"Id": "16665551002"} } },"CdtrAgt": { "FinInstnId": { "Othr": { "Id": "payee-dfsp"} } },"ChrgBr": "CRED","IntrBkSttlmAmt": {"Ccy": "MWK","ActiveCurrencyAndAmount": "1080" },"InstdAmt": {"Ccy": "MWK","ActiveOrHistoricCurrencyAndAmount": "1080" },"ChrgsInf": {"Amt": { "Ccy": "MWK","ActiveOrHistoricCurrencyAndAmount": "0" },"Agt": { "FinInstnId": { "Othr": { "Id": "payee-dfsp"} } } },"VrfctnOfTerms": { "IlpV4PrepPacket": "DIICzQAAAA..." } }}5PUT/quotes/{ID}6PUT/quotes/{ID}/errorpacs.002.001.15Financial Institution to Financial Institution Payment Status Report"GrpHdr": {"MsgId":"01JBVM1CGC5A18XQVYYRF68FD1","CreDtTm":"2024-11-04T12:57:45.228Z"},"TxInfAndSts":{"StsRsnInf":{"Rsn": {"Prtry":"ErrorCode"}}}7PUT/quotes/{ID}/error \ No newline at end of file diff --git a/docs/product/features/Iso20022/SequenceDiagrams/AgreementConversion.plantuml b/docs/product/features/Iso20022/SequenceDiagrams/AgreementConversion.plantuml new file mode 100644 index 000000000..f41bee1ce --- /dev/null +++ b/docs/product/features/Iso20022/SequenceDiagrams/AgreementConversion.plantuml @@ -0,0 +1,92 @@ +@startuml + +Title Agreement phase on providing liquidity ISO 20022 Message Flow +participant PayerDFSP as "Payer DFSP" +participant Mojaloop as "Mojaloop" +participant FXP as "Foreign Exchange Provider" + +autonumber + +PayerDFSP -> Mojaloop: POST /fxQuotes +note left +**pacs.091.001.01** +**Financial Institution Credit Transfer Quote Request** +"GrpHdr": { + "MsgId": "01JBVM16V3Q4MSV8KTG0BRJGZ2", + "CreDtTm": "2024-11-04T12:57:39.427Z", + "NbOfTxs": "1", + "SttlmInf": { "SttlmMtd": "CLRG" }, + "PmtInstrXpryDtTm": "2024-11-04T12:58:39.425Z" +}, +"CdtTrfTxInf": { + "PmtId": { + "TxId": "01JBVM16V1ZXP2DM34BQT40NW9", + "InstrId": "01JBVM16V1ZXP2DM34BQT40NWA", + "EndToEndId": "01JBVM13SQYP507JB1DYBZVCMF" }, + "Dbtr": { "FinInstnId": { "Othr": { "Id": **"payer-dfsp"** } } }, + "UndrlygCstmrCdtTrf": { + "Dbtr": {"Id": {"OrgId": {"Othr": {"Id": "payer-dfsp"}}}}, + "DbtrAgt": {"FinInstnId": {"Othr": {"Id": "payer-dfsp"}}}, + "Cdtr": {"Id": {"OrgId": {"Othr": {"Id": "fxp"}}}}, + "CdtrAgt": {"FinInstnId": {"Othr": {"Id": "fxp"}}}, + "InstdAmt": {"Ccy": **"ZMW"**, + "ActiveOrHistoricCurrencyAndAmount": **"21"**}}, + "Cdtr": {"FinInstnId": {"Othr": {"Id": **"fxp"**}}}, + "IntrBkSttlmAmt": { "Ccy": **"MWK"**, + "ActiveCurrencyAndAmount": "0"}, + "InstrForCdtrAgt": {"InstrInf": **"SEND"**}} +} +end note +Mojaloop -> FXP: POST /fxQuotes +FXP -> FXP: Check to see if liqidity can be provided \n and provide rates. +alt if FXP can provide the payment liquidity +FXP -> Mojaloop: PUT /fxQuotes/{ID} +note right +**pacs.092.001.01** +**Financial Institution Credit Transfer Quote Response** +{ +"GrpHdr": { + "MsgId": "01JBVM176FTHB9F2ZQJJ7AFCN8", + "CreDtTm": "2024-11-04T12:57:39.791Z", + "NbOfTxs": "1", + "SttlmInf": { "SttlmMtd": "CLRG" }, + "PmtInstrXpryDtTm": "2024-11-04T12:58:39.425Z"}, +"CdtTrfTxInf": { + "VrfctnOfTerms": {"Sh256Sgntr": **"KVHFmdTD6A..."**}, + "PmtId": {"InstrId": "01JBVM16V1ZXP2DM34BQT40NWA", + "TxId": "01JBVM13SQYP507JB1DYBZVCMF"}, + "Dbtr": {"FinInstnId": {"Othr": {"Id": **"payer-dfsp"**}}}, + "UndrlygCstmrCdtTrf": { + "Dbtr": {"Id": {"OrgId": {"Othr": {"Id": "payer-dfsp"}}}}, + "DbtrAgt": {"FinInstnId": {"Othr": {"Id": "payer-dfsp"}}}, + "Cdtr": {"Id": {"OrgId": {"Othr": {"Id": "fxp"}}}}, + "CdtrAgt": {"FinInstnId": {"Othr": {"Id": "fxp"}}}, + "InstdAmt": { "Ccy": **"ZMW"**, + "ActiveOrHistoricCurrencyAndAmount": **"21"**}}, + "Cdtr": {"FinInstnId": {"Othr": {"Id": **"fxp"**}}}, + "IntrBkSttlmAmt": {"Ccy": **"MWK"**, + "ActiveCurrencyAndAmount": **"1080"**}, + "InstrForCdtrAgt": {"InstrInf": **"SEND"**}} +} +end note +Mojaloop -> PayerDFSP: PUT /fxQuotes/{ID} + +else + +FXP -> Mojaloop: PUT /fxQuotes/{ID}/error +note right +**pacs.002.001.15** +**Financial Institution to Financial Institution** +**Payment Status Report** +{ +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{"StsRsnInf":{"Rsn": {"Prtry":"ErrorCode"}}} +} +end note +Mojaloop -> PayerDFSP: PUT /fxQuotes/{ID}/error +end + + +@enduml \ No newline at end of file diff --git a/docs/product/features/Iso20022/SequenceDiagrams/AgreementConversion.svg b/docs/product/features/Iso20022/SequenceDiagrams/AgreementConversion.svg new file mode 100644 index 000000000..13041e821 --- /dev/null +++ b/docs/product/features/Iso20022/SequenceDiagrams/AgreementConversion.svg @@ -0,0 +1 @@ +Agreement phase on providing liquidity ISO 20022 Message FlowPayer DFSPPayer DFSPMojaloopMojaloopForeign Exchange ProviderForeign Exchange Provider1POST /fxQuotespacs.091.001.01Financial Institution Credit Transfer Quote Request"GrpHdr": {"MsgId": "01JBVM16V3Q4MSV8KTG0BRJGZ2","CreDtTm": "2024-11-04T12:57:39.427Z","NbOfTxs": "1","SttlmInf": { "SttlmMtd": "CLRG" },"PmtInstrXpryDtTm": "2024-11-04T12:58:39.425Z"},"CdtTrfTxInf": {"PmtId": {"TxId": "01JBVM16V1ZXP2DM34BQT40NW9","InstrId": "01JBVM16V1ZXP2DM34BQT40NWA","EndToEndId": "01JBVM13SQYP507JB1DYBZVCMF" },"Dbtr": { "FinInstnId": { "Othr": { "Id":"payer-dfsp"} } },"UndrlygCstmrCdtTrf": {"Dbtr": {"Id": {"OrgId": {"Othr": {"Id": "payer-dfsp"}}}},"DbtrAgt": {"FinInstnId": {"Othr": {"Id": "payer-dfsp"}}},"Cdtr": {"Id": {"OrgId": {"Othr": {"Id": "fxp"}}}},"CdtrAgt": {"FinInstnId": {"Othr": {"Id": "fxp"}}},"InstdAmt": {"Ccy":"ZMW","ActiveOrHistoricCurrencyAndAmount":"21"}},"Cdtr": {"FinInstnId": {"Othr": {"Id":"fxp"}}},"IntrBkSttlmAmt": { "Ccy":"MWK","ActiveCurrencyAndAmount": "0"},"InstrForCdtrAgt": {"InstrInf":"SEND"}}}2POST /fxQuotes3Check to see if liqidity can be providedand provide rates.alt[if FXP can provide the payment liquidity]4PUT /fxQuotes/{ID}pacs.092.001.01Financial Institution Credit Transfer Quote Response{"GrpHdr": {"MsgId": "01JBVM176FTHB9F2ZQJJ7AFCN8","CreDtTm": "2024-11-04T12:57:39.791Z","NbOfTxs": "1","SttlmInf": { "SttlmMtd": "CLRG" },"PmtInstrXpryDtTm": "2024-11-04T12:58:39.425Z"},"CdtTrfTxInf": {"VrfctnOfTerms": {"Sh256Sgntr":"KVHFmdTD6A..."},"PmtId": {"InstrId": "01JBVM16V1ZXP2DM34BQT40NWA","TxId": "01JBVM13SQYP507JB1DYBZVCMF"},"Dbtr": {"FinInstnId": {"Othr": {"Id":"payer-dfsp"}}},"UndrlygCstmrCdtTrf": {"Dbtr": {"Id": {"OrgId": {"Othr": {"Id": "payer-dfsp"}}}},"DbtrAgt": {"FinInstnId": {"Othr": {"Id": "payer-dfsp"}}},"Cdtr": {"Id": {"OrgId": {"Othr": {"Id": "fxp"}}}},"CdtrAgt": {"FinInstnId": {"Othr": {"Id": "fxp"}}},"InstdAmt": { "Ccy":"ZMW","ActiveOrHistoricCurrencyAndAmount":"21"}},"Cdtr": {"FinInstnId": {"Othr": {"Id":"fxp"}}},"IntrBkSttlmAmt": {"Ccy":"MWK","ActiveCurrencyAndAmount":"1080"},"InstrForCdtrAgt": {"InstrInf":"SEND"}}}5PUT /fxQuotes/{ID}6PUT /fxQuotes/{ID}/errorpacs.002.001.15Financial Institution to Financial Institution Payment Status Report{"GrpHdr": {"MsgId":"01JBVM1CGC5A18XQVYYRF68FD1","CreDtTm":"2024-11-04T12:57:45.228Z"},"TxInfAndSts":{"StsRsnInf":{"Rsn": {"Prtry":"ErrorCode"}}}}7PUT /fxQuotes/{ID}/error \ No newline at end of file diff --git a/docs/product/features/Iso20022/SequenceDiagrams/ConversionTransfer.plantuml b/docs/product/features/Iso20022/SequenceDiagrams/ConversionTransfer.plantuml new file mode 100644 index 000000000..a617ecf3f --- /dev/null +++ b/docs/product/features/Iso20022/SequenceDiagrams/ConversionTransfer.plantuml @@ -0,0 +1,88 @@ +@startuml + +Title Committing to providing Liquidity ISO 20022 Message Flow +participant PayerDFSP as "Payer DFSP" +participant Mojaloop as "Mojaloop" +participant FXP as "Foreign Exchange Provider" + +autonumber + +PayerDFSP -> Mojaloop: POST /fxTransfers +note left +**pacs.009.001.12** +**Execute Financial Institution Credit Transfer** +{ +"GrpHdr":{ + "MsgId":"01JBVM1BW4J0RJZSQ539QB9TKT", + "CreDtTm":"2024-11-04T12:57:44.580Z", + "NbOfTxs":"1", + "SttlmInf":{"SttlmMtd":"CLRG"}, + "PmtInstrXpryDtTm":"2024-11-04T12:58:44.579Z"}, +"CdtTrfTxInf":{ + "PmtId":{"TxId":"01JBVM16V1ZXP2DM34BQT40NWA", + "EndToEndId":"01JBVM13SQYP507JB1DYBZVCMF"}, + "Dbtr":{"FinInstnId":{"Othr":{"Id":"payer-dfsp"}}}, + "UndrlygCstmrCdtTrf":{ + "Dbtr":{"Id":{"OrgId":{"Othr":{"Id":"payer-dfsp"}}}}, + "DbtrAgt":{"FinInstnId":{"Othr":{"Id":"payer-dfsp"}}}, + "Cdtr":{"Id":{"OrgId":{"Othr":{"Id":"fxp"}}}}, + "CdtrAgt":{"FinInstnId":{"Othr":{"Id":"fxp"}}}, + "InstdAmt":{"Ccy":"ZMW", + "ActiveOrHistoricCurrencyAndAmount":"21"}}, + "Cdtr":{"FinInstnId":{"Othr":{"Id":"fxp"}}}, + "IntrBkSttlmAmt":{"Ccy":"MWK", + "ActiveCurrencyAndAmount":"1080"}, + "VrfctnOfTerms":{"Sh256Sgntr":"KVHFmdTD6A..."}} +} +end note +Mojaloop -> FXP: POST /fxTransfers +FXP -> FXP: Check to see liquidity for the transfer can still be provided. +alt if FXP can provide the payment liquidity +FXP -> Mojaloop: PUT /fxTransfers/{ID} +note right +**pacs.002.001.15** +**Financial Institution to Financial Institution** +**Payment Status Report** +{ +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{ + "ExctnConf":"ou1887jmG-l...", + "PrcgDt":{"DtTm":"2024-11-04T12:57:45.213Z"}, + "TxSts":"RESV"} +} +end note +Mojaloop -> PayerDFSP: PUT /fxTransfers/{ID} + +else + +FXP -> Mojaloop: PUT /fxTransfers/{ID}/error +note right +**pacs.002.001.15** +**Financial Institution to Financial Institution** +**Payment Status Report** +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{"StsRsnInf":{"Rsn": {"Prtry":"ErrorCode"}} +end note +Mojaloop -> PayerDFSP: PUT /fxTransfer/{ID}/error +end + +Mojaloop -> Mojaloop: When the determining transfer is committed, \n the FX conversion is committed. + +Mojaloop->FXP: PATCH /fxTransfers/{ID} +note left +**pacs.002.001.15** +**Financial Institution to Financial Institution** +**Payment Status Report** +"GrpHdr":{ + "MsgId":"01JBVM1E2CRWFZFPN7W4AZJ976", + "CreDtTm":"2024-11-04T12:57:46.828Z"}, +"TxInfAndSts":{"PrcgDt":{ + "DtTm":"2024-11-04T12:57:46.812Z"}, + "TxSts":"COMM"}}" +end note + +@enduml \ No newline at end of file diff --git a/docs/product/features/Iso20022/SequenceDiagrams/ConversionTransfer.svg b/docs/product/features/Iso20022/SequenceDiagrams/ConversionTransfer.svg new file mode 100644 index 000000000..5d8929a8c --- /dev/null +++ b/docs/product/features/Iso20022/SequenceDiagrams/ConversionTransfer.svg @@ -0,0 +1 @@ +Committing to providing Liquidity ISO 20022 Message FlowPayer DFSPPayer DFSPMojaloopMojaloopForeign Exchange ProviderForeign Exchange Provider1POST /fxTransferspacs.009.001.12Execute Financial Institution Credit Transfer{"GrpHdr":{"MsgId":"01JBVM1BW4J0RJZSQ539QB9TKT","CreDtTm":"2024-11-04T12:57:44.580Z","NbOfTxs":"1","SttlmInf":{"SttlmMtd":"CLRG"},"PmtInstrXpryDtTm":"2024-11-04T12:58:44.579Z"},"CdtTrfTxInf":{"PmtId":{"TxId":"01JBVM16V1ZXP2DM34BQT40NWA","EndToEndId":"01JBVM13SQYP507JB1DYBZVCMF"},"Dbtr":{"FinInstnId":{"Othr":{"Id":"payer-dfsp"}}},"UndrlygCstmrCdtTrf":{"Dbtr":{"Id":{"OrgId":{"Othr":{"Id":"payer-dfsp"}}}},"DbtrAgt":{"FinInstnId":{"Othr":{"Id":"payer-dfsp"}}},"Cdtr":{"Id":{"OrgId":{"Othr":{"Id":"fxp"}}}},"CdtrAgt":{"FinInstnId":{"Othr":{"Id":"fxp"}}},"InstdAmt":{"Ccy":"ZMW","ActiveOrHistoricCurrencyAndAmount":"21"}},"Cdtr":{"FinInstnId":{"Othr":{"Id":"fxp"}}},"IntrBkSttlmAmt":{"Ccy":"MWK","ActiveCurrencyAndAmount":"1080"},"VrfctnOfTerms":{"Sh256Sgntr":"KVHFmdTD6A..."}}}2POST /fxTransfers3Check to see liquidity for the transfer can still be provided.alt[if FXP can provide the payment liquidity]4PUT /fxTransfers/{ID}pacs.002.001.15Financial Institution to Financial Institution Payment Status Report{"GrpHdr": {"MsgId":"01JBVM1CGC5A18XQVYYRF68FD1","CreDtTm":"2024-11-04T12:57:45.228Z"},"TxInfAndSts":{"ExctnConf":"ou1887jmG-l...","PrcgDt":{"DtTm":"2024-11-04T12:57:45.213Z"},"TxSts":"RESV"}}5PUT /fxTransfers/{ID}6PUT /fxTransfers/{ID}/errorpacs.002.001.15Financial Institution to Financial Institution Payment Status Report"GrpHdr": {"MsgId":"01JBVM1CGC5A18XQVYYRF68FD1","CreDtTm":"2024-11-04T12:57:45.228Z"},"TxInfAndSts":{"StsRsnInf":{"Rsn": {"Prtry":"ErrorCode"}}7PUT /fxTransfer/{ID}/error8When the determining transfer is committed,the FX conversion is committed.9PATCH /fxTransfers/{ID}pacs.002.001.15Financial Institution to Financial InstitutionPayment Status Report"GrpHdr":{"MsgId":"01JBVM1E2CRWFZFPN7W4AZJ976","CreDtTm":"2024-11-04T12:57:46.828Z"},"TxInfAndSts":{"PrcgDt":{"DtTm":"2024-11-04T12:57:46.812Z"},"TxSts":"COMM"}}" \ No newline at end of file diff --git a/docs/product/features/Iso20022/SequenceDiagrams/Discovery.plantuml b/docs/product/features/Iso20022/SequenceDiagrams/Discovery.plantuml new file mode 100644 index 000000000..e74db7ddd --- /dev/null +++ b/docs/product/features/Iso20022/SequenceDiagrams/Discovery.plantuml @@ -0,0 +1,59 @@ +@startuml + +Title Discovery ISO 20022 Message Flow +participant PayerDFSP as "Payer DFSP" +participant Mojaloop as "Mojaloop" +participant PayeeDFSP as "Payee DFSP" + +autonumber + +PayerDFSP -> Mojaloop: GET /parties/{type}/{PartyIdentifier} +Mojaloop -> PayeeDFSP: GET /parties/{type}/{PartyIdentifier} +PayeeDFSP -> PayeeDFSP: Validate payees account status. +alt if account active +PayeeDFSP -> Mojaloop: PUT /parties/{type}/{PartyIdentifier} \n Returns supported currencies and account owner details. +note right +**acmt.024.001.04** +**Account Identification Verification Report** +{ +"Assgnmt": { + "MsgId": "01JBVM14S6SC453EY9XB9GXQB5", + "CreDtTm": "2024-11-04T12:57:37.318Z", + "Assgnr": { "Agt": { "FinInstnId": { "Othr": { "Id": **"payee-dfps"** }}}}, + "Assgne": { "Agt": { "FinInstnId": { "Othr": { "Id": **"payer-dfsp"** }}}}} +"Rpt": { + "Vrfctn": true, + "OrgnlId": **"MSISDN/16665551002"**, + "UpdtdPtyAndAcctId": {"Pty": {"Id": {"PrvtId": {"Othr": {"SchmeNm": {"Prtry": **"MSISDN"**}, + "Id": **"16665551002"**}}}, + "Nm": **"Chikondi Banda"**}, + "Agt": { "FinInstnId": { "Othr": { "Id": **"payee-dfsp"** }}}, + "Acct": { "Ccy": **"MWK"** }} +} +end note +Mojaloop -> PayerDFSP: PUT /parties/{type}/{PartyIdentifier} + +else if account inactive + +PayeeDFSP -> Mojaloop: PUT /parties/{type}/{PartyIdentifier}/error \n Returns error code 3204 Party not found. +note right +**acmt.024.001.04** +**Account Identification Verification Report** +{ + "Assgnmt": { + "Id": 123, + "CreDtTm": "2013-03-07T16:30:00", + "Assgnr": { "Agt": { "FinInstnId": { "Othr": { "Id": **"payee-dfsp"** }}}}, + "Assgne": { "Agt": { "FinInstnId": { "Othr": { "Id": **"payer-dfsp"** }}}}}, + "Rpt": { + "Vrfctn": false, + "OrgnlId": **"MSISDN/16665551002"**, + "CreDtTm": "2013-03-07T16:30:00", + "Rsn": { "Prtry": **3204** }} +} +end note +Mojaloop -> PayerDFSP: PUT /parties/{type}/{PartyIdentifier}/error + +end + +@enduml \ No newline at end of file diff --git a/docs/product/features/Iso20022/SequenceDiagrams/Discovery.svg b/docs/product/features/Iso20022/SequenceDiagrams/Discovery.svg new file mode 100644 index 000000000..a4d5d4587 --- /dev/null +++ b/docs/product/features/Iso20022/SequenceDiagrams/Discovery.svg @@ -0,0 +1 @@ +Discovery ISO 20022 Message FlowPayer DFSPPayer DFSPMojaloopMojaloopPayee DFSPPayee DFSP1GET /parties/{type}/{PartyIdentifier}2GET /parties/{type}/{PartyIdentifier}3Validate payees account status.alt[if account active]4PUT /parties/{type}/{PartyIdentifier}Returns supported currencies and account owner details.acmt.024.001.04Account Identification Verification Report{"Assgnmt": {"MsgId": "01JBVM14S6SC453EY9XB9GXQB5","CreDtTm": "2024-11-04T12:57:37.318Z","Assgnr": { "Agt": { "FinInstnId": { "Othr": { "Id":"payee-dfps"}}}},"Assgne": { "Agt": { "FinInstnId": { "Othr": { "Id":"payer-dfsp"}}}}}"Rpt": {"Vrfctn": true,"OrgnlId":"MSISDN/16665551002","UpdtdPtyAndAcctId": {"Pty": {"Id": {"PrvtId": {"Othr": {"SchmeNm": {"Prtry":"MSISDN"},"Id":"16665551002"}}},"Nm":"Chikondi Banda"},"Agt": { "FinInstnId": { "Othr": { "Id":"payee-dfsp"}}},"Acct": { "Ccy":"MWK"}}}5PUT /parties/{type}/{PartyIdentifier}[if account inactive]6PUT /parties/{type}/{PartyIdentifier}/errorReturns error code 3204 Party not found.acmt.024.001.04Account Identification Verification Report{"Assgnmt": {"Id": 123,"CreDtTm": "2013-03-07T16:30:00","Assgnr": { "Agt": { "FinInstnId": { "Othr": { "Id":"payee-dfsp"}}}},"Assgne": { "Agt": { "FinInstnId": { "Othr": { "Id":"payer-dfsp"}}}}},"Rpt": {"Vrfctn": false,"OrgnlId":"MSISDN/16665551002","CreDtTm": "2013-03-07T16:30:00","Rsn": { "Prtry":3204}}}7PUT /parties/{type}/{PartyIdentifier}/error \ No newline at end of file diff --git a/docs/product/features/Iso20022/SequenceDiagrams/Transfer.plantuml b/docs/product/features/Iso20022/SequenceDiagrams/Transfer.plantuml new file mode 100644 index 000000000..aafcc570b --- /dev/null +++ b/docs/product/features/Iso20022/SequenceDiagrams/Transfer.plantuml @@ -0,0 +1,88 @@ +@startuml + +Title Transfer - ISO 20022 Message Flow +participant PayerDFSP as "Payer DFSP" +participant Mojaloop as "Mojaloop" +participant PayeeDFSP as "Payee DFSP" + +autonumber + +PayerDFSP -> Mojaloop: POST /transfers +note left +**pacs.008.001.13** +**Financial Institution to Financial Institution** +**Customer Credit Transfer** +{ +"GrpHdr":{ + "MsgId":"01JBVM1D2MR6D4WBWWYY3ZHGMM", + "CreDtTm":"2024-11-04T12:57:45.812Z", + "NbOfTxs":"1", + "SttlmInf":{"SttlmMtd":"CLRG"}, + "PmtInstrXpryDtTm":"2024-11-04T12:58:45.810Z"}, +"CdtTrfTxInf":{ + "PmtId":{"TxId":"01JBVM13SQYP507JB1DYBZVCMF"}, + "ChrgBr":"CRED", + "Cdtr":{"Id":{"PrvtId":{"Othr":{"SchmeNm":{"Prtry":"MSISDN"}, + "Id":"16665551002"}}}}, + "Dbtr":{"Id":{"PrvtId":{"Othr":{"SchmeNm":{"Prtry":"MSISDN"}, + "Id":"16135551001"}}}, + "Name":"Joe Blogs"}, + "CdtrAgt":{"FinInstnId":{"Othr":{"Id":"payee-dfsp"}}}, + "DbtrAgt":{"FinInstnId":{"Othr":{"Id":"payer-dfsp"}}}, + "IntrBkSttlmAmt":{"Ccy":"MWK", + "ActiveCurrencyAndAmount":"1080"}, + "VrfctnOfTerms":{"IlpV4PrepPacket":"DIICzQAAAAAAAaX..."}} +} +end note +Mojaloop -> PayeeDFSP: POST /transfers +PayeeDFSP -> PayeeDFSP: Check to see if Payee can receive the payment. +alt if Payee can receive the payment +PayeeDFSP -> Mojaloop: PUT /transfers/{ID} +note right +**pacs.002.001.15** +**Financial Institution to Financial Institution** +**Payment Status Report** +{ +"GrpHdr":{ + "MsgId":"01JBVM1E2CRWFZFPN7W4AZJ976", + "CreDtTm":"2024-11-04T12:57:46.828Z"}, +"TxInfAndSts":{ + "ExctnConf":"-rL3liKeLrsNy7GHJaKgAzeDL_8IVnvER5zUlP1YAoc", + "PrcgDt":{"DtTm":"2024-11-04T12:57:46.812Z"}, + "TxSts":"COMM"} +} +end note +Mojaloop -> PayerDFSP: PUT/transfers/{ID} + +else + +Mojaloop -> PayerDFSP: PUT/transfers/{ID}/error +note right +**pacs.002.001.15** +**Financial Institution to Financial Institution** +**Payment Status Report** +{ +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{"StsRsnInf":{"Rsn": {"Prtry":"ErrorCode"}}} +} +end note +end + +Mojaloop->Mojaloop: If transfer fails, is timed-out,\n or is reserved PUT /transfers message. + +Mojaloop->PayeeDFSP: PATCH /transfers/{ID} +note left +**pacs.002.001.15** +**Financial Institution to Financial Institution** +**Payment Status Report** +{ +"GrpHdr":{ + "MsgId":"01JBVM1E2CRWFZFPN7W4AZJ976", + "CreDtTm":"2024-11-04T12:57:46.828Z"}, +"TxInfAndSts":{"PrcgDt":{"DtTm":"2024-11-04T12:57:46.812Z"}, + "TxSts":"COMM"}}" +} +end note +@enduml \ No newline at end of file diff --git a/docs/product/features/Iso20022/SequenceDiagrams/Transfer.svg b/docs/product/features/Iso20022/SequenceDiagrams/Transfer.svg new file mode 100644 index 000000000..1358e9c60 --- /dev/null +++ b/docs/product/features/Iso20022/SequenceDiagrams/Transfer.svg @@ -0,0 +1 @@ +Transfer - ISO 20022 Message FlowPayer DFSPPayer DFSPMojaloopMojaloopPayee DFSPPayee DFSP1POST /transferspacs.008.001.13Financial Institution to Financial Institution Customer Credit Transfer{"GrpHdr":{"MsgId":"01JBVM1D2MR6D4WBWWYY3ZHGMM","CreDtTm":"2024-11-04T12:57:45.812Z","NbOfTxs":"1","SttlmInf":{"SttlmMtd":"CLRG"},"PmtInstrXpryDtTm":"2024-11-04T12:58:45.810Z"},"CdtTrfTxInf":{"PmtId":{"TxId":"01JBVM13SQYP507JB1DYBZVCMF"},"ChrgBr":"CRED","Cdtr":{"Id":{"PrvtId":{"Othr":{"SchmeNm":{"Prtry":"MSISDN"},"Id":"16665551002"}}}},"Dbtr":{"Id":{"PrvtId":{"Othr":{"SchmeNm":{"Prtry":"MSISDN"},"Id":"16135551001"}}},"Name":"Joe Blogs"},"CdtrAgt":{"FinInstnId":{"Othr":{"Id":"payee-dfsp"}}},"DbtrAgt":{"FinInstnId":{"Othr":{"Id":"payer-dfsp"}}},"IntrBkSttlmAmt":{"Ccy":"MWK","ActiveCurrencyAndAmount":"1080"},"VrfctnOfTerms":{"IlpV4PrepPacket":"DIICzQAAAAAAAaX..."}}}2POST /transfers3Check to see if Payee can receive the payment.alt[if Payee can receive the payment]4PUT /transfers/{ID}pacs.002.001.15Financial Institution to Financial Institution Payment Status Report{"GrpHdr":{"MsgId":"01JBVM1E2CRWFZFPN7W4AZJ976","CreDtTm":"2024-11-04T12:57:46.828Z"},"TxInfAndSts":{"ExctnConf":"-rL3liKeLrsNy7GHJaKgAzeDL_8IVnvER5zUlP1YAoc","PrcgDt":{"DtTm":"2024-11-04T12:57:46.812Z"},"TxSts":"COMM"}}5PUT/transfers/{ID}6PUT/transfers/{ID}/errorpacs.002.001.15Financial Institution to Financial Institution Payment Status Report{"GrpHdr": {"MsgId":"01JBVM1CGC5A18XQVYYRF68FD1","CreDtTm":"2024-11-04T12:57:45.228Z"},"TxInfAndSts":{"StsRsnInf":{"Rsn": {"Prtry":"ErrorCode"}}}}7If transfer fails, is timed-out,or is reserved PUT /transfers message.8PATCH /transfers/{ID}pacs.002.001.15Financial Institution to Financial InstitutionPayment Status Report{"GrpHdr":{"MsgId":"01JBVM1E2CRWFZFPN7W4AZJ976","CreDtTm":"2024-11-04T12:57:46.828Z"},"TxInfAndSts":{"PrcgDt":{"DtTm":"2024-11-04T12:57:46.812Z"},"TxSts":"COMM"}}"} \ No newline at end of file diff --git a/docs/product/features/Iso20022/script/fxquotes_POST.md b/docs/product/features/Iso20022/script/fxquotes_POST.md new file mode 100644 index 000000000..678514b71 --- /dev/null +++ b/docs/product/features/Iso20022/script/fxquotes_POST.md @@ -0,0 +1,779 @@ +## 7.4 POST /fxQuotes/ +| Financial Institution Credit Transfer Quote Request - **pacs.091.001.01**| +|--| + +#### Context +*(DFSP -> FXP)* + +This message is initiated by a DFSP who is requesting liquidity cover in another currency to fund a transfer. The message is sent to a foreign exchange provider and is a request for conversion terms. The source currency is specified in `CdtTrfTxInf.UndrlygCstmrCdtTrf.InstdAmt.Ccy` and the target currency is specified in `CdtTrfTxInf.IntrBkSttlmAmt.Ccy`. + +#### Conversion Type `SEND` +If the `CdtTrfTxInf.InstrForCdtrAgt.InstrInf` is defined as `SEND`, then the source currency amount is expected to be defined `CdtTrfTxInf.UndrlygCstmrCdtTrf.InstdAmt.ActiveOrHistoricCurrencyAndAmount`, and the target currency amount will be calculated based on the source currency amount and fees. (The target amount `CdtTrfTxInf.IntrBkSttlmAmt.ActiveCurrencyAndAmount` should be specified as 0 and will not be used in the calculation.) + +#### Conversion Type `RECEIVE` +If the `CdtTrfTxInf.InstrForCdtrAgt.InstrInf` is defined as `RECEIVE`, then the target currency amount is expected to be defined `CdtTrfTxInf.IntrBkSttlmAmt.ActiveCurrencyAndAmount`, and the source currency amount will be calculated based on the target currency amount and fees. (The source amount `CdtTrfTxInf.UndrlygCstmrCdtTrf.InstdAmt.ActiveOrHistoricCurrencyAndAmount` should be specified as 0 and will not be used in the calculation.) + +In this phase of the transfer all participants to agree on the terms, and are expected to validate whether the transfer will be able to proceed. The Foreign Exchange provider is expected to respond to this request with a PUT /fxQuotes callback. + +Here is an example of the message: +```json +{ +"GrpHdr": { + "MsgId": "01JBVM16V3Q4MSV8KTG0BRJGZ2", + "CreDtTm": "2024-11-04T12:57:39.427Z", + "NbOfTxs": "1", + "SttlmInf": { "SttlmMtd": "CLRG" }, + "PmtInstrXpryDtTm": "2024-11-04T12:58:39.425Z" +}, +"CdtTrfTxInf": { + "PmtId": { + "TxId": "01JBVM16V1ZXP2DM34BQT40NW9", + "InstrId": "01JBVM16V1ZXP2DM34BQT40NWA", + "EndToEndId": "01JBVM13SQYP507JB1DYBZVCMF" }, + "Dbtr": { "FinInstnId": { "Othr": { "Id": "payer-dfsp" } } }, + "UndrlygCstmrCdtTrf": { + "Dbtr": {"Id": {"OrgId": {"Othr": {"Id": "payer-dfsp"}}}}, + "DbtrAgt": {"FinInstnId": {"Othr": {"Id": "payer-dfsp"}}}, + "Cdtr": {"Id": {"OrgId": {"Othr": {"Id": "fxp"}}}}, + "CdtrAgt": {"FinInstnId": {"Othr": {"Id": "fxp"}}}, + "InstdAmt": {"Ccy": "ZMW", + "ActiveOrHistoricCurrencyAndAmount": "21"}}, + "Cdtr": {"FinInstnId": {"Othr": {"Id": "fxp"}}}, + "IntrBkSttlmAmt": { "Ccy": "MWK", + "ActiveCurrencyAndAmount": "0"}, + "InstrForCdtrAgt": {"InstrInf": "SEND"}} +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - GroupHeader[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - Message Identification[1..1]Group Header Set of characteristics shared by all individual transactions included in the message.
     CreDtTm - ISODateTime[1..1]Creation Date and Time
     BtchBookg - BatchBookingIndicator[0..0]
     NbOfTxs - Max15NumericText[1..1]Number of Transactions
     CtrlSum - DecimalNumber[0..0]
     TtlIntrBkSttlmAmt - ActiveCurrencyAndAmount[0..0]A number of monetary units specified in an active currency where the unit of currency is explicit and compliant with ISO 4217.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmInf - Settlement Information[1..1]Group Header Set of characteristics shared by all individual transactions included in the message.
         SttlmMtd - SettlementMethod1Code[1..1]Only the CLRG: Clearing option is supported.
Specifies the details on how the settlement of the original transaction(s) between the
instructing agent and the instructed agent was completed.
         SttlmAcct - CashAccount40[0..0]Provides the details to identify an account.
         ClrSys - ClearingSystemIdentification3Choice[0..0]
         InstgRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         InstgRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         InstdRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         InstdRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         ThrdRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         ThrdRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     PmtTpInf - PaymentTypeInformation28[0..0]Provides further details of the type of payment.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
CdtTrfTxInf - FxRequest_FICreditTransferProposal[1..1]Credit Transfer Transaction Information
     PmtId - PaymentIdentification[1..1]Set of elements used to reference a payment instruction.
         InstrId - Max35Text[0..1]InstructionIdentification (FSPIOP equivalent: transactionRequestId)

Definition: Unique identification, as assigned by an instructing party for an instructed party, to
unambiguously identify the instruction.

Usage: The instruction identification is a point to point reference that can be used between the
instructing party and the instructed party to refer to the individual instruction. It can be included in
several messages related to the instruction.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         EndToEndId - Max35Text[0..1]EndToEndIdentification (FSPIOP equivalent: transactionId)

Definition: Unique identification, as assigned by the initiating party, to unambiguously identify the
transaction. This identification is passed on, unchanged, throughout the entire end-to-end chain.

Usage: The end-to-end identification can be used for reconciliation or to link tasks relating to the
transaction. It can be included in several messages related to the transaction.

Usage: In case there are technical limitations to pass on multiple references, the end-to-end
identification must be passed on throughout the entire end-to-end chain.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         TxId - Max35Text[1..1]TransactionIdentification (FSPIOP equivalent: quoteId in quote request, transferId in transfer request)

Definition: Unique identification, as assigned by the first instructing agent, to unambiguously identify the
transaction that is passed on, unchanged, throughout the entire interbank chain.

Usage: The transaction identification can be used for reconciliation, tracking or to link tasks relating to
the transaction on the interbank level.

Usage: The instructing agent has to make sure that the transaction identification is unique for a preagreed period.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         UETR - UETR[0..1]Universally unique identifier to provide an end-to-end reference of a payment transaction.
         ClrSysRef - ClearingSystemReference[0..1]Unique reference, as assigned by a clearing system, to unambiguously identify the instruction.
     PmtTpInf - PaymentTypeInformation[0..1]Set of elements used to further specify the type of transaction.
         InstrPrty - Priority2Code[0..1]Indicator of the urgency or order of importance that the instructing party
would like the instructed party to apply to the processing of the instruction.

HIGH: High priority
NORM: Normal priority
         ClrChanl - ClearingChannel2Code[0..1]Specifies the clearing channel for the routing of the transaction, as part of
the payment type identification.

RTGS: RealTimeGrossSettlementSystem Clearing channel is a real-time gross settlement system.
RTNS: RealTimeNetSettlementSystem Clearing channel is a real-time net settlement system.
MPNS: MassPaymentNetSystem Clearing channel is a mass payment net settlement system.
BOOK: BookTransfer Payment through internal book transfer.
         SvcLvl - ServiceLevel[0..1]Agreement under which or rules under which the transaction should be processed.
             Cd - Code[0..1]Specifies a pre-agreed service or level of service between the parties, as published in an external service level code list.
             Prtry - Proprietary[0..1]Specifies a pre-agreed service or level of service between the parties, as a proprietary code.
         LclInstrm - LocalInstrument[0..1]Definition: User community specific instrument.
Usage: This element is used to specify a local instrument, local clearing option and/or further qualify the service or service level.
             Cd - Code[0..1]Specifies the local instrument, as published in an external local instrument code list.
             Prtry - Proprietary[0..1]Specifies the local instrument, as a proprietary code.
         CtgyPurp - CategoryPurpose[0..1]Specifies the high level purpose of the instruction based on a set of pre-defined categories.
             Cd - Code[0..1]Category purpose, as published in an external category purpose code list.
             Prtry - Proprietary[0..1]Category purpose, in a proprietary form.
     IntrBkSttlmAmt - InterbankSettlementAmount[1..1]Amount of money moved between the instructing agent and the instructed agent.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmPrty - Priority3Code[0..0]
     SttlmTmIndctn - SettlementDateTimeIndication1[0..0]
     SttlmTmReq - SettlementTimeRequest2[0..0]
     PrvsInstgAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
     PrvsInstgAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
     PrvsInstgAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
     IntrmyAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
     IntrmyAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
     UltmtDbtr - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     Dbtr - Debtor[1..1]Party that owes an amount of money to the (ultimate) creditor.
         FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[1..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     DbtrAcct - DebtorAccount[0..1]Account used to process a payment.
         Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
             IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
             Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                 Id - Identification[0..1]Identification assigned by an institution.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         Tp - Type[0..1]Specifies the nature, or use of the account.
             Cd - Code[0..1]Account type, in a coded form.
             Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
         Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
         Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
         Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
             Tp - Type[0..1]Type of the proxy identification.
                 Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                 Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
             Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
     DbtrAgt - DebtorAgent[0..1]Financial institution servicing an account for the debtor.
         FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[0..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     DbtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     CdtrAgt - CreditorAgent[0..1]Financial institution servicing an account for the creditor.
         FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[0..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     CdtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     Cdtr - Creditor[1..1]Party to which an amount of money is due.
         FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[1..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     CdtrAcct - CreditorAccount[0..1]Account to which a credit entry is made.
         Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
             IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
             Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                 Id - Identification[0..1]Identification assigned by an institution.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         Tp - Type[0..1]Specifies the nature, or use of the account.
             Cd - Code[0..1]Account type, in a coded form.
             Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
         Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
         Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
         Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
             Tp - Type[0..1]Type of the proxy identification.
                 Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                 Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
             Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
     UltmtCdtr - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstrForCdtrAgt - InstructionForCreditorAgent[1..1]Set of elements used to provide information on the remittance advice.
         Cd - Code[0..1]Coded information related to the processing of the payment instruction, provided by the initiating party, and intended for the creditor's agent.
         InstrInf - InstructionInformation[0..1]Further information complementing the coded instruction or instruction to the creditor's agent that is bilaterally agreed or specific to a user community.
     InstrForNxtAgt - InstructionForNextAgent1[0..0]Further information related to the processing of the payment instruction, provided by the initiating party, and intended for the next agent in the payment chain.
     Purp - Purpose[0..1]Underlying reason for the payment transaction.
         Cd - Code[0..1]
Underlying reason for the payment transaction, as published in an external purpose code list.
         Prtry - Proprietary[0..1]
Purpose, in a proprietary form.
     RmtInf - RemittanceInformation2[0..0]
     UndrlygAllcn - TransactionAllocation1[0..0]
     UndrlygCstmrCdtTrf - CreditTransferTransaction63[1..1]Underlying Customer Credit Transfer
TBD
         UltmtDbtr - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
         InitgPty - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
         Dbtr - PartyIdentification272[1..1]Party that owes an amount of money to the (ultimate) creditor.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[1..1]Unique and unambiguous identification of a party.
                 OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - Person[1..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - OtherContact[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
         DbtrAcct - CashAccount40[0..0]Provides the details to identify an account.
         DbtrAgt - BranchAndFinancialInstitutionIdentification8[1..1]Financial institution servicing an account for the debtor.
             FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[1..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
         DbtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         PrvsInstgAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         PrvsInstgAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
         PrvsInstgAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         PrvsInstgAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
         PrvsInstgAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         PrvsInstgAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
         IntrmyAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         IntrmyAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
         IntrmyAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         IntrmyAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
         IntrmyAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         IntrmyAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
         CdtrAgt - BranchAndFinancialInstitutionIdentification8[1..1]Financial institution servicing an account for the creditor.
             FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[1..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
         CdtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         Cdtr - PartyIdentification272[1..1]Party to which an amount of money is due.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[1..1]Unique and unambiguous identification of a party.
                 OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - Person[1..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - OtherContact[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
         CdtrAcct - CashAccount40[0..0]Provides the details to identify an account.
         UltmtCdtr - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
         InstrForCdtrAgt - InstructionForCreditorAgent3[0..0]Further information related to the processing of the payment instruction, provided by the initiating party, and intended for the creditor agent.
         InstrForNxtAgt - InstructionForNextAgent1[0..0]Further information related to the processing of the payment instruction, provided by the initiating party, and intended for the next agent in the payment chain.
         Tax - TaxData1[0..0]Details about tax paid, or to be paid, to the government in accordance with the law, including pre-defined parameters such as thresholds and type of account.
         RmtInf - RemittanceInformation22[0..0]
         InstdAmt - InstructedAmount[1..1]Amount of money to be moved between the debtor and creditor, before deduction of charges, expressed in the currency as ordered by the initiating party.
     SplmtryData - SupplementaryData1[0..0]Additional information that cannot be captured in the structured fields and/or any other specific block.
SplmtryData - SupplementaryData1[0..0]Additional information that cannot be captured in the structured fields and/or any other specific block.
+ diff --git a/docs/product/features/Iso20022/script/fxquotes_PUT.md b/docs/product/features/Iso20022/script/fxquotes_PUT.md new file mode 100644 index 000000000..7f13e852d --- /dev/null +++ b/docs/product/features/Iso20022/script/fxquotes_PUT.md @@ -0,0 +1,776 @@ +## 7.5 PUT /fxQuotes/{ID} +|Financial Institution Credit Transfer Quote Response - **pacs.092.001.01**| +|--| + +#### Context +*(FXP -> DFSP)* + +This is triggered as a callback response to the POST /fxQuotes call. The message is generated by the foreign exchange provider and is a message response that includes the conversion terms. The FXP is expected to respond with this message if a terms requested are favorable and the FXP would like to participate in the transaction. + +The source currency amount is expected to be defined `CdtTrfTxInf.UndrlygCstmrCdtTrf.InstdAmt.ActiveOrHistoricCurrencyAndAmount`, and the target currency amount is provided in the `CdtTrfTxInf.IntrBkSttlmAmt.ActiveCurrencyAndAmount` field. These are clearing amounts and must have fees already included in their calculation. + +The `GrpHdr.PmtInstrXpryDtTm` specifies the expiry of the terms presented. It is the responsibility of the FXP to enforce this expiry in the transfer phase of a transaction. + +The `CdtTrfTxInf.VrfctnOfTerms.Sh256Sgntr` must contain the ILPv4 cryptographically signed condition, which is a cryptographic version of the conversion terms. + +Here is an example of the message: +```json +{ +"GrpHdr": { + "MsgId": "01JBVM176FTHB9F2ZQJJ7AFCN8", + "CreDtTm": "2024-11-04T12:57:39.791Z", + "NbOfTxs": "1", + "SttlmInf": { "SttlmMtd": "CLRG" }, + "PmtInstrXpryDtTm": "2024-11-04T12:58:39.425Z" +}, +"CdtTrfTxInf": { + "VrfctnOfTerms": {"Sh256Sgntr": "KVHFmdTD6A..."}, + "PmtId": {"InstrId": "01JBVM16V1ZXP2DM34BQT40NWA", + "TxId": "01JBVM13SQYP507JB1DYBZVCMF"}, + "Dbtr": {"FinInstnId": {"Othr": {"Id": "payer-dfsp"}}}, + "UndrlygCstmrCdtTrf": { + "Dbtr": {"Id": {"OrgId": {"Othr": {"Id": "payer-dfsp"}}}}, + "DbtrAgt": {"FinInstnId": {"Othr": {"Id": "payer-dfsp"}}}, + "Cdtr": {"Id": {"OrgId": {"Othr": {"Id": "fxp"}}}}, + "CdtrAgt": {"FinInstnId": {"Othr": {"Id": "fxp"}}}, + "InstdAmt": { "Ccy": "ZMW", + "ActiveOrHistoricCurrencyAndAmount": "21"}}, + "Cdtr": {"FinInstnId": {"Othr": {"Id": "fxp"}}}, + "IntrBkSttlmAmt": {"Ccy": "MWK", + "ActiveCurrencyAndAmount": "1080"}, + "InstrForCdtrAgt": {"InstrInf": "SEND"}} +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - GroupHeader[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - Message Identification[1..1]Group Header Set of characteristics shared by all individual transactions included in the message.
     CreDtTm - ISODateTime[1..1]Creation Date and Time
     BtchBookg - BatchBookingIndicator[0..0]
     NbOfTxs - Max15NumericText[1..1]Number of Transactions
     CtrlSum - DecimalNumber[0..0]
     TtlIntrBkSttlmAmt - ActiveCurrencyAndAmount[0..0]A number of monetary units specified in an active currency where the unit of currency is explicit and compliant with ISO 4217.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmInf - Settlement Information[1..1]Group Header Set of characteristics shared by all individual transactions included in the message.
         SttlmMtd - SettlementMethod1Code[1..1]Only the CLRG: Clearing option is supported.
Specifies the details on how the settlement of the original transaction(s) between the
instructing agent and the instructed agent was completed.
         SttlmAcct - CashAccount40[0..0]Provides the details to identify an account.
         ClrSys - ClearingSystemIdentification3Choice[0..0]
         InstgRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         InstgRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         InstdRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         InstdRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         ThrdRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         ThrdRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     PmtTpInf - PaymentTypeInformation28[0..0]Provides further details of the type of payment.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
CdtTrfTxInf - CreditTransferTransaction68_FX_Quotes[1..1]Set of elements providing information specific to the individual credit transfer(s).
     PmtId - PaymentIdentification[1..1]Set of elements used to reference a payment instruction.
         InstrId - Max35Text[0..1]InstructionIdentification (FSPIOP equivalent: transactionRequestId)

Definition: Unique identification, as assigned by an instructing party for an instructed party, to
unambiguously identify the instruction.

Usage: The instruction identification is a point to point reference that can be used between the
instructing party and the instructed party to refer to the individual instruction. It can be included in
several messages related to the instruction.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         EndToEndId - Max35Text[0..1]EndToEndIdentification (FSPIOP equivalent: transactionId)

Definition: Unique identification, as assigned by the initiating party, to unambiguously identify the
transaction. This identification is passed on, unchanged, throughout the entire end-to-end chain.

Usage: The end-to-end identification can be used for reconciliation or to link tasks relating to the
transaction. It can be included in several messages related to the transaction.

Usage: In case there are technical limitations to pass on multiple references, the end-to-end
identification must be passed on throughout the entire end-to-end chain.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         TxId - Max35Text[1..1]TransactionIdentification (FSPIOP equivalent: quoteId in quote request, transferId in transfer request)

Definition: Unique identification, as assigned by the first instructing agent, to unambiguously identify the
transaction that is passed on, unchanged, throughout the entire interbank chain.

Usage: The transaction identification can be used for reconciliation, tracking or to link tasks relating to
the transaction on the interbank level.

Usage: The instructing agent has to make sure that the transaction identification is unique for a preagreed period.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         UETR - UETR[0..1]Universally unique identifier to provide an end-to-end reference of a payment transaction.
         ClrSysRef - ClearingSystemReference[0..1]Unique reference, as assigned by a clearing system, to unambiguously identify the instruction.
     PmtTpInf - PaymentTypeInformation[0..1]Set of elements used to further specify the type of transaction.
         InstrPrty - Priority2Code[0..1]Indicator of the urgency or order of importance that the instructing party
would like the instructed party to apply to the processing of the instruction.

HIGH: High priority
NORM: Normal priority
         ClrChanl - ClearingChannel2Code[0..1]Specifies the clearing channel for the routing of the transaction, as part of
the payment type identification.

RTGS: RealTimeGrossSettlementSystem Clearing channel is a real-time gross settlement system.
RTNS: RealTimeNetSettlementSystem Clearing channel is a real-time net settlement system.
MPNS: MassPaymentNetSystem Clearing channel is a mass payment net settlement system.
BOOK: BookTransfer Payment through internal book transfer.
         SvcLvl - ServiceLevel[0..1]Agreement under which or rules under which the transaction should be processed.
             Cd - Code[0..1]Specifies a pre-agreed service or level of service between the parties, as published in an external service level code list.
             Prtry - Proprietary[0..1]Specifies a pre-agreed service or level of service between the parties, as a proprietary code.
         LclInstrm - LocalInstrument[0..1]Definition: User community specific instrument.
Usage: This element is used to specify a local instrument, local clearing option and/or further qualify the service or service level.
             Cd - Code[0..1]Specifies the local instrument, as published in an external local instrument code list.
             Prtry - Proprietary[0..1]Specifies the local instrument, as a proprietary code.
         CtgyPurp - CategoryPurpose[0..1]Specifies the high level purpose of the instruction based on a set of pre-defined categories.
             Cd - Code[0..1]Category purpose, as published in an external category purpose code list.
             Prtry - Proprietary[0..1]Category purpose, in a proprietary form.
     IntrBkSttlmAmt - InterbankSettlementAmount[1..1]Amount of money moved between the instructing agent and the instructed agent.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmPrty - Priority3Code[0..0]
     SttlmTmIndctn - SettlementDateTimeIndication1[0..0]
     SttlmTmReq - SettlementTimeRequest2[0..0]
     PrvsInstgAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
     PrvsInstgAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
     PrvsInstgAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
     IntrmyAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
     IntrmyAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
     UltmtDbtr - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     Dbtr - Debtor[1..1]Party that owes an amount of money to the (ultimate) creditor.
         FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[1..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     DbtrAcct - DebtorAccount[0..1]Account used to process a payment.
         Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
             IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
             Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                 Id - Identification[0..1]Identification assigned by an institution.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         Tp - Type[0..1]Specifies the nature, or use of the account.
             Cd - Code[0..1]Account type, in a coded form.
             Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
         Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
         Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
         Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
             Tp - Type[0..1]Type of the proxy identification.
                 Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                 Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
             Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
     DbtrAgt - DebtorAgent[0..1]Financial institution servicing an account for the debtor.
         FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[0..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     DbtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     CdtrAgt - CreditorAgent[0..1]Financial institution servicing an account for the creditor.
         FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[0..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     CdtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     Cdtr - Creditor[1..1]Party to which an amount of money is due.
         FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[1..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     CdtrAcct - CreditorAccount[0..1]Account to which a credit entry is made.
         Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
             IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
             Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                 Id - Identification[0..1]Identification assigned by an institution.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         Tp - Type[0..1]Specifies the nature, or use of the account.
             Cd - Code[0..1]Account type, in a coded form.
             Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
         Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
         Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
         Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
             Tp - Type[0..1]Type of the proxy identification.
                 Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                 Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
             Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
     UltmtCdtr - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstrForCdtrAgt - InstructionForCreditorAgent[1..1]Set of elements used to provide information on the remittance advice.
         Cd - Code[0..1]Coded information related to the processing of the payment instruction, provided by the initiating party, and intended for the creditor's agent.
         InstrInf - InstructionInformation[0..1]Further information complementing the coded instruction or instruction to the creditor's agent that is bilaterally agreed or specific to a user community.
     InstrForNxtAgt - InstructionForNextAgent1[0..0]Further information related to the processing of the payment instruction, provided by the initiating party, and intended for the next agent in the payment chain.
     Purp - Purpose[0..1]Underlying reason for the payment transaction.
         Cd - Code[0..1]
Underlying reason for the payment transaction, as published in an external purpose code list.
         Prtry - Proprietary[0..1]
Purpose, in a proprietary form.
     RmtInf - RemittanceInformation2[0..0]
     UndrlygAllcn - TransactionAllocation1[0..0]
     UndrlygCstmrCdtTrf - CreditTransferTransaction63[1..1]Underlying Customer Credit Transfer
TBD
         UltmtDbtr - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
         InitgPty - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
         Dbtr - PartyIdentification272[1..1]Party that owes an amount of money to the (ultimate) creditor.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[1..1]Unique and unambiguous identification of a party.
                 OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - Person[1..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - OtherContact[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
         DbtrAcct - CashAccount40[0..0]Provides the details to identify an account.
         DbtrAgt - BranchAndFinancialInstitutionIdentification8[1..1]Financial institution servicing an account for the debtor.
             FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[1..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
         DbtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         PrvsInstgAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         PrvsInstgAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
         PrvsInstgAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         PrvsInstgAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
         PrvsInstgAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         PrvsInstgAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
         IntrmyAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         IntrmyAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
         IntrmyAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         IntrmyAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
         IntrmyAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         IntrmyAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
         CdtrAgt - BranchAndFinancialInstitutionIdentification8[1..1]Financial institution servicing an account for the creditor.
             FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[1..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
         CdtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         Cdtr - PartyIdentification272[1..1]Party to which an amount of money is due.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[1..1]Unique and unambiguous identification of a party.
                 OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - Person[1..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - OtherContact[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
         CdtrAcct - CashAccount40[0..0]Provides the details to identify an account.
         UltmtCdtr - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
         InstrForCdtrAgt - InstructionForCreditorAgent3[0..0]Further information related to the processing of the payment instruction, provided by the initiating party, and intended for the creditor agent.
         InstrForNxtAgt - InstructionForNextAgent1[0..0]Further information related to the processing of the payment instruction, provided by the initiating party, and intended for the next agent in the payment chain.
         Tax - TaxData1[0..0]Details about tax paid, or to be paid, to the government in accordance with the law, including pre-defined parameters such as thresholds and type of account.
         RmtInf - RemittanceInformation22[0..0]
         InstdAmt - InstructedAmount[1..1]Amount of money to be moved between the debtor and creditor, before deduction of charges, expressed in the currency as ordered by the initiating party.
     SplmtryData - SupplementaryData1[0..0]Additional information that cannot be captured in the structured fields and/or any other specific block.
SplmtryData - SupplementaryData1[0..0]Additional information that cannot be captured in the structured fields and/or any other specific block.
+ diff --git a/docs/product/features/Iso20022/script/fxquotes_error_PUT.md b/docs/product/features/Iso20022/script/fxquotes_error_PUT.md new file mode 100644 index 000000000..e1c8da125 --- /dev/null +++ b/docs/product/features/Iso20022/script/fxquotes_error_PUT.md @@ -0,0 +1,180 @@ + +## 7.6 PUT /fxQuotes/{ID}/error + +|Financial Institution to Financial Institution Payment Status Report - **pacs.002.001.15** | +|--| + +#### Context +*(DFSP -> FXP, FXP -> DFSP, HUB -> DFSP, HUB -> FXP)* + +This is triggered as a callback response to the POST /fxQuotes call when an error occurs. The message is generated by the entity who first encounter the error which can either be the DFSP, the HUB, or the FPX. All other participants involved are informed by this message. The `TxInfAndSts.StsRsnInf.Rsn.Cd` contains the Mojaloop error code, which specified the source and cause of the error. + +Here is an example of the message: +```json +{ +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{"StsRsnInf":{"Rsn": {"Prtry":"ErrorCode"}}} +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - GroupHeader120[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - MessageIdentification[1..1]Definition: Point to point reference, as assigned by the instructing party, and sent to the next party in the chain to unambiguously identify the message.
Usage: The instructing party has to make sure that MessageIdentification is unique per instructed party for a pre-agreed period.
     CreDtTm - CreationDateTime[1..1]Date and time at which the message was created.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     OrgnlBizQry - OriginalBusinessQuery1[0..0]
OrgnlGrpInfAndSts - OriginalGroupHeader22[0..0]
TxInfAndSts - PaymentTransaction161[1..1]Information concerning the original transactions, to which the status report message refers.
     StsId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to unambiguously identify the status report.
     OrgnlGrpInf - OriginalGroupInformation29[0..0]
     OrgnlInstrId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original instruction.

(FSPIOP equivalent: transactionRequestId)
     OrgnlEndToEndId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original end-to-end transaction.

(FSPIOP equivalent: transactionId)
     OrgnlTxId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original transaction.

(FSPIOP equivalent: quoteId)
     OrgnlUETR - UUIDv4Identifier[0..1]Unique end-to-end transaction reference, as assigned by the original sending party, to unambiguously identify the original transaction.
     TxSts - ExternalPaymentTransactionStatus1Code[0..1]Specifies the status of the transaction.
     StsRsnInf - StatusReasonInformation14[1..1]Information concerning the reason for the status.
         Orgtr - Originator[0..1]Party that issues the status.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[0..1]Unique and unambiguous identification of a party.
                 OrgId - Organisation[0..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - Person[0..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - OtherContact[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
         Rsn - Reason[1..1]Specifies the reason for the status report.
             Cd - Code[1..1]Reason for the status, as published in an external reason code list.
             Prtry - Proprietary[1..1]Reason for the status, in a proprietary form.
         AddtlInf - AdditionalInformation[0..1]Additional information about the status report.
     ChrgsInf - Charges16[0..0]NOTE: Unsure on description.

Seemingly a generic schema for charges, with an amount, agent, and type.
     AccptncDtTm - ISODateTime[0..1]Date and time at which the status was accepted.
     PrcgDt - DateAndDateTime2Choice[0..1]Date/time at which the instruction was processed by the specified party.
         Dt - Date[0..1]Specified date.
         DtTm - DateTime[0..1]Specified date and time.
     FctvIntrBkSttlmDt - DateAndDateTime2Choice[0..0]Specifies the reason for the status.
     AcctSvcrRef - Max35Text[0..1]Unique reference, as assigned by the account servicing institution, to unambiguously identify the status report.
     ClrSysRef - Max35Text[0..1]Reference that is assigned by the account servicing institution and sent to the account owner to unambiguously identify the transaction.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     OrgnlTxRef - OriginalTransactionReference42[0..0]
     SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
         PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
         Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
     PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
     Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
+ diff --git a/docs/product/features/Iso20022/script/fxtransfers_PATCH.md b/docs/product/features/Iso20022/script/fxtransfers_PATCH.md new file mode 100644 index 000000000..84574f8b1 --- /dev/null +++ b/docs/product/features/Iso20022/script/fxtransfers_PATCH.md @@ -0,0 +1,182 @@ +## 7.13 PATCH /fxTransfers/{ID} +| Financial Institution to Financial Institution Payment Status Report - **pacs.002.001.15**| +|--| + +#### Context +*(HUB -> FXP)* + +This message use by the HUB to inform the foreign exchange provider participant in a cross currency transfer of the successful conclusion of the conversion. This message is only generated if the dependent transfer is committed in the hub. + +Here is an example of the message: +```json +{ +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{ + "PrcgDt":{ + "DtTm":"2024-11-04T12:57:45.213Z"}, + "TxSts":"COMM"} +} +``` + +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - GroupHeader120[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - MessageIdentification[1..1]Definition: Point to point reference, as assigned by the instructing party, and sent to the next party in the chain to unambiguously identify the message.
Usage: The instructing party has to make sure that MessageIdentification is unique per instructed party for a pre-agreed period.
     CreDtTm - CreationDateTime[1..1]Date and time at which the message was created.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     OrgnlBizQry - OriginalBusinessQuery1[0..0]
OrgnlGrpInfAndSts - OriginalGroupHeader22[0..0]
TxInfAndSts - PaymentTransaction161[1..1]Information concerning the original transactions, to which the status report message refers.
     StsId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to unambiguously identify the status report.
     OrgnlGrpInf - OriginalGroupInformation29[0..0]
     OrgnlInstrId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original instruction.

(FSPIOP equivalent: transactionRequestId)
     OrgnlEndToEndId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original end-to-end transaction.

(FSPIOP equivalent: transactionId)
     OrgnlTxId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original transaction.

(FSPIOP equivalent: quoteId)
     OrgnlUETR - UUIDv4Identifier[0..1]Unique end-to-end transaction reference, as assigned by the original sending party, to unambiguously identify the original transaction.
     TxSts - ExternalPaymentTransactionStatus1Code[1..1]Specifies the status of the transaction.
     StsRsnInf - StatusReasonInformation14[0..1]Information concerning the reason for the status.
         Orgtr - Originator[0..1]Party that issues the status.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[0..1]Unique and unambiguous identification of a party.
                 OrgId - Organisation[0..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - Person[0..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - OtherContact[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
         Rsn - Reason[0..1]Specifies the reason for the status report.
             Cd - Code[0..1]Reason for the status, as published in an external reason code list.
             Prtry - Proprietary[0..1]Reason for the status, in a proprietary form.
         AddtlInf - AdditionalInformation[0..1]Additional information about the status report.
     ChrgsInf - Charges16[0..0]NOTE: Unsure on description.

Seemingly a generic schema for charges, with an amount, agent, and type.
     AccptncDtTm - ISODateTime[0..1]Date and time at which the status was accepted.
     PrcgDt - DateAndDateTime2Choice[1..1]Date/time at which the instruction was processed by the specified party.
         Dt - Date[1..1]Specified date.
         DtTm - DateTime[1..1]Specified date and time.
     FctvIntrBkSttlmDt - DateAndDateTime2Choice[0..0]Specifies the reason for the status.
     AcctSvcrRef - Max35Text[0..1]Unique reference, as assigned by the account servicing institution, to unambiguously identify the status report.
     ClrSysRef - Max35Text[0..1]Reference that is assigned by the account servicing institution and sent to the account owner to unambiguously identify the transaction.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     OrgnlTxRef - OriginalTransactionReference42[0..0]
     SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
         PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
         Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
     PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
     Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
+ diff --git a/docs/product/features/Iso20022/script/fxtransfers_POST.md b/docs/product/features/Iso20022/script/fxtransfers_POST.md new file mode 100644 index 000000000..1124263f3 --- /dev/null +++ b/docs/product/features/Iso20022/script/fxtransfers_POST.md @@ -0,0 +1,776 @@ +## 7.10 POST /fxTransfers +| Execute Financial Institution Credit Transfer - **pacs.009.001.12**| +|--| + +#### Context +*(DFSP -> FXP)* + +This message is initiated by a DFSP who is requesting to transfer funds in another currency. The message is sent to the foreign exchange provider who provided the conversion terms. This message is an acknowledgement that the terms of the conversion are accepted, and is thus an instruction to proceed with the conversion. + +The source amount and currency are defined here `CdtTrfTxInf.UndrlygCstmrCdtTrf.InstdAmt.ActiveOrHistoricCurrencyAndAmount` and here `CdtTrfTxInf.UndrlygCstmrCdtTrf.InstdAmt.Ccy`, and the target amount and currency are defined `CdtTrfTxInf.IntrBkSttlmAmt.ActiveCurrencyAndAmount` and here `CdtTrfTxInf.IntrBkSttlmAmt.Ccy`. + +This message includes can be seen as an agreement to the terms that have previously been set up and established in the fxQuotes resource. The `CdtTrfTxInf.UndrlygCstmrCdtTrf.VrfctnOfTerms.Sh256Sgntr` field is a reference to the ILPv4 cryptographic condition of those terms. + +The `GrpHdr.PmtInstrXpryDtTm` specifies the expiry of the this transfer message. It is the responsibility of the HUB to enforce this expiry. The status of which a DFSP can query by making a `GET /fxTransfers/{ID}` request. + +The currency conversion is dependent on a transfer (the determiningTransferId) and is specified in the `CdtTrfTxInf.PmtId.EndToEndId` field. + +Here is an example of the message: +```json +{ +"GrpHdr":{ + "MsgId":"01JBVM1BW4J0RJZSQ539QB9TKT", + "CreDtTm":"2024-11-04T12:57:44.580Z", + "NbOfTxs":"1", + "SttlmInf":{"SttlmMtd":"CLRG"}, + "PmtInstrXpryDtTm":"2024-11-04T12:58:44.579Z"}, +"CdtTrfTxInf":{ + "PmtId":{"TxId":"01JBVM16V1ZXP2DM34BQT40NWA", + "EndToEndId":"01JBVM13SQYP507JB1DYBZVCMF"}, + "Dbtr":{"FinInstnId":{"Othr":{"Id":"payer-dfsp"}}}, + "UndrlygCstmrCdtTrf":{ + "Dbtr":{"Id":{"OrgId":{"Othr":{"Id":"payer-dfsp"}}}}, + "DbtrAgt":{"FinInstnId":{"Othr":{"Id":"payer-dfsp"}}}, + "Cdtr":{"Id":{"OrgId":{"Othr":{"Id":"fxp"}}}}, + "CdtrAgt":{"FinInstnId":{"Othr":{"Id":"fxp"}}}, + "InstdAmt":{"Ccy":"ZMW", + "ActiveOrHistoricCurrencyAndAmount":"21"}}, + "Cdtr":{"FinInstnId":{"Othr":{"Id":"fxp"}}}, + "IntrBkSttlmAmt":{"Ccy":"MWK", + "ActiveCurrencyAndAmount":"1080"}, + "VrfctnOfTerms":{"Sh256Sgntr":"KVHFmdTD6A..."}} +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - GroupHeader.[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - Message Identification[1..1]Group Header Set of characteristics shared by all individual transactions included in the message.
     CreDtTm - ISODateTime[1..1]Creation Date and Time
     BtchBookg - BatchBookingIndicator[0..0]
     NbOfTxs - Max15NumericText[1..1]Number of Transactions
     CtrlSum - DecimalNumber[0..0]
     TtlIntrBkSttlmAmt - ActiveCurrencyAndAmount[0..0]A number of monetary units specified in an active currency where the unit of currency is explicit and compliant with ISO 4217.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmInf - Settlement Information[1..1]Group Header Set of characteristics shared by all individual transactions included in the message.
         SttlmMtd - SettlementMethod1Code[1..1]Only the CLRG: Clearing option is supported.
Specifies the details on how the settlement of the original transaction(s) between the
instructing agent and the instructed agent was completed.
         SttlmAcct - CashAccount40[0..0]Provides the details to identify an account.
         ClrSys - ClearingSystemIdentification3Choice[0..0]
         InstgRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         InstgRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         InstdRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         InstdRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         ThrdRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         ThrdRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     PmtTpInf - PaymentTypeInformation28[0..0]Provides further details of the type of payment.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
CdtTrfTxInf - CreditTransferTransactionInformation.[1..1]Set of elements providing information specific to the individual credit transfer(s).
     PmtId - PaymentIdentification[1..1]Set of elements used to reference a payment instruction.
         InstrId - Max35Text[0..1]InstructionIdentification (FSPIOP equivalent: transactionRequestId)

Definition: Unique identification, as assigned by an instructing party for an instructed party, to
unambiguously identify the instruction.

Usage: The instruction identification is a point to point reference that can be used between the
instructing party and the instructed party to refer to the individual instruction. It can be included in
several messages related to the instruction.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         EndToEndId - Max35Text[0..1]EndToEndIdentification (FSPIOP equivalent: transactionId)

Definition: Unique identification, as assigned by the initiating party, to unambiguously identify the
transaction. This identification is passed on, unchanged, throughout the entire end-to-end chain.

Usage: The end-to-end identification can be used for reconciliation or to link tasks relating to the
transaction. It can be included in several messages related to the transaction.

Usage: In case there are technical limitations to pass on multiple references, the end-to-end
identification must be passed on throughout the entire end-to-end chain.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         TxId - Max35Text[1..1]TransactionIdentification (FSPIOP equivalent: quoteId in quote request, transferId in transfer request)

Definition: Unique identification, as assigned by the first instructing agent, to unambiguously identify the
transaction that is passed on, unchanged, throughout the entire interbank chain.

Usage: The transaction identification can be used for reconciliation, tracking or to link tasks relating to
the transaction on the interbank level.

Usage: The instructing agent has to make sure that the transaction identification is unique for a preagreed period.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         UETR - UETR[0..1]Universally unique identifier to provide an end-to-end reference of a payment transaction.
         ClrSysRef - ClearingSystemReference[0..1]Unique reference, as assigned by a clearing system, to unambiguously identify the instruction.
     PmtTpInf - PaymentTypeInformation[0..1]Set of elements used to further specify the type of transaction.
         InstrPrty - Priority2Code[0..1]Indicator of the urgency or order of importance that the instructing party
would like the instructed party to apply to the processing of the instruction.

HIGH: High priority
NORM: Normal priority
         ClrChanl - ClearingChannel2Code[0..1]Specifies the clearing channel for the routing of the transaction, as part of
the payment type identification.

RTGS: RealTimeGrossSettlementSystem Clearing channel is a real-time gross settlement system.
RTNS: RealTimeNetSettlementSystem Clearing channel is a real-time net settlement system.
MPNS: MassPaymentNetSystem Clearing channel is a mass payment net settlement system.
BOOK: BookTransfer Payment through internal book transfer.
         SvcLvl - ServiceLevel[0..1]Agreement under which or rules under which the transaction should be processed.
             Cd - Code[0..1]Specifies a pre-agreed service or level of service between the parties, as published in an external service level code list.
             Prtry - Proprietary[0..1]Specifies a pre-agreed service or level of service between the parties, as a proprietary code.
         LclInstrm - LocalInstrument[0..1]Definition: User community specific instrument.
Usage: This element is used to specify a local instrument, local clearing option and/or further qualify the service or service level.
             Cd - Code[0..1]Specifies the local instrument, as published in an external local instrument code list.
             Prtry - Proprietary[0..1]Specifies the local instrument, as a proprietary code.
         CtgyPurp - CategoryPurpose[0..1]Specifies the high level purpose of the instruction based on a set of pre-defined categories.
             Cd - Code[0..1]Category purpose, as published in an external category purpose code list.
             Prtry - Proprietary[0..1]Category purpose, in a proprietary form.
     IntrBkSttlmAmt - InterbankSettlementAmount[1..1]Amount of money moved between the instructing agent and the instructed agent.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmPrty - Priority3Code[0..0]
     SttlmTmIndctn - SettlementDateTimeIndication1[0..0]
     SttlmTmReq - SettlementTimeRequest2[0..0]
     PrvsInstgAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
     PrvsInstgAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
     PrvsInstgAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
     IntrmyAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
     IntrmyAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
     UltmtDbtr - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     Dbtr - Debtor[1..1]Party that owes an amount of money to the (ultimate) creditor.
         FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[1..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     DbtrAcct - DebtorAccount[0..1]Account used to process a payment.
         Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
             IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
             Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                 Id - Identification[0..1]Identification assigned by an institution.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         Tp - Type[0..1]Specifies the nature, or use of the account.
             Cd - Code[0..1]Account type, in a coded form.
             Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
         Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
         Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
         Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
             Tp - Type[0..1]Type of the proxy identification.
                 Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                 Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
             Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
     DbtrAgt - DebtorAgent[0..1]Financial institution servicing an account for the debtor.
         FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[0..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     DbtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     CdtrAgt - CreditorAgent[0..1]Financial institution servicing an account for the creditor.
         FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[0..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     CdtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     Cdtr - Creditor[1..1]Party to which an amount of money is due.
         FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[1..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     CdtrAcct - CreditorAccount[0..1]Account to which a credit entry is made.
         Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
             IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
             Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                 Id - Identification[0..1]Identification assigned by an institution.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         Tp - Type[0..1]Specifies the nature, or use of the account.
             Cd - Code[0..1]Account type, in a coded form.
             Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
         Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
         Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
         Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
             Tp - Type[0..1]Type of the proxy identification.
                 Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                 Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
             Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
     UltmtCdtr - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstrForCdtrAgt - InstructionForCreditorAgent[0..1]Set of elements used to provide information on the remittance advice.
         Cd - Code[0..1]Coded information related to the processing of the payment instruction, provided by the initiating party, and intended for the creditor's agent.
         InstrInf - InstructionInformation[0..1]Further information complementing the coded instruction or instruction to the creditor's agent that is bilaterally agreed or specific to a user community.
     InstrForNxtAgt - InstructionForNextAgent1[0..0]Further information related to the processing of the payment instruction, provided by the initiating party, and intended for the next agent in the payment chain.
     Purp - Purpose[0..1]Underlying reason for the payment transaction.
         Cd - Code[0..1]
Underlying reason for the payment transaction, as published in an external purpose code list.
         Prtry - Proprietary[0..1]
Purpose, in a proprietary form.
     RmtInf - RemittanceInformation2[0..0]
     UndrlygAllcn - TransactionAllocation1[0..0]
     UndrlygCstmrCdtTrf - CreditTransferTransaction63[1..1]Underlying Customer Credit Transfer
TBD
         UltmtDbtr - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
         InitgPty - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
         Dbtr - PartyIdentification272[1..1]Party that owes an amount of money to the (ultimate) creditor.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[1..1]Unique and unambiguous identification of a party.
                 OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - Person[1..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - OtherContact[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
         DbtrAcct - CashAccount40[0..0]Provides the details to identify an account.
         DbtrAgt - BranchAndFinancialInstitutionIdentification8[1..1]Financial institution servicing an account for the debtor.
             FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[1..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
         DbtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         PrvsInstgAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         PrvsInstgAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
         PrvsInstgAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         PrvsInstgAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
         PrvsInstgAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         PrvsInstgAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
         IntrmyAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         IntrmyAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
         IntrmyAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         IntrmyAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
         IntrmyAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         IntrmyAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
         CdtrAgt - BranchAndFinancialInstitutionIdentification8[1..1]Financial institution servicing an account for the creditor.
             FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[1..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
         CdtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         Cdtr - PartyIdentification272[1..1]Party to which an amount of money is due.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[1..1]Unique and unambiguous identification of a party.
                 OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - Person[1..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - OtherContact[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
         CdtrAcct - CashAccount40[0..0]Provides the details to identify an account.
         UltmtCdtr - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
         InstrForCdtrAgt - InstructionForCreditorAgent3[0..0]Further information related to the processing of the payment instruction, provided by the initiating party, and intended for the creditor agent.
         InstrForNxtAgt - InstructionForNextAgent1[0..0]Further information related to the processing of the payment instruction, provided by the initiating party, and intended for the next agent in the payment chain.
         Tax - TaxData1[0..0]Details about tax paid, or to be paid, to the government in accordance with the law, including pre-defined parameters such as thresholds and type of account.
         RmtInf - RemittanceInformation22[0..0]
         InstdAmt - InstructedAmount[1..1]Amount of money to be moved between the debtor and creditor, before deduction of charges, expressed in the currency as ordered by the initiating party.
     SplmtryData - SupplementaryData1[0..0]Additional information that cannot be captured in the structured fields and/or any other specific block.
SplmtryData - SupplementaryData1[0..0]Additional information that cannot be captured in the structured fields and/or any other specific block.
+ diff --git a/docs/product/features/Iso20022/script/fxtransfers_PUT.md b/docs/product/features/Iso20022/script/fxtransfers_PUT.md new file mode 100644 index 000000000..782654982 --- /dev/null +++ b/docs/product/features/Iso20022/script/fxtransfers_PUT.md @@ -0,0 +1,98 @@ +## 7.11 PUT /fxTransfers/{ID} + +| Financial Institution to Financial Institution Payment Status Report - **pacs.002.001.15**| +|--| + +#### Context +*(FXP -> DFSP)* + +This message is a response to the `POST \fxTransfers` call initiated by the DFSP who is requesting to proceed with the conversion terms presented in the `PUT \fxquotes`. It is the FXP's responsibility to check that the clearing amounts align with the agreed conversion terms, and if all requirements are met, use this message to lock-in the agreed terms. Once the hub receives this acceptance message, the conversion can no-longer timeout. Final completion of the conversion will only occur once the dependent transfer is committed. + +The cryptographic ILP fulfillment provided in the `TxInfAndSts.ExctnConf` field, is released by the FXP as an indication to the HUB that the terms have been met. + +Here is an example of the message: +```json +{ +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{ + "ExctnConf":"ou1887jmG-l...", + "PrcgDt":{"DtTm":"2024-11-04T12:57:45.213Z"}, + "TxSts":"RESV"} +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - GroupHeader113[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - MessageIdentification[1..1]Definition: Point to point reference, as assigned by the instructing party, and sent to the next party in the chain to unambiguously identify the message.
Usage: The instructing party has to make sure that MessageIdentification is unique per instructed party for a pre-agreed period.
     CreDtTm - CreationDateTime[1..1]Date and time at which the message was created.
     BtchBookg - BatchBookingIndicator[0..0]
     NbOfTxs - Max15NumericText[0..0]Specifies a numeric string with a maximum length of 15 digits.
     CtrlSum - DecimalNumber[0..0]
     TtlIntrBkSttlmAmt - ActiveCurrencyAndAmount[0..0]A number of monetary units specified in an active currency where the unit of currency is explicit and compliant with ISO 4217.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmInf - SettlementInstruction15[0..0]Only the CLRG: Clearing option is supported.
Specifies the details on how the settlement of the original transaction(s) between the
instructing agent and the instructed agent was completed.
     PmtTpInf - PaymentTypeInformation28[0..0]Provides further details of the type of payment.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
CdtTrfTxInf - CreditTransferTransaction62[0..0]
SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
     PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
     Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
+ diff --git a/docs/product/features/Iso20022/script/fxtransfers_error_PUT.md b/docs/product/features/Iso20022/script/fxtransfers_error_PUT.md new file mode 100644 index 000000000..1e636b8c1 --- /dev/null +++ b/docs/product/features/Iso20022/script/fxtransfers_error_PUT.md @@ -0,0 +1,178 @@ +## 7.12 PUT /fxTransfers/{ID}/error + +| Financial Institution to Financial Institution Payment Status Report - **pacs.002.001.15**| +|--| + +#### Context +*(FXP -> DFSP, FXP -> HUB, DFSP -> HUB, DFSP -> FXP, HUB -> DFSP)* + +This is triggered as a callback response to the POST /fxTransfers call when an error occurs. The message is generated by the entity who first encounter the error which can either be the DFSP, or the HUB. All other participants involved are informed by this message. The `TxInfAndSts.StsRsnInf.Rsn.Cd` contains the Mojaloop error code, which specified the source and cause of the error. + +Here is an example of the message: +```json +{ +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{"StsRsnInf":{"Rsn": {"Prtry":"ErrorCode"}}} +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - GroupHeader120[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - MessageIdentification[1..1]Definition: Point to point reference, as assigned by the instructing party, and sent to the next party in the chain to unambiguously identify the message.
Usage: The instructing party has to make sure that MessageIdentification is unique per instructed party for a pre-agreed period.
     CreDtTm - CreationDateTime[1..1]Date and time at which the message was created.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     OrgnlBizQry - OriginalBusinessQuery1[0..0]
OrgnlGrpInfAndSts - OriginalGroupHeader22[0..0]
TxInfAndSts - PaymentTransaction161[1..1]Information concerning the original transactions, to which the status report message refers.
     StsId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to unambiguously identify the status report.
     OrgnlGrpInf - OriginalGroupInformation29[0..0]
     OrgnlInstrId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original instruction.

(FSPIOP equivalent: transactionRequestId)
     OrgnlEndToEndId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original end-to-end transaction.

(FSPIOP equivalent: transactionId)
     OrgnlTxId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original transaction.

(FSPIOP equivalent: quoteId)
     OrgnlUETR - UUIDv4Identifier[0..1]Unique end-to-end transaction reference, as assigned by the original sending party, to unambiguously identify the original transaction.
     TxSts - ExternalPaymentTransactionStatus1Code[0..1]Specifies the status of the transaction.
     StsRsnInf - StatusReasonInformation14[1..1]Information concerning the reason for the status.
         Orgtr - Originator[0..1]Party that issues the status.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[0..1]Unique and unambiguous identification of a party.
                 OrgId - Organisation[0..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - Person[0..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - OtherContact[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
         Rsn - Reason[1..1]Specifies the reason for the status report.
             Cd - Code[1..1]Reason for the status, as published in an external reason code list.
             Prtry - Proprietary[1..1]Reason for the status, in a proprietary form.
         AddtlInf - AdditionalInformation[0..1]Additional information about the status report.
     ChrgsInf - Charges16[0..0]NOTE: Unsure on description.

Seemingly a generic schema for charges, with an amount, agent, and type.
     AccptncDtTm - ISODateTime[0..1]Date and time at which the status was accepted.
     PrcgDt - DateAndDateTime2Choice[0..1]Date/time at which the instruction was processed by the specified party.
         Dt - Date[0..1]Specified date.
         DtTm - DateTime[0..1]Specified date and time.
     FctvIntrBkSttlmDt - DateAndDateTime2Choice[0..0]Specifies the reason for the status.
     AcctSvcrRef - Max35Text[0..1]Unique reference, as assigned by the account servicing institution, to unambiguously identify the status report.
     ClrSysRef - Max35Text[0..1]Reference that is assigned by the account servicing institution and sent to the account owner to unambiguously identify the transaction.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     OrgnlTxRef - OriginalTransactionReference42[0..0]
     SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
         PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
         Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
     PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
     Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
diff --git a/docs/product/features/Iso20022/script/parties_GET.md b/docs/product/features/Iso20022/script/parties_GET.md new file mode 100644 index 000000000..32017ee06 --- /dev/null +++ b/docs/product/features/Iso20022/script/parties_GET.md @@ -0,0 +1,9 @@ +## 7.1 GET /parties/{type}/{partyIdentifier}[/{subId}] +The GET /parties endpoint does not support or require a payload, and can be seen as an instruction to trigger an Account identification Verification report. +- **{type}** - Party identifier types
+The **{type}** refers to the classification of the party Identifier type. Each scheme only supports a limited number of these codes. The codes supported by the scheme may be derived from the ISO 20022 external organisation or personal identification codes, or they could be FSPIOP supported codes. The full list of supported codes is available in the [**Appendix A**](../Appendix.md). + - **partyIdentifier**
+ This is the party identifier of the party being represented and of the type specified by the {type} above. + - **{subId}**
+ This represent a sub-identifier or sub-type for the party that some implementations require in order to ensure uniqueness of the identifier. + diff --git a/docs/product/features/Iso20022/script/parties_PUT.md b/docs/product/features/Iso20022/script/parties_PUT.md new file mode 100644 index 000000000..1fd19e0c0 --- /dev/null +++ b/docs/product/features/Iso20022/script/parties_PUT.md @@ -0,0 +1,676 @@ +## 7.2 PUT /Parties/{type}/{partyIdentifier}[/{subId}] +|**Account Identification Verification Report - acmt.024.001.04**| +|--| + +#### Context +*(DFSP -> DFSP)* + +This is triggers as a callback response to the GET /parties call. The message is between DFSPs connected in the scheme and is a check that validates that the account represented is active. + +Here is an example of the message: +``` json +{ +"Assgnmt": { + "MsgId": "01JBVM14S6SC453EY9XB9GXQB5", + "CreDtTm": "2024-11-04T12:57:37.318Z", + "Assgnr": { "Agt": { "FinInstnId": { "Othr": { "Id": "payee-dfps" }}}}, + "Assgne": { "Agt": { "FinInstnId": { "Othr": { "Id": "payer-dfsp" }}}}}, +"Rpt": { + "Vrfctn": true, + "OrgnlId": "MSISDN/16665551002", + "UpdtdPtyAndAcctId": { + "Pty": { + "Id": {"PrvtId": {"Othr": {"SchmeNm": {"Prtry": "MSISDN"}, + "Id": "16665551002"}}}, + "Nm": "Chikondi Banda"}, + "Agt": { "FinInstnId": { "Othr": { "Id": "payee-dfsp" }}}, + "Acct": { "Ccy": "MWK" }}} +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
Assgnmt - Assignment[1..1]Identifies the identification assignment.
     MsgId - MessageIdentification[1..1]Unique identification, as assigned by the assigner, to unambiguously identify the message.
     CreDtTm - CreationDateTime[1..1]Date and time at which the identification assignment was created.
     Cretr - Party50Choice[0..0]
     FrstAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     Assgnr - Assignor[1..1]Party that assigns the identification assignment to another party. This is also the sender of the message.
         Pty - Party[1..1]Identification of a person or an organisation.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[1..1]Unique and unambiguous way to identify an organisation.
                 OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Max256Text[0..1]Identification for an organisation. FSPIOP equivalent to Party Identifier for an organisation in ISO 20022. Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - PrivateIdentification[1..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryOfResidence[0..1]Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - ContactDetails[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Name prefix to be used before the name of the person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - Max2048Text[0..0]Specifies a character string with a maximum length of 2048 characters.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - Other[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredMethod[0..1]Preferred method used to reach the contact.
         Agt - Agent[1..1]Identification of a financial institution.
             FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution, as assigned under an internationally recognised or proprietary identification scheme.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[1..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Definition: Identifies a specific branch of a financial institution.
Usage: This component should be used in case the identification information in the financial institution component does not provide identification up to branch level.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEIIdentifier[0..1]Legal Entity Identifier
Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
     Assgne - Assignee[1..1]Party that the identification assignment is assigned to. This is also the receiver of the message.
         Pty - Party[1..1]Identification of a person or an organisation.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[1..1]Unique and unambiguous way to identify an organisation.
                 OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Max256Text[0..1]Identification for an organisation. FSPIOP equivalent to Party Identifier for an organisation in ISO 20022. Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - PrivateIdentification[1..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryOfResidence[0..1]Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - ContactDetails[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Name prefix to be used before the name of the person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - Max2048Text[0..0]Specifies a character string with a maximum length of 2048 characters.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - Other[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredMethod[0..1]Preferred method used to reach the contact.
         Agt - Agent[1..1]Identification of a financial institution.
             FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution, as assigned under an internationally recognised or proprietary identification scheme.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[1..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Definition: Identifies a specific branch of a financial institution.
Usage: This component should be used in case the identification information in the financial institution component does not provide identification up to branch level.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEIIdentifier[0..1]Legal Entity Identifier
Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
OrgnlAssgnmt - MessageIdentification8[0..0]
Rpt - Report[1..1]Information concerning the verification of the identification data for which verification was requested.
     OrgnlId - OriginalIdentification[1..1]Unique identification, as assigned by a sending party, to unambiguously identify the party and account identification information group within the original message.
     Vrfctn - Verification[1..1]Identifies whether the party and/or account information received is correct. Boolean value.
     Rsn - Reason[0..1]Specifies the reason why the verified identification information is incorrect.
         Cd - Code[0..1]Reason why the verified identification information is incorrect, as published in an external reason code list.
         Prtry - Proprietary[0..1]Reason why the verified identification information is incorrect, in a free text form.
     OrgnlPtyAndAcctId - OriginalPartyAndAccountIdentification[0..1]Provides party and/or account identification information as given in the original message.
         Pty - Party[0..1]Account owner that owes an amount of money or to whom an amount of money is due.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[0..1]Unique and unambiguous way to identify an organisation.
                 OrgId - Organisation[0..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Max256Text[0..1]Identification for an organisation. FSPIOP equivalent to Party Identifier for an organisation in ISO 20022. Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - PrivateIdentification[0..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryOfResidence[0..1]Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - ContactDetails[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Name prefix to be used before the name of the person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - Max2048Text[0..0]Specifies a character string with a maximum length of 2048 characters.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - Other[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredMethod[0..1]Preferred method used to reach the contact.
         Acct - Account[0..1]Unambiguous identification of the account of a party.
             Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
                 IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
                 Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                     Id - Identification[0..1]Identification assigned by an institution.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             Tp - Type[0..1]Specifies the nature, or use of the account.
                 Cd - Code[0..1]Account type, in a coded form.
                 Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
             Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
             Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
             Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
                 Tp - Type[0..1]Type of the proxy identification.
                     Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
                 Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
         Agt - Agent[0..1]Financial institution servicing an account for a party.
             FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution, as assigned under an internationally recognised or proprietary identification scheme.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Definition: Identifies a specific branch of a financial institution.
Usage: This component should be used in case the identification information in the financial institution component does not provide identification up to branch level.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEIIdentifier[0..1]Legal Entity Identifier
Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
     UpdtdPtyAndAcctId - UpdatedPartyAndAccountIdentification[1..1]Provides party and/or account identification information.
         Pty - Party[1..1]Account owner that owes an amount of money or to whom an amount of money is due.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[1..1]Unique and unambiguous way to identify an organisation.
                 OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Max256Text[0..1]Identification for an organisation. FSPIOP equivalent to Party Identifier for an organisation in ISO 20022. Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - PrivateIdentification[1..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryOfResidence[0..1]Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - ContactDetails[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Name prefix to be used before the name of the person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - Max2048Text[0..0]Specifies a character string with a maximum length of 2048 characters.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - Other[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredMethod[0..1]Preferred method used to reach the contact.
         Acct - Account[0..1]Unambiguous identification of the account of a party.
             Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
                 IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
                 Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                     Id - Identification[0..1]Identification assigned by an institution.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             Tp - Type[0..1]Specifies the nature, or use of the account.
                 Cd - Code[0..1]Account type, in a coded form.
                 Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
             Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
             Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
             Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
                 Tp - Type[0..1]Type of the proxy identification.
                     Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
                 Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
         Agt - Agent[0..1]Financial institution servicing an account for a party.
             FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution, as assigned under an internationally recognised or proprietary identification scheme.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Definition: Identifies a specific branch of a financial institution.
Usage: This component should be used in case the identification information in the financial institution component does not provide identification up to branch level.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEIIdentifier[0..1]Legal Entity Identifier
Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
SplmtryData - SupplementaryData[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
     PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
     Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
+ diff --git a/docs/product/features/Iso20022/script/parties_error_PUT.md b/docs/product/features/Iso20022/script/parties_error_PUT.md new file mode 100644 index 000000000..3d7111c9c --- /dev/null +++ b/docs/product/features/Iso20022/script/parties_error_PUT.md @@ -0,0 +1,675 @@ + +## 7.3 PUT /parties/{type}/{partyIdentifier}[/{subId}]/error +|**Account Identification Verification Report - acmt.024.001.04**| +|--| + +#### Context +*(DFSP -> DFSP)* + +This is triggered as a callback response to the GET /parties call when an error occurs. The message is between DFSPs connected in the scheme and indicates an error in the account verification process. All DFSP participating the the scheme are expected to respond with this message. + +Here is an example of the message: +```json +{ + "Assgnmt": { + "MsgId": "01JBVM14S6SC453EY9XB9GXQBW", + "CreDtTm": "2013-03-07T16:30:00", + "Assgnr": { "Agt": { "FinInstnId": { "Othr": { "Id": "payee-dfsp" } } } }, + "Assgne": { "Agt": { "FinInstnId": { "Othr": { "Id": "payer-dfsp" } } } } + }, + "Rpt": { + "Vrfctn": false, + "OrgnlId": "MSISDN/16665551002", + "CreDtTm": "2013-03-07T16:30:00", + "Rsn": { "Prtry": 3204 } + } +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
Assgnmt - Assignment[1..1]Information related to the identification assignment.
     MsgId - MessageIdentification[1..1]Unique identification, as assigned by the assigner, to unambiguously identify the message.
     CreDtTm - CreationDateTime[1..1]Date and time at which the identification assignment was created.
     Cretr - Party50Choice[0..0]
     FrstAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     Assgnr - Assignor[1..1]Party that assigns the identification assignment to another party. This is also the sender of the message.
         Pty - Party[1..1]Identification of a person or an organisation.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[1..1]Unique and unambiguous way to identify an organisation.
                 OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Max256Text[0..1]Identification for an organisation. FSPIOP equivalent to Party Identifier for an organisation in ISO 20022. Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - PrivateIdentification[1..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryOfResidence[0..1]Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - ContactDetails[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Name prefix to be used before the name of the person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - Max2048Text[0..0]Specifies a character string with a maximum length of 2048 characters.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - Other[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredMethod[0..1]Preferred method used to reach the contact.
         Agt - Agent[1..1]Identification of a financial institution.
             FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution, as assigned under an internationally recognised or proprietary identification scheme.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[1..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Definition: Identifies a specific branch of a financial institution.
Usage: This component should be used in case the identification information in the financial institution component does not provide identification up to branch level.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEIIdentifier[0..1]Legal Entity Identifier
Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
     Assgne - Assignee[1..1]Party that the identification assignment is assigned to. This is also the receiver of the message.
         Pty - Party[1..1]Identification of a person or an organisation.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[1..1]Unique and unambiguous way to identify an organisation.
                 OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Max256Text[0..1]Identification for an organisation. FSPIOP equivalent to Party Identifier for an organisation in ISO 20022. Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - PrivateIdentification[1..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryOfResidence[0..1]Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - ContactDetails[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Name prefix to be used before the name of the person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - Max2048Text[0..0]Specifies a character string with a maximum length of 2048 characters.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - Other[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredMethod[0..1]Preferred method used to reach the contact.
         Agt - Agent[1..1]Identification of a financial institution.
             FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution, as assigned under an internationally recognised or proprietary identification scheme.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[1..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Definition: Identifies a specific branch of a financial institution.
Usage: This component should be used in case the identification information in the financial institution component does not provide identification up to branch level.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEIIdentifier[0..1]Legal Entity Identifier
Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
OrgnlAssgnmt - MessageIdentification8[0..0]
Rpt - Report[1..1]Information concerning the verification of the identification data for which verification was requested.
     OrgnlId - OriginalIdentification[1..1]Unique identification, as assigned by a sending party, to unambiguously identify the party and account identification information group within the original message.
     Vrfctn - Verification[1..1]Identifies whether the party and/or account information received is correct. Boolean value.
     Rsn - Reason[1..1]Specifies the reason why the verified identification information is incorrect.
         Cd - Code[1..1]Reason why the verified identification information is incorrect, as published in an external reason code list.
         Prtry - Proprietary[1..1]Reason why the verified identification information is incorrect, in a free text form.
     OrgnlPtyAndAcctId - OriginalPartyAndAccountIdentification[0..1]Provides party and/or account identification information as given in the original message.
         Pty - Party[0..1]Account owner that owes an amount of money or to whom an amount of money is due.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[0..1]Unique and unambiguous way to identify an organisation.
                 OrgId - Organisation[0..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Max256Text[0..1]Identification for an organisation. FSPIOP equivalent to Party Identifier for an organisation in ISO 20022. Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - PrivateIdentification[0..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryOfResidence[0..1]Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - ContactDetails[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Name prefix to be used before the name of the person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - Max2048Text[0..0]Specifies a character string with a maximum length of 2048 characters.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - Other[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredMethod[0..1]Preferred method used to reach the contact.
         Acct - Account[0..1]Unambiguous identification of the account of a party.
             Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
                 IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
                 Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                     Id - Identification[0..1]Identification assigned by an institution.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             Tp - Type[0..1]Specifies the nature, or use of the account.
                 Cd - Code[0..1]Account type, in a coded form.
                 Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
             Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
             Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
             Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
                 Tp - Type[0..1]Type of the proxy identification.
                     Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
                 Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
         Agt - Agent[0..1]Financial institution servicing an account for a party.
             FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution, as assigned under an internationally recognised or proprietary identification scheme.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Definition: Identifies a specific branch of a financial institution.
Usage: This component should be used in case the identification information in the financial institution component does not provide identification up to branch level.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEIIdentifier[0..1]Legal Entity Identifier
Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
     UpdtdPtyAndAcctId - UpdatedPartyAndAccountIdentification[0..1]Provides party and/or account identification information.
         Pty - Party[0..1]Account owner that owes an amount of money or to whom an amount of money is due.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[0..1]Unique and unambiguous way to identify an organisation.
                 OrgId - Organisation[0..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Max256Text[0..1]Identification for an organisation. FSPIOP equivalent to Party Identifier for an organisation in ISO 20022. Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - PrivateIdentification[0..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryOfResidence[0..1]Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - ContactDetails[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Name prefix to be used before the name of the person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - Max2048Text[0..0]Specifies a character string with a maximum length of 2048 characters.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - Other[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredMethod[0..1]Preferred method used to reach the contact.
         Acct - Account[0..1]Unambiguous identification of the account of a party.
             Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
                 IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
                 Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                     Id - Identification[0..1]Identification assigned by an institution.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             Tp - Type[0..1]Specifies the nature, or use of the account.
                 Cd - Code[0..1]Account type, in a coded form.
                 Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
             Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
             Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
             Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
                 Tp - Type[0..1]Type of the proxy identification.
                     Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
                 Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
         Agt - Agent[0..1]Financial institution servicing an account for a party.
             FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution, as assigned under an internationally recognised or proprietary identification scheme.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Definition: Identifies a specific branch of a financial institution.
Usage: This component should be used in case the identification information in the financial institution component does not provide identification up to branch level.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEIIdentifier[0..1]Legal Entity Identifier
Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
SplmtryData - SupplementaryData[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
     PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
     Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
+ + diff --git a/docs/product/features/Iso20022/script/quotes_POST.md b/docs/product/features/Iso20022/script/quotes_POST.md new file mode 100644 index 000000000..6cf8c9c88 --- /dev/null +++ b/docs/product/features/Iso20022/script/quotes_POST.md @@ -0,0 +1,631 @@ +## 7.7 POST /quotes +|**Financial Institution to Financial Institution Customer Credit Transfer Quote Request - pacs.081.001.01**| +|--| + +#### Context +*(DFSP -> DFSP)* + +This request for quote message that is initiated by the payer DFSP who is requesting the payee DFSP to provide the terms of the transfer. The reply to this request is a callback made on the PUT /quotes endpoint. In this phase of the transfer all participants present and agree on the terms of the transfer, and are expected to validate whether the transfer will be able to proceed. + +If this transaction includes currency conversion, then the transfer amount and currency specified must be in target currency. The transfer amounts is specified in the `CdtTrfTxInf.IntrBkSttlmAmt.ActiveCurrencyAndAmount` and the `CdtTrfTxInf.IntrBkSttlmAmt.Ccy` fields. +Both the `ChrgBr` type `CRED` and `DEBT` are supported. +#### Charge Type `CRED` +If the `CdtTrfTxInf.ChrgBr` is defined as `CRED`, then the transfer amount is expected to remain the same in the returned transfer terms and the payee party receive amount is adjusted to account for any fees. + +#### Charge Type `DEBT` +If the `CdtTrfTxInf.ChrgBr` is defined as `DEBT`, then the amount the payee party receives must equal the transfer amount specified. The transfer amount in returned transfer terms is adjusted to account for any fees. + +The Identifier for this request must be a ULID generated identifier and is specified in the `CdtTrfTxInf.PmtId.TxId` field. If this transfer is part of a wider transaction, then that too is represented by a ULID specified in the `CdtTrfTxInf.PmtId.EndToEndId` field. + +Here is an example of the message: +```json +{ +"GrpHdr": { + "MsgId": "01JBVM19DJQ96BS9X6VA5AMW2Y", + "CreDtTm": "2024-11-04T12:57:42.066Z", + "NbOfTxs": "1", + "PmtInstrXpryDtTm": "2024-11-04T12:58:42.063Z", + "SttlmInf": { "SttlmMtd": "CLRG" } + }, +"CdtTrfTxInf": { + "PmtId": { + "TxId": "01JBVM19DFKNRWC21FGJNTHRAT", + "EndToEndId": "01JBVM13SQYP507JB1DYBZVCMF"}, + "Cdtr": { "Id": { "PrvtId": { "Othr": { "SchmeNm": { "Prtry": "MSISDN" }, + "Id": "16665551002" }}}}, + "CdtrAgt": { "FinInstnId": { "Othr": { "Id": "test-mwk-dfsp" }}}, + "Dbtr": { "Id": { "PrvtId": { "Othr": { "SchmeNm": { "Prtry": "MSISDN" }, + "Id": "16135551001" }}}, + "Name": "Joe Blogs"}, + "DbtrAgt": { "FinInstnId": { "Othr": { "Id": "payer-dfsp" }}}, + "IntrBkSttlmAmt": { + "Ccy": "MWK", + "ActiveCurrencyAndAmount": "1080"}, + "Purp": { "Prtry": "TRANSFER"}, + "ChrgBr": "CRED"} +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - Group Header[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - Message Identification[1..1]Group Header Set of characteristics shared by all individual transactions included in the message.
     CreDtTm - ISODateTime[1..1]Creation Date and Time
     BtchBookg - BatchBookingIndicator[0..0]
     NbOfTxs - Max15NumericText[1..1]Number of Transactions
     CtrlSum - DecimalNumber[0..0]
     TtlIntrBkSttlmAmt - ActiveCurrencyAndAmount[0..0]A number of monetary units specified in an active currency where the unit of currency is explicit and compliant with ISO 4217.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmInf - Settlement Information[1..1]Group Header Set of characteristics shared by all individual transactions included in the message.
         SttlmMtd - SettlementMethod1Code[1..1]Only the CLRG: Clearing option is supported.
Specifies the details on how the settlement of the original transaction(s) between the
instructing agent and the instructed agent was completed.
         SttlmAcct - CashAccount40[0..0]Provides the details to identify an account.
         ClrSys - ClearingSystemIdentification3Choice[0..0]
         InstgRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         InstgRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         InstdRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         InstdRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         ThrdRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         ThrdRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     PmtTpInf - PaymentTypeInformation28[0..0]Provides further details of the type of payment.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
CdtTrfTxInf - CreditTransferTransaction64[1..1]Credit Transfer Transaction Information
     PmtId - PaymentIdentification[1..1]Set of elements used to reference a payment instruction.
         InstrId - Max35Text[0..1]InstructionIdentification (FSPIOP equivalent: transactionRequestId)

Definition: Unique identification, as assigned by an instructing party for an instructed party, to
unambiguously identify the instruction.

Usage: The instruction identification is a point to point reference that can be used between the
instructing party and the instructed party to refer to the individual instruction. It can be included in
several messages related to the instruction.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         EndToEndId - Max35Text[0..1]EndToEndIdentification (FSPIOP equivalent: transactionId)

Definition: Unique identification, as assigned by the initiating party, to unambiguously identify the
transaction. This identification is passed on, unchanged, throughout the entire end-to-end chain.

Usage: The end-to-end identification can be used for reconciliation or to link tasks relating to the
transaction. It can be included in several messages related to the transaction.

Usage: In case there are technical limitations to pass on multiple references, the end-to-end
identification must be passed on throughout the entire end-to-end chain.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         TxId - Max35Text[1..1]TransactionIdentification (FSPIOP equivalent: quoteId in quote request, transferId in transfer request)

Definition: Unique identification, as assigned by the first instructing agent, to unambiguously identify the
transaction that is passed on, unchanged, throughout the entire interbank chain.

Usage: The transaction identification can be used for reconciliation, tracking or to link tasks relating to
the transaction on the interbank level.

Usage: The instructing agent has to make sure that the transaction identification is unique for a preagreed period.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         UETR - UETR[0..1]Universally unique identifier to provide an end-to-end reference of a payment transaction.
         ClrSysRef - ClearingSystemReference[0..1]Unique reference, as assigned by a clearing system, to unambiguously identify the instruction.
     PmtTpInf - PaymentTypeInformation[0..1]Set of elements used to further specify the type of transaction.
         InstrPrty - Priority2Code[0..1]Indicator of the urgency or order of importance that the instructing party
would like the instructed party to apply to the processing of the instruction.

HIGH: High priority
NORM: Normal priority
         ClrChanl - ClearingChannel2Code[0..1]Specifies the clearing channel for the routing of the transaction, as part of
the payment type identification.

RTGS: RealTimeGrossSettlementSystem Clearing channel is a real-time gross settlement system.
RTNS: RealTimeNetSettlementSystem Clearing channel is a real-time net settlement system.
MPNS: MassPaymentNetSystem Clearing channel is a mass payment net settlement system.
BOOK: BookTransfer Payment through internal book transfer.
         SvcLvl - ServiceLevel[0..1]Agreement under which or rules under which the transaction should be processed.
             Cd - Code[0..1]Specifies a pre-agreed service or level of service between the parties, as published in an external service level code list.
             Prtry - Proprietary[0..1]Specifies a pre-agreed service or level of service between the parties, as a proprietary code.
         LclInstrm - LocalInstrument[0..1]Definition: User community specific instrument.
Usage: This element is used to specify a local instrument, local clearing option and/or further qualify the service or service level.
             Cd - Code[0..1]Specifies the local instrument, as published in an external local instrument code list.
             Prtry - Proprietary[0..1]Specifies the local instrument, as a proprietary code.
         CtgyPurp - CategoryPurpose[0..1]Specifies the high level purpose of the instruction based on a set of pre-defined categories.
             Cd - Code[0..1]Category purpose, as published in an external category purpose code list.
             Prtry - Proprietary[0..1]Category purpose, in a proprietary form.
     IntrBkSttlmAmt - InterbankSettlementAmount[1..1]Amount of money moved between the instructing agent and the instructed agent.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmPrty - Priority3Code[0..0]
     SttlmTmIndctn - SettlementDateTimeIndication1[0..0]
     SttlmTmReq - SettlementTimeRequest2[0..0]
     AccptncDtTm - ISODateTime[0..0]A particular point in the progression of time defined by a mandatory
date and a mandatory time component, expressed in either UTC time
format (YYYY-MM-DDThh:mm:ss.sssZ), local time with UTC offset format
(YYYY-MM-DDThh:mm:ss.sss+/-hh:mm), or local time format
(YYYY-MM-DDThh:mm:ss.sss). These representations are defined in
"XML Schema Part 2: Datatypes Second Edition -
W3C Recommendation 28 October 2004" which is aligned with ISO 8601.

Note on the time format:
1) beginning / end of calendar day
00:00:00 = the beginning of a calendar day
24:00:00 = the end of a calendar day

2) fractions of second in time format
Decimal fractions of seconds may be included. In this case, the
involved parties shall agree on the maximum number of digits that are allowed.
     PoolgAdjstmntDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     InstdAmt - InstructedAmount[0..1]Amount of money to be moved between the debtor and creditor, before deduction of charges, expressed in the currency as ordered by the initiating party.
     XchgRate - ExchangeRate[0..1]Factor used to convert an amount from one currency into another. This reflects the price at which one currency was bought with another currency.
     ChrgBr - ChargeBearerType1Code[1..1]Provides further details specific to the individual transaction(s) included in the message.
     ChrgsInf - ChargesInformation[0..1]Provides information on the charges to be paid by the charge bearer(s) related to the payment transaction.
         Amt - Amount[0..1]Transaction charges to be paid by the charge bearer.
         Agt - Agent[0..1]Agent that takes the transaction charges or to which the transaction charges are due.
             FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
         Tp - Type[0..1]Defines the type of charges.
             Cd - Code[0..1]Charge type, in a coded form.
             Prtry - Proprietary[0..1]Type of charge in a proprietary form, as defined by the issuer.
                 Id - Identification[0..1]Name or number assigned by an entity to enable recognition of that entity, for example, account identifier.
                 Issr - Issuer[0..1]Entity that assigns the identification.
     MndtRltdInf - CreditTransferMandateData1[0..0]
     PrvsInstgAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
     PrvsInstgAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
     PrvsInstgAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
     IntrmyAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
     IntrmyAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
     UltmtDbtr - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
     InitgPty - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
     Dbtr - Debtor[1..1]Party that owes an amount of money to the (ultimate) creditor.
         Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
         PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
             AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                 Cd - Code[0..1]Type of address expressed as a code.
                 Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                     Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                     Issr - Issuer[0..1]Entity that assigns the identification.
                     SchmeNm - SchemeName[0..1]Short textual description of the scheme.
             CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
             Dept - Max70Text[0..1]Name of a department within an organization.
             SubDept - Max70Text[0..1]Name of a sub-department within a department.
             StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
             BldgNb - Max16Text[0..1]Number that identifies a building on the street.
             BldgNm - Max140Text[0..1]Name of the building, if applicable.
             Flr - Max70Text[0..1]Floor number or identifier within a building.
             UnitNb - Max16Text[0..1]Unit or apartment number within a building.
             PstBx - Max16Text[0..1]Post office box number.
             Room - Max70Text[0..1]Room number or identifier within a building.
             PstCd - Max16Text[0..1]Postal code or ZIP code.
             TwnNm - Max140Text[0..1]Name of the town or city.
             TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
             DstrctNm - Max140Text[0..1]Name of the district or region.
             CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
             Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
             AdrLine - Max70Text[0..1]Free-form text line for the address.
         Id - Identification[1..1]Unique and unambiguous identification of a party.
             OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                 AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                 LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                 Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Identification assigned by an institution.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             PrvtId - Person[1..1]Unique and unambiguous identification of a person, for example a passport.
                 DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                     BirthDt - BirthDate[0..1]Date on which a person was born.
                     PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                     CityOfBirth - CityOfBirth[0..1]City where a person was born.
                     CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                 Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
         CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
         CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
             NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
             MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
             FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
             URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
             EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
             EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
             JobTitl - JobTitle[0..1]Title of the function.
             Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
             Dept - Department[0..1]Identification of a division of a large organisation or building.
             Othr - OtherContact[0..1]Contact details in another form.
                 ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                 Id - Identifier[0..1]Communication value such as phone number or email address.
             PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
     DbtrAcct - DebtorAccount[0..1]Unambiguous identification of the account of the debtor to which a debit entry will be made as a result of the transaction.
         Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
             IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
             Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                 Id - Identification[0..1]Identification assigned by an institution.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         Tp - Type[0..1]Specifies the nature, or use of the account.
             Cd - Code[0..1]Account type, in a coded form.
             Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
         Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
         Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
         Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
             Tp - Type[0..1]Type of the proxy identification.
                 Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                 Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
             Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
     DbtrAgt - DebtorAgent[1..1]Financial institution servicing an account for the debtor.
         FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[1..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     DbtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     CdtrAgt - CreditorAgent[1..1]Financial institution servicing an account for the creditor.
         FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[1..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     CdtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     Cdtr - Creditor[1..1]Party to which an amount of money is due.
         Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
         PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
             AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                 Cd - Code[0..1]Type of address expressed as a code.
                 Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                     Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                     Issr - Issuer[0..1]Entity that assigns the identification.
                     SchmeNm - SchemeName[0..1]Short textual description of the scheme.
             CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
             Dept - Max70Text[0..1]Name of a department within an organization.
             SubDept - Max70Text[0..1]Name of a sub-department within a department.
             StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
             BldgNb - Max16Text[0..1]Number that identifies a building on the street.
             BldgNm - Max140Text[0..1]Name of the building, if applicable.
             Flr - Max70Text[0..1]Floor number or identifier within a building.
             UnitNb - Max16Text[0..1]Unit or apartment number within a building.
             PstBx - Max16Text[0..1]Post office box number.
             Room - Max70Text[0..1]Room number or identifier within a building.
             PstCd - Max16Text[0..1]Postal code or ZIP code.
             TwnNm - Max140Text[0..1]Name of the town or city.
             TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
             DstrctNm - Max140Text[0..1]Name of the district or region.
             CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
             Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
             AdrLine - Max70Text[0..1]Free-form text line for the address.
         Id - Identification[1..1]Unique and unambiguous identification of a party.
             OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                 AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                 LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                 Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Identification assigned by an institution.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             PrvtId - Person[1..1]Unique and unambiguous identification of a person, for example a passport.
                 DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                     BirthDt - BirthDate[0..1]Date on which a person was born.
                     PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                     CityOfBirth - CityOfBirth[0..1]City where a person was born.
                     CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                 Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
         CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
         CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
             NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
             MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
             FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
             URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
             EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
             EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
             JobTitl - JobTitle[0..1]Title of the function.
             Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
             Dept - Department[0..1]Identification of a division of a large organisation or building.
             Othr - OtherContact[0..1]Contact details in another form.
                 ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                 Id - Identifier[0..1]Communication value such as phone number or email address.
             PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
     CdtrAcct - CreditorAccount[0..1]Unambiguous identification of the account of the creditor to which a credit entry will be posted as a result of the payment transaction.
         Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
             IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
             Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                 Id - Identification[0..1]Identification assigned by an institution.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         Tp - Type[0..1]Specifies the nature, or use of the account.
             Cd - Code[0..1]Account type, in a coded form.
             Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
         Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
         Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
         Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
             Tp - Type[0..1]Type of the proxy identification.
                 Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                 Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
             Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
     UltmtCdtr - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
     InstrForCdtrAgt - InstructionForCreditorAgent[0..1]Set of elements used to provide information on the remittance advice.
         Cd - Code[0..1]Coded information related to the processing of the payment instruction, provided by the initiating party, and intended for the creditor's agent.
         InstrInf - InstructionInformation[0..1]Further information complementing the coded instruction or instruction to the creditor's agent that is bilaterally agreed or specific to a user community.
     InstrForNxtAgt - InstructionForNextAgent[0..1]Set of elements used to provide information on the remittance advice.
         Cd - Code[0..1]Coded information related to the processing of the payment instruction, provided by the initiating party, and intended for the next agent in the payment chain.
         InstrInf - InstructionInformation[0..1]Further information complementing the coded instruction or instruction to the next agent that is bilaterally agreed or specific to a user community.
     Purp - Purpose[1..1]Underlying reason for the payment transaction.
         Cd - Code[1..1]
Underlying reason for the payment transaction, as published in an external purpose code list.
         Prtry - Proprietary[1..1]
Purpose, in a proprietary form.
     RgltryRptg - RegulatoryReporting[0..1]Information needed due to regulatory and statutory requirements.
         DbtCdtRptgInd - DebitCreditReportingIndicator[0..1]Identifies whether the regulatory reporting information applies to the debit side, to the credit side or to both debit and credit sides of the transaction.
         Authrty - Authority[0..1]
Entity requiring the regulatory reporting information.
             Nm - Name[0..1]
Name of the entity requiring the regulatory reporting information.
             Ctry - Country[0..1]
Country of the entity that requires the regulatory reporting information.
         Dtls - Details[0..1]Identifies whether the regulatory reporting information applies to the debit side, to the credit side or to both debit and credit sides of the transaction.
             Tp - Type[0..1]
Specifies the type of the information supplied in the regulatory reporting details.
             Dt - Date[0..1]
Date related to the specified type of regulatory reporting details.
             Ctry - Country[0..1]
Country related to the specified type of regulatory reporting details.
             Cd - Code[0..1]Specifies the nature, purpose, and reason for the transaction to be reported for regulatory and statutory requirements in a coded form.
             Amt - Amount[0..1]
Amount of money to be reported for regulatory and statutory requirements.
             Inf - Information[0..1]
Additional details that cater for specific domestic regulatory requirements.
     Tax - Tax[0..1]Provides details on the tax.
         Cdtr - Creditor[0..1]
Party on the credit side of the transaction to which the tax applies.
             TaxId - TaxIdentification[0..1]
Tax identification number of the creditor.
             RegnId - RegistrationIdentification[0..1]
Unique identification, as assigned by an organisation, to unambiguously identify a party.
             TaxTp - TaxType[0..1]
Type of tax payer.
         Dbtr - Debtor[0..1]
Party on the debit side of the transaction to which the tax applies.
             TaxId - TaxIdentification[0..1]
Tax identification number of the debtor.
             RegnId - RegistrationIdentification[0..1]
Unique identification, as assigned by an organisation, to unambiguously identify a party.
             TaxTp - TaxType[0..1]
Type of tax payer.
             Authstn - Authorisation[0..1]
Details of the authorised tax paying party.
                 Titl - Title[0..1]
Title or position of debtor or the debtor's authorised representative.
                 Nm - Name[0..1]
Name of the debtor or the debtor's authorised representative.
         UltmtDbtr - UltimateDebtor[0..1]
Ultimate party that owes an amount of money to the (ultimate) creditor, in this case, to the taxing authority.
             TaxId - TaxIdentification[0..1]
Tax identification number of the debtor.
             RegnId - RegistrationIdentification[0..1]
Unique identification, as assigned by an organisation, to unambiguously identify a party.
             TaxTp - TaxType[0..1]
Type of tax payer.
             Authstn - Authorisation[0..1]
Details of the authorised tax paying party.
                 Titl - Title[0..1]
Title or position of debtor or the debtor's authorised representative.
                 Nm - Name[0..1]
Name of the debtor or the debtor's authorised representative.
         AdmstnZone - AdministrationZone[0..1]
Territorial part of a country to which the tax payment is related.
         RefNb - ReferenceNumber[0..1]
Tax reference information that is specific to a taxing agency.
         Mtd - Method[0..1]
Method used to indicate the underlying business or how the tax is paid.
         TtlTaxblBaseAmt - TotalTaxableBaseAmount[0..1]
Total amount of money on which the tax is based.
         TtlTaxAmt - TotalTaxAmount[0..1]
Total amount of money as result of the calculation of the tax.
         Dt - Date[0..1]
Date by which tax is due.
         SeqNb - SequenceNumber[0..1]
Sequential number of the tax report.
         Rcrd - Record[0..1]
Details of the tax record.
             Tp - Type[0..1]
High level code to identify the type of tax details.
             Ctgy - Category[0..1]
Specifies the tax code as published by the tax authority.
             CtgyDtls - CategoryDetails[0..1]
Provides further details of the category tax code.
             DbtrSts - DebtorStatus[0..1]
Code provided by local authority to identify the status of the party that has drawn up the settlement document.
             CertId - CertificateIdentification[0..1]
Identification number of the tax report as assigned by the taxing authority.
             FrmsCd - FormsCode[0..1]
Identifies, in a coded form, on which template the tax report is to be provided.
             Prd - Period[0..1]
Set of elements used to provide details on the period of time related to the tax payment.
                 Yr - Year[0..1]
Year related to the tax payment.
                 Tp - Type[0..1]
Identification of the period related to the tax payment.
                 FrToDt - FromToDate[0..1]
Range of time between a start date and an end date for which the tax report is provided.
                     FrDt - FromDate[0..1]Start date of the range.
                     ToDt - ToDate[0..1]End date of the range.
             TaxAmt - TaxAmount[0..1]
Set of elements used to provide information on the amount of the tax record.
                 Rate - Rate[0..1]
Rate used to calculate the tax.
                 TaxblBaseAmt - TaxableBaseAmount[0..1]
Amount of money on which the tax is based.
                 TtlAmt - TotalAmount[0..1]
Total amount that is the result of the calculation of the tax for the record.
                 Dtls - Details[0..1]
Set of elements used to provide details on the tax period and amount.
                     Prd - Period[0..1]
Set of elements used to provide details on the period of time related to the tax payment.
                         Yr - Year[0..1]
Year related to the tax payment.
                         Tp - Type[0..1]
Identification of the period related to the tax payment.
                         FrToDt - FromToDate[0..1]
Range of time between a start date and an end date for which the tax report is provided.
                             FrDt - FromDate[0..1]Start date of the range.
                             ToDt - ToDate[0..1]End date of the range.
                     Amt - Amount[0..1]
Underlying tax amount related to the specified period.
             AddtlInf - AdditionalInformation[0..1]
Further details of the tax record.
     RltdRmtInf - RemittanceLocation8[0..0]
     RmtInf - RemittanceInformation22[0..0]
     SplmtryData - SupplementaryData1[0..0]Additional information that cannot be captured in the structured fields and/or any other specific block.
SplmtryData - SupplementaryData1[0..0]Additional information that cannot be captured in the structured fields and/or any other specific block.
+ diff --git a/docs/product/features/Iso20022/script/quotes_PUT.md b/docs/product/features/Iso20022/script/quotes_PUT.md new file mode 100644 index 000000000..c48d358c7 --- /dev/null +++ b/docs/product/features/Iso20022/script/quotes_PUT.md @@ -0,0 +1,634 @@ +## 7.8 PUT /quotes/{ID} +|Financial Institution to Financial Institution Customer Credit Transfer Quote Response - **pacs.082.001.01**| +|--| + +#### Context +*(DFSP -> DFSP)* + +This is triggered as a callback response to the POST /quotes call. The message is generated by the payee DFSP and is a message response that includes the transfer terms. The payee DFSP is expected to respond with this message if a terms requested are favorable and the payee DFSP would like to participate in the transaction. + +The transfer amounts is specified in the `CdtTrfTxInf.IntrBkSttlmAmt.ActiveCurrencyAndAmount` and the `CdtTrfTxInf.IntrBkSttlmAmt.Ccy` fields. These are clearing amounts and must have fees already included in their calculation. + +The `GrpHdr.PmtInstrXpryDtTm` specifies the expiry of the terms presented. It is the responsibility of the payee DFSP to enforce this expiry in the transfer phase of a transaction. + +The `CdtTrfTxInf.PmtId.TxId` must reference the message that this is a response to and is the same as what is included in the path as `{ID}`. + +The `CdtTrfTxInf.VrfctnOfTerms.IlpV4PrepPacket` must contain the ILPv4 cryptographically signed packet, which is a cryptographic version of the transfers terms. These are the terms against with the payer DFSP agrees, and against which the non-repudiation of the transfer is base. It is thus important that the payer DFSP inspects these terms. + +Here is an example of the message: +```json +{ +"GrpHdr": { + "MsgId": "01JBVM19SPQAQV9EEP0QC1RNAD", + "CreDtTm": "2024-11-04T12:57:42.455Z", + "NbOfTxs": "1", + "SttlmInf": { "SttlmMtd": "CLRG" }, + "PmtInstrXpryDtTm": "2024-11-04T12:58:42.450Z" +}, +"CdtTrfTxInf": { + "PmtId": { "TxId": "01JBVM19DFKNRWC21FGJNTHRAT" }, + "Dbtr": { "Id": { "PrvtId": { "Othr": { "SchmeNm": { "Prtry": "MSISDN" }, + "Id": "16135551001"}}}, + "Name": "Payer Joe" }, + "DbtrAgt": { "FinInstnId": { "Othr": { "Id": "payer-dfsp"}}}, + "Cdtr": { "Id": { "PrvtId": { "Othr": { "SchmeNm": { "Prtry": "MSISDN" }, + "Id": "16665551002"}}}, + "CdtrAgt": { "FinInstnId": { "Othr": { "Id": "payee-dfsp"}}}, + "ChrgBr": "CRED", + "IntrBkSttlmAmt": { + "Ccy": "MWK", + "ActiveCurrencyAndAmount": "1080" }, + "InstdAmt": { + "Ccy": "MWK", + "ActiveOrHistoricCurrencyAndAmount": "1080" }, + "ChrgsInf": { + "Amt": { "Ccy": "MWK", + "ActiveOrHistoricCurrencyAndAmount": "0" }, + "Agt": { "FinInstnId": { "Othr": { "Id": "payee-dfsp"}}}}, + "VrfctnOfTerms": { "IlpV4PrepPacket": "DIICzQAAAA..." }}} +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - Group Header[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - Message Identification[1..1]Group Header Set of characteristics shared by all individual transactions included in the message.
     CreDtTm - ISODateTime[1..1]Creation Date and Time
     BtchBookg - BatchBookingIndicator[0..0]
     NbOfTxs - Max15NumericText[1..1]Number of Transactions
     CtrlSum - DecimalNumber[0..0]
     TtlIntrBkSttlmAmt - ActiveCurrencyAndAmount[0..0]A number of monetary units specified in an active currency where the unit of currency is explicit and compliant with ISO 4217.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmInf - Settlement Information[1..1]Group Header Set of characteristics shared by all individual transactions included in the message.
         SttlmMtd - SettlementMethod1Code[1..1]Only the CLRG: Clearing option is supported.
Specifies the details on how the settlement of the original transaction(s) between the
instructing agent and the instructed agent was completed.
         SttlmAcct - CashAccount40[0..0]Provides the details to identify an account.
         ClrSys - ClearingSystemIdentification3Choice[0..0]
         InstgRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         InstgRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         InstdRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         InstdRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         ThrdRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         ThrdRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     PmtTpInf - PaymentTypeInformation28[0..0]Provides further details of the type of payment.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
CdtTrfTxInf - CreditTransferTransaction64[1..1]Credit Transfer Transaction Information
Set of elements providing information specific to the individual credit transfer(s).
     PmtId - PaymentIdentification[1..1]Set of elements used to reference a payment instruction.
         InstrId - Max35Text[0..1]InstructionIdentification (FSPIOP equivalent: transactionRequestId)

Definition: Unique identification, as assigned by an instructing party for an instructed party, to
unambiguously identify the instruction.

Usage: The instruction identification is a point to point reference that can be used between the
instructing party and the instructed party to refer to the individual instruction. It can be included in
several messages related to the instruction.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         EndToEndId - Max35Text[0..1]EndToEndIdentification (FSPIOP equivalent: transactionId)

Definition: Unique identification, as assigned by the initiating party, to unambiguously identify the
transaction. This identification is passed on, unchanged, throughout the entire end-to-end chain.

Usage: The end-to-end identification can be used for reconciliation or to link tasks relating to the
transaction. It can be included in several messages related to the transaction.

Usage: In case there are technical limitations to pass on multiple references, the end-to-end
identification must be passed on throughout the entire end-to-end chain.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         TxId - Max35Text[1..1]TransactionIdentification (FSPIOP equivalent: quoteId in quote request, transferId in transfer request)

Definition: Unique identification, as assigned by the first instructing agent, to unambiguously identify the
transaction that is passed on, unchanged, throughout the entire interbank chain.

Usage: The transaction identification can be used for reconciliation, tracking or to link tasks relating to
the transaction on the interbank level.

Usage: The instructing agent has to make sure that the transaction identification is unique for a preagreed period.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         UETR - UETR[0..1]Universally unique identifier to provide an end-to-end reference of a payment transaction.
         ClrSysRef - ClearingSystemReference[0..1]Unique reference, as assigned by a clearing system, to unambiguously identify the instruction.
     PmtTpInf - PaymentTypeInformation[0..1]Set of elements used to further specify the type of transaction.
         InstrPrty - Priority2Code[0..1]Indicator of the urgency or order of importance that the instructing party
would like the instructed party to apply to the processing of the instruction.

HIGH: High priority
NORM: Normal priority
         ClrChanl - ClearingChannel2Code[0..1]Specifies the clearing channel for the routing of the transaction, as part of
the payment type identification.

RTGS: RealTimeGrossSettlementSystem Clearing channel is a real-time gross settlement system.
RTNS: RealTimeNetSettlementSystem Clearing channel is a real-time net settlement system.
MPNS: MassPaymentNetSystem Clearing channel is a mass payment net settlement system.
BOOK: BookTransfer Payment through internal book transfer.
         SvcLvl - ServiceLevel[0..1]Agreement under which or rules under which the transaction should be processed.
             Cd - Code[0..1]Specifies a pre-agreed service or level of service between the parties, as published in an external service level code list.
             Prtry - Proprietary[0..1]Specifies a pre-agreed service or level of service between the parties, as a proprietary code.
         LclInstrm - LocalInstrument[0..1]Definition: User community specific instrument.
Usage: This element is used to specify a local instrument, local clearing option and/or further qualify the service or service level.
             Cd - Code[0..1]Specifies the local instrument, as published in an external local instrument code list.
             Prtry - Proprietary[0..1]Specifies the local instrument, as a proprietary code.
         CtgyPurp - CategoryPurpose[0..1]Specifies the high level purpose of the instruction based on a set of pre-defined categories.
             Cd - Code[0..1]Category purpose, as published in an external category purpose code list.
             Prtry - Proprietary[0..1]Category purpose, in a proprietary form.
     IntrBkSttlmAmt - InterbankSettlementAmount[1..1]Amount of money moved between the instructing agent and the instructed agent.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmPrty - Priority3Code[0..0]
     SttlmTmIndctn - SettlementDateTimeIndication1[0..0]
     SttlmTmReq - SettlementTimeRequest2[0..0]
     AccptncDtTm - ISODateTime[0..0]A particular point in the progression of time defined by a mandatory
date and a mandatory time component, expressed in either UTC time
format (YYYY-MM-DDThh:mm:ss.sssZ), local time with UTC offset format
(YYYY-MM-DDThh:mm:ss.sss+/-hh:mm), or local time format
(YYYY-MM-DDThh:mm:ss.sss). These representations are defined in
"XML Schema Part 2: Datatypes Second Edition -
W3C Recommendation 28 October 2004" which is aligned with ISO 8601.

Note on the time format:
1) beginning / end of calendar day
00:00:00 = the beginning of a calendar day
24:00:00 = the end of a calendar day

2) fractions of second in time format
Decimal fractions of seconds may be included. In this case, the
involved parties shall agree on the maximum number of digits that are allowed.
     PoolgAdjstmntDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     InstdAmt - InstructedAmount[0..1]Amount of money to be moved between the debtor and creditor, before deduction of charges, expressed in the currency as ordered by the initiating party.
     XchgRate - ExchangeRate[0..1]Factor used to convert an amount from one currency into another. This reflects the price at which one currency was bought with another currency.
     ChrgBr - ChargeBearerType1Code[1..1]Provides further details specific to the individual transaction(s) included in the message.
     ChrgsInf - ChargesInformation[0..1]Provides information on the charges to be paid by the charge bearer(s) related to the payment transaction.
         Amt - Amount[0..1]Transaction charges to be paid by the charge bearer.
         Agt - Agent[0..1]Agent that takes the transaction charges or to which the transaction charges are due.
             FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
         Tp - Type[0..1]Defines the type of charges.
             Cd - Code[0..1]Charge type, in a coded form.
             Prtry - Proprietary[0..1]Type of charge in a proprietary form, as defined by the issuer.
                 Id - Identification[0..1]Name or number assigned by an entity to enable recognition of that entity, for example, account identifier.
                 Issr - Issuer[0..1]Entity that assigns the identification.
     MndtRltdInf - CreditTransferMandateData1[0..0]
     PrvsInstgAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
     PrvsInstgAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
     PrvsInstgAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
     IntrmyAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
     IntrmyAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
     UltmtDbtr - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
     InitgPty - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
     Dbtr - Debtor[1..1]Party that owes an amount of money to the (ultimate) creditor.
         Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
         PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
             AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                 Cd - Code[0..1]Type of address expressed as a code.
                 Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                     Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                     Issr - Issuer[0..1]Entity that assigns the identification.
                     SchmeNm - SchemeName[0..1]Short textual description of the scheme.
             CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
             Dept - Max70Text[0..1]Name of a department within an organization.
             SubDept - Max70Text[0..1]Name of a sub-department within a department.
             StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
             BldgNb - Max16Text[0..1]Number that identifies a building on the street.
             BldgNm - Max140Text[0..1]Name of the building, if applicable.
             Flr - Max70Text[0..1]Floor number or identifier within a building.
             UnitNb - Max16Text[0..1]Unit or apartment number within a building.
             PstBx - Max16Text[0..1]Post office box number.
             Room - Max70Text[0..1]Room number or identifier within a building.
             PstCd - Max16Text[0..1]Postal code or ZIP code.
             TwnNm - Max140Text[0..1]Name of the town or city.
             TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
             DstrctNm - Max140Text[0..1]Name of the district or region.
             CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
             Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
             AdrLine - Max70Text[0..1]Free-form text line for the address.
         Id - Identification[1..1]Unique and unambiguous identification of a party.
             OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                 AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                 LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                 Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Identification assigned by an institution.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             PrvtId - Person[1..1]Unique and unambiguous identification of a person, for example a passport.
                 DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                     BirthDt - BirthDate[0..1]Date on which a person was born.
                     PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                     CityOfBirth - CityOfBirth[0..1]City where a person was born.
                     CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                 Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
         CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
         CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
             NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
             MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
             FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
             URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
             EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
             EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
             JobTitl - JobTitle[0..1]Title of the function.
             Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
             Dept - Department[0..1]Identification of a division of a large organisation or building.
             Othr - OtherContact[0..1]Contact details in another form.
                 ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                 Id - Identifier[0..1]Communication value such as phone number or email address.
             PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
     DbtrAcct - DebtorAccount[0..1]Unambiguous identification of the account of the debtor to which a debit entry will be made as a result of the transaction.
         Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
             IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
             Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                 Id - Identification[0..1]Identification assigned by an institution.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         Tp - Type[0..1]Specifies the nature, or use of the account.
             Cd - Code[0..1]Account type, in a coded form.
             Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
         Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
         Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
         Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
             Tp - Type[0..1]Type of the proxy identification.
                 Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                 Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
             Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
     DbtrAgt - DebtorAgent[1..1]Financial institution servicing an account for the debtor.
         FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[1..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     DbtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     CdtrAgt - CreditorAgent[1..1]Financial institution servicing an account for the creditor.
         FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[1..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     CdtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     Cdtr - Creditor[1..1]Party to which an amount of money is due.
         Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
         PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
             AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                 Cd - Code[0..1]Type of address expressed as a code.
                 Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                     Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                     Issr - Issuer[0..1]Entity that assigns the identification.
                     SchmeNm - SchemeName[0..1]Short textual description of the scheme.
             CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
             Dept - Max70Text[0..1]Name of a department within an organization.
             SubDept - Max70Text[0..1]Name of a sub-department within a department.
             StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
             BldgNb - Max16Text[0..1]Number that identifies a building on the street.
             BldgNm - Max140Text[0..1]Name of the building, if applicable.
             Flr - Max70Text[0..1]Floor number or identifier within a building.
             UnitNb - Max16Text[0..1]Unit or apartment number within a building.
             PstBx - Max16Text[0..1]Post office box number.
             Room - Max70Text[0..1]Room number or identifier within a building.
             PstCd - Max16Text[0..1]Postal code or ZIP code.
             TwnNm - Max140Text[0..1]Name of the town or city.
             TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
             DstrctNm - Max140Text[0..1]Name of the district or region.
             CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
             Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
             AdrLine - Max70Text[0..1]Free-form text line for the address.
         Id - Identification[1..1]Unique and unambiguous identification of a party.
             OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                 AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                 LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                 Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Identification assigned by an institution.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             PrvtId - Person[1..1]Unique and unambiguous identification of a person, for example a passport.
                 DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                     BirthDt - BirthDate[0..1]Date on which a person was born.
                     PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                     CityOfBirth - CityOfBirth[0..1]City where a person was born.
                     CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                 Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
         CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
         CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
             NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
             MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
             FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
             URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
             EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
             EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
             JobTitl - JobTitle[0..1]Title of the function.
             Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
             Dept - Department[0..1]Identification of a division of a large organisation or building.
             Othr - OtherContact[0..1]Contact details in another form.
                 ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                 Id - Identifier[0..1]Communication value such as phone number or email address.
             PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
     CdtrAcct - CreditorAccount[0..1]Unambiguous identification of the account of the creditor to which a credit entry will be posted as a result of the payment transaction.
         Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
             IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
             Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                 Id - Identification[0..1]Identification assigned by an institution.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         Tp - Type[0..1]Specifies the nature, or use of the account.
             Cd - Code[0..1]Account type, in a coded form.
             Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
         Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
         Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
         Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
             Tp - Type[0..1]Type of the proxy identification.
                 Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                 Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
             Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
     UltmtCdtr - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
     InstrForCdtrAgt - InstructionForCreditorAgent[0..1]Set of elements used to provide information on the remittance advice.
         Cd - Code[0..1]Coded information related to the processing of the payment instruction, provided by the initiating party, and intended for the creditor's agent.
         InstrInf - InstructionInformation[0..1]Further information complementing the coded instruction or instruction to the creditor's agent that is bilaterally agreed or specific to a user community.
     InstrForNxtAgt - InstructionForNextAgent[0..1]Set of elements used to provide information on the remittance advice.
         Cd - Code[0..1]Coded information related to the processing of the payment instruction, provided by the initiating party, and intended for the next agent in the payment chain.
         InstrInf - InstructionInformation[0..1]Further information complementing the coded instruction or instruction to the next agent that is bilaterally agreed or specific to a user community.
     Purp - Purpose[0..1]Underlying reason for the payment transaction.
         Cd - Code[0..1]
Underlying reason for the payment transaction, as published in an external purpose code list.
         Prtry - Proprietary[0..1]
Purpose, in a proprietary form.
     RgltryRptg - RegulatoryReporting[0..1]Information needed due to regulatory and statutory requirements.
         DbtCdtRptgInd - DebitCreditReportingIndicator[0..1]Identifies whether the regulatory reporting information applies to the debit side, to the credit side or to both debit and credit sides of the transaction.
         Authrty - Authority[0..1]
Entity requiring the regulatory reporting information.
             Nm - Name[0..1]
Name of the entity requiring the regulatory reporting information.
             Ctry - Country[0..1]
Country of the entity that requires the regulatory reporting information.
         Dtls - Details[0..1]Identifies whether the regulatory reporting information applies to the debit side, to the credit side or to both debit and credit sides of the transaction.
             Tp - Type[0..1]
Specifies the type of the information supplied in the regulatory reporting details.
             Dt - Date[0..1]
Date related to the specified type of regulatory reporting details.
             Ctry - Country[0..1]
Country related to the specified type of regulatory reporting details.
             Cd - Code[0..1]Specifies the nature, purpose, and reason for the transaction to be reported for regulatory and statutory requirements in a coded form.
             Amt - Amount[0..1]
Amount of money to be reported for regulatory and statutory requirements.
             Inf - Information[0..1]
Additional details that cater for specific domestic regulatory requirements.
     Tax - Tax[0..1]Provides details on the tax.
         Cdtr - Creditor[0..1]
Party on the credit side of the transaction to which the tax applies.
             TaxId - TaxIdentification[0..1]
Tax identification number of the creditor.
             RegnId - RegistrationIdentification[0..1]
Unique identification, as assigned by an organisation, to unambiguously identify a party.
             TaxTp - TaxType[0..1]
Type of tax payer.
         Dbtr - Debtor[0..1]
Party on the debit side of the transaction to which the tax applies.
             TaxId - TaxIdentification[0..1]
Tax identification number of the debtor.
             RegnId - RegistrationIdentification[0..1]
Unique identification, as assigned by an organisation, to unambiguously identify a party.
             TaxTp - TaxType[0..1]
Type of tax payer.
             Authstn - Authorisation[0..1]
Details of the authorised tax paying party.
                 Titl - Title[0..1]
Title or position of debtor or the debtor's authorised representative.
                 Nm - Name[0..1]
Name of the debtor or the debtor's authorised representative.
         UltmtDbtr - UltimateDebtor[0..1]
Ultimate party that owes an amount of money to the (ultimate) creditor, in this case, to the taxing authority.
             TaxId - TaxIdentification[0..1]
Tax identification number of the debtor.
             RegnId - RegistrationIdentification[0..1]
Unique identification, as assigned by an organisation, to unambiguously identify a party.
             TaxTp - TaxType[0..1]
Type of tax payer.
             Authstn - Authorisation[0..1]
Details of the authorised tax paying party.
                 Titl - Title[0..1]
Title or position of debtor or the debtor's authorised representative.
                 Nm - Name[0..1]
Name of the debtor or the debtor's authorised representative.
         AdmstnZone - AdministrationZone[0..1]
Territorial part of a country to which the tax payment is related.
         RefNb - ReferenceNumber[0..1]
Tax reference information that is specific to a taxing agency.
         Mtd - Method[0..1]
Method used to indicate the underlying business or how the tax is paid.
         TtlTaxblBaseAmt - TotalTaxableBaseAmount[0..1]
Total amount of money on which the tax is based.
         TtlTaxAmt - TotalTaxAmount[0..1]
Total amount of money as result of the calculation of the tax.
         Dt - Date[0..1]
Date by which tax is due.
         SeqNb - SequenceNumber[0..1]
Sequential number of the tax report.
         Rcrd - Record[0..1]
Details of the tax record.
             Tp - Type[0..1]
High level code to identify the type of tax details.
             Ctgy - Category[0..1]
Specifies the tax code as published by the tax authority.
             CtgyDtls - CategoryDetails[0..1]
Provides further details of the category tax code.
             DbtrSts - DebtorStatus[0..1]
Code provided by local authority to identify the status of the party that has drawn up the settlement document.
             CertId - CertificateIdentification[0..1]
Identification number of the tax report as assigned by the taxing authority.
             FrmsCd - FormsCode[0..1]
Identifies, in a coded form, on which template the tax report is to be provided.
             Prd - Period[0..1]
Set of elements used to provide details on the period of time related to the tax payment.
                 Yr - Year[0..1]
Year related to the tax payment.
                 Tp - Type[0..1]
Identification of the period related to the tax payment.
                 FrToDt - FromToDate[0..1]
Range of time between a start date and an end date for which the tax report is provided.
                     FrDt - FromDate[0..1]Start date of the range.
                     ToDt - ToDate[0..1]End date of the range.
             TaxAmt - TaxAmount[0..1]
Set of elements used to provide information on the amount of the tax record.
                 Rate - Rate[0..1]
Rate used to calculate the tax.
                 TaxblBaseAmt - TaxableBaseAmount[0..1]
Amount of money on which the tax is based.
                 TtlAmt - TotalAmount[0..1]
Total amount that is the result of the calculation of the tax for the record.
                 Dtls - Details[0..1]
Set of elements used to provide details on the tax period and amount.
                     Prd - Period[0..1]
Set of elements used to provide details on the period of time related to the tax payment.
                         Yr - Year[0..1]
Year related to the tax payment.
                         Tp - Type[0..1]
Identification of the period related to the tax payment.
                         FrToDt - FromToDate[0..1]
Range of time between a start date and an end date for which the tax report is provided.
                             FrDt - FromDate[0..1]Start date of the range.
                             ToDt - ToDate[0..1]End date of the range.
                     Amt - Amount[0..1]
Underlying tax amount related to the specified period.
             AddtlInf - AdditionalInformation[0..1]
Further details of the tax record.
     RltdRmtInf - RemittanceLocation8[0..0]
     RmtInf - RemittanceInformation22[0..0]
     SplmtryData - SupplementaryData1[0..0]Additional information that cannot be captured in the structured fields and/or any other specific block.
SplmtryData - SupplementaryData1[0..0]Additional information that cannot be captured in the structured fields and/or any other specific block.
+ diff --git a/docs/product/features/Iso20022/script/quotes_error_PUT.md b/docs/product/features/Iso20022/script/quotes_error_PUT.md new file mode 100644 index 000000000..17eb44914 --- /dev/null +++ b/docs/product/features/Iso20022/script/quotes_error_PUT.md @@ -0,0 +1,180 @@ + +## 7.9 PUT /quotes/{ID}/error +| Financial Institution to Financial Institution Payment Status Report - **pacs.002.001.15**| +|--| + +#### Context +*(DFSP -> DFSP, HUB -> DFSP)* + +This is triggered as a callback response to the POST /quotes call when an error occurs. The message is generated by the entity who first encounter the error which can either be the DFSP, or the HUB. All other participants involved are informed by this message. The `TxInfAndSts.StsRsnInf.Rsn.Cd` contains the Mojaloop error code, which specified the source and cause of the error. + +Here is an example of the message: +```json +{ +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{"StsRsnInf":{"Rsn": {"Prtry":"ErrorCode"}}} +} +``` + +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - GroupHeader120[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - MessageIdentification[1..1]Definition: Point to point reference, as assigned by the instructing party, and sent to the next party in the chain to unambiguously identify the message.
Usage: The instructing party has to make sure that MessageIdentification is unique per instructed party for a pre-agreed period.
     CreDtTm - CreationDateTime[1..1]Date and time at which the message was created.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     OrgnlBizQry - OriginalBusinessQuery1[0..0]
OrgnlGrpInfAndSts - OriginalGroupHeader22[0..0]
TxInfAndSts - PaymentTransaction161[1..1]Information concerning the original transactions, to which the status report message refers.
     StsId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to unambiguously identify the status report.
     OrgnlGrpInf - OriginalGroupInformation29[0..0]
     OrgnlInstrId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original instruction.

(FSPIOP equivalent: transactionRequestId)
     OrgnlEndToEndId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original end-to-end transaction.

(FSPIOP equivalent: transactionId)
     OrgnlTxId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original transaction.

(FSPIOP equivalent: quoteId)
     OrgnlUETR - UUIDv4Identifier[0..1]Unique end-to-end transaction reference, as assigned by the original sending party, to unambiguously identify the original transaction.
     TxSts - ExternalPaymentTransactionStatus1Code[0..1]Specifies the status of the transaction.
     StsRsnInf - StatusReasonInformation14[1..1]Information concerning the reason for the status.
         Orgtr - Originator[0..1]Party that issues the status.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[0..1]Unique and unambiguous identification of a party.
                 OrgId - Organisation[0..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - Person[0..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - OtherContact[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
         Rsn - Reason[1..1]Specifies the reason for the status report.
             Cd - Code[1..1]Reason for the status, as published in an external reason code list.
             Prtry - Proprietary[1..1]Reason for the status, in a proprietary form.
         AddtlInf - AdditionalInformation[0..1]Additional information about the status report.
     ChrgsInf - Charges16[0..0]NOTE: Unsure on description.

Seemingly a generic schema for charges, with an amount, agent, and type.
     AccptncDtTm - ISODateTime[0..1]Date and time at which the status was accepted.
     PrcgDt - DateAndDateTime2Choice[0..1]Date/time at which the instruction was processed by the specified party.
         Dt - Date[0..1]Specified date.
         DtTm - DateTime[0..1]Specified date and time.
     FctvIntrBkSttlmDt - DateAndDateTime2Choice[0..0]Specifies the reason for the status.
     AcctSvcrRef - Max35Text[0..1]Unique reference, as assigned by the account servicing institution, to unambiguously identify the status report.
     ClrSysRef - Max35Text[0..1]Reference that is assigned by the account servicing institution and sent to the account owner to unambiguously identify the transaction.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     OrgnlTxRef - OriginalTransactionReference42[0..0]
     SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
         PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
         Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
     PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
     Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
+ diff --git a/docs/product/features/Iso20022/script/transfers_PATCH.md b/docs/product/features/Iso20022/script/transfers_PATCH.md new file mode 100644 index 000000000..d72267e16 --- /dev/null +++ b/docs/product/features/Iso20022/script/transfers_PATCH.md @@ -0,0 +1,180 @@ +## 7.17 PATCH /transfers/{ID} +| Financial Institution to Financial Institution Payment Status Report - **pacs.002.001.15**| +|--| + +#### Context +*(HUB -> DFSP)* + +This message use by the HUB to inform a payee DFSP participant of the successful conclusion of a transfer. This message is only generated if the payee DFSP response with a Reserved status when providing the fulfillment in the `PUT \transfers` message. + +Here is an example of the message: +```json +{ +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{ + "PrcgDt":{"DtTm":"2024-11-04T12:57:45.213Z"}, + "TxSts":"COMM"} +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - GroupHeader120[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - MessageIdentification[1..1]Definition: Point to point reference, as assigned by the instructing party, and sent to the next party in the chain to unambiguously identify the message.
Usage: The instructing party has to make sure that MessageIdentification is unique per instructed party for a pre-agreed period.
     CreDtTm - CreationDateTime[1..1]Date and time at which the message was created.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     OrgnlBizQry - OriginalBusinessQuery1[0..0]
OrgnlGrpInfAndSts - OriginalGroupHeader22[0..0]
TxInfAndSts - PaymentTransaction161[1..1]Information concerning the original transactions, to which the status report message refers.
     StsId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to unambiguously identify the status report.
     OrgnlGrpInf - OriginalGroupInformation29[0..0]
     OrgnlInstrId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original instruction.

(FSPIOP equivalent: transactionRequestId)
     OrgnlEndToEndId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original end-to-end transaction.

(FSPIOP equivalent: transactionId)
     OrgnlTxId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original transaction.

(FSPIOP equivalent: quoteId)
     OrgnlUETR - UUIDv4Identifier[0..1]Unique end-to-end transaction reference, as assigned by the original sending party, to unambiguously identify the original transaction.
     TxSts - ExternalPaymentTransactionStatus1Code[1..1]Specifies the status of the transaction.
     StsRsnInf - StatusReasonInformation14[0..1]Information concerning the reason for the status.
         Orgtr - Originator[0..1]Party that issues the status.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[0..1]Unique and unambiguous identification of a party.
                 OrgId - Organisation[0..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - Person[0..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - OtherContact[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
         Rsn - Reason[0..1]Specifies the reason for the status report.
             Cd - Code[0..1]Reason for the status, as published in an external reason code list.
             Prtry - Proprietary[0..1]Reason for the status, in a proprietary form.
         AddtlInf - AdditionalInformation[0..1]Additional information about the status report.
     ChrgsInf - Charges16[0..0]NOTE: Unsure on description.

Seemingly a generic schema for charges, with an amount, agent, and type.
     AccptncDtTm - ISODateTime[0..1]Date and time at which the status was accepted.
     PrcgDt - DateAndDateTime2Choice[1..1]Date/time at which the instruction was processed by the specified party.
         Dt - Date[1..1]Specified date.
         DtTm - DateTime[1..1]Specified date and time.
     FctvIntrBkSttlmDt - DateAndDateTime2Choice[0..0]Specifies the reason for the status.
     AcctSvcrRef - Max35Text[0..1]Unique reference, as assigned by the account servicing institution, to unambiguously identify the status report.
     ClrSysRef - Max35Text[0..1]Reference that is assigned by the account servicing institution and sent to the account owner to unambiguously identify the transaction.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     OrgnlTxRef - OriginalTransactionReference42[0..0]
     SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
         PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
         Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
     PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
     Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
+ diff --git a/docs/product/features/Iso20022/script/transfers_POST.md b/docs/product/features/Iso20022/script/transfers_POST.md new file mode 100644 index 000000000..2fccb0fee --- /dev/null +++ b/docs/product/features/Iso20022/script/transfers_POST.md @@ -0,0 +1,623 @@ +## 7.14 POST /transfers +| Financial Institution to Financial Institution Customer Credit Transfer - **pacs.008.001.13**| +|--| + +#### Context +*(DFSP -> DFSP)* + +This message is initiated by a payer DFSP who is requesting to transfer funds. The message is sent to the payee DFSP who provided the transfer terms in the `PUT /quotes` message. This message is an acknowledgement that the terms of the transfer are accepted, and is thus an instruction to proceed with the transfer. + +The transfer amount which is the clearing amount that the payee DFSP receives is defined in the `CdtTrfTxInf.IntrBkSttlmAmt.Ccy` and `CdtTrfTxInf.IntrBkSttlmAmt.ActiveCurrencyAndAmount` fields. If this transfer includes currency conversion, then this amount an currency must correspond with the target amount and currency. + +This message can be seen as an agreement to the terms that have previously been set up and established in the `PUT \quotes` message. The `CdtTrfTxInf.VrfctnOfTerms.IlpV4PrepPacket` field is the ILP packet containing the terms that have been agreed to. + +The `GrpHdr.PmtInstrXpryDtTm` specifies the expiry of the this transfer message. It is the responsibility of the HUB to enforce this expiry. The status of which a DFSP can query by making a `GET /transfers/{ID}` request. + +Here is an example of the message: +```json +{ +"GrpHdr":{ + "MsgId":"01JBVM1D2MR6D4WBWWYY3ZHGMM", + "CreDtTm":"2024-11-04T12:57:45.812Z", + "NbOfTxs":"1", + "SttlmInf":{"SttlmMtd":"CLRG"}, + "PmtInstrXpryDtTm":"2024-11-04T12:58:45.810Z"}, +"CdtTrfTxInf":{ + "PmtId":{"TxId":"01JBVM13SQYP507JB1DYBZVCMF"}, + "ChrgBr":"CRED", + "Cdtr":{"Id":{"PrvtId":{"Othr":{"SchmeNm":{"Prtry":"MSISDN"}, + "Id":"16665551002"}}}}, + "Dbtr":{"Id":{"PrvtId":{"Othr":{"SchmeNm":{"Prtry":"MSISDN"}, + "Id":"16135551001"}}}, + "Name":"Joe Blogs"}, + "CdtrAgt":{"FinInstnId":{"Othr":{"Id":"payee-dfsp"}}}, + "DbtrAgt":{"FinInstnId":{"Othr":{"Id":"payer-dfsp"}}}, + "IntrBkSttlmAmt":{"Ccy":"MWK", + "ActiveCurrencyAndAmount":"1080"}, + "VrfctnOfTerms":{"IlpV4PrepPacket":"DIICzQAAAAAAAaX..."}} +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - Group Header[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - Message Identification[1..1]Group Header Set of characteristics shared by all individual transactions included in the message.
     CreDtTm - ISODateTime[1..1]Creation Date and Time
     BtchBookg - BatchBookingIndicator[0..0]
     NbOfTxs - Max15NumericText[1..1]Number of Transactions
     CtrlSum - DecimalNumber[0..0]
     TtlIntrBkSttlmAmt - ActiveCurrencyAndAmount[0..0]A number of monetary units specified in an active currency where the unit of currency is explicit and compliant with ISO 4217.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmInf - Settlement Information[1..1]Group Header Set of characteristics shared by all individual transactions included in the message.
         SttlmMtd - SettlementMethod1Code[1..1]Only the CLRG: Clearing option is supported.
Specifies the details on how the settlement of the original transaction(s) between the
instructing agent and the instructed agent was completed.
         SttlmAcct - CashAccount40[0..0]Provides the details to identify an account.
         ClrSys - ClearingSystemIdentification3Choice[0..0]
         InstgRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         InstgRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         InstdRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         InstdRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
         ThrdRmbrsmntAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
         ThrdRmbrsmntAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     PmtTpInf - PaymentTypeInformation28[0..0]Provides further details of the type of payment.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
CdtTrfTxInf - CreditTransferTransaction64[1..1]Credit Transfer Transaction Information
Set of elements providing information specific to the individual credit transfer(s).
     PmtId - PaymentIdentification[1..1]Set of elements used to reference a payment instruction.
         InstrId - Max35Text[0..1]InstructionIdentification (FSPIOP equivalent: transactionRequestId)

Definition: Unique identification, as assigned by an instructing party for an instructed party, to
unambiguously identify the instruction.

Usage: The instruction identification is a point to point reference that can be used between the
instructing party and the instructed party to refer to the individual instruction. It can be included in
several messages related to the instruction.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         EndToEndId - Max35Text[0..1]EndToEndIdentification (FSPIOP equivalent: transactionId)

Definition: Unique identification, as assigned by the initiating party, to unambiguously identify the
transaction. This identification is passed on, unchanged, throughout the entire end-to-end chain.

Usage: The end-to-end identification can be used for reconciliation or to link tasks relating to the
transaction. It can be included in several messages related to the transaction.

Usage: In case there are technical limitations to pass on multiple references, the end-to-end
identification must be passed on throughout the entire end-to-end chain.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         TxId - Max35Text[1..1]TransactionIdentification (FSPIOP equivalent: quoteId in quote request, transferId in transfer request)

Definition: Unique identification, as assigned by the first instructing agent, to unambiguously identify the
transaction that is passed on, unchanged, throughout the entire interbank chain.

Usage: The transaction identification can be used for reconciliation, tracking or to link tasks relating to
the transaction on the interbank level.

Usage: The instructing agent has to make sure that the transaction identification is unique for a preagreed period.

This field has been changed from the original ISO20022 `Max35Text`` schema to a ULIDIdentifier schema.
         UETR - UETR[0..1]Universally unique identifier to provide an end-to-end reference of a payment transaction.
         ClrSysRef - ClearingSystemReference[0..1]Unique reference, as assigned by a clearing system, to unambiguously identify the instruction.
     PmtTpInf - PaymentTypeInformation[0..1]Set of elements used to further specify the type of transaction.
         InstrPrty - Priority2Code[0..1]Indicator of the urgency or order of importance that the instructing party
would like the instructed party to apply to the processing of the instruction.

HIGH: High priority
NORM: Normal priority
         ClrChanl - ClearingChannel2Code[0..1]Specifies the clearing channel for the routing of the transaction, as part of
the payment type identification.

RTGS: RealTimeGrossSettlementSystem Clearing channel is a real-time gross settlement system.
RTNS: RealTimeNetSettlementSystem Clearing channel is a real-time net settlement system.
MPNS: MassPaymentNetSystem Clearing channel is a mass payment net settlement system.
BOOK: BookTransfer Payment through internal book transfer.
         SvcLvl - ServiceLevel[0..1]Agreement under which or rules under which the transaction should be processed.
             Cd - Code[0..1]Specifies a pre-agreed service or level of service between the parties, as published in an external service level code list.
             Prtry - Proprietary[0..1]Specifies a pre-agreed service or level of service between the parties, as a proprietary code.
         LclInstrm - LocalInstrument[0..1]Definition: User community specific instrument.
Usage: This element is used to specify a local instrument, local clearing option and/or further qualify the service or service level.
             Cd - Code[0..1]Specifies the local instrument, as published in an external local instrument code list.
             Prtry - Proprietary[0..1]Specifies the local instrument, as a proprietary code.
         CtgyPurp - CategoryPurpose[0..1]Specifies the high level purpose of the instruction based on a set of pre-defined categories.
             Cd - Code[0..1]Category purpose, as published in an external category purpose code list.
             Prtry - Proprietary[0..1]Category purpose, in a proprietary form.
     IntrBkSttlmAmt - InterbankSettlementAmount[1..1]Amount of money moved between the instructing agent and the instructed agent.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmPrty - Priority3Code[0..0]
     SttlmTmIndctn - SettlementDateTimeIndication1[0..0]
     SttlmTmReq - SettlementTimeRequest2[0..0]
     AccptncDtTm - ISODateTime[0..0]A particular point in the progression of time defined by a mandatory
date and a mandatory time component, expressed in either UTC time
format (YYYY-MM-DDThh:mm:ss.sssZ), local time with UTC offset format
(YYYY-MM-DDThh:mm:ss.sss+/-hh:mm), or local time format
(YYYY-MM-DDThh:mm:ss.sss). These representations are defined in
"XML Schema Part 2: Datatypes Second Edition -
W3C Recommendation 28 October 2004" which is aligned with ISO 8601.

Note on the time format:
1) beginning / end of calendar day
00:00:00 = the beginning of a calendar day
24:00:00 = the end of a calendar day

2) fractions of second in time format
Decimal fractions of seconds may be included. In this case, the
involved parties shall agree on the maximum number of digits that are allowed.
     PoolgAdjstmntDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     InstdAmt - InstructedAmount[0..1]Amount of money to be moved between the debtor and creditor, before deduction of charges, expressed in the currency as ordered by the initiating party.
     XchgRate - ExchangeRate[0..1]Factor used to convert an amount from one currency into another. This reflects the price at which one currency was bought with another currency.
     ChrgBr - ChargeBearerType1Code[1..1]Provides further details specific to the individual transaction(s) included in the message.
     ChrgsInf - ChargesInformation[0..1]Provides information on the charges to be paid by the charge bearer(s) related to the payment transaction.
         Amt - Amount[0..1]Transaction charges to be paid by the charge bearer.
         Agt - Agent[0..1]Agent that takes the transaction charges or to which the transaction charges are due.
             FinInstnId - FinancialInstitutionIdentification[0..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
                 BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
                 ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                     ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                         Cd - Code[0..1]Clearing system identification code, as published in an external list.
                         Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                     MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
                 LEI - LEI[0..1]Legal entity identifier of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
                 Othr - Other[0..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
                 Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
                 LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
                 Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
                 PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                     AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                         Cd - Code[0..1]Type of address expressed as a code.
                         Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                             Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                             Issr - Issuer[0..1]Entity that assigns the identification.
                             SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                     CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                     Dept - Max70Text[0..1]Name of a department within an organization.
                     SubDept - Max70Text[0..1]Name of a sub-department within a department.
                     StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                     BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                     BldgNm - Max140Text[0..1]Name of the building, if applicable.
                     Flr - Max70Text[0..1]Floor number or identifier within a building.
                     UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                     PstBx - Max16Text[0..1]Post office box number.
                     Room - Max70Text[0..1]Room number or identifier within a building.
                     PstCd - Max16Text[0..1]Postal code or ZIP code.
                     TwnNm - Max140Text[0..1]Name of the town or city.
                     TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                     DstrctNm - Max140Text[0..1]Name of the district or region.
                     CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                     Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                     AdrLine - Max70Text[0..1]Free-form text line for the address.
         Tp - Type[0..1]Defines the type of charges.
             Cd - Code[0..1]Charge type, in a coded form.
             Prtry - Proprietary[0..1]Type of charge in a proprietary form, as defined by the issuer.
                 Id - Identification[0..1]Name or number assigned by an entity to enable recognition of that entity, for example, account identifier.
                 Issr - Issuer[0..1]Entity that assigns the identification.
     MndtRltdInf - CreditTransferMandateData1[0..0]
     PrvsInstgAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
     PrvsInstgAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
     PrvsInstgAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     PrvsInstgAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt1 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt1Acct - CashAccount40[0..0]Provides the details to identify an account.
     IntrmyAgt2 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt2Acct - CashAccount40[0..0]Provides the details to identify an account.
     IntrmyAgt3 - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     IntrmyAgt3Acct - CashAccount40[0..0]Provides the details to identify an account.
     UltmtDbtr - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
     InitgPty - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
     Dbtr - Debtor[1..1]Party that owes an amount of money to the (ultimate) creditor.
         Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
         PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
             AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                 Cd - Code[0..1]Type of address expressed as a code.
                 Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                     Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                     Issr - Issuer[0..1]Entity that assigns the identification.
                     SchmeNm - SchemeName[0..1]Short textual description of the scheme.
             CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
             Dept - Max70Text[0..1]Name of a department within an organization.
             SubDept - Max70Text[0..1]Name of a sub-department within a department.
             StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
             BldgNb - Max16Text[0..1]Number that identifies a building on the street.
             BldgNm - Max140Text[0..1]Name of the building, if applicable.
             Flr - Max70Text[0..1]Floor number or identifier within a building.
             UnitNb - Max16Text[0..1]Unit or apartment number within a building.
             PstBx - Max16Text[0..1]Post office box number.
             Room - Max70Text[0..1]Room number or identifier within a building.
             PstCd - Max16Text[0..1]Postal code or ZIP code.
             TwnNm - Max140Text[0..1]Name of the town or city.
             TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
             DstrctNm - Max140Text[0..1]Name of the district or region.
             CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
             Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
             AdrLine - Max70Text[0..1]Free-form text line for the address.
         Id - Identification[1..1]Unique and unambiguous identification of a party.
             OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                 AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                 LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                 Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Identification assigned by an institution.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             PrvtId - Person[1..1]Unique and unambiguous identification of a person, for example a passport.
                 DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                     BirthDt - BirthDate[0..1]Date on which a person was born.
                     PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                     CityOfBirth - CityOfBirth[0..1]City where a person was born.
                     CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                 Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
         CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
         CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
             NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
             MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
             FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
             URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
             EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
             EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
             JobTitl - JobTitle[0..1]Title of the function.
             Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
             Dept - Department[0..1]Identification of a division of a large organisation or building.
             Othr - OtherContact[0..1]Contact details in another form.
                 ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                 Id - Identifier[0..1]Communication value such as phone number or email address.
             PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
     DbtrAcct - DebtorAccount[0..1]Unambiguous identification of the account of the debtor to which a debit entry will be made as a result of the transaction.
         Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
             IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
             Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                 Id - Identification[0..1]Identification assigned by an institution.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         Tp - Type[0..1]Specifies the nature, or use of the account.
             Cd - Code[0..1]Account type, in a coded form.
             Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
         Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
         Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
         Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
             Tp - Type[0..1]Type of the proxy identification.
                 Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                 Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
             Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
     DbtrAgt - DebtorAgent[1..1]Financial institution servicing an account for the debtor.
         FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[1..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     DbtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     CdtrAgt - CreditorAgent[1..1]Financial institution servicing an account for the creditor.
         FinInstnId - FinancialInstitutionIdentification[1..1]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
             BICFI - BICFI[0..1]Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362 "Banking - Banking telecommunication messages - Business identifier code (BIC)"
             ClrSysMmbId - ClearingSystemMemberIdentification[0..1]Information used to identify a member within a clearing system
                 ClrSysId - ClearingSystemIdentification[0..1]Specification of a pre-agreed offering between clearing agents or the channel through which the payment instruction is processed.
                     Cd - Code[0..1]Clearing system identification code, as published in an external list.
                     Prtry - Proprietary[0..1]Proprietary identification of the clearing system.
                 MmbId - MemberIdentification[0..1]Identification of a member of a clearing system.
             LEI - LEI[0..1]Legal entity identifier of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..0]Specifies a character string with a maximum length of 140 characters.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..0]Specifies a character string with a maximum length of 16 characters.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Othr - Other[1..1]Unique identification of an agent, as assigned by an institution, using an identification scheme.
                 Id - Identification[1..1]Unique and unambiguous identification of a person.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         BrnchId - BranchIdentification[0..1]Identifies a specific branch of a financial institution.
             Id - Identification[0..1]Unique and unambiguous identification of a branch of a financial institution.
             LEI - LEI[0..1]Legal entity identification for the branch of the financial institution.
             Nm - Name[0..1]Name by which an agent is known and which is usually used to identify that agent.
             PstlAdr - PostalAddress[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
     CdtrAgtAcct - CashAccount40[0..0]Provides the details to identify an account.
     Cdtr - Creditor[1..1]Party to which an amount of money is due.
         Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
         PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
             AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                 Cd - Code[0..1]Type of address expressed as a code.
                 Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                     Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                     Issr - Issuer[0..1]Entity that assigns the identification.
                     SchmeNm - SchemeName[0..1]Short textual description of the scheme.
             CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
             Dept - Max70Text[0..1]Name of a department within an organization.
             SubDept - Max70Text[0..1]Name of a sub-department within a department.
             StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
             BldgNb - Max16Text[0..1]Number that identifies a building on the street.
             BldgNm - Max140Text[0..1]Name of the building, if applicable.
             Flr - Max70Text[0..1]Floor number or identifier within a building.
             UnitNb - Max16Text[0..1]Unit or apartment number within a building.
             PstBx - Max16Text[0..1]Post office box number.
             Room - Max70Text[0..1]Room number or identifier within a building.
             PstCd - Max16Text[0..1]Postal code or ZIP code.
             TwnNm - Max140Text[0..1]Name of the town or city.
             TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
             DstrctNm - Max140Text[0..1]Name of the district or region.
             CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
             Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
             AdrLine - Max70Text[0..1]Free-form text line for the address.
         Id - Identification[1..1]Unique and unambiguous identification of a party.
             OrgId - Organisation[1..1]Unique and unambiguous way to identify an organisation.
                 AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                 LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                 Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Identification assigned by an institution.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
             PrvtId - Person[1..1]Unique and unambiguous identification of a person, for example a passport.
                 DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                     BirthDt - BirthDate[0..1]Date on which a person was born.
                     PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                     CityOfBirth - CityOfBirth[0..1]City where a person was born.
                     CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                 Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                     Id - Identification[0..1]Unique and unambiguous identification of a person.
                     SchmeNm - SchemeName[0..1]Name of the identification scheme.
                         Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                         Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                     Issr - Issuer[0..1]Entity that assigns the identification.
         CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
         CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
             NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
             MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
             FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
             URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
             EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
             EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
             JobTitl - JobTitle[0..1]Title of the function.
             Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
             Dept - Department[0..1]Identification of a division of a large organisation or building.
             Othr - OtherContact[0..1]Contact details in another form.
                 ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                 Id - Identifier[0..1]Communication value such as phone number or email address.
             PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
     CdtrAcct - CreditorAccount[0..1]Unambiguous identification of the account of the creditor to which a credit entry will be posted as a result of the payment transaction.
         Id - Identification[0..1]Unique and unambiguous identification for the account between the account owner and the account servicer.
             IBAN - IBAN[0..1]International Bank Account Number (IBAN) - identifier used internationally by financial institutions to uniquely identify the account of a customer. Further specifications of the format and content of the IBAN can be found in the standard ISO 13616 "Banking and related financial services - International Bank Account Number (IBAN)" version 1997-10-01, or later revisions.
             Othr - Other[0..1]Unique identification of an account, as assigned by the account servicer, using an identification scheme.
                 Id - Identification[0..1]Identification assigned by an institution.
                 SchmeNm - SchemeName[0..1]Name of the identification scheme.
                     Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                     Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                 Issr - Issuer[0..1]Entity that assigns the identification.
         Tp - Type[0..1]Specifies the nature, or use of the account.
             Cd - Code[0..1]Account type, in a coded form.
             Prtry - Proprietary[0..1]Nature or use of the account in a proprietary form.
         Ccy - Currency[0..1]Identification of the currency in which the account is held.
Usage: Currency should only be used in case one and the same account number covers several currencies and the initiating party needs to identify which currency needs to be used for settlement on the account.
         Nm - Name[0..1]Name of the account, as assigned by the account servicing institution, in agreement with the account owner in order to provide an additional means of identification of the account.
Usage: The account name is different from the account owner name. The account name is used in certain user communities to provide a means of identifying the account, in addition to the account owner's identity and the account number.
         Prxy - Proxy[0..1]Specifies an alternate assumed name for the identification of the account.
             Tp - Type[0..1]Type of the proxy identification.
                 Cd - Code[0..1]Proxy account type, in a coded form as published in an external list.
                 Prtry - Proprietary[0..1]Proxy account type, in a proprietary form.
             Id - Identification[0..1]Identification used to indicate the account identification under another specified name.
     UltmtCdtr - PartyIdentification272[0..0]Specifies the identification of a person or an organisation.
     InstrForCdtrAgt - InstructionForCreditorAgent[0..1]Set of elements used to provide information on the remittance advice.
         Cd - Code[0..1]Coded information related to the processing of the payment instruction, provided by the initiating party, and intended for the creditor's agent.
         InstrInf - InstructionInformation[0..1]Further information complementing the coded instruction or instruction to the creditor's agent that is bilaterally agreed or specific to a user community.
     InstrForNxtAgt - InstructionForNextAgent[0..1]Set of elements used to provide information on the remittance advice.
         Cd - Code[0..1]Coded information related to the processing of the payment instruction, provided by the initiating party, and intended for the next agent in the payment chain.
         InstrInf - InstructionInformation[0..1]Further information complementing the coded instruction or instruction to the next agent that is bilaterally agreed or specific to a user community.
     Purp - Purpose[0..1]Underlying reason for the payment transaction.
         Cd - Code[0..1]
Underlying reason for the payment transaction, as published in an external purpose code list.
         Prtry - Proprietary[0..1]
Purpose, in a proprietary form.
     RgltryRptg - RegulatoryReporting[0..1]Information needed due to regulatory and statutory requirements.
         DbtCdtRptgInd - DebitCreditReportingIndicator[0..1]Identifies whether the regulatory reporting information applies to the debit side, to the credit side or to both debit and credit sides of the transaction.
         Authrty - Authority[0..1]
Entity requiring the regulatory reporting information.
             Nm - Name[0..1]
Name of the entity requiring the regulatory reporting information.
             Ctry - Country[0..1]
Country of the entity that requires the regulatory reporting information.
         Dtls - Details[0..1]Identifies whether the regulatory reporting information applies to the debit side, to the credit side or to both debit and credit sides of the transaction.
             Tp - Type[0..1]
Specifies the type of the information supplied in the regulatory reporting details.
             Dt - Date[0..1]
Date related to the specified type of regulatory reporting details.
             Ctry - Country[0..1]
Country related to the specified type of regulatory reporting details.
             Cd - Code[0..1]Specifies the nature, purpose, and reason for the transaction to be reported for regulatory and statutory requirements in a coded form.
             Amt - Amount[0..1]
Amount of money to be reported for regulatory and statutory requirements.
             Inf - Information[0..1]
Additional details that cater for specific domestic regulatory requirements.
     Tax - Tax[0..1]Provides details on the tax.
         Cdtr - Creditor[0..1]
Party on the credit side of the transaction to which the tax applies.
             TaxId - TaxIdentification[0..1]
Tax identification number of the creditor.
             RegnId - RegistrationIdentification[0..1]
Unique identification, as assigned by an organisation, to unambiguously identify a party.
             TaxTp - TaxType[0..1]
Type of tax payer.
         Dbtr - Debtor[0..1]
Party on the debit side of the transaction to which the tax applies.
             TaxId - TaxIdentification[0..1]
Tax identification number of the debtor.
             RegnId - RegistrationIdentification[0..1]
Unique identification, as assigned by an organisation, to unambiguously identify a party.
             TaxTp - TaxType[0..1]
Type of tax payer.
             Authstn - Authorisation[0..1]
Details of the authorised tax paying party.
                 Titl - Title[0..1]
Title or position of debtor or the debtor's authorised representative.
                 Nm - Name[0..1]
Name of the debtor or the debtor's authorised representative.
         UltmtDbtr - UltimateDebtor[0..1]
Ultimate party that owes an amount of money to the (ultimate) creditor, in this case, to the taxing authority.
             TaxId - TaxIdentification[0..1]
Tax identification number of the debtor.
             RegnId - RegistrationIdentification[0..1]
Unique identification, as assigned by an organisation, to unambiguously identify a party.
             TaxTp - TaxType[0..1]
Type of tax payer.
             Authstn - Authorisation[0..1]
Details of the authorised tax paying party.
                 Titl - Title[0..1]
Title or position of debtor or the debtor's authorised representative.
                 Nm - Name[0..1]
Name of the debtor or the debtor's authorised representative.
         AdmstnZone - AdministrationZone[0..1]
Territorial part of a country to which the tax payment is related.
         RefNb - ReferenceNumber[0..1]
Tax reference information that is specific to a taxing agency.
         Mtd - Method[0..1]
Method used to indicate the underlying business or how the tax is paid.
         TtlTaxblBaseAmt - TotalTaxableBaseAmount[0..1]
Total amount of money on which the tax is based.
         TtlTaxAmt - TotalTaxAmount[0..1]
Total amount of money as result of the calculation of the tax.
         Dt - Date[0..1]
Date by which tax is due.
         SeqNb - SequenceNumber[0..1]
Sequential number of the tax report.
         Rcrd - Record[0..1]
Details of the tax record.
             Tp - Type[0..1]
High level code to identify the type of tax details.
             Ctgy - Category[0..1]
Specifies the tax code as published by the tax authority.
             CtgyDtls - CategoryDetails[0..1]
Provides further details of the category tax code.
             DbtrSts - DebtorStatus[0..1]
Code provided by local authority to identify the status of the party that has drawn up the settlement document.
             CertId - CertificateIdentification[0..1]
Identification number of the tax report as assigned by the taxing authority.
             FrmsCd - FormsCode[0..1]
Identifies, in a coded form, on which template the tax report is to be provided.
             Prd - Period[0..1]
Set of elements used to provide details on the period of time related to the tax payment.
                 Yr - Year[0..1]
Year related to the tax payment.
                 Tp - Type[0..1]
Identification of the period related to the tax payment.
                 FrToDt - FromToDate[0..1]
Range of time between a start date and an end date for which the tax report is provided.
                     FrDt - FromDate[0..1]Start date of the range.
                     ToDt - ToDate[0..1]End date of the range.
             TaxAmt - TaxAmount[0..1]
Set of elements used to provide information on the amount of the tax record.
                 Rate - Rate[0..1]
Rate used to calculate the tax.
                 TaxblBaseAmt - TaxableBaseAmount[0..1]
Amount of money on which the tax is based.
                 TtlAmt - TotalAmount[0..1]
Total amount that is the result of the calculation of the tax for the record.
                 Dtls - Details[0..1]
Set of elements used to provide details on the tax period and amount.
                     Prd - Period[0..1]
Set of elements used to provide details on the period of time related to the tax payment.
                         Yr - Year[0..1]
Year related to the tax payment.
                         Tp - Type[0..1]
Identification of the period related to the tax payment.
                         FrToDt - FromToDate[0..1]
Range of time between a start date and an end date for which the tax report is provided.
                             FrDt - FromDate[0..1]Start date of the range.
                             ToDt - ToDate[0..1]End date of the range.
                     Amt - Amount[0..1]
Underlying tax amount related to the specified period.
             AddtlInf - AdditionalInformation[0..1]
Further details of the tax record.
     RltdRmtInf - RemittanceLocation8[0..0]
     RmtInf - RemittanceInformation22[0..0]
     SplmtryData - SupplementaryData1[0..0]Additional information that cannot be captured in the structured fields and/or any other specific block.
SplmtryData - SupplementaryData1[0..0]Additional information that cannot be captured in the structured fields and/or any other specific block.
+ diff --git a/docs/product/features/Iso20022/script/transfers_PUT.md b/docs/product/features/Iso20022/script/transfers_PUT.md new file mode 100644 index 000000000..af096fbc0 --- /dev/null +++ b/docs/product/features/Iso20022/script/transfers_PUT.md @@ -0,0 +1,99 @@ +## 7.15 PUT /transfers/{ID} +| Financial Institution to Financial Institution Payment Status Report - **pacs.002.001.15**| +|--| + +#### Context +*(DFSP -> DFSP, DFSP -> HUB, HUB -> DFSP)* + +This message is a response to the `POST \transfers` call initiated by the DFSP who is requesting to proceed with the transfer terms presented in the `PUT \quotes`. It is the payee DFSPs responsibility to check that the clearing amounts align with the agreed transfer terms, and if all requirements are met, this message is used to lock-in the agreed terms. Once the hub receives this acceptance message, the transfer can no-longer timeout and will be committed. If this transfer is a dependent transfer in a currency conversion, then that currency conversion will be committed at the same time as this transfer. + +The cryptographic ILP fulfillment provided in the `TxInfAndSts.ExctnConf` field, is released by the payee DFSP as an indication to the HUB that the terms have been met. + +Here is an example of the message: +```json +{ +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{ + "ExctnConf":"ou1887jmG-l...", + "PrcgDt":{ + "DtTm":"2024-11-04T12:57:45.213Z"}, + "TxSts":"RESV"} +} +``` + +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - GroupHeader113[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - MessageIdentification[1..1]Definition: Point to point reference, as assigned by the instructing party, and sent to the next party in the chain to unambiguously identify the message.
Usage: The instructing party has to make sure that MessageIdentification is unique per instructed party for a pre-agreed period.
     CreDtTm - CreationDateTime[1..1]Date and time at which the message was created.
     BtchBookg - BatchBookingIndicator[0..0]
     NbOfTxs - Max15NumericText[0..0]Specifies a numeric string with a maximum length of 15 digits.
     CtrlSum - DecimalNumber[0..0]
     TtlIntrBkSttlmAmt - ActiveCurrencyAndAmount[0..0]A number of monetary units specified in an active currency where the unit of currency is explicit and compliant with ISO 4217.
     IntrBkSttlmDt - ISODate[0..0]A particular point in the progression of time in a calendar year expressed in the YYYY-MM-DD format. This representation is defined in "XML Schema Part 2: Datatypes Second Edition - W3C Recommendation 28 October 2004" which is aligned with ISO 8601.
     SttlmInf - SettlementInstruction15[0..0]Only the CLRG: Clearing option is supported.
Specifies the details on how the settlement of the original transaction(s) between the
instructing agent and the instructed agent was completed.
     PmtTpInf - PaymentTypeInformation28[0..0]Provides further details of the type of payment.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
CdtTrfTxInf - CreditTransferTransaction64[0..0]
SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
     PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
     Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
+ diff --git a/docs/product/features/Iso20022/script/transfers_error_PUT.md b/docs/product/features/Iso20022/script/transfers_error_PUT.md new file mode 100644 index 000000000..459cb3cdd --- /dev/null +++ b/docs/product/features/Iso20022/script/transfers_error_PUT.md @@ -0,0 +1,179 @@ +## 7.16 PUT /transfers/{ID}/error + +| Financial Institution to Financial Institution Payment Status Report - **pacs.002.001.15**| +|--| + +#### Context +*(DFSP -> DFSP, DFSP -> HUB, HUB -> DFSP)* + +This is triggered as a callback response to the POST /transfers call when an error occurs. The message is generated by the entity who first encounter the error which can either be the DFSP, or the HUB. All other participants involved are informed by this message. The `TxInfAndSts.StsRsnInf.Rsn.Cd` contains the Mojaloop error code, which specified the source and cause of the error. + +Here is an example of the message: +```json +{ +"GrpHdr": { + "MsgId":"01JBVM1CGC5A18XQVYYRF68FD1", + "CreDtTm":"2024-11-04T12:57:45.228Z"}, +"TxInfAndSts":{"StsRsnInf":{"Rsn": {"Prtry":"ErrorCode"}}} +} +``` +#### Message Details +The details on how to compose and make this API are covered in the following sections: +1. [Core Data Elements](#core-data-elements)
This section specifies which fields are required, which fields are optional, and which fields are unsupported in order to meet the message validating requirements. +2. [Header Details](../MarketPracticeDocument.md#_3-3-1-header-details)
This general section specifies the header requirements for the API are specified. +3. [Supported HTTP Responses](../MarketPracticeDocument.md#_3-3-2-supported-http-responses)
This general section specifies the http responses that must be supported. +4. [Common Error Payload](../MarketPracticeDocument.md#_3-3-3-common-error-payload)
This general section specifies the common error payload that is provided in synchronous http error response. + +#### Core Data Elements +Here are the core data elements that are needed to meet this market practice requirement. + +The background colours indicate the classification of the data element. + + + + + + + +
Data Model Type Key Description
requiredThese fields are required in order to meet the message validating requirements.
optionalThese fields can be optionally included in the message. (Some of these fields may be required for a specific scheme as defined in the Scheme Rules for that scheme.)
unsupportedThese fields are actively not supported. The functionality specifying data in these fields are not compatible with a Mojaloop scheme, and will fail message validation if provided.
+

+ + +Here is the defined core data element table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ISO 20022 FieldData ModelDescription
GrpHdr - GroupHeader120[1..1]Set of characteristics shared by all individual transactions included in the message.
     MsgId - MessageIdentification[1..1]Definition: Point to point reference, as assigned by the instructing party, and sent to the next party in the chain to unambiguously identify the message.
Usage: The instructing party has to make sure that MessageIdentification is unique per instructed party for a pre-agreed period.
     CreDtTm - CreationDateTime[1..1]Date and time at which the message was created.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     OrgnlBizQry - OriginalBusinessQuery1[0..0]
OrgnlGrpInfAndSts - OriginalGroupHeader22[0..0]
TxInfAndSts - PaymentTransaction161[1..1]Information concerning the original transactions, to which the status report message refers.
     StsId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to unambiguously identify the status report.
     OrgnlGrpInf - OriginalGroupInformation29[0..0]
     OrgnlInstrId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original instruction.

(FSPIOP equivalent: transactionRequestId)
     OrgnlEndToEndId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original end-to-end transaction.

(FSPIOP equivalent: transactionId)
     OrgnlTxId - Max35Text[0..1]Unique identification, as assigned by the original sending party, to
unambiguously identify the original transaction.

(FSPIOP equivalent: quoteId)
     OrgnlUETR - UUIDv4Identifier[0..1]Unique end-to-end transaction reference, as assigned by the original sending party, to unambiguously identify the original transaction.
     TxSts - ExternalPaymentTransactionStatus1Code[0..1]Specifies the status of the transaction.
     StsRsnInf - StatusReasonInformation14[1..1]Information concerning the reason for the status.
         Orgtr - Originator[0..1]Party that issues the status.
             Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
             PstlAdr - Postal Address[0..1]Information that locates and identifies a specific address, as defined by postal services.
                 AdrTp - AddressType3Choice[0..1]Type of address, as defined by the postal services.
                     Cd - Code[0..1]Type of address expressed as a code.
                     Prtry - Proprietary[0..1]Type of address expressed as a proprietary code.
                         Id - Identification[0..1]Proprietary information, often a code, issued by the data source scheme issuer.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                         SchmeNm - SchemeName[0..1]Short textual description of the scheme.
                 CareOf - Max140Text[0..1]Name of the person or entity the mail is directed to, if different from the recipient.
                 Dept - Max70Text[0..1]Name of a department within an organization.
                 SubDept - Max70Text[0..1]Name of a sub-department within a department.
                 StrtNm - Max140Text[0..1]Name of the street or thoroughfare.
                 BldgNb - Max16Text[0..1]Number that identifies a building on the street.
                 BldgNm - Max140Text[0..1]Name of the building, if applicable.
                 Flr - Max70Text[0..1]Floor number or identifier within a building.
                 UnitNb - Max16Text[0..1]Unit or apartment number within a building.
                 PstBx - Max16Text[0..1]Post office box number.
                 Room - Max70Text[0..1]Room number or identifier within a building.
                 PstCd - Max16Text[0..1]Postal code or ZIP code.
                 TwnNm - Max140Text[0..1]Name of the town or city.
                 TwnLctnNm - Max140Text[0..1]Name of the location within a town or city.
                 DstrctNm - Max140Text[0..1]Name of the district or region.
                 CtrySubDvsn - Max35Text[0..1]Name of the country subdivision, such as a state or province.
                 Ctry - CountryCode[0..1]Country code, as defined by ISO 3166-1 alpha-2.
                 AdrLine - Max70Text[0..1]Free-form text line for the address.
             Id - Identification[0..1]Unique and unambiguous identification of a party.
                 OrgId - Organisation[0..1]Unique and unambiguous way to identify an organisation.
                     AnyBIC - AnyBIC[0..1]Business identification code of the organisation.
                     LEI - LEI[0..1]Legal entity identification as an alternate identification for a party.
                     Othr - Other[0..1]Unique identification of an organisation, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Identification assigned by an institution.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
                 PrvtId - Person[0..1]Unique and unambiguous identification of a person, for example a passport.
                     DtAndPlcOfBirth - DateAndPlaceOfBirth[0..1]Date and place of birth of a person.
                         BirthDt - BirthDate[0..1]Date on which a person was born.
                         PrvcOfBirth - ProvinceOfBirth[0..1]Province where a person was born.
                         CityOfBirth - CityOfBirth[0..1]City where a person was born.
                         CtryOfBirth - CountryOfBirth[0..1]Country where a person was born.
                     Othr - Other[0..1]Unique identification of a person, as assigned by an institution, using an identification scheme.
                         Id - Identification[0..1]Unique and unambiguous identification of a person.
                         SchmeNm - SchemeName[0..1]Name of the identification scheme.
                             Cd - Code[0..1]Name of the identification scheme, in a coded form as published in an external list.
                             Prtry - Proprietary[0..1]Name of the identification scheme, in a free text form.
                         Issr - Issuer[0..1]Entity that assigns the identification.
             CtryOfRes - CountryCode[0..1]Country of Residence
Country in which a person resides (the place of a person's home). In the case of a company, it is the country from which the affairs of that company are directed.
             CtctDtls - Contact Details[0..1]Set of elements used to indicate how to contact the party.
                 NmPrfx - NamePrefix[0..1]Specifies the terms used to formally address a person.
                 Nm - Name[0..1]Name by which a party is known and which is usually used to identify that party.
                 PhneNb - PhoneNumber[0..1]Collection of information that identifies a phone number, as defined by telecom services.
                 MobNb - MobilePhoneNumber[0..1]Collection of information that identifies a mobile phone number, as defined by telecom services.
                 FaxNb - FaxNumber[0..1]Collection of information that identifies a fax number, as defined by telecom services.
                 URLAdr - URLAddress[0..1]Address for the Universal Resource Locator (URL), for example an address used over the www (HTTP) service.
                 EmailAdr - EmailAddress[0..1]Address for electronic mail (e-mail).
                 EmailPurp - EmailPurpose[0..1]Purpose for which an email address may be used.
                 JobTitl - JobTitle[0..1]Title of the function.
                 Rspnsblty - Responsibility[0..1]Role of a person in an organisation.
                 Dept - Department[0..1]Identification of a division of a large organisation or building.
                 Othr - OtherContact[0..1]Contact details in another form.
                     ChanlTp - ChannelType[0..1]Method used to contact the financial institution's contact for the specific tax region.
                     Id - Identifier[0..1]Communication value such as phone number or email address.
                 PrefrdMtd - PreferredContactMethod[0..1]Preferred method used to reach the contact.
         Rsn - Reason[1..1]Specifies the reason for the status report.
             Cd - Code[1..1]Reason for the status, as published in an external reason code list.
             Prtry - Proprietary[1..1]Reason for the status, in a proprietary form.
         AddtlInf - AdditionalInformation[0..1]Additional information about the status report.
     ChrgsInf - Charges16[0..0]NOTE: Unsure on description.

Seemingly a generic schema for charges, with an amount, agent, and type.
     AccptncDtTm - ISODateTime[0..1]Date and time at which the status was accepted.
     PrcgDt - DateAndDateTime2Choice[0..1]Date/time at which the instruction was processed by the specified party.
         Dt - Date[0..1]Specified date.
         DtTm - DateTime[0..1]Specified date and time.
     FctvIntrBkSttlmDt - DateAndDateTime2Choice[0..0]Specifies the reason for the status.
     AcctSvcrRef - Max35Text[0..1]Unique reference, as assigned by the account servicing institution, to unambiguously identify the status report.
     ClrSysRef - Max35Text[0..1]Reference that is assigned by the account servicing institution and sent to the account owner to unambiguously identify the transaction.
     InstgAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     InstdAgt - BranchAndFinancialInstitutionIdentification8[0..0]Unique and unambiguous identification of a financial institution or a branch of a financial institution.
     OrgnlTxRef - OriginalTransactionReference42[0..0]
     SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
         PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
         Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
SplmtryData - SupplementaryData1[0..1]Additional information that cannot be captured in the structured elements and/or any other specific block.
     PlcAndNm - PlaceAndName[0..1]Unambiguous reference to the location where the supplementary data must be inserted in the message instance.
     Envlp - Envelope[0..1]Technical element wrapping the supplementary data.
Technical component that contains the validated supplementary data information. This technical envelope allows to segregate the supplementary data information from any other information.
+ diff --git a/docs/product/features/SimpleInterscheme.svg b/docs/product/features/SimpleInterscheme.svg new file mode 100644 index 000000000..33e945028 --- /dev/null +++ b/docs/product/features/SimpleInterscheme.svg @@ -0,0 +1,4 @@ + + + +
Scheme 1
Scheme 1
Scheme 2
Scheme 2
DFSP 1
DFSP 1
DFSP 2
DFSP 2
Proxy
Proxy
\ No newline at end of file diff --git a/docs/product/features/Test.png b/docs/product/features/Test.png new file mode 100644 index 000000000..c68bb2e19 Binary files /dev/null and b/docs/product/features/Test.png differ diff --git a/docs/product/features/XB.svg b/docs/product/features/XB.svg new file mode 100644 index 000000000..ac97cc76a --- /dev/null +++ b/docs/product/features/XB.svg @@ -0,0 +1,4 @@ + + + +
Jurisdiction B
Jurisdiction B
Jurisdiction A
Jurisdiction A
Scheme 1
Scheme 1
Scheme 2
Scheme 2
DFSP 1
DFSP 1
DFSP 2
DFSP 2
Proxy
Proxy
FXP 1
FXP 1
FXP 3
FXP 3
FXP 2
FXP 2
\ No newline at end of file diff --git a/docs/product/features/connectivity.md b/docs/product/features/connectivity.md new file mode 100644 index 000000000..ef87e4329 --- /dev/null +++ b/docs/product/features/connectivity.md @@ -0,0 +1,35 @@ +# Connectivity + +In principle, having developed and documented the [Mojaloop APIs](./transaction.md#Mojaloop APIs), this should be sufficient to enable DFSPs to connect to a Mojaloop Hub. However, as part of the Mojaloop Community's mission to address financial inclusion, it has long been felt that the key to minimising the cost and complexity of connecting a DFSP's back office to a Mojaloop Hub is through the provision of a portfolio of connectivity solutions, allowing a DFSP to select the approach that best meets their needs. + +The current connectivity portfolio includes a toolkit that would allow a Systems Integrator (SI) to create a connection by combining the various elements of a toolkit in a way that best meets the DFSP's needs. These elements include: + - Mojaloop Connection Manager (MCM); + - Mojaloop Connector (for integrating with the Mojaloop Hub); + - A set of example Core Connectors (for integrating with the DFSP's back office); + - Integration Toolkit; + - Documentation, including "how to" guides and templates. + +For detailed guidance on which connectivity solution is most appropriate for different participant types and requirements, please refer to the [Participant Feature Matrix](./connectivity/participant-matrix.md). + +This toolkit is complemented by three exemplar implementations, ready for customisation and use by a DFSP (or their SI): + - "Premium Service Manager": A fully functional, Payment Manager-type service, for use by larger DFSPs. Operation of this needs significant resources; it must be hosted either in the DFSP's existing data centre or in the cloud. + + - "Enhanced Service Manager": Based on the "Standard Service Manager" (below), this extends it by adding a Kafka deployment and support for bulk payments. It can be hosted in a basic server, but the Raspberry Pi option is not recommended. + + - "Standard Service Manager": A minimal functionality Integration Toolkit-based solution (bundled with some form of BI tool). This can be hosted in a basic server, ranging from a mid-specification server for a large MFI or a small bank, right down to a Raspberry PI for the smallest DFSPs with less rigorous service continuity requirements and lower transaction volumes. The Standard Service Manager does not support bulk payments. + + +All DFSPs should be aware that reaping the benefits of an inclusive instant payments solution such as Mojaloop relies on the implementation of a "whole ecosystem" approach - and this means extending the reach of the Mojaloop service into the DFSPs' domains, giving them and their customers the advantages of assurance of transaction finality, lower cost and the reliable delivery of every valid transaction. + +Note that the adoption of an exemplar installation affects the type of service a DFSP can provide to their customers. The Premium option is suitable for DFSPs with high throughout and reliability requirements, the Enhanced option places some limits on throughput and availability and may be best suited to medium or small DFSPs, and the Standard option places strict limits on throughput and availability and removes the ability to initiate bulk payments, and so may only be suitable for small DFSPs. + +## Applicability + +This version of this document relates to Mojaloop Version [17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.2|9th June 2025| Tony Williams|Added reference to participant feature matrix| +|1.1|14th April 2025| Paul Makin|Updates related to the release of V17| +|1.0|5th February 2025| Paul Makin|Initial version| \ No newline at end of file diff --git a/docs/product/features/connectivity/participant-matrix.md b/docs/product/features/connectivity/participant-matrix.md new file mode 100644 index 000000000..981709f26 --- /dev/null +++ b/docs/product/features/connectivity/participant-matrix.md @@ -0,0 +1,176 @@ +# Participant Feature Matrix + +This document provides a comprehensive matrix of different participant types, their requirements, and recommended connectivity solutions for Mojaloop integration. + + + +## Payment Use-Case DFSPs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Participant CategoryDescriptionExpected Use-CasesInfrastructure Requirements for Mojaloop IntegrationExpected Production SLALikely Relevant RegulationSpecial Security RequirementsSolution Options
Small self-hosting DFSP- Small FI with single branch.
- Own workstations
- Minimal cloud and/or SaaS.
- All moja transfer types except bulk.
- Open banking (incl PISP, AISP)
- Single, cheap, low-end dedicated mini-pc (e.g. RPi)
- Single small business broadband Internet connection
- Self-hosted core banking system e.g. Mifos
- Use OS/Software firewall on same HW node as integration layer.
- "Some" downtime acceptable if hardware fails.
- Some schemes may rule out DFSPs that cant meet a certain downtime SLA.
- May take many days/weeks to purchase replacement hardware on total failure.
- Full Mojaloop security feature set: mTLS, JWS, ILP
- ~10 TPS peak sustained for 1 hour.
- Max capable of 864000 per 24 hours.
- Record keeping?
- Security?
- No need to integrate with existing enterprise security platforms.
- Need a fully secure solution "in-a-box" following best industry practice for internet facing services i.e. including firewall.
The “Standard Service Manager” is recommended: A minimal functionality Integration Toolkit-based solution (accessible locally by means of a BI tool). This can be hosted in a basic server, ranging from a mid-specification server for a large MFI or a small bank, right down to a Raspberry PI for the smallest DFSPs with less rigorous service continuity requirements and lower transaction volumes. The Standard Service Manager does not support bulk payments.
- Docker compose based integration layer.
- Minimal, self-contained integration layer.
Low Medium self-hosted DFSP- Small FI with one or two branches.
- Own "data centre" i.e. broom cupboard with a few servers, router, firewall etc...
- Some cloud knowledge and/or SaaS usage.
- All moja transfer types
- Bulk (1000's of transfers).
- Open banking (incl PISP, AISP)
- Single enterprise grade server hardware node.
- Use OS/Software firewall on same HW node as integration layer OR dedicated HW firewall.
- "Some" downtime acceptable if hardware fails.
- Some schemes may rule out DFSPs that cant meet a certain downtime SLA.
- May take hours to replace hardware on total failure.
- Full Mojaloop security feature set: mTLS, JWS, ILP
- ~50 TPS peak sustained for 1 hour.
- Record keeping?
- Security?
- May need integration with existing enterprise security platforms e.g. firewalls, gateways etc...
?? needs more clarification
The “Enhanced Service Manager” is recommended: Based on the “Standard Service Manager” described earlier, this extends it by adding a Kafka deployment and support for bulk payments. It can be hosted at minimum in a basic server in the DFSP's own "data centre".
- Docker compose or docker swarm based integration layer.
- Minimal, self-contained integration layer.
High Medium self-hosted DFSP- Small FI with one or two branches.
- Own "data centre" i.e. broom cupboard with a few servers, router, firewall etc...
- Some cloud knowledge and/or SaaS usage.
- All moja transfer types
- Bulk (1000's of transfers).
- Open banking (incl PISP, AISP)
- In order to tolerate failure on 1 hardware node 3 or more hardware nodes are required. (2n+1)- "Some" limited (minutes) downtime acceptable if hardware fails.
- Some schemes may rule out DFSPs that cant meet a certain downtime SLA.
- Should have spare hardware waiting or very fast replacement services in case of failures.
- Full Mojaloop security feature set: mTLS, JWS, ILP
- ~50 TPS peak sustained for 1 hour.
- Record keeping?
- Security?
- May need integration with existing enterprise security platforms e.g. firewalls, gateways etc...The “Enhanced Service Manager” is recommended: Based on the “Standard Service Manager” described earlier, this extends it by adding a Kafka deployment and support for bulk payments. It can be hosted at minimum in a redundant, multiple server configuration in the DFSP's own "data centre".
- Kubernetes based integration layer
- Possibly have existing integration technology.
Large self-hosted DFSP- Mature, multi-branch FI with high internal IT capability
- Has own data centre and experts to manage systems
- Comfortable with Cloud and hybrid applications
- Has internal software engineering capability.
- All moja transfer types including bulk.
- Bulk (1000000's of transfers in a transaction @ 1000 per chunk, sorted per payee DFSP).
- Open banking (incl PISP, AISP)
- High availability of internal infrastructure is necessary
- Multiple active instances of all critical integration services spread across multiple hardware nodes.
- High availability, replicated data storage.
- may be multi-site / availability zone / region.
- No downtime acceptable
- High-availability of connectivity.
- multiple active connections via diverse routes.
- Optional persistent storage.
- Scheme connection and integration layer SLA should match SLA for existing internal infrastructure.
- Up to 800 TPS peak sustained for 1 hour for e.g. FXPs.
- Record keeping?
- Security?
- May need integration with existing enterprise security platforms e.g. firewalls, gateways etc...The “Premium Service Manager” is recommended: A fully functional, Payment Manager-type service, for use by larger DFSPs. Operation of this needs significant resources; it must be hosted either in the DFSP’s existing data centre or in the cloud.
- Kubernetes based integration layer
- Possibly have existing integration technology.
+ +## Fintechs which use PISP and/or AISP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Participant CategoryDescriptionExpected Use-CasesInfrastructure Requirements for Mojaloop IntegrationExpected Production SLALikely Relevant RegulationSpecial Security RequirementsSolution Options
Small self-hosting PISP/AISP- Small org with single "branch" fintech with one or two products.
- Own workstations / servers
- Minimal cloud and/or SaaS.
- Relatively small bulk payments e.g. salary payments for SMEs- Single, cheap, low-end dedicated mini-pc (e.g. RPi)
- Single small business broadband Internet connection
- Self-hosted core banking system e.g. Mifos
- Use OS/Software firewall on same HW node as integration layer.
- "Some" downtime acceptable if hardware fails.
- Some schemes may rule out DFSPs that cant meet a certain downtime SLA.
- May take many days/weeks to purchase replacement hardware on total failure.
- Full Mojaloop security feature set: mTLS, JWS, ILP
- Bulk interface SLA?
- How should this be defined? Batch size? time to send batch over API? response time for callbacks?
- Max batch size approx 10k payments
- Sending 10k payments via bulk API should take < 30 seconds.
- Responding to callbacks should take < 5 seconds.
- Record keeping?
- Security?
- No need to integrate with existing enterprise security platforms.
- Need a fully secure solution "in-a-box" following best industry practice for internet facing services i.e. including firewall.
- Docker compose based integration layer.
- Minimal, self-contained integration layer.
Low Medium self-hosting PISP/AISP- Small org with one or two branches.
- Own "data centre" i.e. broom cupboard with a few servers, router, firewall etc...
- Some cloud knowledge and/or SaaS usage.
- Relatively small bulk payments e.g. salary payments for SMEs
- Account aggregation
- Single enterprise grade server hardware node.
- Use OS/Software firewall on same HW node as integration layer OR dedicated HW firewall.
- "Some" downtime acceptable if hardware fails.
- Some schemes may rule out DFSPs that cant meet a certain downtime SLA.
- May take hours to replace hardware on total failure.
- Full Mojaloop security feature set: mTLS, JWS, ILP
- Bulk interface SLA?
- How should this be defined? Batch size? time to send batch over API? response time for callbacks?
- Max batch size approx 25k payments
- Sending 25k payments via bulk API should take < 60 seconds.
- Responding to callbacks should take < 10 seconds.
- Record keeping?
- Security?
- May need integration with existing enterprise security platforms e.g. firewalls, gateways etc...
?? needs more clarification
- Docker compose or docker swarm based integration layer.
- Minimal, self-contained integration layer.
High Medium self-hosting PISP/AISP- Small org with one or two branches.
- Own "data centre" i.e. broom cupboard with a few servers, router, firewall etc...
- Some cloud knowledge and/or SaaS usage.
- Bulk payment for large organisations e.g. government depts.
- Account aggregation
- In order to tolerate failure on 1 hardware node 3 or more hardware nodes are required. (2n+1)- "Some" limited (minutes) downtime acceptable if hardware fails.
- Some schemes may rule out DFSPs that cant meet a certain downtime SLA.
- Should have spare hardware waiting or very fast replacement services in case of failures.
- Full Mojaloop security feature set: mTLS, JWS, ILP
- Bulk interface SLA?
- How should this be defined? Batch size? time to send batch over API? response time for callbacks?
- Max batch size approx 100-200k payments
- Sending 100-200k payments via bulk API should take < 300 seconds.
- Responding to callbacks should take < 120 seconds.
- Record keeping?
- Security?
- May need integration with existing enterprise security platforms e.g. firewalls, gateways etc...- Kubernetes based integration layer
- Possibly have existing integration technology.
Large self-hosting PISP/AISP- Mature, multi-branch org with high internal IT capability
- Has own data centre and experts to manage systems
- Comfortable with Cloud and hybrid applications
- Has internal software engineering capability.
- Bulk payment for large organisations e.g. government depts.- High availability of internal infrastructure is necessary
- Multiple active instances of all critical integration services spread across multiple hardware nodes.
- High availability, replicated data storage.
- may be multi-site / availability zone / region.
- No downtime acceptable
- High-availability of connectivity.
- multiple active connections via diverse routes.
- Optional persistent storage.
- Scheme connection and integration layer SLA should match SLA for existing internal infrastructure.
- Bulk interface SLA?
- How should this be defined? Batch size? time to send batch over API? response time for callbacks?
- Max batch size approx 1mil payments
- Sending 1mil payments via bulk API should take < 600 seconds.
- Responding to callbacks should take < 300 seconds.
- Record keeping?
- Security?
- May need integration with existing enterprise security platforms e.g. firewalls, gateways etc...- Kubernetes based integration layer
- Possibly have existing integration technology.
+ +## Document History +|Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.0|9th June 2025|Tony Williams|Initial version| \ No newline at end of file diff --git a/docs/product/features/deployment.md b/docs/product/features/deployment.md new file mode 100644 index 000000000..20271c1cd --- /dev/null +++ b/docs/product/features/deployment.md @@ -0,0 +1,16 @@ +# Deploying Mojaloop +There is a range of different reasons to deploy Mojaloop, ranging from a desire to learn more about Mojaloop or a wish to evaluate its suitability for some purpose, through developers who wish to develop or test new features, or perhaps an adopter who wishes to evaluate its functionality and connectivity, through to a production-grade deployment of a national payments system. + +## Deployment Guide + +For each scenario, the Mojaloop Community has developed appropriate deployment tools. The following [deployment guide](./deployment/deploying.md) includes a matrix cross-referencing user types and the purpose of the deployment, including notes about the footprint/hardware expectation and the associated SLAs. For each, a deployment tool is recommended, and a separate table provides a brief introduction to each tool. + +## Deployment Tools + +Having established which deployment tool is appropriate for the reader's requirements, the [deployment tools guide](./deployment/tools.md) provides more details for each of the tools, including performance and security features each supports. + + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.0|3rd June 2025| Paul Makin|Initial version| \ No newline at end of file diff --git a/docs/product/features/deployment/deploying.md b/docs/product/features/deployment/deploying.md new file mode 100644 index 000000000..0bc1ed39c --- /dev/null +++ b/docs/product/features/deployment/deploying.md @@ -0,0 +1,232 @@ +# Deploying Mojaloop + +This section details the deployment aspects of the Mojaloop Hub. + +## Deployment of Mojaloop Hub (excluding participant integrations) + +The following table provides guidance on which Mojaloop deployment scenario is most appropriate for different user types and use cases. + +For detailed information about each deployment tool, please refer to the [Deployment Tools](./tools) documentation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Deployment Scenario / User typeLearningEvaluation (choosing Mojaloop)Use-case TestingFeature Development and Dev TestingProduction
StudentFootprint: Single machine e.g. laptop or single VM.
SLA: None
??Footprint: Single machine e.g. laptop or single VM.
SLA: None
N/A
DeveloperFootprint: Single machine e.g. laptop or single VM.
SLA: None
?Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
N/A
Business analystFootprint: Single machine e.g. laptop or single VM.
SLA: None
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
N/A
Potential adopterFootprint: Single machine e.g. laptop or single VM.
SLA: None
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
N/A
Auditor / External QA / Security AnalystFootprint: Single machine e.g. laptop or single VM.
SLA: None
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
N/AN/A
System IntegratorFootprint: Single machine e.g. laptop or single VM.
SLA: None
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
Footprint:
- Fully redundant, replicated, high availability deployment
- On-premises or cloud
SLA: High SLA in many areas.
Hub OperatorFootprint: Single machine e.g. laptop or single VM.
SLA: None
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
Footprint:
- Single machine e.g. laptop or single VM.
- Production like environment (sandbox? lower SLA than prod)
SLA:
- Lower than prod but possibility of testing NFRs.
Footprint:
- Fully redundant, replicated, high availability deployment
- On-premises or cloud
SLA: High SLA in many areas.
+ +## Deployment Tools + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ToolFeaturesMinimum Resource RequirementsSecurityDocumentationSLACaveats, Assumptions, Limitations etc...
core test harness- single node
- docker-compose
- "profiles" available
- No HELM
- No gateway
- No ingress/egress components
- No IAM stack
- Deploys:
- core services & backing services
- portals (optional)
- monitoring stack (optional)

Used in CI pipelines for integration testing.
Mid level laptop or desktop workstationZero security- Developer focused documentation.
- Non-technical user documentation to support learning objectives.
- Product level documentation to explain features e.g. what it does and where it is appropriate for use
- No SLA- Never to be used in production.
- Never to be used to process real money transactions.
HELM deploy- Just HELM charts needed to deploy Mojaloop services and backing services.- High end laptop or workstation
- Small cloud kubernetes cluster.
User is required to harden their own Kubernetes cluster.- Developer focused documentation
- Semi-technical / BA focused documentation to support use-case experimentation and testing.
- Product level documentation to explain features e.g. what it does and where it is appropriate for use.
- Must be able to achieve SLAs (given baseline hardware specs):
- Availability:
- ? 4/5 9's?
- RTO/RPO: ? As close to zero as possible.
- Throughput/Performance
- TPS: 1000+ (sustained for 1 hour)
- Latency (Percentiles) (excluding external latencies):
- Clearing: 99% < 1 second.
- Lookup: 99% < second.
- Agreement of Terms: 99% < 1 second.
- Data management:
- Mitigations against data loss i.e. replication, disaster recovery.
- Retention (audit, compliance)
- Archiving.

NB: Strategy is high availability over disaster recovery.
- Can be used in production.
- Safe for processing real money transactions.
- User/adopter is required to deploy and configure their own infrastructure, including Kubernetes cluster(s), ingress/egress, firewalls etc...
- Security is limited to what HELM charts provide. Additional security design and configuration is required.
Infrastructure as Code- multiple deployment platform targets
- AWS, On-prem, other clouds, (modular)
- multiple orchestration layer options
- managed k8s, microk8s, eks
- GitOps pattern (control centre)
- can deploy and manage multiple hub instances / environments
- Deploys:
- control centre
- core services & backing services (options for managed backing services)
- portals
- IAM stack
- monitoring stack
- pm4ml
- GitOps pattern
- High end cloud or on-premise infrastructure.Full security- Multiple levels of documentation targeting all levels of "user".
- Developer docs to enable use, maintenance, enhancement, extenstion of IaC capabilities e.g. adding new targets / services / features.
- Detailed architecture diagrams and explanation to enable deep understanding.
- Tech ops focused docs to enable "infrastructure engineer" level users to use IaC to deploy and maintain multiple mojaloop instances for development, testing and production.
- Product level documentation to explain IaC features e.g. what it does and where it is appropriate for use.
- Must be able to achieve SLAs (given baseline hardware specs):
- Availability:
- ? 4/5 9's?
- RTO/RPO: ? As close to zero as possible.
- Throughput/Performance
- TPS: 1000+ (sustained for 1 hour)
- Latency (Percentiles) (excluding external latencies):
- Clearing: 99% < 1 second.
- Lookup: 99% < second.
- Agreement of Terms: 99% < 1 second.
- Data management:
- Mitigations against data loss i.e. replication, disaster recovery.
- Retention (audit, compliance)
- Archiving.

NB: Strategy is high availability over disaster recovery.
- Can be used in production.
- Safe for processing real money transactions.
+ +## Document History +|Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.1|3rd June 2025|Paul Makin|Removed performance section, moved it to new doc| +|1.0|7th May 2025|Tony Williams|Initial version| \ No newline at end of file diff --git a/docs/product/features/deployment/tools.md b/docs/product/features/deployment/tools.md new file mode 100644 index 000000000..ed3f77c3e --- /dev/null +++ b/docs/product/features/deployment/tools.md @@ -0,0 +1,134 @@ +# Mojaloop Deployment Tools + +This document outlines the three deployment options for Mojaloop, ordered by complexity and production-readiness. Each tool serves specific use cases and deployment scenarios. + +## Core Test Harness + +
+
+ Development and Testing Environment +
+ +The Core Test Harness provides a single-node development environment using docker-compose. This tool implements a minimal Mojaloop stack without production components, making it suitable for development and testing. + +> **🔗 Technical Documentation:** +> **GAP** - No dedicated technical documentation found for Core Test Harness. Related references in: +> - [Deployment Guide - Prerequisite Backend Helm Deployment](../../../technical/technical/deployment-guide/README.md#_5-1-prerequisite-backend-helm-deployment) (mentions docker-compose examples) +> - [Release Notes](../../../technical/technical/releases.md) (mentions Core-test-harness validation) + +### Implementation Details + +The Core Test Harness runs on a single machine using docker-compose for orchestration. It deploys core services and backing services without production-grade components like gateways, ingress/egress, or IAM stacks. The implementation uses configurable profiles to manage different deployment scenarios. + +Resource requirements include a mid-level laptop or desktop workstation with sufficient memory for container orchestration. The tool integrates with CI pipelines for automated testing and validation. + +### Development Workflow + +Developers interact with the Core Test Harness through docker-compose commands. The tool supports local development workflows with hot-reloading capabilities. Configuration occurs through environment variables and docker-compose override files. + +### Testing Capabilities + +The Core Test Harness enables unit testing, integration testing, and end-to-end testing of Mojaloop components. It provides a controlled environment for testing service interactions and validating business logic. + +## HELM Deploy + +
+
+ Production Deployment Solution +
+ +HELM Deploy provides production-ready deployment capabilities through HELM charts. This implementation requires a pre-configured Kubernetes cluster and implements production-grade security and performance requirements. + +> **🔗 Technical Documentation:** +> - [Mojaloop Deployment Guide](../../../technical/technical/deployment-guide/README.md) - Comprehensive HELM deployment documentation +> - [Upgrade Strategy Guide](../../../technical/technical/deployment-guide/upgrade-strategy-guide.md) - HELM upgrade procedures +> - [Deployment Troubleshooting](../../../technical/technical/deployment-guide/deployment-troubleshooting.md) - Common issues and solutions + +### Infrastructure Requirements + +The deployment requires: +- A hardened Kubernetes cluster +- Network policies and security configurations +- Storage class definitions +- Resource quotas and limits + +### Performance Specifications + +The implementation must meet these performance criteria: +- 1000+ TPS sustained for one hour +- 99th percentile latency under 1 second for: + - Clearing operations + - Lookup operations + - Agreement of Terms +- 99.99% availability +- Zero RTO/RPO for critical operations + +### Security Implementation + +Security implementation includes: +- Network policy enforcement +- Pod security policies +- Service mesh integration +- Secret management +- Certificate management + +## Infrastructure as Code + +
+
+ Enterprise Deployment Solution +
+ +The Infrastructure as Code (IaC) implementation provides a comprehensive deployment solution supporting multiple platforms and orchestration layers. It implements GitOps patterns for managing multiple hub instances. + +> **🔗 Technical Documentation:** +> **GAP** - Limited internal technical documentation for IaC setup and configuration +> - [IaC Installation Guide](../../../getting-started/installation/installing-mojaloop.md) - Basic IaC overview (see item 2) +> - [IaC Deployment Blog](https://infitx.com/deploying-mojaloop-using-iac) - External detailed guide +> - [IaC AWS Platform Repository](https://github.com/mojaloop/iac-aws-platform) - AWS-specific implementation + +### Platform Support + +The implementation supports: +- AWS deployment through CloudFormation/Terraform +- On-premises deployment through Terraform +- Multi-cloud deployment through provider-agnostic modules +- Multiple Kubernetes distributions: + - Managed k8s services + - Microk8s + - EKS + +### Control Center Architecture + +The control center implements GitOps patterns for: +- Multi-environment management +- Configuration versioning +- Deployment automation +- State management +- Drift detection + +### Component Deployment + +The implementation deploys: +- Control center services +- Core Mojaloop services +- Backing services +- Portal applications +- IAM infrastructure +- Monitoring stack +- PM4ML components + +### Performance and Security + +The IaC implementation enforces: +- Production-grade security controls +- Performance requirements matching HELM Deploy +- High availability configurations +- Disaster recovery procedures +- Compliance requirements + +## Document History +|Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.1|5th June 2025| Tony Williams|Added links to technical documentation| +|1.0|14th May 2025| Tony Williams|Initial version| \ No newline at end of file diff --git a/docs/product/features/ecosystem.svg b/docs/product/features/ecosystem.svg new file mode 100644 index 000000000..e18dc9867 --- /dev/null +++ b/docs/product/features/ecosystem.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/product/features/engineering.md b/docs/product/features/engineering.md new file mode 100644 index 000000000..e02c0f17d --- /dev/null +++ b/docs/product/features/engineering.md @@ -0,0 +1,84 @@ +# Engineering Principles + +This section details the principles behind the engineering aspects of +the Mojaloop Hub. + +## Logging + +Industry-standard logging mechanisms for containers (stdout, stderr) are +the default. + +## Transfers + +1. Resource identifiers are unique within a scheme and enforced by the hub. + +2. API methods which can potentially return large result sets are paged + by default. + +3. Settlement model lookups use the currencies of payer and payee DFSP. + +4. Resources/entities are typed so they can be differentiated + +5. Names (of objects, methods, types, functions etc...) are clear and + not open to misinterpretation. + +## Accounts & Balances + +1. Ledger implementation uses a strongly consistent underlying data + store. + +2. Critical financial data is replicated to multiple geographically + distributed nodes in a manner that is strongly consistent and highly + performant, such that the failure of multiple physical nodes will + result in zero data loss. + +## Participants + +1. Participant connectivity concerns are handled at a gateway layer to + facilitate the use of industry standard tooling. + +## Scalability and Resilience + +1. Overall system transfer throughput (all three transfer phases) is + scalable in as near linear manner as possible by the addition of low + specification, commodity hardware nodes. + +2. Business critical data can be replicated to multiple geographically + distributed nodes in a manner that is strongly consistent and highly + performant; Failure of multiple physical nodes will result in zero + data loss. + +## Mojaloop Specification + +1. JWS is supported + +2. Mutually authenticated (x.509) TLS v1.2 should be supported between + participants and the hub + +## General + +1. Context specific processing is done once and results cached in + memory where required later in the same call stack. + +2. All log messages contain contextual information. + +3. Failures are anticipated and handled as gracefully as possible. + +4. Cross process / network queries ask for only the data required. + +5. Layers of abstraction are kept to an absolute minimum. + +6. Interprocess communication uses the same transport mechanism + wherever possible. + +7. Aggregates are stateless. + +## Applicability + +This version of this document relates to Mojaloop Version [17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) + +## Document History +|Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.1|14th April 2025| Paul Makin|Removed deployment sections| +|1.0|5th February 2025| James Bush|Initial version| \ No newline at end of file diff --git a/docs/product/features/fx.md b/docs/product/features/fx.md new file mode 100644 index 000000000..3e6b007b5 --- /dev/null +++ b/docs/product/features/fx.md @@ -0,0 +1,127 @@ +# Foreign Exchange - Currency Conversion + +The Mojaloop currency conversion functionality enables foreign exchange (FX) transactions, supporting multiple approaches for currency conversion within the ecosystem. Currently, the system implements **Payer DFSP currency conversion**, where the Payer DFSP (Digital Financial Services Provider) coordinates with a foreign exchange provider (FXP) to obtain liquidity in another currency to facilitate a transfer. + +Future enhancements to the currency conversion design include: +1. **Payee DFSP conversion**
The Payee DFSP arranges for foreign exchange conversion. +1. **Reference currency conversion**
Both the Payer and Payee DFSPs engage with FXPs to convert funds via a reference currency. +1. **Bulk conversion**
DFSPs can procure currency liquidity from an FXP in bulk. + +## Role of the Foreign Exchange Provider (FXP) + +A core feature of Mojaloop's currency conversion capability is its support for a competitive FX marketplace, where multiple FXPs can provide real-time exchange rate quotes. This design fosters an open and dynamic environment for foreign exchange transactions. + +The currency conversion process follows a three-step workflow: +1. **Quote Request**
The Payer DFSP requests a quote from an FXP. For example, a Zambian DFSP can obtain a conversion quote for a specific transfer. +1. **Quote Agreement**
The Payer DFSP reviews the exchange rate and terms provided by the FXP. Once accepted, the FXP locks in the rate. +1. **Transfer Finalization**
Upon notification from the Mojaloop scheme that the dependent transfer has been completed, the conversion process is finalized. + +This streamlined approach ensures transparency and competitiveness in FX transactions, benefiting both DFSPs and end users. + +## Impact of Amount Type on Currency Conversion + +The Payer DFSP conversion implementation supports two distinct scenarios based on the amount type specified in the transaction: +1. **Sending funds in the source (local) currency** +1. **Making a payment in target (a foreign) currency** + +### Sending Funds to an Account in Another Currency +In this use case, the **Payer DFSP** initiates a transfer using the amount type **SEND**, specifying the transfer amount in the payer's local currency (source currency). This method is commonly used for **P2P remittance** transfers, where the sender transfers funds in their local currency, and the recipient receives the equivalent amount in their respective currency after conversion. + +### Currency Conversion Transfer (source currency) +Below is a simplified sequence diagram showing the flows between the Participant organizations, the foreign exchange providers and the Mojaloop switch for a currency conversion transfer specified in source currency. + +The flow is divided up into: +1. [Discovery Phase](#discovery-phase) +1. [Agreement Phase - Currency Conversion](#agreement-phase---currency-conversion) +1. [Agreement Phase](#agreement-phase) +1. [Payer DFSP presents terms to Payer](#payer-dfsp-presents-terms-to-payer) +1. [Transfer Phase](#transfer-phase) + +#### Discovery Phase +The Payer DFSP identifies the Payee DFSP organization and confirms the account validity and currency. + +![Discovery Phase](./CurrencyConversion/Payer_SEND_Discovery.svg) + +#### Agreement Phase - Currency Conversion +The Payer DFSP makes a request to the FXP for liquidity cover for transfer. The currency conversion terms are returned. +![Currency Conversion](./CurrencyConversion/PAYER_SEND_CurrencyConversion.svg) + +#### Agreement Phase +The Payer DFSP makes a request to the Payee DFSP for the transfer terms. +![Agreement](./CurrencyConversion/PAYER_SEND_Agreement.svg) + +#### Payer DFSP presents terms to Payer +At this point the party information, the conversion terms, and the transfer terms have been provided to the Payer DFSP. The Payer DFSP presents these terms to the Payer and asks wether to proceed or not. +![Send Confirmation](./CurrencyConversion/PAYER_SEND_Confirmation.svg) + +#### Transfer Phase +Now that the terms of the transfer have been agreed to, the transfer can proceed. +Both the Conversion and the transfer terms are comitted together. +![Transfer](./CurrencyConversion/PAYER_SEND_Transfer.svg) + + +### Mojaloop Connector Integration for Currency Conversion + +Below is a detailed sequence diagram that shows the complete flow, and includes the **Mojaloop Connector** and integration APIs for all participant organizations. (This is a useful view if you are building integrations as a participant organization.) + +#### Discovery phase - Mojaloop Connector +Mojaloop make use of an Oracle to identify the DFSP organization associated with the Party identifier. The Payee DFSP must respond to the GET /parties to confirm that the account exists and is active for that Party identifier. The supported currencies for that account are returned. +![Discovery Phase](./CurrencyConversion/FXAPI_Discovery.svg) + + +#### Agreement Phase Currency Conversion - Mojaloop Connector +The Payer DFSP does not transact in any of the Payee DFPSs supported currencies. This triggers the requirement for currency conversion inside the Mojaloop Connector. The Payer DFSP uses it's local cache of FXPs to select and makes a request to the Foreign Exchange provider for liquidity cover and a conversion rate. +![Currecny Conversion](./CurrencyConversion/FXAPI_Payer_CurrencyConversion.svg) + +#### Agreement Phase - Mojaloop Connector +Liquidity in target currency has been secured. The Payer DFSP can now proceed to request an agreement of terms from the Payee DFSP. These terms are in target currency. +![Agreement Phase](./CurrencyConversion/FXAPI_Payer_Agreement.svg) + +#### Sender Confirmation +All the terms for the currency conversion and transfer have been obtained by the Payer DFSP and FXP. It is now time to collate those terms and present them to the Payer for confirmation. +![Confirmatiom](./CurrencyConversion/FXAPI_Payer_SenderConfirmation.svg) + +#### Transfer Phase +The terms of the transfer have been accepted. The transfer phase can now commence. +![Transfer](./CurrencyConversion/FXAPI_Payer_Transfer.svg) + +## Currency Conversion Transfer (target currency) +For this use case, the Payer DFSP will specify the transfer with amount type **RECEIVE** and define the transfer amount in the **Payee's local currency** (the target currency). +An secondary use case example for this is a cross boarder Merchant Payment. + +Below is a detailed sequence diagram that shows the complete flow, and includes the Mojaloop connector and integration APIs for all participant organizations. + +#### Discovery +Mojaloop make use of an Oracle to identify the DFSP organization associated with the Party identifier. The Payee DFSP must respond to the GET /parties to confirm that the account exists and is active for that Party identifier. The supported currencies for that account are returned. +![Discovery](./CurrencyConversion/FXAPI_Payer_Receive_Discovery.svg) + + +#### Agreement +The Payer DFSP does not support any of the Payee DFSP's currencies, requiring currency conversion within the Mojaloop Connector. Since the payment request is in the target currency, an agreement with the Payee DFSP must be established before initiating a liquidity request with the foreign exchange provider. The Payer DFSP first negotiates the transfer terms with the Payee DFSP, then uses its local cache of foreign exchange providers to select one and request liquidity coverage and a conversion rate. +![Agreement](./CurrencyConversion/FXAPI_Payer_Receive_Agreement.svg) + +#### Sender Confirmation +All the terms for the currency conversion and transfer have been obtained by the Payer DFSP and FXP. It is now time to collate those terms and present them to the Payer for confirmation. +![Sender Confirmation](./CurrencyConversion/FXAPI_Payer_Receive_SenderConfirmation.svg) + +#### Transfer +The terms of the transfer have been accepted. The transfer phase can now commence. +![Transfer](./CurrencyConversion/FXAPI_Payer_Receive_TransferPhase.svg) + + +## Abort flows +This sequence diagram show how the design implements abort messages during the currency conversion transfer phase. + +![Transfer](./CurrencyConversion/Payer_SEND_ABORT_TransferPhase.svg) + +## Open API References +These Open API references are designed to be readable for both software an review person. The show the detailed requirements and implementations of the API design. + +- [FSPIOP v2.0 specification](https://mojaloop.github.io/api-snippets/?urls.primaryName=v2.0) - [Open Api definition](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v2.0-document-set/fspiop-v2.0-openapi3-implementation-draft.yaml). +- [FSPIOP v2.0 ISO 20022 specification](https://mojaloop.github.io/api-snippets/?urls.primaryName=v2.0_ISO20022) - [Open Api definition](https://github.com/mojaloop/api-snippets/blob/main/docs/fspiop-rest-v2.0-ISO20022-openapi3-snippets.yaml). +- [API Snippets Open Api definition](https://github.com/mojaloop/api-snippets/blob/main/docs/fspiop-rest-v2.0-openapi3-snippets.yaml) +- [Mojaloop Connector backend](https://mojaloop.github.io/api-snippets/?urls.primaryName=SDK%20Backend%20v2.1.0) - [Open Api definition](https://github.com/mojaloop/api-snippets/blob/main/docs/sdk-scheme-adapter-backend-v2_1_0-openapi3-snippets.yaml) +- [Mojaloop Connector outbound](https://mojaloop.github.io/api-snippets/?urls.primaryName=SDK%20Outbound%20v2.1.0) - [Open Api definition](https://github.com/mojaloop/api-snippets/blob/main/docs/sdk-scheme-adapter-outbound-v2_1_0-openapi3-snippets.yaml) + + + diff --git a/docs/product/features/htlc.md b/docs/product/features/htlc.md new file mode 100644 index 000000000..8bedf0b08 --- /dev/null +++ b/docs/product/features/htlc.md @@ -0,0 +1,34 @@ +# Hashed Timelock Contracts +Mojaloop uses ILP's cryptographic locks to ensure atomic, conditional transfers between DFSPs. The mechanism centres around Hashed Timelock Contracts (HTLCs), which allow Mojaloop to support conditional transfers — ensuring a transfer either completes fully across all participating parties, or not at all. + +A contract is agreed between the Payee and Payer DFSPs during the Agreement of Terms phase of a Mojaloop transaction, which begins when the Payer DFSP proposes a transaction, by means of a quotation request. + +When the Payee DFSP is satisfied that the transaction can go ahead (having completed its own internal checks), the Payee DFSP: +- Amends the proposed terms of the transaction to set out the conditions on which it will carry out the transaction (which might include, for example, the fees it will charge and any compliance conditions); +- Creates the Transaction object, which defines the terms on which it is prepared to honour the payment request; +- Creates and retains the Fulfilment, which is a hash of the Transaction object, itself signed with the Payee DFSP's private key (a key created specifically for, and restricted to, this purpose); +- Creates the Condition, which is a hash of the Fulfilment; +- Appends the Condition to the Transaction object; +- And returns it to the Payer DFSP in a quotation response. + +If the Payer DFSP accepts the terms of the transaction, it sends a transfer request, comprising the Transaction object, the received Condition and an expiry time, to the Mojaloop Hub. + +The Mojaloop Hub stores the Condition, and forwards the transfer request to the Payee DFSP. It also starts a timer to match the specified expiry time. + +On receipt of the transfer request, the Payee DFSP: +- Verifies that the Condition received matches that agreed (this includes a check that the payment requested is the same as the payment it agreed to), and satisfies itself that the compliance conditions have been met; +- Returns the Fulfilment to the Mojaloop Hub in a transfer response. + +The Mojaloop Hub hashes the returned Fulfilment to validate that it matches the Condition received from the Payer DFSP, and if successful notifies the Payer DFSP (and the Payee DFSP, if this has been requested) that an obligation has been created between them; that is, that the payment has been cleared. + +The notification to the Payer DFSP includes the fulfilment, which acts as cryptographic proof of irrevocable completion. If the Payer DFSP re-generates the Condition and finds that it has changed from that agreed, then they should raise a dispute with the Payee DFSP. + +Note that if the transaction timer expires at the Hub before the Fulfilment is received from the Payee DFSP, the Hub will notify each DFSP that the transaction has been cancelled. + +## Applicability +This document relates to Mojaloop Version 17.0.0 +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.1|2nd July 2025| Paul Makin|Updated after review by Michael Richards| +|1.0|30th June 2025| Paul Makin|Initial version| \ No newline at end of file diff --git a/docs/product/features/interscheme.md b/docs/product/features/interscheme.md new file mode 100644 index 000000000..17be33f59 --- /dev/null +++ b/docs/product/features/interscheme.md @@ -0,0 +1,79 @@ +# Interscheme + +Interscheme is the approach adopted by the Mojaloop community to connect schemes while preserving the three phases of a Mojaloop transfer and ensuring end-to-end non-repudiation. This means that the agreement reached during a transfer remains between the originating and receiving DFSP/FXP organizations, regardless of the routing path or the number of schemes involved. + + +:::tip Non-repudiation +Ensuring non-repudiation across schemes means that the proxy is not involved in the agreement of terms which helps reduce costs. +::: + +The initial implementation of this feature enables the connection of multiple Mojaloop schemes. Over time, this ecosystem is expected to expand as additional national schemes adopt this protocol and new connectors are developed to enhance interoperability. + +To support this effort, Mojaloop introduced a new proxy participant organization. The proxy adapter serves as the implementation of the Mojaloop-to-Mojaloop connection component. + +## What is a Proxy +Schemes are connected via a proxy participant, which is registered to act as an intermediary within the scheme for adjacent DFSPs/FXPs in other schemes. + +## Dynamic Routing of Parties +This implementation makes use of a dynamic routing. This meaning that no initial and ongoing maintenance of party identifiers is required between schemes. The system makes use of a broadcast to scheme discovery that identifier and caches the organisation associated with a party identifier. + +## Assumptions +This approach is based off the following assumptions: +1. No two connected participants share the same identifier. +1. Each connected scheme is responsible for routing party identifiers within its own system. (In Mojaloop, this means each scheme maintains the oracles needed to route payments for participant parties in its network.) + +## General Patterns +There are certain general patterns that emerge +### Happy Path Patterns +![Happy Path Patterns](./Interscheme/Interscheme-Happypath.svg) + +### Error Patterns +![Error Patterns](./Interscheme/Interscheme-ErrorCases.svg) + +## Interscheme On Demand Discovery Design +The discovery flows are summarized as follows: +1. On Demand loading of cross network identifiers - using Oracles for identifier lookups in local scheme +2. On Demand loading for all identifiers + +### Using Oracles to Cache Identifiers +- Scheme uses Oracles to map local identifiers to participants of the scheme +- Identifiers for other schemes are discovered via a depth first search, but asking all participants. Proxy participant then forward the request to the connected scheme +- This diagram shows two connected schemes, but this design work for any number of connected schemes. + +![Interscheme - On Demand Discovery Sequence Diagram](./Interscheme/Interscheme-OnDemandDiscovery.svg) + + +### On Demand Discover with incorrectly cached results +- When an identifier moved to another dfsp provider, then the store cache for that participant will route to an unsuccessful get \parties call. +- Self heal if there is an error routing the payment or proxy cache reference is lost + +Here is a sequence diagram show how that gets updated. +#### Sequence Diagram +![Interscheme - Managing Stale Cache](./Interscheme/Interscheme-StalePartyIdentifierCache.svg) + +## Interscheme - Agreement Phase +The Agreement phase makes use of the proxy cache to route the messages. +Here are the implementation details. + +![Interscheme - Agreement](./Interscheme/Interscheme-Agreement.svg) + +## Interscheme - Transfer Phase +The Transfer phase makes use of the proxy cache to route the messages. +Here are the implementation details. + +![Interscheme - Transfers](./Interscheme/Interscheme-Transfer.svg) + +## Interscheme - GET Transfer +The GET Transfer is resolved locally to return the local schemes status of the transfer. +Here are the implementation details. +![Interscheme - GET Transfers](./Interscheme/Interscheme-GETTransfer.svg) + +## Admin API - defining Proxy Participants +This is how Proxies are defined. +![Admin API](./Interscheme/SettingUpProxys.svg) + +## Clearing Accounts for Inter-scheme FX transfers +This diagram illustrated how the obligations are updated during transaction clearing. + +![Clearing Accounts](./Interscheme/InterschemeAccounts-Clearing.png) + diff --git a/docs/product/features/invariants.md b/docs/product/features/invariants.md new file mode 100644 index 000000000..ddc0945d1 --- /dev/null +++ b/docs/product/features/invariants.md @@ -0,0 +1,360 @@ +# Invariants + +## General Principles + +**The primary function of the platform is to clear payments in real-time +and facilitate regular settlement, by the end of the value day.** + +1. The platform allows participants to clear funds immediately to their + customers while keeping the risks and costs associated with this to + a minimum. + +2. The platform supports per-transfer checks on available liquidity + where these are required in support of the first objective. + +3. The hub is optimized for critical path. + +4. Intra-day Automated Settlement; configured by scheme and + implementation using recommended settlement models for financial + market infrastructure. + +**The hub supports fully automatic straight-through processing.** + +1. Straight through processing helps reduce human errors in the + transfer process which ultimately reduces costs. + +2. The automated nature of straight through processing leads to faster + value transfers between end customers. + +**The hub requires no manual reconciliation as the protocol for +interacting with the hub guarantees deterministic outcomes.** + +1. When a transfer is finalized, there can be no doubt about the status + of that transfer (alternatively, it is not finalized and active + notice is provided to participants). +2. The hub guarantees deterministic outcomes for transfers and is + accepted by all participants as the final authority ("system of + record") on the status of transfers. +3. Determinism means individual transfers are traceable, auditable + (based on limits, constraints), with final result provided within + guaranteed time limit. +4. For the avoidance of doubt, batch transfers are processed + line-by-line with potentially differing deterministic outcomes for + each. + +**Transaction setup logic, which is use case-specific, is separated from +the policy-free transfer of money.** + +1. Transaction details and business rules should be captured and agreed + as scheme rules and technical operating guidelines. They may then be + applied during the quoting phase by those counterparties, and will + be carried between those counterparties by the Hub. +2. The agreement phase establishes a signed use-case specific + transaction object which incorporates all transaction-specific + details. +3. The transfer phase orchestrates the clearance of the transfer of + retail value between institutions for the benefit of the + counterparties (i.e only system limit checks are applied) and + without reference to transaction details. +4. No additional transaction-specific processing during the transfer + phase. + +**The hub doesn't parse or act on end-to-end transaction details; +transfer messages contain only the values required to complete clearing +and settlement.** + +1. Checks & validations during the transfer step are only for + conformance to scheme rules, limit checks, signature authentication, + and validation of payment condition and fulfillment. +2. Transfers that are committed for settlement are final and are + guaranteed to settle under the scheme rules. + +**Credit-push transfer semantics are reduced to their simplest form and +standardized for all transaction types.** + +1. Simplifies implementation and participant integration as many + transaction types and use-cases can reuse the same underlying value + transfer message flow. +2. Abstracts use-case complexity away from the critical path. + +**Internet-based API service hub is not a "message switch."** + +1. The service hub provides real-time API services for participants to + support retail credit-push instant transfers. +2. API services such as ID-to-participant look-up, transaction + agreement between participants, submission of prepared transfers, + and submission of fulfillment advice. +3. Auxiliary API services for participants are provided to support + onboarding, position management, reporting for reconciliation, and + other non-realtime functions not associated with transfer + processing. +4. All messages are validated for conformance to the API specification; + non-conforming messages are actively rejected with a standardized + machine-interpretable reason code. + +**The hub exposes asynchronous interfaces** + +1. To maximize system throughput and overall efficiency. +2. To isolate leaf-node connectivity issues so they don't impact other + end-users. +3. To enable the hub system to process requests in its own priority + order and without holding an active connection-per-transfer. +4. To handle numerous concurrent long-running processes through + internal batching and load balancing. +5. To have a single mechanism for handling requests (Examples are + transactions such as bulk or those needing end user input or that + span multiple hops). +6. To better support real world networking as issues with connection + speed and reliability for one participant should have minimal impact + on other participants or system availability more generally. + +**The transfer API is idempotent** + +1. This ensures duplicate requests may be made safely by message + originators in conditions of degraded network connectivity. +2. Duplicate requests are recognized and result in the same outcome + (valid duplicates) or are rejected as duplicate (when not allowed by + specification) with reference to the original. + +**Finalized Transfer records are held for a scheme-configurable period +to support scheme processes such as reconciliation, billing, and for +forensic purposes** + +1. It is not possible to query the "sub-status" of an in-process + Transfer; the API provides a deterministic outcome with active + notice provided within the guaranteed service time. + +**Transfer records for finalized transfers are held indefinitely in +long-term storage to support business analysis by the scheme operator +and by participants (through appropriate interfaces)** + +1. Availability of Transfer records may lag online process finality to + accommodate separation of record-keeping from real-time processing + of Transfer requests. + +**Hub may serve as a proxy for some inter-participant messages +(e.g. during the Agreement phase) to simplify interconnection, but +without parsing, storing (other than to support forwarding), or further +processing the messages.** + +1. In some messaging flows e.g. party lookup, it may be desirable for + participants to have a single point of contact for routing of scheme + related messages, even when the messages are not intended for the + hub, nor require any inspection or other processing. + +**To ensure system is arithmetically consistent, only fixed point +arithmetic is used.** + +1. For the avoidance of doubt, floating point calculations may lose + accuracy and must not be used in any financial calculation. +2. See Level One Decimal Type representation and forms. +3. This specification enables seamless interchange with XML-based + financial systems without loss of precision or accuracy + +## Security and Safety + +**API messages are confidential, tamper-evident, and non-repudiable.** + +1. Confidentiality is required to protect the privacy of the + participants and their customers. +2. There are legal requirements in many regulatory domains where + Mojaloop is expected to operate and as such, the hub must employ + best practices to ensure that the privacy of the participants and + their customers is protected. +3. Tamper-evident integrity mechanisms are required to ensure that + messages cannot be altered in transit. +4. To ensure the integrity of the overall system, each recipient of a + message should be able to independently tell, with a high degree of + confidence, that the message was not altered in transit. +5. Public key cryptography (digital signing) provides the current best + known mechanism for tamper-evident messaging. +6. The security of the sender's private (signing) key is critical. +7. Scheme rules must be established to clarify the responsibilities for + key management and the potential for financial liability upon + compromise of a private key. +8. Non-repudiation is required to ensure that the message was sent by + the party which purported to send it and that provenance can not be + repudiated by the sender. +9. This is important for determining the liable party during audit and + dispute resolution processes. + +**API messages are authenticated upon receipt prior to acceptance or +further processing** + +1. Authentication gives a degree of confidence that the message was + sent by the party which purported to send it. +2. Authentication gives a degree of confidence that the message was not + sent by an unauthorized party. + +**Authenticated Messages are not acknowledged as accepted until safely +recorded to permanent store** + +1. The Mojaloop API assigns significant scheme related business meaning + to certain HTTP response codes at various points in transaction + flows. +2. Certain HTTP responses, e.g. "202 Accepted", are intended to provide + financial guarantees to participants, and as such must only be sent + once the receiving entity is confident it has made safe, permanent + record(s) in support of: + - Facilitating system wide recovery to a consistent state after + failure(s) in one or more distributed components/entities. + - Accurate settlement processes + - Audit and dispute resolution processes +3. For example a "202 Accepted" from the hub to the payee participant + upon receipt of a transfer fulfilment message indicates a guarantee + of transaction settlement to the payee. +4. The Mojaloop API is designed to operate safely under imperfect + network conditions and as such has built in support for retries and + state synchronisation between participants. + +**Three levels of communication security to ensure integrity, +confidentiality, and non-repudiation of messages between an API server +and API client.** + +1. Secure Connections: mTLS required for all communications between the + hub and authorized participants. + - Ensures communications are confidential, between known + correspondents, and communications are protected against + tampering. +2. Secure Messages: JSON message content is cryptographically signed + according to the JWS specification. + - Assures recipients that messages were sent by the party which + purported to send them, and that provenance cannot be repudiated + by the sender. +3. Secure Terms of Transfer: Interledger Protocol (ILP) between Payer + and Payee participants. + - Protects the integrity of the payment condition and its + fulfilment. + - Limits the time within which a transfer instruction is valid. + +## Operational Characteristics + +**Baseline system demonstrated on minimal hardware supports clearing +1,000 transfers per second, sustained for one hour, with not more than +1% (of transfer stage) taking more than 1 second through the hub.** + +1. This measurement includes all necessary hardware and software + components with production grade security and data persistence in + place. +2. This measurement includes all three transfer stages: discovery, + agreement, and transfer. +3. This measurement does not include any participant-introduced + latency. +4. A one hour period is a reasonable approximation of a demand peak for + a national payment system. +5. A lower unit cost to scale than to initially provision. +6. 1000 transfers (clearing) per second is a reasonable starting point + for a national payment system. +7. 1% of transfers (clearing) taking more than 1 second is a reasonable + starting point for a national payment system. +8. Mojaloop schemes should be able to start at a reasonable cost point, + for national financial infrastructure, and scale economically as + demand grows. + +**Properly deployed, the hub is highly available and resilient to +failures.** + +1. In this instance we define the term "highly available" as meaning + "the ability to provide and maintain an acceptable level of service + in the face of faults and challenges to normal operation." +2. Although schemes may determine their own definition of what + constitutes an "acceptable level of service", Mojaloop makes certain + contributing tradeoff choices: + - When fault modes permit, service is degraded across the entire + participant population rather than individual participants + suffering total outages while others remain serviceable. + - The hub has no single point of failure; meaning that it + continues to operate with minimum degradation of service in the + event of a failure of any single component. + - Multiple active instances of each component are deployed in a + distributed manner behind load balancers. + - Each active component instance can handle requests from any + client/participant, meaning no single participant loses the + ability to transact in the event of a failure of any single + component. +3. Given appropriate infrastructure to operate upon, the Mojaloop + software can be deployed in configurations which deliver 99.999% + uptime (five nines) overall. +4. This includes active:active and active:passive multiple, + geographically distributed data center configurations where both + services and data are replicated across multiple physical nodes + which are expected to fail independently. +5. Note that it is expected that nodes in replication groups (and/or + clusters) will be located in diverse physical locations (racks + and/or data centres) with independent power supplies and network + interconnects. +6. Should multiple component failures occur which have not been + mitigated either in the Mojaloop software, deployment configuration + or infrastructure, the Mojaloop API provides mechanisms for each + entity in the scheme to recover to a consistent state, with the hub + being the ultimate source of truth upon full restoration of service. +7. Also see further points relating to resistance to data loss in the + event of failures. +8. Given that Mojaloop schemes are intended to form parts of national + financial infrastructure they must have as close to zero downtime as + possible, given reasonable cost constraints. +9. Failures in hardware and software components are to be expected, + even in the highest quality components available. Best practice + suggests these failures should be anticipated and planned for as + much as possible in the design of the hub with a view to minimising + loss or degradation of service and/or data. +10. For the avoidance of doubt this means the tradeoffs chosen favour + overall service availability and state consistency over performance, + so that: + + - All participants can continue to transact at a reduced rate rather + than some participants being unable to transact at all. + - Inconsistencies in state between scheme entities are resolvable post + service restoration via the Mojaloop API, with minimal manual + reconciliation necessary; the hub being the ultimate source of + truth. + +**The hub is resistant to loss of data in the event of failures.** + +1. Given appropriate infrastructure to operate upon, the Mojaloop + software can be deployed in configurations which reliably replicate + data across multiple, redundant physical storage nodes prior to + processing. +2. Database engine components which are provided by the Mojaloop + deployment mechanisms support the following: + + - Primary:secondary asynchronous replication. + - Primary:primary synchronous replication. + - Synchronous quorum consensus algorithm based replication. + +3. The replication mechanisms available are dependant on the particular + storage layer and database technologies employed. +4. Should multiple component failures occur which have not been + mitigated either in the Mojaloop software, deployment configuration + or infrastructure, the Mojaloop API provides mechanisms for each + entity in the scheme to recover to a consistent state with minimal + financial exposure risk. +5. Transfers become financially binding only when the hub has + successfully responded to a transfer fulfilment message from the + payee participant. This response is only sent when the hub has + persisted the fulfilment message and its outcome to its ledger + database. +6. Expiration timestamps on all financially significant API messages + facilitate timely and deterministic failure path outcomes for all + participants via automated retry mechanisms. +7. When Mojaloop schemes are intended to form parts of national + financial infrastructure, they must do as much as possible, given + reasonable cost constraints, to avoid loss of data in the event of a + failure. +8. Failures in hardware and software components are to be expected, + even in the highest quality components available. Best practice + suggests these failures should be anticipated and planned for in the + design of the hub with a view to avoiding data loss. +9. Participants need timely confidence in the status of financial + transactions across the scheme in order to minimise exposure risk + and deliver excellent customer experiences. + +## Applicability + +This version of this document relates to Mojaloop Version [17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.1|14th April 2025| Paul Makin|Added version control| +|1.0|5th February 2025| James Bush|Initial version| \ No newline at end of file diff --git a/docs/product/features/iso20022.md b/docs/product/features/iso20022.md new file mode 100644 index 000000000..f657e0800 --- /dev/null +++ b/docs/product/features/iso20022.md @@ -0,0 +1,3 @@ +# ISO 20022 + +To be completed. diff --git a/docs/product/features/merchant-payments.md b/docs/product/features/merchant-payments.md new file mode 100644 index 000000000..b07194a0a --- /dev/null +++ b/docs/product/features/merchant-payments.md @@ -0,0 +1,11 @@ +# Merchant Payments + +To be completed. + +Addressing: +USSD vs QR +Merchant Registry - the link to LEIs +Creation of a QR code (with reference to EMVCo) +Customisation of the QR code - how to make it conform to a scheme's or a country's standard. + +In future: link to GLEIF \ No newline at end of file diff --git a/docs/product/features/ml-feature-list.md b/docs/product/features/ml-feature-list.md new file mode 100644 index 000000000..23e8b11c8 --- /dev/null +++ b/docs/product/features/ml-feature-list.md @@ -0,0 +1,85 @@ +# About Mojaloop + +Mojaloop is open source instant payments software that interconnects +disparate financial institutions in a manner that promotes financial +inclusion and provides robust risk management for all participants. It +is available for use by any body that wishes to use it to implement and +operate an inclusive instant payments scheme. + +## Mojaloop's Core Functions + +These are the core functions that Mojaloop provides to connected +financial institutions: + + |Alias Resolution|Clearing|Settlement| +|:--------------:|:--------------:|:--------------:| +|Payee address or **alias resolution**, ensuring that the account-holding institution – and thereby the correct payee account - is reliably identified|**Clearing** of payments end to end, with robust measures that remove any element of doubt about the success of a transaction|Orchestration of **Settlement** of cleared transactions between financial institutions using a model agreed between those institutions, and according to a predefined schedule.| + +  + +These core functions are supported by some [unique characteristics](./transaction.html#unique-transaction-characteristics), which +together make Mojaloop a low cost, inclusive instant payments system: + +1. **A Three Phase Transaction Flow**, as follows: + + **Discovery,** when the Payer's DFSP works with the Mojaloop Hub to determine where the payment should be sent, so ensuring that transactions are not misdirected. This phase resolves an alias to a specific Payee DFSP and, in collaboration with that DFSP, an individual account. + + + **Agreement of Terms, or Quotation,** when the two DFSP parties to the transaction both agree that the transaction can go ahead (supporting, for example, restrictions relating to tiered KYC), and on what terms (including fees), **before** either commits to it. + + + **Transfer,** when the transaction between the two DFSPs (and by proxy their customers' accounts) is cleared, and it is guaranteed that both parties have the same, real-time view of the success or failure of the transaction. +  + +2. **End to End Non-Repudiation** guarantees that each party to a message can be assured that the message has not been modified, and that it really was sent by the purported originator. This underlying technology is leveraged by Mojaloop to guarantee that a transaction will only be committed if *both* the Payer *and* the Payee DFSPs accept that it is, and neither party can repudiate the transaction. Naturally, it also guarantees that no third party can modify the transaction. +3. **The PISP API is made available through the Mojaloop Hub,** not by individual DFSPs. Consequently a fintech can integrate with the Hub and immediately be connected to **all** connected DFSPs.  + +**Note** In Mojaloop terms, a DFSP - or Digital Financial Service Provider - is a generic term for any financial institution, of any size or status, that is able to transact digitally. It applies equally to the largest international bank and the smallest Microfinance Institution or mobile wallet operator. "DFSP" is used throughout this document. +  + +## The Mojaloop Ecosystem +In reading this document, it is important to understand the terminology used to identify the various actors, and how they interact. The following diagram provides a high level view of the Mojaloop ecosystem. + +![Mojaloop Ecosystem](./ecosystem.svg) + +## Feature List + +This document presents a feature list which covers the following aspects +of Mojaloop: + +- [**Use Cases**](./use-cases.md), describing the use cases supported by every Mojaloop deployment. +- [**Transactions**](./transaction.md), describing the Mojaloop APIs, how a transaction proceeds, and the aspects of a Mojaloop transaction that make it uniquely suited to the implementation of an inclusive instant payments service. + +- [**Risk Management**](./risk.md), setting out the measures taken to ensure that no DFSP participating in a Mojaloop scheme is exposed to any counterparty risk, and that the integrity of the scheme as a whole is protected. + +- [**Connectivity Support**](./connectivity.md), describing the various tools and options for straightforward onboarding of participating DFSPs. + +- [**Portals and Operational Features**](./product.md), such as portals for user and service management, and the configuration and operation of a Mojaloop Hub. +- [**Fees and Tariffs**](./tariffs.md) sets out the mechanisms that Mojaloop provides to support a range of different tariff models and the opportunities for participants and hub operators to levy fees. + +- [**Performance**](./performance.md), outlining the transaction processing performance adopters might expect. +- [**Deployment**](./deployment.md), describing the different ways to deploy Mojaloop for a range of different purposes, and the tools that facilitate these deployment types. +- [**Security**](./security.md), covering the security of the transactions between connected DFSPs and the Mojaloop Hub, the security of the Hub itself (including the operator portals), and the QA Framework currently being developed to validate the security and quality of a Mojaloop deployment. +- [**Engineering Principles**](./engineering.md), such as algorithmic adherence to the Mojaloop specification, code quality, security practices, scalability and performance patterns (amongst others). + +- [**Invariants**](./invariants.md), setting out the development and operational principles to which any Mojaloop implementation must adhere. This includes the principles which ensure the security and integrity of a Mojaloop deployment. + +  + +# About This Document + +## Purpose of This Document + +This document catalogues the features of Mojaloop, independent of +implementation. It is intended to both inform potential adopters of the features they can expect and (where appropriate) how those features can be expected to function, and to inform developers of the features they must implement in order for their efforts to be accepted as an official instance of Mojaloop. + +The Mojaloop Foundation (MLF) defines an implementation as being an +official instance of Mojaloop if it implements all of the features of +Mojaloop, without exception, and they pass the standard set of Mojaloop tests. + +## Applicability + +This version of this document relates to Mojaloop Version [17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.3|23rd June 2025| Paul Makin|Added the ecosystem text and diagram| +|1.2|14th April 2025| Paul Makin|Updates related to the release of V17| \ No newline at end of file diff --git a/docs/product/features/mojaloop_security_layers.jpg b/docs/product/features/mojaloop_security_layers.jpg new file mode 100644 index 000000000..d70949b68 Binary files /dev/null and b/docs/product/features/mojaloop_security_layers.jpg differ diff --git a/docs/product/features/performance.md b/docs/product/features/performance.md new file mode 100644 index 000000000..b9b1326d2 --- /dev/null +++ b/docs/product/features/performance.md @@ -0,0 +1,26 @@ +# Performance +Naturally, transaction throughput performance - usually measured as transactions per second - is a key metric for adopters, who need to be confident that Mojaloop can support their requirements, whether it be a national deployment, or sector-specific, or multi-national. + +For this reason, the Mojaloop Community has established a performance baseline, and works continuously to refine and improve the efficiency of transaction processing. + +## Performance Baseline + +Version 17.0.0 of the Mojaloop Hub has been demonstrated to support the following performance characteristics on ***minimal*** hardware: + +- Clearing 1,000 transfers per second +- Sustained for one hour +- With not more than 1% (of transfer stage) taking more than 1 second through the hub + +This baseline performance can be used as a reference point for system sizing and capacity planning. + +Naturally, higher performance may be expected using greater hardware resources. + +## Future Performance Expectations + +Work continues to replace Mojaloop's existing ledger technology with the [TigerBeetle](https://tigerbeetle.com/) financial transactions database. As the ledger performance is a significant element of the overall performance of Mojaloop, a significant uptick in that performance is expected through the adoption of TigerBeetle, with this expected to be completed by the time of the release of Mojaloop Version 19.0. + + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.0|3rd June 2025| Paul Makin|Initial version; performance text moved from deployment documentation| \ No newline at end of file diff --git a/docs/product/features/product.md b/docs/product/features/product.md new file mode 100644 index 000000000..aa4bf0610 --- /dev/null +++ b/docs/product/features/product.md @@ -0,0 +1,211 @@ +# Portals and Operational Features + +The aspects of portals and other operational features that are addressed are: + +- User Management + +- Participant Management + +- Transaction Review + +- Settlement + +- Logging & Audit + +- Hub Management + +- Oracle Management + +- Participant Portal + +- Reporting + +These functions are provided through Mojaloop's Business Operations +Framework (BOF), which not only provides the core functions described +here but also provides a set of APIs to allow a Hub operator to extend +these portals, and create new ones, to meet their specific requirements. + +The BOF channels all activity through a single Identity and Access +Management (IAM) framework, which incorporates Role Based Access +Controls (RBACs), giving a hub operator granular control of an individual's +access to the management capabilities of the Mojaloop Hub. + +Access to each of the above functions is implemented using the BOF, and +is managed using the IAM and RBAC. + +## User Management + +These features relate to the management of the hub operator's staff +using the integrated IAM module, rather than management of the service +itself. + +1. Create and manage user accounts for staff of the hub operator and + participants through the IAM portal. +2. Define roles associated with access to various sub-elements of the + portals. +3. Assign roles to user accounts, defining which users have access to + which features of the portals. +4. For sensitive functions, define a maker/checker requirement, + including the roles that must be held by the maker and the checker, + and any restrictions. +5. Enable/disable user accounts. +6. Create user accounts for participants, to facilitate self service + through the Participant Portal (when it is implemented). +7. Allow a user to be a maker and a checker (but not of their own + work). + +Note that the Participant Portal is not yet implemented by any Mojaloop +hub, and so it is not currently a requirement. + +## Participant Management + +Features that allow a hub operator to manage a participating DFSP (note +that this is distinct from the Participant Portal). + +1. Onboarding a participating DFSP. +2. Define and manage end-points (including specification of + certificates and source IPs) +3. Manage Participant contacts (name, email, MSISDN, role etc). +4. Define thresholds (for notifications). +5. Define and manage accounts for Participant by type, currency. +6. Disable a participating DFSP (though it should not be possible to + disable a DFSP with outstanding/unsettled transactions). +7. Pause/Resume a Participant's connection. +8. Assign/adjust liquidity (for multiple currencies), controlled with + maker/checker. +9. Assign/adjust a Net Debit Cap (NDC) for each Participant, controlled + by maker/checker, to include two options for NDC: fixed value + (manual adjustment after each liquidity change), or variable (as a + fixed percentage of available liquidity). +10. Restrict Participant connection to send or receive only. + +## Transaction Review + +The hub operator's staff need to be able to find details about a +transaction, whatever its status. They are able to search by: + +- Date/time range + +- Payer or Payee DFSP (Participant) + +- Value - Mojaloop transaction ID + +- Transfer state + +- Settlement Batch ID + +- Transaction type + +- Error code + +The search returns a list of all the transactions matching the search +criteria, each clickable for a detailed view, which gives access to: + +- All details held by the Mojaloop Hub, grouped in a set of + sub-windows to improve usability + +This will include the settlement window/batch ID, which is itself +clickable to allow the operator to review the settlement status of the +batch and therefore the transaction itself. + +## Settlement + +Management of the settlement function of the Mojaloop Hub needs to be +robust and reliable. The related features are: + +1. To define the settlement model to be used for the service +2. To close a settlement window or batch either manually or + automatically, according to a predefined schedule +3. To automatically create all of the necessary settlement files for + integration with settlement partner(s) when a settlement window is + closed +4. To review the positions of all Participants in the settlement + window/batch +5. Once settlement has been completed/finalised, to automatically + update the positions and current available liquidity based on + reports from the settlement partner(s) +6. To provide tools to support the integration between the Mojaloop Hub + and settlement partner(s). + +Note that at least one settlement window or batch will always be open, +and transactions will be added to the open settlement window/batch as +they are processed. This means that the creation of a new settlement +window is automatic when the existing settlement window is closed. + +## Logging & Audit + +The Mojaloop Hub provides a range of tools that support the logging and +audit of operator activity, in addition to low level audit functions for +the detailed analysis of transaction processing (which are defined +elsewhere in this document). These tools have been developed with the +requirements of both Hub operator management and external auditors in +mind. + +1. All modifications arising from hub operator activity (including user + management) are logged in an uneditable data store, with the + operator's credentials attached + +2. "Auditor" is a default hub user role; auditors have unrestricted + read access to the logs. + +3. An audit portal is available, which has Search/refine functionality + available + +4. Log/audit entries include changes to Hub configuration. + +## Hub Management + +There are some basic requirements for the configuration of a Mojaloop +Hub, defining the service that it supports. + +1. A Mojaloop Hub supports all ISO-defined currencies by default. Each + is enabled for use by a particular deployment by the creation of + settlement and position accounts for that currency. In support of + this, there is a requirement to be able to view the balances in Hub + operating accounts (settlement and position, replicated per currency + supported) + +2. Add/view/delete the CA certificates needed for normal operation. + +## Oracle Management + +Management of the oracles used by the Account Lookup Service (ALS) for +the resolution of aliases to DFSPs/Participants (and then, in +collaboration with the identified DFSP, to a specific account). + +1. View the registered oracles + +2. Register an Oracle + +3. Define an endpoint + +4. Test the health of an oracle + +## Participant Portal + +Currently, the Mojaloop Hub does not offer a Participant Portal. +Instead, this functionality is provided by another open source project, +Payment Manager (). Other tools, such as +Mojaloop's Integration Toolkit, provide an API to allow DFSPs to access +the same information. + +## Reports + +Mojaloop provides a flexible reporting engine as part of the Business +Operations Framework, which allows a Hub operator's staff to design and +generate a wide range of reports based on data held in Mojaloop's +databases and ledgers. The Framework also supports the integration of +those reports into any of the operator portals, allowing the reports to +be generated as required by operations staff. + +This includes the reports relating to settlement. + +## Applicability + +This version of this document relates to Mojaloop Version [17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.1|14th April 2025| Paul Makin|Updates related to the release of V17| +|1.0|5th February 2025| Paul Makin|Initial version| \ No newline at end of file diff --git a/docs/product/features/risk.md b/docs/product/features/risk.md new file mode 100644 index 000000000..4d6dd0c60 --- /dev/null +++ b/docs/product/features/risk.md @@ -0,0 +1,54 @@ +# Risk Management + +A key aspect of the operation of a payment scheme that is built around a +Mojaloop hub is the management of risk between transacting parties, who +will themselves have different appetites for risk. The principles +applied are: + +1. All Participants (FSPs) are required to deposit an agreed form of + liquidity with the Scheme settlement partner. This liquidity can + only be withdrawn, in whole or in part, from the Scheme with the + agreement of the Scheme Operator. +   +2. A transaction will only be cleared (during the Transfer phase) if + there is sufficient liquidity available to cover it, as measured + against the liquidity balance, the DFSP's current Position (the net + total of previously-cleared transactions since the last settlement + activity, as either payer or payee), and any reserved funds. +   +3. The value of a cleared transaction will be added to the payer DFSP's Position, and debited from the payee DFSP's Position. +   +4. During settlement, for each DFSP, a negative Position will be debited from the + Liquidity balance and transferred to the settlement partner for + distribution to the creditors; a positive Position will be credited + to the Liquidity balance by the settlement partner, using funds from the debtors. +   +5. Successful settlement clears the value represented by the transactions in the associated settlement window/batch from each DFSP's Position. +   +6. A DFSP is expected to manage their liquidity, adding to it if it + drops to a level where anticipated transaction values will result in + failed transactions, or withdrawing some (on application to the + scheme operator) if the value is too high. This activity takes place + outside of Mojaloop, but it is a requirement that it is declared + within the Mojaloop scheme, by either the DFSP or the settlement + partner. +   +7. Where the settlement partner is not available 24/7, a DFSP can + deposit extra balance to their liquidity account, for example to + cover anticipated transactions over a holiday period. A DFSP can + manage this extra balance using a Net Debit Cap (NDC), which might + be used for example to limit the use of liquidity to the levels that + are expected on a particular day, in order to ensure that the DFSP + can continue to trade throughout the whole of the holiday period. + The NDC is used in tandem with the liquidity balance in the + authorisation of transactions during the Quotation phase. + +## Applicability + +This version of this document relates to Mojaloop Version [17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.1|14th April 2025| Paul Makin|Updates related to the release of V17| +|1.0|13th March 2025| Paul Makin|Initial version| \ No newline at end of file diff --git a/docs/product/features/security.md b/docs/product/features/security.md new file mode 100644 index 000000000..6a0861938 --- /dev/null +++ b/docs/product/features/security.md @@ -0,0 +1,65 @@ +# Security +Mojaloop security is multi-layered, complex, and subject to continuous oversight and review. Broadly, it can be broken down into three areas of scope: + +- The security of the connection between the Mojaloop Hub and the Participating DFSPs (this includes both the security of transactions and the security, establishment and maintenance of the underlying connection itself); +- The security of the Hub's operations, as reflected in the activities of the operational staff; +- The quality and security of the Mojaloop Hub deployment. + +How Mojaloop approaches each of these areas is explored in the following sections. + +## DFSP Connection Security +The connection between a participant DFSP and the Mojaloop Hub benefits from three levels of security which together ensure the integrity, confidentiality, and non-repudiation of messages between a DFSP, the Mojaloop Hub, and (where appropriate) the other DFSP participating in a transaction. + +The following diagram illustrates these three levels. + +![Mojaloop's Connection Security Layers](./mojaloop_security_layers.jpg) + +At the lowest level, the security of the point-to-point connection between a DFSP (an authorised participant) and the Mojaloop Hub is assured through the use of mTLS, which ensures that communications are confidential and between known correspondents, and that communications are protected against tampering. + +Next, the content of the JSON messages used to communicate between the Hub and the DFSPs is cryptographically signed, according to the method defined in the JWS specification ([see RFC 7515](https://www.rfc-editor.org/rfc/rfc7515.html)). This assures recipients that messages were sent by the party which purported to send them, and simultaneously that that provenance cannot be repudiated by the sender. + +Finally, the terms of a transaction/ transfer are secured using the Interledger Protocol (ILP) between Payer and Payee participants. ILP uses a [Hashed Timelock Contract (HTLC)](./htlc.html) to protect the integrity of the payment condition and its fulfilment. In this way, Mojaloop ensures that a transfer either completes fully across all participating parties, or not at all. It also limits the time within which a transfer instruction is valid. + +These three layers are all built into the Mojaloop Hub. On the DFSP side, these can be directly established and managed by the DFSP's own engineering teams. However, the Mojaloop Community also [makes available a set of tools](./connectivity.html) which both establish these security layers and maintain them during the lifetime of the connection. The tools also help a DFSP to manage and orchestrate their use of the various communications/APIs with the Mojaloop Hub, handling many of the complexities on behalf of the DFSP, whilst existing entirely within the DFSP's own domain (and so not forming part of the Mojaloop Hub). + +## Hub Operational Security +Security at the Mojaloop Hub itself reaches beyond the connections to participating DFSPs (as described in the previous section), and includes the security of operator actions through the use of the various [Hub Portals](.product.html). + +Portals are implemented using Mojaloop's Business Operations Framework (BOF), which not only provides the core Mojaloop portals, but also provides a set of APIs to allow a Hub operator to extend these portals, and create new ones, to meet their specific requirements. + +In order to facilitate the management of the security of these portals, the BOF channels all activity through a single Identity and Access Management (IAM) framework, which incorporates Role Based Access Controls (RBACs), and intrinsically supports industry-standard Maker/Checker (also known as Four Eyes) controls. + +This approach gives a Mojaloop Hub operator granular control of an individual's access to the management capabilities of the Mojaloop Hub, as well as the controls applied to every activity. However, it remains the responsibility of the Hub operator to ensure that their staff are properly screened before recruitment, that they are registered on the IAM to access the portals, that they are assigned appropriate roles, and the the RBAC framework properly assigns roles to patrol management functions (including, where appropriate, maker/checker controls). In particular, policies such as password expiry, lengths and content of passwords, re-use etc are directly supported by the IAM framework, and it also supports the use of Multi-Factor Authentication (MFA) for all operators, as determined by the Hub operator (though the use of SMS or USSD as an MFA channel is strongly discouraged). + +In addition, it remains the responsibility of the hub operator to ensure that control points appropriate to the operation of a financial service are put in place (such as, where it applies, physical access to the servers hosting the Mojaloop Hub, control of operator use of mobile phones, video surveillance, supply chain management, visitor management, etc), and that business processes are defined to ensure the correct application of those control points. + +## Maintaining Security +The Mojaloop Community has defined a set of procedures and techniques to ensure that the security of a Mojaloop deployment is maintained as attacks evolve and vulnerabilities are identified, either in Mojaloop itself of in one of the myriad of other open source programs that Mojaloop relies on. This is collectively referred to as the Vulnerability Management Process, and comprises: +- A Security Committee, whose role is the coordination of all aspects of vulnerability management. +- Processes for handling possible vulnerabilities, when they have been brought to the attention of the Security Committee. +- Pro-active vulnerability identification and management processes, including: + - The continuous monitoring of open-source components for vulnerabilities; + - Static Application Security Testing (SAST), using multiple tools which together provide detailed insights into code-level vulnerabilities by leveraging public vulnerability databases; + - Automated maintenance of a Software Bill of Materials (SBOM), which facilitates inventory and dependency management; + - The scanning of container images for vulnerabilities before release; + - The use of an automated license scanner to ensure that only external components with compatible licenses are used; + - Following Mojaloop Release v17.1.0, Mojaloop's helm charts are signed at publishing and can be verified at install / deploy time, to ensure the provenance of artefacts related to charts; + - Mojaloop employs a CI/CD pipeline that automatically integrates security checks throughout the software development process; + - Mojaloop operates a Coordinated Vulnerability Disclosure (CVD) process, ensuring responsible parties have adequate time to address and remedy vulnerabilities before public disclosure; + - Comprehensive reports are generated after each scan, detailing outcomes, remediation actions, and their effectiveness. All reports are stored for auditing and compliance, ensuring transparency and accountability. + +The reader can find more detailed, technical information on the [Mojaloop Vulnerability Management Process here](https://docs.mojaloop.io/technical/technical/security/security-overview.html). + + +## Deployment Quality and Security +Members of the Mojaloop Community are currently developing a Quality Assessment Framework, the purpose of which is to develop a Toolkit that can be used to validate the configuration, functionality, security, interoperability readiness and performance of a deployment. + +This framework might be used by adopters to "self certify", or it might be used by an external reviewer in order to create a higher level of assurance for supervisory authorities and participants. + +## Applicability +This document relates to Mojaloop Version 17.1.0 +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.1|15th July 2025| Paul Makin|Added the "Maintaining Security" section.| +|1.0|24th June 2025| Paul Makin|Initial version| \ No newline at end of file diff --git a/docs/product/features/tariffs.md b/docs/product/features/tariffs.md new file mode 100644 index 000000000..88ac4e7fb --- /dev/null +++ b/docs/product/features/tariffs.md @@ -0,0 +1,9 @@ +# Fees and Tariffs +This section describes the mechanisms that Mojaloop provides to support a range of different tariff models and the opportunities for participants and hub operators to levy fees. + +To be completed. + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.0|3rd June 2025| Paul Makin|Initial version| \ No newline at end of file diff --git a/docs/product/features/transaction.md b/docs/product/features/transaction.md new file mode 100644 index 000000000..cef753a3f --- /dev/null +++ b/docs/product/features/transaction.md @@ -0,0 +1,93 @@ + +# Mojaloop Transactions +This section deals with all of the aspects of a Mojaloop transaction. + +## Phases of a Mojaloop Transaction + +A payments hub based on the Mojaloop platform clears (routes and guarantees) payments between accounts held by end parties (people, business, +government departments etc) at DFSPs, and integrates with a settlement +partner to orchestrate the movement of funds in settlement between +participating DFSPs either simultaneously (continuous gross settlement) or at a later time (various forms of net settlement), according to an agreed settlement +schedule. + +All Mojaloop transactions are asynchronous (to ensure the most efficient +use of resources), and proceed through three phases: + +1. **Discovery,** when the Payer's DFSP works with the Mojaloop Hub to determine where the payment should be sent. This phase resolves an alias to a specific Payee DFSP and, in collaboration with that DFSP, an individual account. +   +2. **Agreement of Terms, or Quotation,** when the two DFSP parties to the transaction agree that the transaction can go ahead (subject to, for example, restrictions relating to tiered KYC), and on what terms (including fees). +   + +3. **Transfer,** when the transaction between the two DFSPs (and by proxy their customers' accounts) is cleared. +  + +These phases are complemented by the asynchronous nature of Mojaloop. A transaction is always unique, ensuring that it will only be processed once, regardless of how frequently it is submitted for processing. This quality is known as idempotency, and ensures that even if a customer experiences intermittent connectivity, they can be assured that their account will only be debited once, regardless of the number of retries. + +This three-phase approach, complemented by idempotency, has been designed to minimize the risk of transaction failures or duplication. Consequently, Mojaloop eliminates the technical need for transaction reconciliation by DFSPs, reduces most causes of disputes, and thereby minimizes costs for all parties. + +Coupled with the Mojaloop approach to [Risk Management](./risk.md), this ensures that even the smallest MFI and the largest international bank can participate on equal terms, without either imposing risk on the other or indeed on the Hub itself. + +  +## Mojaloop APIs + +The Mojaloop Hub supports four APIs. The first two relate to end-customer transactions, whilst the last two relate to the administration of the Hub's relationship with participating DFSPs, and the settlement of cleared transactions: + +1. **Transactional API** +Mojaloop offers two functionally-equivalent transactional APIs, which each support direct connections with Participants for the purpose of conducting transactions. Both support all of the [**Mojaloop use cases**](./use-cases.md), and have been developed in accordance with the [Level One Principles](https://www.leveloneproject.org/project_guide/level-one-project-design-principles/). These APIs are: + - **FSP Interoperability (FSPIOP) API**, the long-established and well-proven API; +  + - An **ISO 20022 Messaging Schema**, using an ISO 20022 message set provisionally agreed by the Mojaloop Foundation with the ISO 20022 Registration Management Group (RMG),and tailored to the needs of an Inclusive Instant Payments System (IIPS)such as Mojaloop. This is offered to adopters as an alternative to FSPIOP. Full details of the Mojaloop implementation of the ISO20022 messaging schema and how it is expected that participating DFSPs will use it can be found in the [**Mojaloop ISO 20022 Market Practice Document**](./Iso20022/MarketPracticeDocument.html). + +2. **Third-party Payment Initiation (3PPI/PISP) API** + + This API is used to manage third party payment arrangements - payments initiated by fintechs on behalf of their customers from accounts held by those customers at DFSPs connected to the Mojaloop Hub. - and to initiate those payments when authorized. + + +3. **Administration API** + + The purpose of the Administration API is to enable Hub Operators to manage admin processes around: + + - creating/activating/deactivating participants in the Hub + + - adding and updating participant endpoint information + + - managing participant accounts, limits, and positions + + - creating Hub accounts + + - performing Funds In and Funds Out operations + + - creating/updating/viewing settlement models, for subsequent management using the Settlement API + + - retrieving transfer details + +4. **Settlement API** + + The settlement API is used to manage the settlement process. It is not intended for the purpose of managing settlement models. + +  + +## Unique Transaction Characteristics + +Most, if not all, of the functions Mojaloop supports are also offered by +other payment clearing hubs. What differentiates Mojaloop is: + +1. **The Three Phase Transaction Flow and Idempotency**, described above.   +2. **The Agreement of Terms, or Quotation,** phase of a transaction, + which allows two DFSPs to agree that a transaction can take place *before* it is committed. This supports some of the most complex aspects of transactions between differing types of Participant; a Payee DFSP can verify that the customer's account can receive the payment, that it hasn't been suspended, or the payment won't breach transaction or balance limits. If that's all OK, then the Payee DFSP will indicate that it can accept the transaction, subject to any fees that it will charge (any Hub fees are outside of the transaction itself). Only if the Payer DFSP, and the Payer him/herself, agree to those charges (and any other conditions attached to the terms returned by the Payee DFSP) will the transaction then be initiated. This removes the uncertainty, and all but guarantees that the transaction will succeed, even before it happens. + +3. **End to End Non-Repudiation** in the Transfer phase of the transaction guarantees that each party to a message can be assured that the message has not been modified, and that it really was sent by the purported originator. This underlying technology is leveraged by Mojaloop to guarantee that a transaction will only be committed if *both* the Payer *and* the Payee DFSPs accept that it is, and neither party can repudiate the transaction. This obviates the need for transaction-level reconciliation, which drives down on the level of disputed transactions and eliminates exception processing, and so substantially reduces costs for all participants. This also directly supports the financial inclusion objectives of the Mojaloop Foundation, since it addresses one of the key barriers to inclusion: lack of certainty, and therefore confidence, in payments. + + The Mojaloop community provides a number of tools that can be freely used by DFSPs to connect to a Mojaloop Hub. These remain within the DFSP's domain, and are not the concern of the hub operator or any other party. As well as managing the connection to the Hub and facilitating transactions, these tools also ensure the security of the connection and in particular provide the key DFSP link to this non-repudiation capability. +   +4. **The PISP API is made available through the Mojaloop Hub,** not by individual Participants. Consequently a fintech can integrate with the Hub and immediately be connected to all connected DFSPs, rather than needing to complete an API integration with the all individually. This substantially reduces costs and increases reliability for fintechs and their customers. + +## Applicability + +This version of this document relates to Mojaloop Version [17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.3|30th June 2025| Paul Makin|Minor clarifications to the Agreement of Terms description| +|1.2|14th April 2025| Paul Makin|Updates related to the release of V17| \ No newline at end of file diff --git a/docs/product/features/use-cases.md b/docs/product/features/use-cases.md new file mode 100644 index 000000000..efbfe4495 --- /dev/null +++ b/docs/product/features/use-cases.md @@ -0,0 +1,95 @@ + +# Use Cases + +A Mojaloop Hub's core function is the clearing of the transfer of funds between two accounts, each of which is held at a DFSP connected to the Hub, commonly referred to as a push payment. This enables it to support a wide range of use cases. + +This description of the use cases supported by Mojaloop is grouped according to the underlying protocol types, in order to demonstrate the extensible nature of a Mojaloop Hub. So we have: +- **Push payments**, which supports the core use cases of P2P, B2B, etc; +- **Request To Pay**, which supports some types of merchant payments, e-commerce and collections; +- A range of **cash services**, including CICO and offline; +- **PISP/3PPI protocols**, which allow fintechs and others to develop services such as merchant payments, small-scale salary runs, collections etc; +- **Bulk payments**, to support nation-scale social payments and salaries; +- **Cross-Border payments**, including both remittances and merchant payments. + +These are described in more detail below. + +(For an API-led view of use cases, please refer to the [use cases section of the Mojaloop API documentation](https://docs.mojaloop.io/api/fspiop/use-cases.html#table-1)) +## Core Use Cases +This means that, at the most basic level, a Mojaloop Hub directly supports the following use cases: +- Person to Person (**P2P**); +- Person to Business (**P2B**), including simple forms of merchant payments, both face to face and remote (online); +- Business to Business (**B2B**); +- Business to Government (**B2G**); +- Simple forms of Person to Government (**P2G**) payments + +In all types of merchant payment, a payment can be facilitated using merchant IDs (for USSD) or QR codes (smartphones). + +## Request To Pay + +As well as push payments, Mojaloop supports Request To Pay (RTP) transactions, in which a payee requests a payment from a payer, and _when the payer consents_ their DFSP pushes the payment to the payee on their behalf. This supports the following use cases: + +- **Merchant payments**, in a face to face environment, for example using a QR code; + - The practicalities of configuring Mojaloop's Merchant Payments solution, including the content of QR codes, are explored in How to Configure Merchant Payments for Mojaloop. + - In all types of face to face merchant payment, a payment can be facilitated using merchant IDs (for USSD) or QR codes (smartphones). +- **e-Commerce**, sometimes also known as remote merchant payments, when for example a checkout page (web page or mobile app) would include a "pay from my bank account" button, which would trigger an RTP. + +- **Collections**, including P2G, P2B, B2B and B2G - though this can also be achieved through the fintech/3PPI interface described below. + +## Cash Services +A Mojaloop Hub directly supports the common interoperable cash in/out transactions that every DFSP (and their customers) would expect: +- **Cardless ATM**; +- **Cash In at off-us Agent**; +- **Cash Out at off-us Agent**; +- **Offline Cash**. + +A Mojaloop Hub is able to offer support to **offline cash** payment schemes because such a payment scheme is viewed as cash - albeit digital. So a withdrawal to an offline cash wallet (a load) is analogous to a "cash out" transaction; and a deposit from an offline cash wallet (an upload) is analogous to a "cash in" transaction. However, the operator of such a scheme might consider that all such wallet load/upload transactions, whether on-us or off-us, should be processed through the Mojaloop Hub, for ease of reconciliation by the offline scheme. + +## Fintechs and Others +A Mojaloop Hub directly supports Third Party Payment Initiation (3PPI), so that Payment Initiation Service Providers (PISPs) - better known as fintechs - can, using their own smartphone apps, recruit customers, and offer them a unified or enhanced payments service. Most DFSPs connected to a Mojaloop Hub can support 3PPI services, if they have a reasonably modern back office. + +A fintech can use the 3PPI service to initiate a Request To Pay (RTP) - asking their customer's DFSP to initiate a payment to a payee. This supports the following use cases: +- **Collections**, in particular P2G and P2B; +- **Salary payments**, essentially the processing of a bulk payments list, on behalf of small/medium businesses; +- **Merchant payments** (P2B), using a QR code for initiation. + +## Bulk Payments +Every payments service needs to facilitate bulk payments, and Mojaloop offers this service using an extremely efficient model. All but the very smallest DFSPs are able to offer this service to their customers, allowing them to submit payments lists that can reach every customer of every connected DFSP. This is in support of: +- **Pensions, Social and other payments** (G2P); +- **Salaries** (G2P and B2P). + +In addition, the bulk payment functionality is available through the **3PPI service** (above), which would enable all DFSPs - even the very smallest - to offer a smaller scale bulk payments service through either a fintech, or directly through their own 3PPI service. + + +## Cross Border Payments + +A Mojaloop Hub can enable a DFSP's customers to send money across borders in a cost-effective manner, facilitating the foreign exchange (FX) process as part of the transaction. This supports the following use cases: +- **P2P** and **P2B** (sending money to friend and family in another country, or paying a bill in another country); +- **Merchant Payments**, using RTP cross-border (supporting, for example, a small merchant that wishes to cross a nearby border to trade at a local market, taking payments in the local currency) + +In order to explore the aspects of the Mojaloop ecosystem that enable this, it is recommended to review: +1. The ability to connect a Mojaloop Hub to neighbouring payment schemes, either within the same country or elsewhere, so that interoperability is supported. This capability is introduced here. + +2. The support for foreign exchange providers (FXPs) to connect to a Mojaloop Hub and offer FX services. Neither the payer not the payee needs to define the currency to be used for a transaction; they each transact in their own currency, and the Mojaloop Hub(s) facilitate the interchange. This capability is introduced here. + +3. How the interconnection/interscheme and foreign exchange capabilities are brought together to support cross border transactions. + +## Extended Use Cases + +In addition to these standard use cases, Mojaloop supports the implementation +of more complex use cases by adopters, which add additional features and +are layered over the top of the standard use cases. + +These +scheme-specific use cases can readily be added by individual scheme +operators. + +## Applicability + +This version of this document relates to Mojaloop Version [17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) + +## Document History + |Version|Date|Author|Detail| +|:--------------:|:--------------:|:--------------:|:--------------:| +|1.4|12th June 2025| Paul Makin|Extended the introductory text to explain the use case grouping.| +|1.3|10th June 2025| Paul Makin|Added a description of e-commerce payments using RTP. Retitled 3PPI payments as Fintech payments.Clarified bulk payment initiation via 3PPI. Finally, some cosmetic updates to highlight hyperlinks to other documents.| +|1.2|14th April 2025| Paul Makin|Updates related to the release of V17, including links to the interscheme and FX documentation.| \ No newline at end of file diff --git a/docs/quickstarts/README.md b/docs/quickstarts/README.md new file mode 100644 index 000000000..ee06bcdbe --- /dev/null +++ b/docs/quickstarts/README.md @@ -0,0 +1,10 @@ +# Your First Action + +To help get you started with Mojaloop, select which of the options below best suits your needs: + +1. [View the quickstarts](/1-overview/) +1. [Watch a demo](/99-demos/) +1. [Read the documentation](/1-overview/) +1. [Test out Mojaloop APIs](/1-overview/#apis) +1. [Take a training program](/3-guides/1_dfsp_setup/) +1. [Contribute to Mojaloop](https://docs.mojaloop.io/documentation/) \ No newline at end of file diff --git a/docs/quickstarts/one.md b/docs/quickstarts/one.md new file mode 100644 index 000000000..ee06bcdbe --- /dev/null +++ b/docs/quickstarts/one.md @@ -0,0 +1,10 @@ +# Your First Action + +To help get you started with Mojaloop, select which of the options below best suits your needs: + +1. [View the quickstarts](/1-overview/) +1. [Watch a demo](/99-demos/) +1. [Read the documentation](/1-overview/) +1. [Test out Mojaloop APIs](/1-overview/#apis) +1. [Take a training program](/3-guides/1_dfsp_setup/) +1. [Contribute to Mojaloop](https://docs.mojaloop.io/documentation/) \ No newline at end of file diff --git a/docs/quickstarts/two.md b/docs/quickstarts/two.md new file mode 100644 index 000000000..ee06bcdbe --- /dev/null +++ b/docs/quickstarts/two.md @@ -0,0 +1,10 @@ +# Your First Action + +To help get you started with Mojaloop, select which of the options below best suits your needs: + +1. [View the quickstarts](/1-overview/) +1. [Watch a demo](/99-demos/) +1. [Read the documentation](/1-overview/) +1. [Test out Mojaloop APIs](/1-overview/#apis) +1. [Take a training program](/3-guides/1_dfsp_setup/) +1. [Contribute to Mojaloop](https://docs.mojaloop.io/documentation/) \ No newline at end of file diff --git a/docs/technical/README.md b/docs/technical/README.md new file mode 100644 index 000000000..cad24cb63 --- /dev/null +++ b/docs/technical/README.md @@ -0,0 +1,16 @@ +# Mojaloop Technical Overview + +## Mojaloop Services + +The basic idea behind Mojaloop is that we need to connect multiple Digital Financial Services Providers (DFSPs) together into a competitive and interoperable network in order to maximize opportunities for poor people to get access to financial services with low or no fees. We don't want a single monopoly power in control of all payments in a country, or a system that shuts out new players. It also doesn't help if there are too many isolated subnetworks. The following diagrams shows the Mojaloop interconnects between DFSPs and the Mojaloop Hub (schema implementation example) for a Peer-to-Peer (P2P) Transfer: + +Mojaloop addresses these issues in several key ways: +* A set of central services provides a hub through which money can flow from one DFSP to another. This is similar to how money moves through a central bank or clearing house in developed countries. Besides a central ledger, central services can provide identity lookup, fraud management, and enforce scheme rules. +* A standard set of interfaces a DFSP can implement to connect to the system, and example code that shows how to use the system. A DFSP that wants to connect up can adapt our example code or implement the standard interfaces into their own software. The goal is for it to be as straightforward as possible for a DFSP to connect to the interoperable network. +* Complete working open-source implementations of both sides of the interfaces - an example DFSP that can send and receive payments and the client that an existing DFSP could host to connect to the network. + +![Mojaloop End-to-end Architecture Flow PI5](./technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg) + +The Mojaloop Hub is the primary container and reference we use to describe the Mojaloop ecosystem which is split in to the following domains: +* Mojaloop Open Source Services - Core Mojaloop Open Source Software (OSS) that has been supported by the Bill & Melinda Gates Foundation in partnership with the Open Source Community. +* Mojaloop Hub - Overall Mojaloop reference (and customizable) implementation for Hub Operators is based on the above OSS solution. \ No newline at end of file diff --git a/docs/technical/api/README.md b/docs/technical/api/README.md new file mode 100644 index 000000000..ef01e4ff5 --- /dev/null +++ b/docs/technical/api/README.md @@ -0,0 +1,17 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- + +# API Catalog + +The Mojaloop Family of APIs is a set of several different APIs that cater for several business or transactional functions. So far, the well defined and adopted APIs are: + +- [FSP Interoperability (FSPIOP) APIs](./fspiop/) +- [Administration API](./administration/) +- [Settlement API](./settlement/) +- [Third-party Payment Initiation (3PPI/PISP) API](./thirdparty/) + +There are other APIs that are either in active development and design or on the roadmap: + +- Cross-network API (FX) +- Reporting API diff --git a/docs/technical/api/administration/README.md b/docs/technical/api/administration/README.md new file mode 100644 index 000000000..80323e1b1 --- /dev/null +++ b/docs/technical/api/administration/README.md @@ -0,0 +1,15 @@ +# Administration API + +The Administration API includes the following documents. + +## Administration Central Ledger API + +[The specification of the Central Ledger API](./central-ledger-api.md) introduces and describes the **Central Ledger API**. The purpose of the API is to enable Hub Operators to manage admin processes around: + +- Creating/activating/deactivating participants in the Hub +- Adding and updating participant endpoint information +- Managing participant accounts, limits, and positions +- Creating Hub accounts +- Performing Funds In and Funds Out operations +- Creating/updating/viewing settlement models +- Retrieving transfer details diff --git a/docs/technical/api/administration/central-ledger-api.md b/docs/technical/api/administration/central-ledger-api.md new file mode 100644 index 000000000..0b63b5d7f --- /dev/null +++ b/docs/technical/api/administration/central-ledger-api.md @@ -0,0 +1,1728 @@ +--- +showToc: true +--- +# Central Ledger API + +## Introduction + +This document provides detailed information about the Central Ledger API. The Central Ledger API is a Mojaloop API enabling Hub Operators to manage admin processes around: + +- Creating/activating/deactivating participants in the Hub +- Adding and updating participant endpoint information +- Managing participant accounts, limits, and positions +- Creating Hub accounts +- Performing Funds In and Funds Out operations +- Creating/updating/viewing settlement models +- Retrieving transfer details + + For background information about the participant and settlement model details that the Hub Operator can administer using the Central Ledger API, see section [Basic concepts](#basic-concepts). + +
+ +## Basic concepts + +To provide context for the admin operations that the Central Ledger API enables, this section gives a brief definition of some basic concepts. + +### Participant + +Either the Hub itself or a Digital Financial Service Provider (DFSP) that is a participant in a Mojaloop scheme. + +### Endpoint + +The DFSP callback URL where the Hub routes API callbacks. The URL specified is the endpoint set up in the outbound API gateway. + +### Limit + +Currently, only one type of limit is supported, it is called "_Net Debit Cap (NDC)_". In the future, it is possible to add support for further types of limits. + +The _Net Debit Cap_ represents the liquidity cover available for a specific account (the Position account). It is the total amount of good funds which the scheme attests are available to guarantee that a participant is able to settle the liabilities it incurs on the Position account as a consequence of transferring funds. This amount of good funds is represented as the balance of an account (the Settlement account), which is tied to the Position account by a settlement model. The source of the funds in this account can be either funds recorded by the scheme's administrators as having been deposited to or withdrawn from the Settlement account, or funds which are automatically credited to or debited from the account by the scheme if the account is the Settlement account for an immediate gross settlement model. + +It should also be possible for a participant to specify that an amount, or a proportion, of the funds available in a Settlement account should be excluded from the Net Debit Cap calculation. In cases where a participant is a long-term net beneficiary of funds via settlement, or where participants keep extra funds in their Settlement account to cover periods when it may not be possible to deposit funds to those accounts, it may wish to exclude part of the balance of its Settlement account from use as cover for transfers. + +### Account + +Also called _Ledger_. The Hub maintains a number of internal accounts to keep track of the movement of money (both e-money and real money) between DFSPs. + +### Position + +The Position represents the net of: +- transfers on that account which have cleared but have not yet settled, and +- transfers on that account where: + - the DFSP is the debtor party, and + - the transfer has been accepted for processing by the Hub, but has not yet cleared. + +The Position for a given account is always verifiably up to date. + +When a transfer is requested, the Hub will check that the DFSP has liquidity cover available on that account to cover the amount of the transfer. If it does not, the transfer will be rejected. + +We currently allow liabilities to the participant which have been created as a consequence of transfers on the account where the participant is the beneficiary to reduce the participant's Position as if the liabilities had already been settled. + +### Funds In and Funds Out + +Funds In and Funds Out operations are used to track (in the Hub accounts) money movements related to deposits and withdrawals, as well as settlements. + +Funds In operations record either the deposit of money into a DFSP's settlement bank account or the settlement amount for a receiving DFSP. + +Funds Out operations record either the withdrawal of money from a DFSP's settlement bank account or the settlement amount for a sending DFSP. + +### Settlement model + +Refers to how settlement happens within a scheme. Settlement is the process of transferring funds from one DSFP to another, so that the payer's DFSP reimburses the payee's DFSP for funds given to the payee during a transaction. A settlement model specifies if participants settle with each other separately or settle with the scheme, whether transfers are settled one by one or as a batch, whether transfers are settled immediately or with a delay, and so on. + +
+ +## HTTP details + +This section contains detailed information regarding the use of the application-level protocol HTTP in the API. + +### HTTP header fields + +HTTP headers are generally described in [RFC 7230](https://tools.ietf.org/html/rfc7230). Any headers specific to the Central Ledger API will be standardised in the future. + +### HTTP methods + +The following HTTP methods, as defined in [RFC 7231](https://tools.ietf.org/html/rfc7231#section-4), are supported by the API: + +- `GET` – The HTTP GET method is used from a client to retrieve information about a previously-created object on a server. +- `POST` – The HTTP POST method is used from a client to request an object to be created on the server. +- `PUT` – The HTTP PUT method is used from a client to request an object already existing on the server to be modified (to replace a representation of the target resource with the request payload). + +> **NOTE:** The `DELETE` method is not supported. + +### HTTP response status codes + +The [HTTP response status codes](#http-response-status-codes) table lists the HTTP response status codes that the API supports: + +|Status Code|Reason|Description| +|---|---|---| +|**200**|OK|Standard response for a successful `GET`, `PUT`, or `POST` operation. The response will contain an entity corresponding to the requested resource.| +|**201**|Created|The `POST` request has been fulfilled, resulting in the creation of a new resource. The response will not contain an entity describing or containing the result of the action.| +|**202**|Accepted|The request has been accepted for processing, but the processing has not been completed.| +|**400**|Bad Request|The server could not understand the request due to invalid syntax.| +|**401**|Unauthorized|The request requires authentication in order to be processed.| +|**403**|Forbidden|The request was denied and will be denied in the future.| +|**404**|Not Found|The requested resource is not available at the moment.| +|**405**|Method Not Allowed|An unsupported HTTP method for the request was used.| +|**406**|Not Acceptable|The requested resource is capable of generating only content not acceptable according to the Accept headers sent in the request.| +|**500**|Internal Server Error|A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.| +|**501**|Not Implemented|The server does not support the requested service. The client should not retry.| +|**503**|Service Unavailable|The server is currently unavailable to accept any new service requests. This should be a temporary state, and the client should retry within a reasonable time frame.| + +
+ +## API services + +This section introduces and details all services that the API supports for each resource and HTTP method. + +### High-level API services + +On a high level, the API can be used to perform the following actions: + +- **`/participants`**: View, create, update participant-related details, such as limit (Net Debit Cap), position, or endpoints configured. +- **`/settlementModels`**: View, create, update settlement-model-related details, such as granularity, delay, liquidity check, and so on. +- **`/transactions`**: View transaction details for a particular transfer. + +### Supported API services + +The [Supported API services](#supported-api-services) table includes high-level descriptions of the services that the API provides. For more detailed information, see the sections that follow. + +| URI | HTTP method `GET`| HTTP method `PUT` | HTTP method `POST` | HTTP method `DELETE` | +|---|---|---|---|---| +| **`/participants`** | Get information about all participants | Not supported | Create participants in the Hub | Not supported | +| `/participants/limits` | View limits for all participants | Not supported | Not supported | Not supported | +| `/participants/{name}` | Get information about a particular participant | Update participant details (activate/deactivate a participant) | Not supported | Not supported | +| `/participants/{name}/endpoints` | View participant endpoints | Not supported | Add/Update participant endpoints | Not supported | +| `/participants/{name}/limits` | View participant limits | Adjust participant limits | Not supported | Not supported | +| `/participants/{name}/positions` | View participant positions | Not supported | Not supported | Not supported | +| `/participants/{name}/accounts` | View participant accounts and balances | Not supported | Create Hub accounts | Not supported | +| `/participants/{name}/accounts/{id}` | Not supported | Update participant accounts | Record Funds In or Out of participant account | Not supported | +| `/participants/{name}/accounts/{id}/transfers/{transferId}` | Not supported | Not supported | Record a Transfer as a Funds In or Out transaction for a participant account | Not supported | +| `/participants/{name}/initialPositionAndLimits` | Not supported | Not supported | Add initial participant limits and position | Not supported | +| **`/settlementModels`** | View all settlement models | Not supported | Create a settlement model | Not supported | +| `/settlementModels/{name}` | View settlement model by name | Update a settlement model (activate/deactivate a settlement model) | Not supported | Not supported | +| **`/transactions/{id}`** | Retrieve transaction details by `transferId` | Not supported | Not supported | Not supported | + + +
+ +## API Resource `/participants` + +The services provided by the resource `/participants` are primarily used by the Hub Operator for viewing, creating, and updating participant-related details, such as limit (Net Debit Cap), position, or endpoints configured. + +### GET /participants + +Retrieves information about all participants. + +#### Example request + +``` +curl 'http:///participants' +``` + +#### Example response + +> **NOTE:** In the example below, `dev1-central-ledger.mojaloop.live` indicates where the Central Ledger service of the Mojaloop Hub is running. This detail will be different in your implementation. + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "name": "greenbankfsp", + "id": "dev1-central-ledger.mojaloop.live/participants/greenbankfsp", + "created": "\"2021-03-04T14:20:17.000Z\"", + "isActive": 1, + "links": { + "self": "dev1-central-ledger.mojaloop.live/participants/greenbankfsp" + }, + "accounts": [ + { + "id": 15, + "ledgerAccountType": "POSITION", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 16, + "ledgerAccountType": "SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 21, + "ledgerAccountType": "INTERCHANGE_FEE_SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + } + ] + }, + { + "name": "Hub", + "id": "dev1-central-ledger.mojaloop.live/participants/Hub", + "created": "\"2021-03-04T13:37:25.000Z\"", + "isActive": 1, + "links": { + "self": "dev1-central-ledger.mojaloop.live/participants/Hub" + }, + "accounts": [ + { + "id": 1, + "ledgerAccountType": "HUB_MULTILATERAL_SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 2, + "ledgerAccountType": "HUB_RECONCILIATION", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + } + ] + } +] +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [String](#string) | The identifier of the participant in the form of a fully qualified domain name combined with the participant's `fspId`. | +| `created` | yes | [DateTime](#datetime) | Date and time when the participant was created. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the participant is active. Possible values are `1` and `0`. | +| `links` | yes | [Self](#self) | List of links for a Hypermedia-Driven RESTful Web Service. | +| `accounts` | yes | [Accounts](#accounts) | The list of ledger accounts configured for the participant. | + +
+ +### POST /participants + +Creates a participant in the Hub. + +#### Example request + +``` +curl -X POST -H "Content-Type: application/json" \ + -d '{"name": "payerfsp", "currency": "USD"}' \ + http:///participants +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency that the participant will transact in. | + +#### Example response + +> **NOTE:** In the example below, `dev1-central-ledger.mojaloop.live` indicates where the Central Ledger service of the Mojaloop Hub is running. This detail will be different in your implementation. + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "name": "payerfsp", + "id": "dev1-central-ledger.mojaloop.live/participants/payerfsp", + "created": "\"2021-01-12T10:56:30.000Z\"", + "isActive": 0, + "links": { + "self": "dev1-central-ledger.mojaloop.live/participants/hub" + }, + "accounts": [ + { + "id": 30, + "ledgerAccountType": "POSITION", + "currency": "USD", + "isActive": 0, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 31, + "ledgerAccountType": "SETTLEMENT", + "currency": "USD", + "isActive": 0, + "createdDate": null, + "createdBy": "unknown" + } + ] +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [String](#string) | The identifier of the participant in the form of a fully qualified domain name combined with the participant's `fspId`. | +| `created` | yes | [DateTime](#datetime) | Date and time when the participant was created. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the participant is active. Possible values are `1` and `0`. | +| `links` | yes | [Self](#self) | List of links for a Hypermedia-Driven RESTful Web Service. | +| `accounts` | yes | [Accounts](#accounts) | The list of ledger accounts configured for the participant. | + +
+ +### GET /participants/limits + +Retrieves limits information for all participants. + +#### Query parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | no | [CurrencyEnum](#currencyenum) | The currency of the limit. | +| `limit` | no | [String](#string) | Limit type. | + +#### Example request + +``` +curl 'http:///participants/limits' +``` + +#### Example response + +> **NOTE:** In the example below, `dev1-central-ledger.mojaloop.live` indicates where the Central Ledger service of the Mojaloop Hub is running. This detail will be different in your implementation. + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "name": "payerfsp", + "currency": "USD", + "limit": { + "type": "NET_DEBIT_CAP", + "value": 10000, + "alarmPercentage": 10 + } + }, + { + "name": "payeefsp", + "currency": "USD", + "limit": { + "type": "NET_DEBIT_CAP", + "value": 10000, + "alarmPercentage": 10 + } + } +] +``` + +#### Response data model + +Each limit in the returned list is applied to the specified participant name and currency in each object. + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the participant. | +| `limit` | yes | [ParticipantLimit](#participantlimit) | The limit configured for the participant. | + +
+ +### GET /participants/{name} + +Retrieves information about a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl 'http:///participants/payerfsp' +``` + +#### Example response + +> **NOTE:** In the example below, `dev1-central-ledger.mojaloop.live` indicates where the Central Ledger service of the Mojaloop Hub is running. This detail will be different in your implementation. + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "name": "payerfsp", + "id": "dev1-central-ledger.mojaloop.live/participants/payerfsp", + "created": "\"2021-03-04T13:42:02.000Z\"", + "isActive": 1, + "links": { + "self": "dev1-central-ledger.mojaloop.live/participants/payerfsp" + }, + "accounts": [ + { + "id": 3, + "ledgerAccountType": "POSITION", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 4, + "ledgerAccountType": "SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 24, + "ledgerAccountType": "INTERCHANGE_FEE_SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + } + ] +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [String](#string) | The identifier of the participant in the form of a fully qualified domain name combined with the participant's `fspId`. | +| `created` | yes | [DateTime](#datetime) | Date and time when the participant was created. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the participant is active. Possible values are `1` and `0`. | +| `links` | yes | [Self](#self) | List of links for a Hypermedia-Driven RESTful Web Service. | +| `accounts` | yes | [Accounts](#accounts) | The list of ledger accounts configured for the participant. | + +
+ +### PUT /participants/{name} + +Updates participant details (activates/deactivates a participant). + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl -X PUT -H "Content-Type: application/json" \ + -d '{"isActive": true}' \ + http:///participants/payerfsp +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `isActive` | yes | [Boolean](boolean) | A flag to indicate whether or not the participant is active. | + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "name": "payerfsp", + "id": "dev1-central-ledger.mojaloop.live/participants/payerfsp", + "created": "\"2021-03-04T13:42:02.000Z\"", + "isActive": 1, + "links": { + "self": "dev1-central-ledger.mojaloop.live/participants/payerfsp" + }, + "accounts": [ + { + "id": 3, + "ledgerAccountType": "POSITION", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 4, + "ledgerAccountType": "SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 24, + "ledgerAccountType": "INTERCHANGE_FEE_SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + } + ] +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [String](#string) | The identifier of the participant in the form of a fully qualified domain name combined with the participant's `fspId`. | +| `created` | yes | [DateTime](#datetime) | Date and time when the participant was created. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the participant is active. Possible values are `1` and `0`. | +| `links` | yes | [Self](#self) | List of links for a Hypermedia-Driven RESTful Web Service. | +| `accounts` | yes | [Accounts](#accounts) | The list of ledger accounts configured for the participant. | + +
+ +### GET /participants/{name}/endpoints + +Retrieves information about the endpoints configured for a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl 'http:///participants/payerfsp/endpoints' +``` + +#### Example response +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{partyIdType}}/{{partyIdentifier}}/{{partySubIdOrType}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{partyIdType}}/{{partyIdentifier}}/{{partySubIdOrType}}/error" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_DELETE", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{partyIdType}}/{{partyIdentifier}}/{{partySubIdOrType}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_GET", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/parties/{{partyIdType}}/{{partyIdentifier}}/{{partySubIdOrType}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/parties/{{partyIdType}}/{{partyIdentifier}}/{{partySubIdOrType}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_PUT_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/parties/{{partyIdType}}/{{partyIdentifier}}/{{partySubIdOrType}}/error" + }, + { + "type": "FSPIOP_CALLBACK_URL_AUTHORIZATIONS", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{partyIdType}}/{{partyIdentifier}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{partyIdType}}/{{partyIdentifier}}/error" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{requestId}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{requestId}}/error" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTIES_GET", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/parties/{{partyIdType}}/{{partyIdentifier}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTIES_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/parties/{{partyIdType}}/{{partyIdentifier}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/parties/{{partyIdType}}/{{partyIdentifier}}/error" + }, + { + "type": "FSPIOP_CALLBACK_URL_QUOTES", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000" + }, + { + "type": "FSPIOP_CALLBACK_URL_TRX_REQ_SERVICE", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000" + }, + { + "type": "FSPIOP_CALLBACK_URL_TRANSFER_POST", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/transfers" + }, + { + "type": "FSPIOP_CALLBACK_URL_TRANSFER_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/transfers/{{transferId}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_TRANSFER_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/transfers/{{transferId}}/error" + }, + { + "type": "FSPIOP_CALLBACK_URL_BULK_TRANSFER_POST", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/bulkTransfers" + }, + { + "type": "FSPIOP_CALLBACK_URL_BULK_TRANSFER_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/bulkTransfers/{{id}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_BULK_TRANSFER_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/bulkTransfers/{{id}}/error" + }, + { + "type": "NET_DEBIT_CAP_THRESHOLD_BREACH_EMAIL", + "value": "some.email@gmail.com" + }, + { + "type": "NET_DEBIT_CAP_ADJUSTMENT_EMAIL", + "value": "some.email@gmail.com" + }, + { + "type": "SETTLEMENT_TRANSFER_POSITION_CHANGE_EMAIL", + "value": "some.email@gmail.com" + } +] +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `type` | yes | [String](#string) | Type of endpoint. | +| `value` | yes | [String](#string) | Endpoint value. | + +
+ +### POST /participants/{name}/endpoints + +Adds/updates endpoints for a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl -X POST -H "Content-Type: application/json" \ + -d '{"type": "NET_DEBIT_CAP_ADJUSTMENT_EMAIL", "value": "some.email@org.com"}' + http:///participants/payerfsp/endpoints +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `type` | yes | [String](#string) | Type of endpoint. | +| `value` | yes | [String](#string) | Endpoint value. | + +#### Example response + +``` +HTTP/1.1 201 Created +Content-Type: application/json +``` + +
+ + +### GET /participants/{name}/limits + +Retrieves limits information for a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Query parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | no | [CurrencyEnum](#currencyenum) | The currency of the limit. | +| `limit` | no | [String](#string) | Limit type. | + +#### Example request + +``` +curl 'http:///participants/payerfsp/limits' +``` + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "currency": "USD", + "limit": { + "type": "NET_DEBIT_CAP", + "value": 10000, + "alarmPercentage": 10 + } + } +] +``` + +#### Response data model + +Each limit in the returned list is applied to the specified participant name and currency in each object. + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the participant. | +| `limit` | yes | [ParticipantLimit](#participantlimit) | The limit configured for the participant. | + +
+ +### PUT /participants/{name}/limits + +Adjusts limits for a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl -X PUT -H "Content-Type: application/json" \ + -d '{ \ + "currency": "USD", \ + "limit": { \ + "type": NET_DEBIT_CAP", \ + "value": 10000, \ + "alarmPercentage": 20 + } \ + }' \ + http:///participants/payerfsp/limits +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the participant. | +| `limit` | yes | [ParticipantLimit](#participantlimit) | The limit configured for the participant. | + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "currency": "USD", + "limit": { + "type": "NET_DEBIT_CAP", + "value": 10000, + "alarmPercentage": 20 + } +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the participant. | +| `limit` | yes | [ParticipantLimit](#participantlimit) | The limit configured for the participant. | + +
+ +### GET /participants/{name}/positions + +Retrieves the position of a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Query parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | no | [CurrencyEnum](#currencyenum) | The currency of the limit. | + +#### Example request + +``` +curl 'http:///participants/payerfsp/positions' +``` + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "currency": "USD", + "value": 150, + "changedDate": "2021-05-10T08:01:38.000Z" + } +] +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the participant. | +| `value` | yes | [Number](#number) | Position value. | +| `changedDate` | yes | [DateTime](#datetime) | Date and time when the position last changed. | + +
+ +### GET /participants/{name}/accounts + +Retrieves the accounts and balances of a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl 'http:///participants/payerfsp/accounts' +``` + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "id": 3, + "ledgerAccountType": "POSITION", + "currency": "USD", + "isActive": 1, + "value": 150, + "reservedValue": 0, + "changedDate": "2021-05-10T08:01:38.000Z" + }, + { + "id": 4, + "ledgerAccountType": "SETTLEMENT", + "currency": "USD", + "isActive": 1, + "value": -165000, + "reservedValue": 0, + "changedDate": "2021-05-10T14:27:02.000Z" + }, + { + "id": 24, + "ledgerAccountType": "INTERCHANGE_FEE_SETTLEMENT", + "currency": "USD", + "isActive": 1, + "value": 0, + "reservedValue": 0, + "changedDate": "2021-03-30T12:23:06.000Z" + } +] +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `id` | yes | [Integer](#integer) | Identifier of the ledger account. | +| `ledgerAccountType` | yes | [String](#string) | Type of ledger account. | +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency of the ledger account. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the ledger account is active. Possible values are `1` and `0`. | +| `value` | yes | [Number](#number) | Account balance value. | +| `reservedValue` | yes | [Number](#number) | Value reserved in the account. | +| `changedDate` | yes | [DateTime](#datetime) | Date and time when the ledger account last changed. | + +
+ +### POST /participants/{name}/accounts + +Creates accounts in the Hub. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl -X POST -H "Content-Type: application/json" \ + -d '{"currency": "USD", "type": "HUB_MULTILATERAL_SETTLEMENT"}' \ + http:///participants/payerfsp/accounts +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency of the participant ledger account. | +| `type` | yes | [String](#string) | Type of ledger account. | + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "name": "hub", + "id": "dev1-central-ledger.mojaloop.live/participants/hub", + "created": "2021-01-12T10:56:30.000Z", + "isActive": 0, + "links": { + "self": "dev1-central-ledger.mojaloop.live/participants/hub" + }, + "accounts": [ + { + "id": 1, + "ledgerAccountType": "HUB_MULTILATERAL_SETTLEMENT", + "currency": "USD", + "isActive": 0, + "createdDate": "2021-01-12T10:56:30.000Z", + "createdBy": "unknown" + } + ] +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String](#string) | The name of the participant. | +| `id` | yes | [String](#string) | The identifier of the participant in the form of a fully qualified domain name combined with the participant's `fspId`. | +| `created` | yes | [DateTime](#datetime) | Date and time when the participant was created. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the participant is active. Possible values are `1` and `0`. | +| `links` | yes | [Self](#self) | List of links for a Hypermedia-Driven RESTful Web Service. | +| `accounts` | yes | [Accounts](#accounts) | The list of ledger accounts configured for the participant. | + +
+ +### POST /participants/{name}/accounts/{id} + +Records Funds In or Out of a participant account. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [Integer](#integer) | Account identifier. | + +#### Example request + +```` +curl -X POST -H "Content-Type: application/json" \ + -d '{ \ + "transferId": "bfd38d14-893f-469d-a6ca-a312a0223949", \ + "externalReference": "660616", \ + "action": "recordFundsIn", \ + "reason": "settlement", \ + "amount": { \ + "amount": "5000", \ + "currency": "USD" \ + }, \ + "extensionList": { \ + "extension": [ \ + { \ + "key": "scheme", \ + "value": "abc" \ + } \ + ] \ + } \ + }' \ + http:///participants/payerfsp/accounts/2 +```` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `transferId` | yes | [UUID](#uuid) | Transfer identifier. | +| `externalReference` | yes | [String](#string) | Reference to any external data, such as an identifier from the settlement bank. | +| `action` | yes | [Enum](#enum) | The action performed on the funds. Possible values are: `recordFundsIn` and `recordFundsOutPrepareReserve`. | +| `reason` | yes | [String](#string) | The reason for the FundsIn or FundsOut action. | +| `amount` | yes | [Money](#money) | The FundsIn or FundsOut amount. | +| `extensionList` | no | [ExtensionList](#extensionlist) | Additional details. | + +#### Example response + +```` +HTTP/1.1 202 Accepted +```` + +
+ +### PUT /participants/{name}/accounts/{id} + +Updates a participant account. Currently, updating only the `isActive` flag is supported. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [Integer](#integer) | Account identifier. | + +#### Example request + +``` +curl -X PUT -H "Content-Type: application/json" \ + -d '{"isActive": true}' \ + http:///participants/payerfsp/account/2 +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `isActive` | yes | [Boolean](boolean) | A flag to indicate whether or not the participant account is active. | + +#### Example response + +``` +HTTP/1.1 200 OK +``` + +
+ +### PUT /participants/{name}/accounts/{id}/transfers/{transferId} + +Records a transfer as a Funds In or Out transaction for a participant account. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [Integer](#integer) | Account identifier. | +| `transferId` | yes | [UUID](#uuid) | Transfer identifier. | + +#### Example request + +``` +curl -X PUT -H "Content-Type: application/json" \ + -d '{"action": "recordFundsOutCommit", "reason": "fix"}' \ + http:///participants/payerfsp/account/2/transfers/bfd38d14-893f-469d-a6ca-a312a0223949 +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `action` | yes | [Enum](#enum) | The FundsOut action performed. Possible values are: `recordFundsOutCommit` and `recordFundsOutAbort`. | +| `reason` | yes | [String](#string) | The reason for the FundsOut action. | + +#### Example response + +``` +HTTP/1.1 202 Accepted +``` + +
+ +### POST /participants/{name}/initialPositionAndLimits + +Adds initial limits and a position for a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +```` +curl -X POST -H "Content-Type: application/json" \ + -d '{ \ + "currency": "USD", \ + "limit": { \ + "type": "NET_DEBIT_CAP", \ + "value": "10000" \ + }, \ + "initialPosition": 0 \ + }' \ + http:///participants/payerfsp/initialPositionAndLimits +```` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency of the participant. | +| `limit` | yes | [ParticipantLimit](#participantlimit) | The limit configured for the participant. | +| `initialPosition` | no | [Number](#number) | Initial Position. | + +#### Example response + +``` +HTTP/1.1 201 Created +``` + +
+ +## API Resource `/settlementModels` + +The services provided by the resource `/settlementModels` are used by the Hub Operator for creating, updating, and viewing settlement models. + +### GET /settlementModels + +Retrieves information about all settlement models. + +#### Example request + +``` +curl 'http:///settlementModels' +``` + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "settlementModelId": 1, + "name": "DEFERREDNETUSD", + "isActive": true, + "settlementGranularity": "NET", + "settlementInterchange": "MULTILATERAL", + "settlementDelay": "DEFERRED", + "currency": "USD", + "requireLiquidityCheck": true, + "ledgerAccountTypeId": "POSITION", + "autoPositionReset": true + }, + { + "settlementModelId": 4, + "name": "DEFERREDNETEUR", + "isActive": true, + "settlementGranularity": "NET", + "settlementInterchange": "MULTILATERAL", + "settlementDelay": "DEFERRED", + "currency": "EUR", + "requireLiquidityCheck": true, + "ledgerAccountTypeId": "SETTLEMENT", + "autoPositionReset": true + } +] +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementModelId` | yes | [Integer](#integer) | Settlement model identifier. | +| `name` | yes | [String](#string) | Settlement model name. | +| `isActive` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model is active.| +| `settlementGranularity` | yes | [String](#string) | Specifies whether transfers are settled one by one or as a batch. Possible values are:
`GROSS`: Settlement is executed after each transfer is completed, that is, there is a settlement transaction that corresponds to every transaction.
`NET`: A group of transfers is settled together in a single settlement transaction, with each participant settling the net of all transfers over a given period of time.| +| `settlementInterchange` | yes | [String](#string) | Specifies the type of settlement arrangement between parties. Possible values are:
`BILATERAL`: Each participant settles its obligations with each other separately, and the scheme is not a party to the settlement.
`MULTILATERAL`: Each participant settles with the scheme for the net of its obligations, rather than settling separately with each other party.| +| `settlementDelay` | yes | [String](#string) | Specifies if settlement happens immediately after a transfer has completed or with a delay. Possible values are:
`IMMEDIATE`: Settlement happens immediately after a transfer has completed.
`DEFERRED`: Settlement is managed by the Hub operator on-demand or via a schedule.| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the settlement model. | +| `requireLiquidityCheck` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires liquidity check. | +| `ledgerAccountTypeId` | yes | [String](#string) | Type of ledger account. Possible values are:
`INTERCHANGE_FEE`: Tracks the interchange fees charged for transfers.
`POSITION`: Tracks how much a DFSP owes or is owed.
`SETTLEMENT`: The DFSP's Settlement Bank Account mirrored in the Hub. Acts as a reconciliation account and mirrors the movement of real funds.| +| `autoPositionReset` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires the automatic reset of the position. | + +
+ +### POST /settlementModels + +Creates a settlement model. + +#### Example request + +``` +curl -X POST -H "Content-Type: application/json" \ + -d '{ \ + "name": "DEFERREDNET", \ + "settlementGranularity": "NET", \ + "settlementInterchange": "MULTILATERAL", \ + "settlementDelay": "DEFERRED", \ + "requireLiquidityCheck": true, \ + "ledgerAccountType": "POSITION", \ + "autoPositionReset": true \ + }' \ + http:///settlementModels +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String](#string) | Settlement model name. | +| `settlementGranularity` | yes | [String](#string) | Specifies whether transfers are settled one by one or as a batch. Possible values are:
`GROSS`: Settlement is executed after each transfer is completed, that is, there is a settlement transaction that corresponds to every transaction.
`NET`: A group of transfers is settled together in a single settlement transaction, with each participant settling the net of all transfers over a given period of time.| +| `settlementInterchange` | yes | [String](#string) | Specifies the type of settlement arrangement between parties. Possible values are:
`BILATERAL`: Each participant settles its obligations with each other separately, and the scheme is not a party to the settlement.
`MULTILATERAL`: Each participant settles with the scheme for the net of its obligations, rather than settling separately with each other party.| +| `settlementDelay` | yes | [String](#string) | Specifies if settlement happens immediately after a transfer has completed or with a delay. Possible values are:
`IMMEDIATE`: Settlement happens immediately after a transfer has completed.
`DEFERRED`: Settlement is managed by the Hub operator on-demand or via a schedule.| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the settlement model. | +| `requireLiquidityCheck` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires liquidity check. | +| `ledgerAccountTypeId` | yes | [String](#string) | Type of ledger account. Possible values are:
`INTERCHANGE_FEE`: Tracks the interchange fees charged for transfers.
`POSITION`: Tracks how much a DFSP owes or is owed.
`SETTLEMENT`: The DFSP's Settlement Bank Account mirrored in the Hub. Acts as a reconciliation account and mirrors the movement of real funds.| +| `settlementAccountType` | yes | [String](#string) | A special type of ledger account into which settlements should be settled. Possible values are:
`SETTLEMENT`: A settlement account for the principal value of transfers (that is, the amount of money that the Payer wants the Payee to receive).
`INTERCHANGE_FEE_SETTLEMENT`: A settlement account for the fees associated with transfers. | +| `autoPositionReset` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires the automatic reset of the position. | + +#### Example response + +``` +HTTP/1.1 201 Created +``` + +
+ +### GET /settlementModels/{name} + +Retrieves information about a particular settlement model. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String](#string) | The name of the settlement model. | + +#### Example request + +``` +curl 'http:///settlementModels/DEFERREDNET' +``` + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "settlementModelId": 1, + "name": "DEFERREDNET", + "isActive": true, + "settlementGranularity": "NET", + "settlementInterchange": "MULTILATERAL", + "settlementDelay": "DEFERRED", + "currency": "USD", + "requireLiquidityCheck": true, + "ledgerAccountTypeId": "POSITION", + "autoPositionReset": true +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementModelId` | yes | [Integer](#integer) | Settlement model identifier. | +| `name` | yes | [String](#string) | Settlement model name. | +| `isActive` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model is active. | +| `settlementGranularity` | yes | [String](#string) | Specifies whether transfers are settled one by one or as a batch. Possible values are:
`GROSS`: Settlement is executed after each transfer is completed, that is, there is a settlement transaction that corresponds to every transaction.
`NET`: A group of transfers is settled together in a single settlement transaction, with each participant settling the net of all transfers over a given period of time.| +| `settlementInterchange` | yes | [String](#string) | Specifies the type of settlement arrangement between parties. Possible values are:
`BILATERAL`: Each participant settles its obligations with each other separately, and the scheme is not a party to the settlement.
`MULTILATERAL`: Each participant settles with the scheme for the net of its obligations, rather than settling separately with each other party.| +| `settlementDelay` | yes | [String](#string) | Specifies if settlement happens immediately after a transfer has completed or with a delay. Possible values are:
`IMMEDIATE`: Settlement happens immediately after a transfer has completed.
`DEFERRED`: Settlement is managed by the Hub operator on-demand or via a schedule.| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the settlement model. | +| `requireLiquidityCheck` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires liquidity check. | +| `ledgerAccountTypeId` | yes | [String](#string) | Type of ledger account. Possible values are:
`INTERCHANGE_FEE`: Tracks the interchange fees charged for transfers.
`POSITION`: Tracks how much a DFSP owes or is owed.
`SETTLEMENT`: The DFSP's Settlement Bank Account mirrored in the Hub. Acts as a reconciliation account and mirrors the movement of real funds. | +| `autoPositionReset` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires the automatic reset of the position. | + +
+ +### PUT /settlementModels/{name} + +Updates a settlement model (activates/deactivates a settlement model). + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String](#string) | The name of the settlement model. | + +#### Example request + +``` +curl -X PUT -H "Content-Type: application/json" \ + -d '{"isActive": true}' \ + http:///settlementModels/DEFERREDNET +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `isActive` | yes | [Boolean](#boolean) | A flag to indicate whether or not the settlement model is active. | + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "settlementModelId": 1, + "name": "DEFERREDNET", + "isActive": true, + "settlementGranularity": "NET", + "settlementInterchange": "MULTILATERAL", + "settlementDelay": "DEFERRED", + "currency": "USD", + "requireLiquidityCheck": true, + "ledgerAccountTypeId": "POSITION", + "autoPositionReset": true +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementModelId` | yes | [Integer](#integer) | Settlement model identifier. | +| `name` | yes | [String](#string) | Settlement model name. | +| `isActive` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model is active. | +| `settlementGranularity` | yes | [String](#string) | Specifies whether transfers are settled one by one or as a batch. Possible values are:
`GROSS`: Settlement is executed after each transfer is completed, that is, there is a settlement transaction that corresponds to every transaction.
`NET`: A group of transfers is settled together in a single settlement transaction, with each participant settling the net of all transfers over a given period of time.| +| `settlementInterchange` | yes | [String](#string) | Specifies the type of settlement arrangement between parties. Possible values are:
`BILATERAL`: Each participant settles its obligations with each other separately, and the scheme is not a party to the settlement.
`MULTILATERAL`: Each participant settles with the scheme for the net of its obligations, rather than settling separately with each other party.| +| `settlementDelay` | yes | [String](#string) | Specifies if settlement happens immediately after a transfer has completed or with a delay. Possible values are:
`IMMEDIATE`: Settlement happens immediately after a transfer has completed.
`DEFERRED`: Settlement is managed by the Hub operator on-demand or via a schedule.| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the settlement model. | +| `requireLiquidityCheck` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires liquidity check. | +| `ledgerAccountTypeId` | yes | [String](#string) | Type of ledger account. Possible values are:
`INTERCHANGE_FEE`: Tracks the interchange fees charged for transfers.
`POSITION`: Tracks how much a DFSP owes or is owed.
`SETTLEMENT`: The DFSP's Settlement Bank Account mirrored in the Hub. Acts as a reconciliation account and mirrors the movement of real funds. | +| `autoPositionReset` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires the automatic reset of the position. | + +
+ +## API Resource `/transactions` + +The services provided by the resource `/transactions` are used by the Hub Operator for retrieving transfer details. + +### GET /transactions/{id} + +Retrieves information about a particular transaction. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `id` | yes | [UUID](#uuid) | Transfer identifier. | + +#### Example request + +``` +curl 'http:///transactions/85feac2f-39b2-491b-817e-4a03203d4f14' +``` + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "quoteId": "7c23e80c-d078-4077-8263-2c047876fcf6", + "transactionId": "85feac2f-39b2-491b-817e-4a03203d4f14", + "transactionRequestId": "a8323bc6-c228-4df2-ae82-e5a997baf898", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "123456789", + "fspId": "MobileMoneyAbc" + }, + "name": "John Doe", + "personalInfo": { + "complexName": { + "firstName": "John", + "middleName": "William", + "lastName": "Doe" + }, + "dateOfBirth": "1966-06-16" + } + }, + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "987654321", + "fspId": "MobileMoneyXyz" + }, + "name": "Jane Doe", + "personalInfo": { + "complexName": { + "firstName": "Mary", + "middleName": "Jane", + "lastName": "Doe" + }, + "dateOfBirth": "1975-05-15" + } + }, + "amount": { + "currency": "USD", + "amount": "50" + }, + "transactionType": { + "scenario": "DEPOSIT", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + } +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `quoteId` | | [UUID](#uuid) | Quote identifier. | +| `transactionId` | | [UUID](#uuid) | Transaction identifier. | +| `transactionRequestId` | | [String](#string) | Identifies an optional previously-sent transaction request. | +| `payee` | | [Party](#party) | Payee details. | +| `payer` | | [Party](#party) | Payer details. | +| `amount` | | [Money](#money) | Transaction amount. | +| `transactionType` | | [TransactionType](#transactiontype) | Transaction details. | +| `note` | | [String](#string) | A memo that will be attached to the transaction. | +| `extensionList` | | [ExtensionList](#extensionlist) | Additional details. | + +
+ +## Data models used by the API + +### Format + +For details on the formats used for element data types used by the API, see section [Element Data Type Formats](../fspiop/logical-data-model#element-data-type-formats) in the Mojaloop FSPIOP API Definition. + +### Element Data Type Formats + +This section defines element data types used by the API. + +#### Amount + +For details, see section [Amount](../fspiop/logical-data-model#amount) in the Mojaloop FSPIOP API Definition. + +#### Boolean + +A `"true"` or `"false"` value. + +#### DateTime + +For details, see section [DateTime](../fspiop/logical-data-model#datetime) in the Mojaloop FSPIOP API Definition. + +#### Enum + +For details, see section [Enum](../fspiop/logical-data-model#enum) in the Mojaloop FSPIOP API Definition. + +#### Integer + +For details, see section [Integer](../fspiop/logical-data-model#integer) in the Mojaloop FSPIOP API Definition. + +#### Number + +The API data type `Number` is a an arbitrary-precision, base-10 decimal number value. + +#### String + +For details, see section [String](../fspiop/logical-data-model#string) in the Mojaloop FSPIOP API Definition. + +#### UUID + +For details, see section [UUID](../fspiop/logical-data-model#uuid) in the Mojaloop FSPIOP API Definition. + +
+ +## Element Definitions + +This section defines element types used by the API. + +#### IsActive + +Data model for the element **IsActive**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not a ledger account / participant is active. Possible values are `1` (active) and `0` (not active). | + +#### IsActiveBoolean + +Data model for the element **IsActiveBoolean**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `isActive` | yes | [Boolean](#boolean) | A flag to indicate whether or not an account / participant / settlement model is active. | + +#### CurrencyEnum + +For details, see section [Currency](../fspiop/logical-data-model#currencycode-enum) enum in the Mojaloop FSPIOP API Definition. + +#### RequireLiquidityCheck + +Data model for the element **RequireLiquidityCheck**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `requireLiquidityCheck` | yes | [Boolean](#boolean) | A flag to indicate whether or not a settlement model requires liquidity check. | + +#### Self + +Data model for the element **Self**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `self` | yes | [String](#string) | Fully qualified domain name combined with the `fspId` of the participant. | + +#### SettlementDelay + +Data model for the element **SettlementDelay**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementDelay` | yes | [Enum](#enum) of String | Specifies if settlement happens immediately after a transfer has completed or with a delay. Allowed values for the enumeration are:
`IMMEDIATE`: Settlement happens immediately after a transfer has completed.
`DEFERRED`: Settlement is managed by the Hub operator on-demand or via a schedule. | + +#### SettlementGranularity + +Data model for the element **SettlementGranularity**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementGranularity` | yes | [Enum](#enum) of String | Specifies whether transfers are settled one by one or as a batch. Allowed values for the enumeration are:
`GROSS`: Settlement is executed after each transfer is completed, that is, there is a settlement transaction that corresponds to every transaction.
`NET`: A group of transfers is settled together in a single settlement transaction, with each participant settling the net of all transfers over a given period of time. | + +#### SettlementInterchange + +Data model for the element **SettlementInterchange**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementInterchange` | yes | [Enum](#enum) of String | Specifies the type of settlement arrangement between parties. Allowed values for the enumeration are:
`BILATERAL`: Each participant settles its obligations with each other separately, and the scheme is not a party to the settlement.
`MULTILATERAL`: Each participant settles with the scheme for the net of its obligations, rather than settling separately with each other party. | + +
+ +## Complex types + +#### Accounts + +The list of ledger accounts configured for the participant. For details on the account object, see [IndividualAccount](#individualaccount). + +#### ErrorInformation + +For details, see section [ErrorInformation](../fspiop/logical-data-model#errorinformation) in the Mojaloop FSPIOP API Definition. + +#### ErrorInformationResponse + +Data model for the complex type object that contains an optional element [ErrorInformation](#errorinformation) used along with 4xx and 5xx responses. + +#### Extension + +For details, see section [Extension](../fspiop/logical-data-model#extension) in the Mojaloop FSPIOP API Definition. + +#### ExtensionList + +For details, see section [ExtensionList](../fspiop/logical-data-model#extensionlist) in the Mojaloop FSPIOP API Definition. + +#### IndividualAccount + +Data model for the complex type **IndividualAccount**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `id` | yes | [Integer](#integer) | Identifier of the ledger account. | +| `ledgerAccountType` | yes | [String](#string) | Type of the ledger account (for example, POSITION). | +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency of the account. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the ledger account is active. Possible values are `1` and `0`. | +| `createdDate` | yes | [DateTime](#datetime) | Date and time when the ledger account was created. | +| `createdBy` | yes | [String](#string) | The entity that created the ledger account. | + +#### Limit + +Data model for the complex type **Limit**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `type` | yes | [String](#string) | Limit type. | +| `value` | yes | a positive [Number](#number) | Limit value. | + +#### Money + +For details, see section [Money](../fspiop/logical-data-model#mondey) in the Mojaloop FSPIOP API Definition. + +#### Participant + +Data model for the complex type **Participant**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String](#string) | The name of the participant. | +| `id` | yes | [String](#string) | The identifier of the participant in the form of a fully qualified domain name combined with the participant's `fspId`. | +| `created` | yes | [DateTime](#datetime) | Date and time when the participant was created. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the participant is active. Possible values are `1` and `0`. | +| `links` | yes | [Self](#self) | List of links for a Hypermedia-Driven RESTful Web Service. | +| `accounts` | yes | [Accounts](#accounts) | The list of ledger accounts configured for the participant. | + +#### ParticipantFunds + +Data model for the complex type **ParticipantFunds**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `transferId` | yes | [UUID](#uuid) | Transfer identifier. | +| `externalReference` | yes | [String](#string) | Reference to any external data, such as an identifier from the settlement bank. | +| `action` | yes | [Enum](#enum) | The action performed on the funds. Possible values are: `recordFundsIn` and `recordFundsOutPrepareReserve`. | +| `reason` | yes | [String](#string) | The reason for the FundsIn or FundsOut action. | +| `amount` | yes | [Money](#money) | The FundsIn or FundsOut amount. | +| `extensionList` | no | [ExtensionList](#extensionlist) | Additional details. | + +#### ParticipantLimit + +Data model for the complex type **ParticipantLimit**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `type` | yes | [String](#string) | The type of participant limit (for example, `NET_DEBIT_CAP`.) | +| `value` | yes | [Number](#number) | The value of the limit that has been set for the participant. | +| `alarmPercentage` | yes | [Number](#number) | An alarm notification is triggered when a pre-specified percentage of the limit is reached. Specifying an `alarmPercentage` is optional. If not specified, it will default to 10 percent, expressed as `10`. | + +#### ParticipantsNameEndpointsObject + +Data model for the complex type **ParticipantsNameEndpointsObject**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `type` | yes | [String](#string) | The endpoint type. | +| `value` | yes | [String](#string) | The endpoint value. | + +#### ParticipantsNameLimitsObject + +Data model for the complex type **ParticipantsNameLimitsObject**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the participant. | +| `limit` | yes | [ParticipantLimit](#participantlimit) | The limit configured for the participant. | + +#### Party + +For details, see section [Party](../fspiop/logical-data-model#party) in the Mojaloop FSPIOP API Definition. + +#### PartyComplexName + +For details, see section [PartyComplexName](../fspiop/logical-data-model#partycomplexname) in the Mojaloop FSPIOP API Definition. + +#### PartyIdInfo + +For details, see section [PartyIdInfo](../fspiop/logical-data-model#partyidinfo) in the Mojaloop FSPIOP API Definition. + +#### PartyPersonalInfo + +For details, see section [PartyPersonalInfo](../fspiop/logical-data-model#partypersonalinfo) in the Mojaloop FSPIOP API Definition. + +#### RecordFundsOut + +Data model for the complex type **RecordFundsOut**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `action` | yes | [Enum](#enum) | The FundsOut action performed. Possible values are: `recordFundsOutCommit` and `recordFundsOutAbort`. | +| `reason` | yes | [String](#string) | The reason for the FundsOut action. | + +#### Refund + +Data model for the complex type **Refund**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `originalTransactionId` | yes | [UUID](#uuid) | Reference to the original transaction id that is requested to be refunded. | +| `refundReason` | no | [String(1-128)](#string) | Free text indicating the reason for the refund. | + +#### SettlementModelsObject + +Data model for the complex type **SettlementModelsObject**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementModelId` | yes | [Integer](#integer) | Settlement model identifier. | +| `name` | yes | [String](#string) | Settlement model name. | +| `isActive` | yes | [Boolean](#boolean) | A flag to indicate whether or not the settlement model is active. | +| `settlementGranularity` | yes | [String](#string) | Specifies whether transfers are settled one by one or as a batch. Possible values are:
`GROSS`: Settlement is executed after each transfer is completed, that is, there is a settlement transaction that corresponds to every transaction.
`NET`: A group of transfers is settled together in a single settlement transaction, with each participant settling the net of all transfers over a given period of time.| +| `settlementInterchange` | yes | [String](#string) | Specifies the type of settlement arrangement between parties. Possible values are:
`BILATERAL`: Each participant settles its obligations with each other separately, and the scheme is not a party to the settlement.
`MULTILATERAL`: Each participant settles with the scheme for the net of its obligations, rather than settling separately with each other party.| +| `settlementDelay` | yes | [String](#string) | Specifies if settlement happens immediately after a transfer has completed or with a delay. Possible values are:
`IMMEDIATE`: Settlement happens immediately after a transfer has completed.
`DEFERRED`: Settlement is managed by the Hub operator on-demand or via a schedule.| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the settlement model. | +| `requireLiquidityCheck` | yes | [Boolean](#boolean) | A flag to indicate whether or not the settlement model requires liquidity check. | +| `ledgerAccountTypeId` | yes | [String](#string) | Type of ledger account. Possible values are:
`INTERCHANGE_FEE`: Tracks the interchange fees charged for transfers.
`POSITION`: Tracks how much a DFSP owes or is owed.
`SETTLEMENT`: The DFSP's Settlement Bank Account mirrored in the Hub. Acts as a reconciliation account and mirrors the movement of real funds.| +| `autoPositionReset` | yes | [Boolean](#boolean) | A flag to indicate whether or not the settlement model requires the automatic reset of the position. | + +#### TransactionType + +For details, see section [TransactionType](../fspiop/logical-data-model#transactiontype) in the Mojaloop FSPIOP API Definition. diff --git a/docs/technical/api/assets/diagrams/images/figure1-platforms-layout.svg b/docs/technical/api/assets/diagrams/images/figure1-platforms-layout.svg new file mode 100644 index 000000000..8a12de358 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure1-platforms-layout.svg @@ -0,0 +1,3 @@ + + +
CA
CA
ALS
ALS
FSP-1
FSP-1
FSP-2
FSP-2
Switch
Switch
FSP-3
FSP-3
FSP-4
FSP-4
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Legend:
Solid lines indicate TLS-secured communication.
Dashed lines indicate certificate owner.
Legend:...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure11.svg b/docs/technical/api/assets/diagrams/images/figure11.svg new file mode 100644 index 000000000..773d8495b --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure11.svg @@ -0,0 +1,4 @@ + + + +
 1 USD 
 1 USD 
Agent Commission account
Agent Comm...
 2 USD 
 2 USD 
Fee account
Fee account
 98 USD 
 98 USD 
Payer's account
Payer's ac...
 99 USD 
 99 USD 
Payer FSP's Switch account
Payer FSP'...
 99 USD 
 99 USD 
Payer FSP Switch account
Payer FSP...
 99 USD 
 99 USD 
Payee FSP Switch account
Payee FSP...
 98 USD 
 98 USD 
1 USD
1 USD
Payee FSP's Switch account
Payee FSP'...
FSP Commision account
FSP Commis...
Fee account
Fee account
Agent Commision account
Agent Comm...
Payee's account
Payee's ac...
FSO Commission account
FSO Commis...
Payer FSP
Payer FSP
Payee FSP
Payee FSP
Switch
Switch
Text is not SVG - cannot display
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure12.svg b/docs/technical/api/assets/diagrams/images/figure12.svg new file mode 100644 index 000000000..c5183f904 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure12.svg @@ -0,0 +1,3 @@ + + +
Payer FSP fee
[Not supported by viewer]
Payer
Payer
 Payee FSP transaction fee 
[Not supported by viewer]
Payee FSP commission
to subsidize transaction 
[Not supported by viewer]
Internal Payee fee to Payee FSP
<font color="#ff3333">Internal Payee fee to Payee FSP</font>
Internal Payee FSP
bonus/commission
to Payee
[Not supported by viewer]
Payee
Payee
InternalPayer FSP
bonus/ commission
to Payer
[Not supported by viewer]
Switch
Switch
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure14.svg b/docs/technical/api/assets/diagrams/images/figure14.svg new file mode 100644 index 000000000..070228ec6 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure14.svg @@ -0,0 +1,3 @@ + + +
 1 USD 
[Not supported by viewer]
Agent Commission account
Agent Commission account
Fee account
Fee account
 100 USD 
 100 USD 
Payer's account
Payer's account
 99 USD 
 99 USD 
Payer FSP's Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payer FSP Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
1 USD
1 USD
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure16.svg b/docs/technical/api/assets/diagrams/images/figure16.svg new file mode 100644 index 000000000..8f8828555 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure16.svg @@ -0,0 +1,3 @@ + + +
 2 USD 
[Not supported by viewer]
Agent Commission account
Agent Commission account
Fee account
Fee account
 98 USD 
 98 USD 
Payer's account
Payer's account
 99 USD 
 99 USD 
Payer FSP's Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payer FSP Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payee FSP Switch account
[Not supported by viewer]
 98 USD 
 98 USD 
1 USD
1 USD
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
 1 USD 
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure18.svg b/docs/technical/api/assets/diagrams/images/figure18.svg new file mode 100644 index 000000000..a50ef985a --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure18.svg @@ -0,0 +1,3 @@ + + +
 1 USD 
[Not supported by viewer]
Agent Commission account
Agent Commission account
Fee account
Fee account
 99 USD 
 99 USD 
Payer's account
Payer's account
 97 USD 
 97 USD 
Payer FSP's Switch account
[Not supported by viewer]
 97 USD 
 97 USD 
Payer FSP Switch account
[Not supported by viewer]
 97 USD 
 97 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
 3 USD 
 3 USD 
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
 2 USD 
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure20.svg b/docs/technical/api/assets/diagrams/images/figure20.svg new file mode 100644 index 000000000..12a57a2a1 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure20.svg @@ -0,0 +1,3 @@ + + +
 1 USD 
[Not supported by viewer]
Agent Commission account
Agent Commission account
Fee account
Fee account
 100 USD 
 100 USD 
Payer's account
Payer's account
 99 USD 
 99 USD 
Payer FSP's Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payer FSP Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
 1 USD 
 1 USD 
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
 1 USD 
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure22.svg b/docs/technical/api/assets/diagrams/images/figure22.svg new file mode 100644 index 000000000..60b81e1c7 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure22.svg @@ -0,0 +1,3 @@ + + +
 1 USD 
[Not supported by viewer]
Agent Commission account
Agent Commission account
Fee account
Fee account
 100 USD 
 100 USD 
Payer's account
Payer's account
 98 USD 
 98 USD 
Payer FSP's Switch account
[Not supported by viewer]
 98 USD 
 98 USD 
Payer FSP Switch account
[Not supported by viewer]
 98 USD 
 98 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
 2 USD 
 2 USD 
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
 2 USD 
[Not supported by viewer]
Agent
Agent
Customer
Customer
$
[Not supported by viewer]
100 USD in cash from Payee (Customer) to Payer (Agent)
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure24.svg b/docs/technical/api/assets/diagrams/images/figure24.svg new file mode 100644 index 000000000..411df60cc --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure24.svg @@ -0,0 +1,3 @@ + + +
 1 USD 
[Not supported by viewer]
Agent Commission account
Agent Commission account
Fee account
Fee account
 100 USD 
 100 USD 
Payer's account
Payer's account
 99 USD 
 99 USD 
Payer FSP's Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payer FSP Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
 1 USD 
 1 USD 
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
 1 USD 
[Not supported by viewer]
 1 USD 
[Not supported by viewer]
Agent
Agent
Customer
Customer
$
[Not supported by viewer]
101 USD in cash from Payee (Customer) to Payer (Agent)
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure26.svg b/docs/technical/api/assets/diagrams/images/figure26.svg new file mode 100644 index 000000000..cee48e5df --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure26.svg @@ -0,0 +1,3 @@ + + +
Agent Commission account
Agent Commission account
Fee account
Fee account
 100 USD 
 100 USD 
Payer's account
Payer's account
 100 USD 
 100 USD 
Payer FSP's Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
Payer FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
 1 USD 
 1 USD 
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
Customer
Customer
Merchant
Merchant
 1 USD 
 1 USD 
Goods/Service worth
100 USD from Merchant (Payee)
 to Customer (Payer)
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure28.svg b/docs/technical/api/assets/diagrams/images/figure28.svg new file mode 100644 index 000000000..2083fcd31 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure28.svg @@ -0,0 +1,3 @@ + + +
Agent Commission account
Agent Commission account
Fee account
Fee account
 100 USD 
 100 USD 
Payer's account
Payer's account
 102 USD 
 102 USD 
Payer FSP's Switch account
[Not supported by viewer]
 102 USD 
 102 USD 
Payer FSP Switch account
[Not supported by viewer]
 102 USD 
 102 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
 1 USD 
 1 USD 
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
 3 USD 
 3 USD 
 2 USD 
 2 USD 
 2 USD 
 2 USD 
Customer
Customer
Agent
Agent
$
[Not supported by viewer]
100 USD in cash from Agent (Payee) to Customer (Payer)
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure30.svg b/docs/technical/api/assets/diagrams/images/figure30.svg new file mode 100644 index 000000000..f91ca847a --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure30.svg @@ -0,0 +1,3 @@ + + +
Agent Commission account
Agent Commission account
Fee account
Fee account
 97 USD 
 97 USD 
Payer's account
Payer's account
 99 USD 
 99 USD 
Payer FSP's Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payer FSP Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payee FSP Switch account
[Not supported by viewer]
 97 USD 
 97 USD 
 1 USD 
 1 USD 
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
 3 USD 
 3 USD 
 2 USD 
 2 USD 
 2 USD 
 2 USD 
Customer
Customer
Agent
Agent
$
[Not supported by viewer]
97 USD in cash from Agent (Payee) to Customer (Payer)
97 USD in cash from Agent (Payee) to Customer (Payer)
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure32.svg b/docs/technical/api/assets/diagrams/images/figure32.svg new file mode 100644 index 000000000..943d49ae4 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure32.svg @@ -0,0 +1,3 @@ + + +
Agent Commission account
Agent Commission account
Fee account
Fee account
 100 USD 
 100 USD 
Payer's account
Payer's account
 102 USD 
 102 USD 
Payer FSP's Switch account
[Not supported by viewer]
 102 USD 
 102 USD 
Payer FSP Switch account
[Not supported by viewer]
 102 USD 
 102 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
 1 USD 
 1 USD 
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
 3 USD 
 3 USD 
 2 USD 
 2 USD 
 2 USD 
 2 USD 
Customer
Customer
Agent
Agent
$
[Not supported by viewer]
100 USD in cash from Agent (Payee) to Customer (Payer)
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure34.svg b/docs/technical/api/assets/diagrams/images/figure34.svg new file mode 100644 index 000000000..db4f8f046 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure34.svg @@ -0,0 +1,3 @@ + + +
Agent Commission account
Agent Commission account
Fee account
Fee account
 100 USD 
 100 USD 
Payer's account
Payer's account
 101 USD 
 101 USD 
Payer FSP's Switch account
[Not supported by viewer]
 101 USD 
 101 USD 
Payer FSP Switch account
[Not supported by viewer]
 101 USD 
 101 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
Customer
Customer
Merchant
Merchant
 1 USD 
 1 USD 
Goods/Service worth
100 USD from Merchant (Payee)
to Customer (Payer)
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure36.svg b/docs/technical/api/assets/diagrams/images/figure36.svg new file mode 100644 index 000000000..d5941799f --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure36.svg @@ -0,0 +1,3 @@ + + +
Agent Commission account
Agent Commission account
Fee account
Fee account
 100 USD 
 100 USD 
Payer's account
Payer's account
 101 USD 
 101 USD 
Payer FSP's Switch account
[Not supported by viewer]
 101 USD 
 101 USD 
Payer FSP Switch account
[Not supported by viewer]
 101 USD 
 101 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
 1 USD 
 1 USD 
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
 1 USD 
[Not supported by viewer]
Customer
Customer
 2 USD 
[Not supported by viewer]
$
[Not supported by viewer]
100 USD in cash from ATM (Payee) to Customer (Payer)
100 USD in cash from ATM (Payee) to Customer (Payer)
ATM
ATM
diff --git a/docs/technical/api/assets/diagrams/images/figure38.svg b/docs/technical/api/assets/diagrams/images/figure38.svg new file mode 100644 index 000000000..9e6187188 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure38.svg @@ -0,0 +1,3 @@ + + +
Agent Commission account
Agent Commission account
Fee account
Fee account
 100 USD 
 100 USD 
Payer's account
Payer's account
 99 USD 
 99 USD 
Payer FSP's Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payer FSP Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
Customer
Customer
Merchant
Merchant
 1 USD 
 1 USD 
Goods/Service worth
100 USD from Merchant (Payee)
to Customer (Payer)
[Not supported by viewer]
 1 USD 
 1 USD 
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure40.svg b/docs/technical/api/assets/diagrams/images/figure40.svg new file mode 100644 index 000000000..ae2cf6677 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure40.svg @@ -0,0 +1,3 @@ + + +
 1 USD 
[Not supported by viewer]
Agent Commission account
Agent Commission account
Fee account
Fee account
 100 USD 
 100 USD 
Payer's account
Payer's account
 99 USD 
 99 USD 
Payer FSP's Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payer FSP Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
 1 USD 
 1 USD 
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP 
Commission account
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
 1 USD 
[Not supported by viewer]
Customer
Customer
Agent
Agent
 1 USD 
[Not supported by viewer]
$
[Not supported by viewer]
101 USD in cash from Agent (Payee) to Customer (Payer)
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure46.svg b/docs/technical/api/assets/diagrams/images/figure46.svg new file mode 100644 index 000000000..75093833a --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure46.svg @@ -0,0 +1,3 @@ + + +
RECEIVED
<b>RECEIVED</b>
PENDING
<b>PENDING</b>
REJECTED
<b>REJECTED</b>
ACCEPTED
<b>ACCEPTED</b>
Payer FSP receives
the transaction
request from 
the Payee FSP
[Not supported by viewer]
Payer FSP sends
the transaction
request to 
the Payee
[Not supported by viewer]
Payer 
responds
[Not supported by viewer]
Payer  approved 
the transaction
[Not supported by viewer]
Payer rejected 
the transaction
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure48.svg b/docs/technical/api/assets/diagrams/images/figure48.svg new file mode 100644 index 000000000..1a7fa406f --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure48.svg @@ -0,0 +1,3 @@ + + +
RECEIVED
<b>RECEIVED</b>
PENDING
<b>PENDING</b>
REJECTED
<b>REJECTED</b>
ACCEPTED
<b>ACCEPTED</b>
Peer FSP 
receives the 
request 
from the FSP
[Not supported by viewer]
Peer FSP 
validates 
the quote 
request
[Not supported by viewer]
Peer FSP
tries to 
create a 
quote
[Not supported by viewer]
Peer FSP 
successfully 
create a quote
[Not supported by viewer]
Peer FSP 
failed to 
create a quote
[Not supported by viewer]
EXPIRED
<b>EXPIRED</b>
The quote 
expires and 
is no longer 
valid
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure56.svg b/docs/technical/api/assets/diagrams/images/figure56.svg new file mode 100644 index 000000000..b0d58be95 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure56.svg @@ -0,0 +1,3 @@ + + +
RECEIVED
<b>RECEIVED</b>
RESERVED
<b>RESERVED</b>
ABORTED
<b>ABORTED</b>
COMMITTED
<b>COMMITTED</b>
The ledger 
receives a 
transfer 
request
[Not supported by viewer]
The ledger 
reserves 
the transfer
[Not supported by viewer]
The ledger 
receives 
results 
from the 
next ledger
[Not supported by viewer]
Next ledger 
successfully 
performed the 
transfer
[Not supported by viewer]
Next ledger 
failed to 
perform the 
transfer or the 
transfer expired
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure58.svg b/docs/technical/api/assets/diagrams/images/figure58.svg new file mode 100644 index 000000000..5d8ba0c93 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure58.svg @@ -0,0 +1,3 @@ + + +
RECEIVED
<b>RECEIVED</b>
PENDING
<b>PENDING</b>
REJECTED
<b>REJECTED</b>
COMPLETED
<b>COMPLETED</b>
Payee FSP
receives the
transaction
from the
Payer FSP
[Not supported by viewer]
Payee FSP 
validates 
the
transaction
[Not supported by viewer]
Payee FSP 
tries to 
perform the 
transaction
[Not supported by viewer]
Payee FSP 
successfully 
performed the 
transaction
[Not supported by viewer]
Payee FSP failed 
to 
perform 
the transaction
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure60.svg b/docs/technical/api/assets/diagrams/images/figure60.svg new file mode 100644 index 000000000..9f97ba682 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure60.svg @@ -0,0 +1,3 @@ + + +
RECEIVED
<b>RECEIVED</b>
PENDING
<b>PENDING</b>
REJECTED
<b>REJECTED</b>
ACCEPTED
<b>ACCEPTED</b>
Payee FSP 
receives the 
request 
from the 
Payer FSP
[Not supported by viewer]
Payee FSP
validates 
the bulk 
quote 
request
[Not supported by viewer]
Payee FSP 
tries to 
create a 
quote
[Not supported by viewer]
Payee FSP 
successfully 
created a quote
[Not supported by viewer]
Payee FSP 
failed to 
create a quote
[Not supported by viewer]
EXPIRED
<b>EXPIRED</b>
The quote 
expires and 
is no longer 
valid
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure62.svg b/docs/technical/api/assets/diagrams/images/figure62.svg new file mode 100644 index 000000000..466446b23 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure62.svg @@ -0,0 +1,3 @@ + + +
RECEIVED
<b>RECEIVED</b>
PENDING
<b>PENDING</b>
REJECTED
<b>REJECTED</b>
ACCEPTED
<b>ACCEPTED</b>
Payee FSP 
receives 
the bulk 
transfer 
from the 
Payer FSP
[Not supported by viewer]
Payee FSP 
validates 
the bulk 
transfer
[Not supported by viewer]
Payee FSP 
finishes 
validation 
of the bulk 
transfer
[Not supported by viewer]
Payee FSP 
accepts to 
process 
the bulk 
transfer
[Not supported by viewer]
Payee FSP 
rejects to 
process the 
bulk transfer
[Not supported by viewer]
PROCESSING
<b>PROCESSING</b>
Payee FSP 
starts to 
transfer 
funds to 
the Payees
[Not supported by viewer]
COMPLETED
<b>COMPLETED</b>
Payee FSP 
completes 
transfer of 
funds to 
the Payees
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure63.svg b/docs/technical/api/assets/diagrams/images/figure63.svg new file mode 100644 index 000000000..1f262897d --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure63.svg @@ -0,0 +1,3 @@ + + +
High-level 
category
[Not supported by viewer]
Low-level 
category
[Not supported by viewer]
Specific error
Specific error
1 digit
1 digit
1 digit
1 digit
2 digit
2 digit
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure7.svg b/docs/technical/api/assets/diagrams/images/figure7.svg new file mode 100644 index 000000000..e3b0e5548 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure7.svg @@ -0,0 +1,3 @@ + + +
Payer fee to Payer FSP
<font color="#ff3333">Payer fee to Payer FSP</font>
Payer
Payer
 Payee FSP transaction fee 
[Not supported by viewer]
Payee FSP commission
to Payer FSP
[Not supported by viewer]
Internal Payee fee to Payee FSP
<font color="#ff3333">Internal Payee fee to Payee FSP</font>
internal Payee FSP
bonus/commission
to Payee
[Not supported by viewer]
Payee
Payee
Payer FSP
bonus/commission
 to Payee
[Not supported by viewer]
Switch
Switch
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure73.svg b/docs/technical/api/assets/diagrams/images/figure73.svg new file mode 100644 index 000000000..148715368 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure73.svg @@ -0,0 +1,3 @@ + + +
Switch
(Identifier = Switch)
Switch<br>(Identifier = <b>Switch</b>)
FSP
(Identifier = MobileMoney)
FSP<br>(<b>Identifier = MobileMoney</b>)
FSP
(Identifier = BankNrOne)
FSP<br>(<b>Identifier = BankNrOne</b>)
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/images/figure9.svg b/docs/technical/api/assets/diagrams/images/figure9.svg new file mode 100644 index 000000000..68f6c3716 --- /dev/null +++ b/docs/technical/api/assets/diagrams/images/figure9.svg @@ -0,0 +1,3 @@ + + +
 1 USD 
[Not supported by viewer]
Agent Commission account
Agent Commission account
 1 USD 
 1 USD 
Fee account
Fee account
 100 USD 
 100 USD 
Payer's account
Payer's account
 99 USD 
 99 USD 
Payer FSP's Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payer FSP Switch account
[Not supported by viewer]
 99 USD 
 99 USD 
Payee FSP Switch account
[Not supported by viewer]
 100 USD 
 100 USD 
1 USD
1 USD
Payee FSP's Switch account
[Not supported by viewer]
FSP Commission account
FSP Commission account
Fee account
Fee account
Agent Commission account
Agent Commission account
Payee's account
Payee's account
FSP Commission account
FSP Commission account
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Switch
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/api/assets/diagrams/sequence/figure1.plantuml b/docs/technical/api/assets/diagrams/sequence/figure1.plantuml new file mode 100644 index 000000000..e80fedf1c --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure1.plantuml @@ -0,0 +1,68 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +' declare title +' title HTTP POST call flow + +' Actor Keys: +' participant - FSP, Peer FSP and Optional Switch + +' declare actors +participant "\nFSP" as FSP +participant "Optional\nSwitch" as Switch +participant "Peer\nFSP" as PEERFSP + +' start flow +FSP ->> Switch: **POST /service**\n(Service information, ID) +activate FSP +activate Switch +FSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PEERFSP: **POST /service**\n(Service information, ID) +activate PEERFSP +Switch <<-- PEERFSP: **HTTP 202** (Accepted) +PEERFSP -> PEERFSP: Create service object\naccording to request +Switch <<- PEERFSP: **PUT /service/**////\n(Service object information) +Switch -->> PEERFSP: **HTTP 200** (OK) +deactivate PEERFSP +FSP <<- Switch: **PUT /service/**////\n(Service object information) +FSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +FSP -> FSP: Handle service\nobject information +FSP -[hidden]> Switch +deactivate FSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure1.svg b/docs/technical/api/assets/diagrams/sequence/figure1.svg new file mode 100644 index 000000000..50be4512d --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure1.svg @@ -0,0 +1,77 @@ + + + + + + + + + + +   + FSP + + Optional + Switch + + Peer + FSP + + + + + + + POST /service + (Service information, ID) + + + + HTTP 202 + (Accepted) + + + + POST /service + (Service information, ID) + + + + HTTP 202 + (Accepted) + + + + + Create service object + according to request + + + + PUT /service/ + <ID> + (Service object information) + + + + HTTP 200 + (OK) + + + + PUT /service/ + <ID> + (Service object information) + + + + HTTP 200 + (OK) + + + + + Handle service + object information + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure10.plantuml b/docs/technical/api/assets/diagrams/sequence/figure10.plantuml new file mode 100644 index 000000000..41c039e8f --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure10.plantuml @@ -0,0 +1,138 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Example of non-disclosing send amount + +' Actor Keys: +' participant - FSP(Payer/Payee) and Optional Switch +' actor - Payee and Payer + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +Payer ->> PayerFSP: I would like to Payee to\nsend 100 USD to Payee +activate PayerFSP +PayerFSP -> PayerFSP: Rate fee for Payer for\nhandling transaction in\nPayer FSP => fee 1 USD +PayerFSP ->> Switch: **POST /quotes**\n(amountType=SEND,\namount=99 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=SEND,\namount=99 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Rate transaction fee\nor commission for\nhandeling transaction in\nPayee FSP => fee 1 USD +Switch <<- PayeeFSP: **PUT /quotes/**\n(transferAmount=99 USD,\nPayeeReceiveamount=98 USD\npayeeFspFee=1 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quotes/**\n(transferAmount=99 USD,\nPayeeReceiveamount=98 USD\npayeeFspFee=1 USD) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Show total fees to Payer +PayerFSP ->> Payer: Payee will receive 98 USD\nif you send 100 USD +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure10.svg b/docs/technical/api/assets/diagrams/sequence/figure10.svg new file mode 100644 index 000000000..83d930001 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure10.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + Payee + + + + + + + + + I would like to Payee to + send 100 USD to Payee + + + + + Rate fee for Payer for + handling transaction in + Payer FSP => fee 1 USD + + + + POST /quotes + (amountType=SEND, + amount=99 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=SEND, + amount=99 USD) + + + + HTTP 202 + (Accepted) + + + + + Rate transaction fee + or commission for + handeling transaction in + Payee FSP => fee 1 USD + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + PayeeReceiveamount=98 USD + payeeFspFee=1 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + PayeeReceiveamount=98 USD + payeeFspFee=1 USD) + + + + HTTP 200 + (OK) + + + + + Show total fees to Payer + + + + Payee will receive 98 USD + if you send 100 USD + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure13.plantuml b/docs/technical/api/assets/diagrams/sequence/figure13.plantuml new file mode 100644 index 000000000..7ea6e0dfa --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure13.plantuml @@ -0,0 +1,146 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Example of disclosing receive amount + +' Actor Keys: +' participant - FSP(Payer/Payee) and Optional Switch +' actor - Payee and Payer + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +Payer ->> PayerFSP: I would like to send\n100 USD to Payee +activate PayerFSP +PayerFSP -> PayerFSP: Rate fee for Payer for\nhandling transaction in\nPayer FSP => fee 1 USD +PayerFSP ->> Switch: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD, fees=1 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD, fees=1 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Rate transaction fee or\ncommission for handeling\ntransaction in Payee FSP =>\nFSP commission 1 USD +group Optional + hnote left of PayeeFSP + Notify/Ask Payee + for approval + end note + PayeeFSP ->> Payee: If accepted, you will receive\n100 USD + PayeeFSP <<- Payee: OK +end +Switch <<- PayeeFSP: **PUT /quotes/**\n(transferAmount=99 USD,\nPayeeFspCommission=1 USD,\npayeeReceivedAmount=100 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quotes/**\n(transferAmount=99 USD,\nPayeeFspCommission=1 USD\npayeeReceivedAmouint=100 USD) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Transaction is subsidized with the\ncommission as fees are disclosed,\nshow total fees to Payer +PayerFSP ->> Payer: Sending 100 USD to Payee\nwill cost 0 USD in fees +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure13.svg b/docs/technical/api/assets/diagrams/sequence/figure13.svg new file mode 100644 index 000000000..63a4002d7 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure13.svg @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + Payee + + + + + + + + + I would like to send + 100 USD to Payee + + + + + Rate fee for Payer for + handling transaction in + Payer FSP => fee 1 USD + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD, fees=1 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD, fees=1 USD) + + + + HTTP 202 + (Accepted) + + + + + Rate transaction fee or + commission for handeling + transaction in Payee FSP => + FSP commission 1 USD + + + Optional + + Notify/Ask Payee + for approval + + + + If accepted, you will receive + 100 USD + + + + OK + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + PayeeFspCommission=1 USD, + payeeReceivedAmount=100 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + PayeeFspCommission=1 USD + payeeReceivedAmouint=100 USD) + + + + HTTP 200 + (OK) + + + + + Transaction is subsidized with the + commission as fees are disclosed, + show total fees to Payer + + + + Sending 100 USD to Payee + will cost 0 USD in fees + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure15.plantuml b/docs/technical/api/assets/diagrams/sequence/figure15.plantuml new file mode 100644 index 000000000..2c33654b8 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure15.plantuml @@ -0,0 +1,146 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Example of disclosing send amount + +' Actor Keys: +' participant - FSP(Payer/Payee) and Optional Switch +' actor - Payee and Payer + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +Payer ->> PayerFSP: I would like to\ nsend 100 USD to Payee +activate PayerFSP +PayerFSP -> PayerFSP: Rate fee for Payer for\nhandling transaction in\nPayer FSP => fee 1 USD +PayerFSP ->> Switch: **POST /quotes**\n(amountType=SEND,\namount=99 USD, fees=1 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=SEND,\namount=99 USD, fees=1 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Rate transaction fee\nor commission for\nhandeling transaction in\nPayee FSP => fee 1 USD +group Optional +PayeeFSP ->> Payee: If accepted, you will receive\n98 USD out of Payer's 100 USD +hnote left of PayeeFSP + Notify/Ask Payee + for approval +end note +PayeeFSP <<- Payee: OK +end +Switch <<- PayeeFSP: **PUT /quotes/**\n(transferAmount=99 USD,\npayeeReceiveAmount=98 USD,\npayeeFspFee=1 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quotes/**\n(transferAmount=99 USD,\npayeeReceiveAmount=98 USD\npayeeFspFees=1 USD) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Show total fees to Payer +PayerFSP ->> Payer: Payee will receive 98 USD\nif you send 100 USD +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure15.svg b/docs/technical/api/assets/diagrams/sequence/figure15.svg new file mode 100644 index 000000000..94a536f15 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure15.svg @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + Payee + + + + + + + + + I would like to\ nsend 100 USD to Payee + + + + + Rate fee for Payer for + handling transaction in + Payer FSP => fee 1 USD + + + + POST /quotes + (amountType=SEND, + amount=99 USD, fees=1 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=SEND, + amount=99 USD, fees=1 USD) + + + + HTTP 202 + (Accepted) + + + + + Rate transaction fee + or commission for + handeling transaction in + Payee FSP => fee 1 USD + + + Optional + + + + If accepted, you will receive + 98 USD out of Payer's 100 USD + + Notify/Ask Payee + for approval + + + + OK + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + payeeReceiveAmount=98 USD, + payeeFspFee=1 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + payeeReceiveAmount=98 USD + payeeFspFees=1 USD) + + + + HTTP 200 + (OK) + + + + + Show total fees to Payer + + + + Payee will receive 98 USD + if you send 100 USD + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure17.plantuml b/docs/technical/api/assets/diagrams/sequence/figure17.plantuml new file mode 100644 index 000000000..e95153b41 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure17.plantuml @@ -0,0 +1,146 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Example of disclosing send amount + +' Actor Keys: +' participant - FSP(Payer/Payee) and Optional Switch +' actor - Payee and Payer + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +Payer ->> PayerFSP: I would like to \nsend 100 USD to Payee +activate PayerFSP +PayerFSP -> PayerFSP: Rate fee for Payer for\nhandling transaction in\nPayer FSP => fee 1 USD +PayerFSP ->> Switch: **POST /quotes**\n(amountType=SEND,\namount=99 USD, fees=1 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=SEND,\namount=99 USD, fees=1 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Rate transaction fee or commission\nfor handeling transaction in\nPayee FSP => FSP commission 3\nUSD (1 USD to pay for Payer's\nfee, 2 USD in excess commission) +group Optional +PayeeFSP ->> Payee: If accepted, you will receive\n100 USD out of Payer's 100 USD +hnote left of PayeeFSP + Notify/Ask Payee + for approval +end note +PayeeFSP <<- Payee: OK +end +Switch <<- PayeeFSP: **PUT /quotes/**\n(transferAmount=97 USD,\npayeeReceivedAmount=100 USD,\npayeeFspCommission=3 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quotes/**\n(transferAmount=97 USD,\npayeeReceiveAmount=100 USD\npayeeFspCommission=3 USD) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Payer should pay 100 USD, Payer\nFSP will earn in total 3 USD in fees\n(Payer fee of 1 USD paid by\nPayeeFSP, plus 2 USD in access\ncommission) +PayerFSP ->> Payer: Payee will receive 100 USD\nif you send 100 USD +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure17.svg b/docs/technical/api/assets/diagrams/sequence/figure17.svg new file mode 100644 index 000000000..aa3f4fdb4 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure17.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + Payee + + + + + + + + + I would like to + send 100 USD to Payee + + + + + Rate fee for Payer for + handling transaction in + Payer FSP => fee 1 USD + + + + POST /quotes + (amountType=SEND, + amount=99 USD, fees=1 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=SEND, + amount=99 USD, fees=1 USD) + + + + HTTP 202 + (Accepted) + + + + + Rate transaction fee or commission + for handeling transaction in + Payee FSP => FSP commission 3 + USD (1 USD to pay for Payer's + fee, 2 USD in excess commission) + + + Optional + + + + If accepted, you will receive + 100 USD out of Payer's 100 USD + + Notify/Ask Payee + for approval + + + + OK + + + + PUT /quotes/ + <ID> + (transferAmount=97 USD, + payeeReceivedAmount=100 USD, + payeeFspCommission=3 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=97 USD, + payeeReceiveAmount=100 USD + payeeFspCommission=3 USD) + + + + HTTP 200 + (OK) + + + + + Payer should pay 100 USD, Payer + FSP will earn in total 3 USD in fees + (Payer fee of 1 USD paid by + PayeeFSP, plus 2 USD in access + commission) + + + + Payee will receive 100 USD + if you send 100 USD + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure19.plantuml b/docs/technical/api/assets/diagrams/sequence/figure19.plantuml new file mode 100644 index 000000000..33ed308f9 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure19.plantuml @@ -0,0 +1,159 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title P2P Transfer example with receive amount + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee and Payer + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +Payer ->> PayerFSP: I would like Payee\nto receive 100 USD +activate PayerFSP +PayerFSP ->> Switch: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Commission is 1 USD in\nPayee FSP for P2P +Switch <<- PayeeFSP: **PUT /quotes/**\n(transferAmount=99 USD,\npayeeReceiveAmount=100 USD,\npayeeFspCommission=1 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quotes/**\n(transferAmount=99 USD,\npayeeReceiveAmount=100 USD,\npayeeFspCommission=1 USD) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Payer FSP keeps commission\nas fee, Payer also should pay\nfee of 1 USD +PayerFSP ->> Payer: Transfering 100 USD to Payee\nwill cost you 101 USD\nincluding fees +deactivate PayerFSP +Payer ->> PayerFSP: Perform transaction +activate PayerFSP +PayerFSP -> PayerFSP: Receive 101 USD from Payer\naccount, 99 USD to Switch\naccount, 1 USD to fee account,\n1 USD to FSP commission account +PayerFSP ->> Switch: **POST /transfers**\n(amount=99 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Receive 99 USD from Payer FSP\naccount to Payee FSP account +Switch ->> PayeeFSP: **POST /transfers**\n(amount=99 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Transfer 99 USD from Switch\naccount and 1 USD from\ncommission account\nto Payee account +PayeeFSP -> Payee: You have received 100 USD\nfrom Payer +Switch <<- PayeeFSP: **PUT /transfers/** +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch -> Switch: Commit reserved transfer +PayerFSP <<- Switch: **PUT /transfers/** +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Commit reserved transfer +Payer <- PayerFSP: Transaction successful,\nyou have paid 1 USD in fee +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure19.svg b/docs/technical/api/assets/diagrams/sequence/figure19.svg new file mode 100644 index 000000000..cb8eef462 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure19.svg @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + +   + Switch + + Payee + FSP + + Payee + + + + + + + + + + + + I would like Payee + to receive 100 USD + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Commission is 1 USD in + Payee FSP for P2P + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + payeeReceiveAmount=100 USD, + payeeFspCommission=1 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + payeeReceiveAmount=100 USD, + payeeFspCommission=1 USD) + + + + HTTP 200 + (OK) + + + + + Payer FSP keeps commission + as fee, Payer also should pay + fee of 1 USD + + + + Transfering 100 USD to Payee + will cost you 101 USD + including fees + + + + Perform transaction + + + + + Receive 101 USD from Payer + account, 99 USD to Switch + account, 1 USD to fee account, + 1 USD to FSP commission account + + + + POST /transfers + (amount=99 USD) + + + + HTTP 202 + (Accepted) + + + + + Receive 99 USD from Payer FSP + account to Payee FSP account + + + + POST /transfers + (amount=99 USD) + + + + HTTP 202 + (Accepted) + + + + + Transfer 99 USD from Switch + account and 1 USD from + commission account + to Payee account + + + You have received 100 USD + from Payer + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + Transaction successful, + you have paid 1 USD in fee + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure1_http-timeout.plantuml b/docs/technical/api/assets/diagrams/sequence/figure1_http-timeout.plantuml new file mode 100644 index 000000000..0b5116c3f --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure1_http-timeout.plantuml @@ -0,0 +1,68 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam sequencearrowcolor Black + +hide footbox + +' declare title +' title HTTP POST call flow + +' Actor Keys: +' participant - FSP, Peer FSP and Optional Switch + +' declare actors +participant "\nFSP" as FSP +participant "Optional\nSwitch" as Switch +participant "Peer\nFSP" as PEERFSP + +' start flow +FSP ->> Switch: **POST /service**\n(Service information, ID) +activate FSP +activate Switch +FSP <<[#Red]-- Switch : **HTTP 202** (Accepted) +Switch ->> PEERFSP: **POST /service**\n(Service information, ID) +activate PEERFSP +Switch <<[#Red]-- PEERFSP: **HTTP 202** (Accepted) +PEERFSP -> PEERFSP: Create service object\naccording to request +Switch <<- PEERFSP: **PUT /service/**////\n(Service object information) +Switch --[#Red]>> PEERFSP: **HTTP 200** (OK) +deactivate PEERFSP +FSP <<- Switch: **PUT /service/**////\n(Service object information) +FSP --[#Red]>> Switch: **HTTP 200** (OK) +deactivate Switch +FSP -> FSP: Handle service object information +FSP -[hidden]> Switch +deactivate FSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure1_http-timeout.svg b/docs/technical/api/assets/diagrams/sequence/figure1_http-timeout.svg new file mode 100644 index 000000000..49c15b416 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure1_http-timeout.svg @@ -0,0 +1,76 @@ + + + + + + + + + + +   + FSP + + Optional + Switch + + Peer + FSP + + + + + + + POST /service + (Service information, ID) + + + + HTTP 202 + (Accepted) + + + + POST /service + (Service information, ID) + + + + HTTP 202 + (Accepted) + + + + + Create service object + according to request + + + + PUT /service/ + <ID> + (Service object information) + + + + HTTP 200 + (OK) + + + + PUT /service/ + <ID> + (Service object information) + + + + HTTP 200 + (OK) + + + + + Handle service object information + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure2.plantuml b/docs/technical/api/assets/diagrams/sequence/figure2.plantuml new file mode 100644 index 000000000..5a7668cd6 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure2.plantuml @@ -0,0 +1,68 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml +' declare skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +' declare title +' title HTTP GET call flow + +' Actor Keys: +' participant - FSP, Peer FSP and Optional Switch + +' declare actors +participant "\nFSP" as FSP +participant "Optional\nSwitch" as Switch +participant "Peer\nFSP" as PEERFSP + +' start flow +FSP ->> Switch: **GET /service/**//// +activate FSP +activate Switch +FSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PEERFSP: **GET /service/**//// +activate PEERFSP +Switch <<-- PEERFSP: **HTTP 202** (Accepted) +PEERFSP -> PEERFSP: Lookup service\ninformation regarding\nservice with//// +Switch <<- PEERFSP: **PUT /service/**////\n(Service object information) +Switch -->> PEERFSP: **HTTP 200** (OK) +deactivate PEERFSP +FSP <<- Switch: **PUT /service/**////\n(Service object information) +FSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +FSP -> FSP: Handle service object\ninformation update +FSP -[hidden]> FSP +deactivate FSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure2.svg b/docs/technical/api/assets/diagrams/sequence/figure2.svg new file mode 100644 index 000000000..0b32be0cf --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure2.svg @@ -0,0 +1,79 @@ + + + + + + + + + + +   + FSP + + Optional + Switch + + Peer + FSP + + + + + + + GET /service/ + <ID> + + + + HTTP 202 + (Accepted) + + + + GET /service/ + <ID> + + + + HTTP 202 + (Accepted) + + + + + Lookup service + information regarding + service with + <ID> + + + + PUT /service/ + <ID> + (Service object information) + + + + HTTP 200 + (OK) + + + + PUT /service/ + <ID> + (Service object information) + + + + HTTP 200 + (OK) + + + + + Handle service object + information update + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure21.plantuml b/docs/technical/api/assets/diagrams/sequence/figure21.plantuml new file mode 100644 index 000000000..294c13d52 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure21.plantuml @@ -0,0 +1,167 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Agent-initiated Cash-In example with send amount + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer(OTC) + +' declare actors +actor "<$actor>\nPayer\n(OTC)" as PayerOTC +actor "<$actor>\nPayer\n" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\n\nSwitch" as Switch +participant "\nPayee\nFSP" as PayeeFSP +actor "<$actor>\nPayee\n" as Payee + +' start flow +PayerOTC ->> Payer: I would like to Cash-in\nthis 100 USD bill +PayerOTC <<- Payer: OK, you will receive a\nnotification from your FSP\ndisplaying the fees +Payer ->> PayerFSP: I would like to send\n100 USD to Payee +activate PayerFSP +PayerFSP -> PayerFSP: Fee is 2 USD in Payer\nFSP for Cash-in,\nPayer will receive 1\nUSD in internal commission. +PayerFSP ->> Switch: **POST /quotes**\n(amountType=SEND,\namount=98 USD, fees=2 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=SEND,\namount=98 USD, fees=2 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Payee FSP decides to give\n2 USD in FSP commission to\nPayer so that\nCash-in is free +PayeeFSP ->> Payee: By paying 100 USD in cash\nto Payer, you will receive\n100 USD to your account +PayeeFSP <<-- Payee: OK +Switch <<- PayeeFSP: **PUT /quotes/**\n(transferAmount=98 USD,\npayeeReceiveAmount=100 USD,\npayeeFspCommission=2 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quotes/**\n(transferAmount=98 USD,\npayeeReceiveAmount=100 USD,\npayeeFspCommission=2 USD) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +Payer <<- PayerFSP: Payee will receive 100 USD\nand has accepted the\nquote, you will receive\n1 USD in commission +deactivate PayerFSP +PayerOTC <<- Payer: You will receive 100 USD\non your account. Please give\nme the 100 USD bill +PayerOTC ->> Payer: OK, here is 100 USD +Payer ->> PayerFSP: Perform transaction +activate PayerFSP +PayerFSP -> PayerFSP: Reserve 100 USD from Payer\naccount, 98 USD to Switch\naccount and 2 USD to fee account,\n1 USD from agent commission\naccount to Payer +PayerFSP ->> Switch: **POST /transfers**\n(amount=98 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve 98 USD from Payer FSP\naccount to Payee FSP account +Switch ->> PayeeFSP: **POST /transfers**\n(amount=98 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Transfer 98 USD from Switch\naccount and 2 USD from\nFSP commission account\nto Payee account +PayeeFSP -> Payee: You have Cash-in 100 USD +Switch <<- PayeeFSP: **PUT /transfers/** +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch -> Switch: Commit reserved transfer +PayerFSP <<- Switch: **PUT /transfers/** +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Commit reserved transfer +Payer <- PayerFSP: Transaction successful, you have\nsent 100 USD and received\n1 USD in commission +deactivate PayerFSP +PayerOTC <- Payer: Thank you! +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure21.svg b/docs/technical/api/assets/diagrams/sequence/figure21.svg new file mode 100644 index 000000000..35f3955eb --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure21.svg @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + Payer + (OTC) + + + + Payer +   + + + +   + Payer + FSP + +   +   + Switch + +   + Payee + FSP + + Payee +   + + + + + + + + + + + + I would like to Cash-in + this 100 USD bill + + + + OK, you will receive a + notification from your FSP + displaying the fees + + + + I would like to send + 100 USD to Payee + + + + + Fee is 2 USD in Payer + FSP for Cash-in, + Payer will receive 1 + USD in internal commission. + + + + POST /quotes + (amountType=SEND, + amount=98 USD, fees=2 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=SEND, + amount=98 USD, fees=2 USD) + + + + HTTP 202 + (Accepted) + + + + + Payee FSP decides to give + 2 USD in FSP commission to + Payer so that + Cash-in is free + + + + By paying 100 USD in cash + to Payer, you will receive + 100 USD to your account + + + + OK + + + + PUT /quotes/ + <ID> + (transferAmount=98 USD, + payeeReceiveAmount=100 USD, + payeeFspCommission=2 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=98 USD, + payeeReceiveAmount=100 USD, + payeeFspCommission=2 USD) + + + + HTTP 200 + (OK) + + + + Payee will receive 100 USD + and has accepted the + quote, you will receive + 1 USD in commission + + + + You will receive 100 USD + on your account. Please give + me the 100 USD bill + + + + OK, here is 100 USD + + + + Perform transaction + + + + + Reserve 100 USD from Payer + account, 98 USD to Switch + account and 2 USD to fee account, + 1 USD from agent commission + account to Payer + + + + POST /transfers + (amount=98 USD) + + + + HTTP 202 + (Accepted) + + + + + Reserve 98 USD from Payer FSP + account to Payee FSP account + + + + POST /transfers + (amount=98 USD) + + + + HTTP 202 + (Accepted) + + + + + Transfer 98 USD from Switch + account and 2 USD from + FSP commission account + to Payee account + + + You have Cash-in 100 USD + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + Transaction successful, you have + sent 100 USD and received + 1 USD in commission + + + Thank you! + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure23.plantuml b/docs/technical/api/assets/diagrams/sequence/figure23.plantuml new file mode 100644 index 000000000..bb636328f --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure23.plantuml @@ -0,0 +1,167 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Agent-initiated Cash-In example with received amount + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer(OTC) + +' declare actors +actor "<$actor>\nPayer\n(OTC)" as PayerOTC +actor "<$actor>\nPayer\n" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\n\nSwitch" as Switch +participant "\nPayee\nFSP" as PayeeFSP +actor "<$actor>\nPayee\n" as Payee + +' start flow +PayerOTC ->> Payer: I would like to Cash-in\nso that I receive 100 USD +PayerOTC <<- Payer: OK, you will receive a\nnotification from your FSP\ndisplaying the fees +Payer ->> PayerFSP: I would like Agent (Payee) to\nreceive 100 USD +activate PayerFSP +PayerFSP -> PayerFSP: Fee is 2 USD in Payer\nFSP for Cash-in,\nPayer will receive 1\nUSD in internal commission. +PayerFSP ->> Switch: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD, fees=2 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD, fees=2 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Payee FSP decides to give\n1 USD in commission to\nPayer so that\nCash-in only costs 1 USD +PayeeFSP ->> Payee: By paying 101 USD in cash\nto Payer, you will receive\n100 USD to your account +PayeeFSP <<-- Payee: OK +Switch <<- PayeeFSP: **PUT /quotes/** \n(transferAmount=99 USD,\npayeeReceiveAmount=100 USD,\npayeeFspCommission=1 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quotes/**\n(transferAmount=99 USD,\npayeeReceiveAmount=100 USD,\npayeeFspCommission=1 USD) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +Payer <<- PayerFSP: Payee will receive 100 USD\nand fee is 1 USD, you will receive\n1 USD in commission +deactivate PayerFSP +PayerOTC <<- Payer: You will receive 100 USD on your\naccount. Please give me 101 USD +PayerOTC ->> Payer: OK, here is 101 USD +Payer ->> PayerFSP: Perform transaction +activate PayerFSP +PayerFSP -> PayerFSP: Reserve 1 USD from Agent\ncommission to Payer account,\n100 USD from Payer account,\n99 USD to Switch account and 1\nUSD to fee account, 1 USD from\nFSP Commission to fee account +PayerFSP ->> Switch: **POST /transfers**\n(amount = 99 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve 99 USD from Payer FSP\naccount to Payee FSP account +Switch ->> PayeeFSP: **POST /transfers**\n(amount = 99 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Transfer 99 USD from Switch\naccount and 1 USD from\ninternal commission account\nto Payee account +PayeeFSP -> Payee: You have Cashed-in 100 USD +Switch <<- PayeeFSP: **PUT /transfers/** +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch -> Switch: Commit reserved transfer +PayerFSP <<- Switch: **PUT /transfers/** +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Commit reserved transfer +Payer <- PayerFSP: Transaction successful, you have\nsent 100 USD and received\n1 USD in commission +deactivate PayerFSP +PayerOTC <- Payer: Thank you! +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure23.svg b/docs/technical/api/assets/diagrams/sequence/figure23.svg new file mode 100644 index 000000000..84b41a512 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure23.svg @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + Payer + (OTC) + + + + Payer +   + + + +   + Payer + FSP + +   +   + Switch + +   + Payee + FSP + + Payee +   + + + + + + + + + + + + I would like to Cash-in + so that I receive 100 USD + + + + OK, you will receive a + notification from your FSP + displaying the fees + + + + I would like Agent (Payee) to + receive 100 USD + + + + + Fee is 2 USD in Payer + FSP for Cash-in, + Payer will receive 1 + USD in internal commission. + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD, fees=2 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD, fees=2 USD) + + + + HTTP 202 + (Accepted) + + + + + Payee FSP decides to give + 1 USD in commission to + Payer so that + Cash-in only costs 1 USD + + + + By paying 101 USD in cash + to Payer, you will receive + 100 USD to your account + + + + OK + + + + PUT /quotes/ + <ID> +   + (transferAmount=99 USD, + payeeReceiveAmount=100 USD, + payeeFspCommission=1 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + payeeReceiveAmount=100 USD, + payeeFspCommission=1 USD) + + + + HTTP 200 + (OK) + + + + Payee will receive 100 USD + and fee is 1 USD, you will receive + 1 USD in commission + + + + You will receive 100 USD on your + account. Please give me 101 USD + + + + OK, here is 101 USD + + + + Perform transaction + + + + + Reserve 1 USD from Agent + commission to Payer account, + 100 USD from Payer account, + 99 USD to Switch account and 1 + USD to fee account, 1 USD from + FSP Commission to fee account + + + + POST /transfers + (amount = 99 USD) + + + + HTTP 202 + (Accepted) + + + + + Reserve 99 USD from Payer FSP + account to Payee FSP account + + + + POST /transfers + (amount = 99 USD) + + + + HTTP 202 + (Accepted) + + + + + Transfer 99 USD from Switch + account and 1 USD from + internal commission account + to Payee account + + + You have Cashed-in 100 USD + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + Transaction successful, you have + sent 100 USD and received + 1 USD in commission + + + Thank you! + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure25.plantuml b/docs/technical/api/assets/diagrams/sequence/figure25.plantuml new file mode 100644 index 000000000..97b9d89ee --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure25.plantuml @@ -0,0 +1,163 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Customer-Initiated Merchant Payment example + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer(OTC) + +' declare actors +actor "<$actor>\nPayer\n" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\n\nSwitch" as Switch +participant "\nPayee\nFSP" as PayeeFSP +actor "<$actor>\nPayee\n" as Payee +actor "<$actor>\nPayer\n(OTC)" as PayerOTC + +' start flow +Payee <<- PayerOTC: I would like to buy\nthis goods or service +Payee ->> PayerOTC: The goods or service cost\n100 USD before any fees,\nplease initiate the transaction +Payer ->> PayerFSP: I would like Payee to\nreceive 100 USD +activate PayerFSP +PayerFSP ->> Switch: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Interoperable fee is 0 USD in\nPayee FSP for Merchant\nPayment, but 1 USD in\ninternal Payee fee for Merchant +Switch <<- PayeeFSP: **PUT /quotes/**\n(transferAmount=100 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quotes/**\n(transferAmount=100 USD) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Fee is 1 USD in Payer\nFSP for Merchant Payment,\ntotal fee is 1 USD +Payer <<- PayerFSP: Will you approve Merchant Payment\nof 100 USD to Payee? It will\ncost you 1 USD in fees. +deactivate PayerFSP +Payer ->> PayerFSP: Perform transaction +activate PayerFSP +PayerFSP -> PayerFSP: Reserve 101 USD from Payer\naccount, 100 USD to Switch\naccount and 1 USD to\nfee account +PayerFSP ->> Switch: **POST /transfers**\n(amount=100 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve 100 USD from Payer FSP\naccount to Payee FSP account +Switch ->> PayeeFSP: **POST /transfers**\n(amount=100 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Transfer 100 USD from Switch\naccount to Payee account, 1 USD\nfrom Payee to fee account +PayeeFSP -> Payee: You have received 100 USD\nfrom Payer and paid 1 USD\nin internal fee. Please give\ngoods or service to Payer. +Payee ->> PayerOTC: Here is your goods or service +Switch <<- PayeeFSP: **PUT /transfers/** +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch -> Switch: Commit reserved transfer +PayerFSP <<- Switch: **PUT /transfers/** +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Commit reserved transfer +Payer <- PayerFSP: Payment successful, you\nhave paid 100 USD to Payee\nplus 1 USD in fees +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure25.svg b/docs/technical/api/assets/diagrams/sequence/figure25.svg new file mode 100644 index 000000000..54293ab7b --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure25.svg @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + Payer +   + + + +   + Payer + FSP + +   +   + Switch + +   + Payee + FSP + + Payee +   + + + + Payer + (OTC) + + + + + + + + + + + + I would like to buy + this goods or service + + + + The goods or service cost + 100 USD before any fees, + please initiate the transaction + + + + I would like Payee to + receive 100 USD + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Interoperable fee is 0 USD in + Payee FSP for Merchant + Payment, but 1 USD in + internal Payee fee for Merchant + + + + PUT /quotes/ + <ID> + (transferAmount=100 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=100 USD) + + + + HTTP 200 + (OK) + + + + + Fee is 1 USD in Payer + FSP for Merchant Payment, + total fee is 1 USD + + + + Will you approve Merchant Payment + of 100 USD to Payee? It will + cost you 1 USD in fees. + + + + Perform transaction + + + + + Reserve 101 USD from Payer + account, 100 USD to Switch + account and 1 USD to + fee account + + + + POST /transfers + (amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Reserve 100 USD from Payer FSP + account to Payee FSP account + + + + POST /transfers + (amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Transfer 100 USD from Switch + account to Payee account, 1 USD + from Payee to fee account + + + You have received 100 USD + from Payer and paid 1 USD + in internal fee. Please give + goods or service to Payer. + + + + Here is your goods or service + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + Payment successful, you + have paid 100 USD to Payee + plus 1 USD in fees + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure27.plantuml b/docs/technical/api/assets/diagrams/sequence/figure27.plantuml new file mode 100644 index 000000000..41fcc2b28 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure27.plantuml @@ -0,0 +1,163 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Customer-Initiated Cash-Out example (receive amount) + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer(Agent/OTC) + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee\n(Agent)" as Payee +actor "<$actor>\nPayer\n(OTC)" as PayerOTC + +' start flow +Payee <<- PayerOTC: I would like to\nCash-Out 100 USD +Payee ->> PayerOTC: Please initiate the transaction +Payer ->> PayerFSP: I would like to Cash-Out\n100 USD from Agent (Payee) +activate PayerFSP +PayerFSP ->> Switch: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Fee is 2 USD in Payee\nFSP to cover agent\ncommission, agent will receive\n1 USD in agent commission +Switch <<- PayeeFSP: **PUT /quotes/** \n(transferAmount=102 USD,\nPayFspFee=2 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quotes/**\n(transferAmount=102 USD,\npayeeFspFee=2 USD) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Payer fee is 1 USD in Payer\nFSP for Cash-Out, total fee\nis 3 USD +Payer <<- PayerFSP: Will you approve Cash-Out\nof 100 USD? It will\ncost you 3 USD in fees. +deactivate PayerFSP +Payer ->> PayerFSP: Perform transaction +activate PayerFSP +PayerFSP -> PayerFSP: Reserve 103 USD from Payer\naccount, 102 USD to Switch\naccount and 1 USD to\nfee account +PayerFSP ->> Switch: **POST /transfers**\n(amount=102 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve 102 USD from Payer FSP\naccount to Payee FSP account +Switch ->> PayeeFSP: **POST /transfers**\n(amount=102 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Transfer 102 USD from Switch\naccount, 101 USD to Payee\n(1 USD commission), and\n1 USD to fee account +PayeeFSP ->> Payee: You have received 100 USD\nfrom Payer plus 1 USD in\ncommission, please give 100 USD\nin cash to Payer +Payee ->> PayerOTC: Here is your 100 USD in cash +Switch <<- PayeeFSP: **PUT /transfers/** +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch -> Switch: Commit reserved transfer +PayerFSP <<- Switch: **PUT /transfers/** +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Commit reserved transfer +Payer <<- PayerFSP: Transaction successful,\nyou should receive 100 USD\nin cash from Payee. You have\npaid 3 USD in fees. +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure27.svg b/docs/technical/api/assets/diagrams/sequence/figure27.svg new file mode 100644 index 000000000..45e0d08a2 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure27.svg @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + +   + Switch + + Payee + FSP + + Payee + (Agent) + + + + Payer + (OTC) + + + + + + + + + + + + I would like to + Cash-Out 100 USD + + + + Please initiate the transaction + + + + I would like to Cash-Out + 100 USD from Agent (Payee) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Fee is 2 USD in Payee + FSP to cover agent + commission, agent will receive + 1 USD in agent commission + + + + PUT /quotes/ + <ID> +   + (transferAmount=102 USD, + PayFspFee=2 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=102 USD, + payeeFspFee=2 USD) + + + + HTTP 200 + (OK) + + + + + Payer fee is 1 USD in Payer + FSP for Cash-Out, total fee + is 3 USD + + + + Will you approve Cash-Out + of 100 USD? It will + cost you 3 USD in fees. + + + + Perform transaction + + + + + Reserve 103 USD from Payer + account, 102 USD to Switch + account and 1 USD to + fee account + + + + POST /transfers + (amount=102 USD) + + + + HTTP 202 + (Accepted) + + + + + Reserve 102 USD from Payer FSP + account to Payee FSP account + + + + POST /transfers + (amount=102 USD) + + + + HTTP 202 + (Accepted) + + + + + Transfer 102 USD from Switch + account, 101 USD to Payee + (1 USD commission), and + 1 USD to fee account + + + + You have received 100 USD + from Payer plus 1 USD in + commission, please give 100 USD + in cash to Payer + + + + Here is your 100 USD in cash + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + Transaction successful, + you should receive 100 USD + in cash from Payee. You have + paid 3 USD in fees. + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure29.plantuml b/docs/technical/api/assets/diagrams/sequence/figure29.plantuml new file mode 100644 index 000000000..e6886c6b9 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure29.plantuml @@ -0,0 +1,164 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Customer-Initiated Cash-Out example (send amount) + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer(Agent/OTC) + +' declare actors +actor "<$actor>\nPayer\n" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\n\nSwitch" as Switch +participant "\nPayee\nFSP" as PayeeFSP +actor "<$actor>\nPayee\n(Agent)" as Payee +actor "<$actor>\nPayer\n(OTC)" as PayerOTC + +' start flow +Payee <<- PayerOTC: I would like to\nCash-Out 100 USD +Payee ->> PayerOTC: Please initiate the transaction +Payer ->> PayerFSP: I would like to Cash-Out from\nAgent (Payee) so that 100 USD is\nwithdrawn from my account +activate PayerFSP +PayerFSP -> PayerFSP: Fee is 1 USD in Payer\nFSP from Cash-Out +PayerFSP ->> Switch: **POST /quotes**\n(amountType=SEND,\namount=99 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=SEND,\namount=99 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Fee is 2 USD in Payee FSP to\ncover agent commission, agent will\nreceive 1 USD in internal commission +Switch <<- PayeeFSP: **PUT /quotes/** \n(transferAmount=99 USD,\nPayeeFspFee=2 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quotes/**\n(transferAmount=99 USD,\npayeeFspFee=2 USD) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Calculate Payee receive amount\nas not sent from Payee FSP\n(transferAmount -\npayeeFspFee=97 USD) +Payer <<- PayerFSP: Will you approve Cash-Out\nof 97 USD? It will\ncost you 3 USD in fees. +deactivate PayerFSP +Payer ->> PayerFSP: Perform transaction +activate PayerFSP +PayerFSP -> PayerFSP: Reserve 100 USD from Payer\naccount, 99 USD to Switch\naccount and 1 USD to\nfee account +PayerFSP ->> Switch: **POST /transfers**\n(amount=99 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve 99 USD from Payer FSP\naccount to Payee FSP account +Switch ->> PayeeFSP: **POST /transfers**\n(amount=99 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Transfer 99 USD from Switch\naccount, 2 USD to fee account and\n98 USD (including 1 USD in\ncommission) to Payee +PayeeFSP ->> Payee: You have received 97 USD\nfrom Payer plus 1 USD in\ncommission, please give 97 USD\nin cash to Payer +Payee ->> PayerOTC: Here is your 97 USD in cash +Switch <<- PayeeFSP: **PUT /transfers/** +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch -> Switch: Commit reserved transfer +PayerFSP <<- Switch: **PUT /transfers/** +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Commit reserved transfer +Payer <<- PayerFSP: Transaction successful,\nyou should receive 97 USD\nin cash from Payee. You have\npaid 3 USD in fees. +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure29.svg b/docs/technical/api/assets/diagrams/sequence/figure29.svg new file mode 100644 index 000000000..8e1c5bd64 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure29.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + Payer +   + + + +   + Payer + FSP + +   +   + Switch + +   + Payee + FSP + + Payee + (Agent) + + + + Payer + (OTC) + + + + + + + + + + + + I would like to + Cash-Out 100 USD + + + + Please initiate the transaction + + + + I would like to Cash-Out from + Agent (Payee) so that 100 USD is + withdrawn from my account + + + + + Fee is 1 USD in Payer + FSP from Cash-Out + + + + POST /quotes + (amountType=SEND, + amount=99 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=SEND, + amount=99 USD) + + + + HTTP 202 + (Accepted) + + + + + Fee is 2 USD in Payee FSP to + cover agent commission, agent will + receive 1 USD in internal commission + + + + PUT /quotes/ + <ID> +   + (transferAmount=99 USD, + PayeeFspFee=2 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + payeeFspFee=2 USD) + + + + HTTP 200 + (OK) + + + + + Calculate Payee receive amount + as not sent from Payee FSP + (transferAmount - + payeeFspFee=97 USD) + + + + Will you approve Cash-Out + of 97 USD? It will + cost you 3 USD in fees. + + + + Perform transaction + + + + + Reserve 100 USD from Payer + account, 99 USD to Switch + account and 1 USD to + fee account + + + + POST /transfers + (amount=99 USD) + + + + HTTP 202 + (Accepted) + + + + + Reserve 99 USD from Payer FSP + account to Payee FSP account + + + + POST /transfers + (amount=99 USD) + + + + HTTP 202 + (Accepted) + + + + + Transfer 99 USD from Switch + account, 2 USD to fee account and + 98 USD (including 1 USD in + commission) to Payee + + + + You have received 97 USD + from Payer plus 1 USD in + commission, please give 97 USD + in cash to Payer + + + + Here is your 97 USD in cash + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + Transaction successful, + you should receive 97 USD + in cash from Payee. You have + paid 3 USD in fees. + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure2_callback_timeout.plantuml b/docs/technical/api/assets/diagrams/sequence/figure2_callback_timeout.plantuml new file mode 100644 index 000000000..4834069c2 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure2_callback_timeout.plantuml @@ -0,0 +1,68 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml +' declare skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +' declare title +' title HTTP GET call flow + +' Actor Keys: +' participant - FSP, Peer FSP and Optional Switch + +' declare actors +participant "\nFSP" as FSP +participant "Optional\nSwitch" as Switch +participant "Peer\nFSP" as PEERFSP + +' start flow +FSP ->> Switch: **GET /service/**//// +activate FSP +activate Switch +FSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PEERFSP: **GET /service/**//// +activate PEERFSP +Switch <<-- PEERFSP: **HTTP 202** (Accepted) +PEERFSP -> PEERFSP: Lookup service\ninformation regarding\nservice with//// +Switch <<[#Red]- PEERFSP: **PUT /service/**////\n(Service object information) +Switch -->> PEERFSP: **HTTP 200** (OK) +deactivate PEERFSP +FSP <<[#Red]- Switch: **PUT /service/**////\n(Service object information) +FSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +FSP -> FSP: Handle service object\ninformation update +FSP -[hidden]> FSP +deactivate FSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure2_callback_timeout.svg b/docs/technical/api/assets/diagrams/sequence/figure2_callback_timeout.svg new file mode 100644 index 000000000..43254c4a9 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure2_callback_timeout.svg @@ -0,0 +1,79 @@ + + + + + + + + + + +   + FSP + + Optional + Switch + + Peer + FSP + + + + + + + GET /service/ + <ID> + + + + HTTP 202 + (Accepted) + + + + GET /service/ + <ID> + + + + HTTP 202 + (Accepted) + + + + + Lookup service + information regarding + service with + <ID> + + + + PUT /service/ + <ID> + (Service object information) + + + + HTTP 200 + (OK) + + + + PUT /service/ + <ID> + (Service object information) + + + + HTTP 200 + (OK) + + + + + Handle service object + information update + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure3.plantuml b/docs/technical/api/assets/diagrams/sequence/figure3.plantuml new file mode 100644 index 000000000..04af955c2 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure3.plantuml @@ -0,0 +1,59 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +' declare title +' title HTTP DELETE call flow + +' Actor Keys: +' participant - FSP and Account Lookup + +' declare actors +participant "\nFSP" as FSP +participant "Account\nLookup" as ALS + +' start flow +FSP ->> ALS: **DELETE /service/**//// +activate FSP +activate ALS +FSP <<-- ALS: **HTTP 202** (Accepted) +ALS -> ALS: Delete object\naccording to request +FSP <<- ALS: **PUT /service/**////\n(Delete object information) +FSP -->> ALS: **HTTP 200** (OK) +deactivate ALS +FSP -> FSP: Handle delete object\ninformation +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure3.svg b/docs/technical/api/assets/diagrams/sequence/figure3.svg new file mode 100644 index 000000000..abeab0e1e --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure3.svg @@ -0,0 +1,50 @@ + + + + + + + + +   + FSP + + Account + Lookup + + + + + + DELETE /service/ + <ID> + + + + HTTP 202 + (Accepted) + + + + + Delete object + according to request + + + + PUT /service/ + <ID> + (Delete object information) + + + + HTTP 200 + (OK) + + + + + Handle delete object + information + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure31.plantuml b/docs/technical/api/assets/diagrams/sequence/figure31.plantuml new file mode 100644 index 000000000..5f62c990d --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure31.plantuml @@ -0,0 +1,177 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Agent-Initiated Cash-Out example + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer(Agent/OTC) + +' declare actors +actor "<$actor>\nPayer\n" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\n\nSwitch" as Switch +participant "\nPayee\nFSP" as PayeeFSP +actor "<$actor>\nPayee\n(Agent)" as Payee +actor "<$actor>\nPayer\n(OTC)" as PayerOTC + +' start flow +Payee <<- PayerOTC: I would like to\nCash-Out 100 USD +PayeeFSP <<- Payee: I would like to receive\n100 USD from Payer +activate PayeeFSP +PayeeFSP ->> Switch: **POST /transactionRequest**\n(amount=100 USD) +activate Switch +PayeeFSP <<-- Switch: **HTTP 202** (Accepted) +PayerFSP <<- Switch: **POST /transactionRequests**\n(amount=100 USD) +activate PayerFSP +PayerFSP -->> Switch: **HTTP 202** (Accepted) +PayerFSP -> PayerFSP: Perform optional validation +PayerFSP ->> Switch: **PUT /transactionRequests/**\n(Received status) +PayerFSP <<-- Switch: **HTTP 200** (OK) +deactivate PayerFSP +Switch ->> PayeeFSP: **PUT /transactionRequests/**\n(Received status) +Switch <<-- PayeeFSP: **HTTP 200** (OK) +deactivate Switch +deactivate PayeeFSP +PayerFSP ->> Switch: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate PayerFSP +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Fee is 2 USD in Payee FSP\nto cover agent\ncommission, agent will\nreceive 1 USD in commission +Switch <<- PayeeFSP: **PUT /quotes/**\n(transferAmount=102 USD,\npayeeFSPFee=2 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch ->> PayerFSP: **PUT /quotes/**\n(transferAmount=102 USD,\npayeeFSPFee=2 USD) +Switch <<-- PayerFSP: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Payer fee is 1 USD in Payer\nFSP for Cash-Out, total fees\nare 3 USD +Payer <<- PayerFSP: Will you approve Cash-out of\n100 USD to Payee? It will\ncost you 3 USD in fees. +deactivate PayerFSP +Payer ->> PayerFSP: Perform transaction +activate PayerFSP +PayerFSP -> PayerFSP: Reserve 103 USD for Payer\naccount, 102 USD to Switch\naccount, 1 USD to fee account +PayerFSP ->> Switch: **POST /transfers**\n(amount=102 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve 102 USD from Payer FSP\naccount to Payee FSP account +Switch ->> PayeeFSP: **POST /transfers**\n(amount=102 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Transfer 102 USD from Switch\naccount, 101 USD to Payee\n(1 USD commission), and\n1 USD to fee account +PayeeFSP ->> Payee: You have received 100 USD\nfrom Payer plus 1 USD in\ncommission, please give 100 USD\nin cash to Payer +Payee ->> PayerOTC: Here is your 100 USD in cash +Switch <<- PayeeFSP: **PUT /transfers/** +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch -> Switch: Commit reserved transfer +PayerFSP <<- Switch: **PUT /transfers/** +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Commit reserved transfer +Payer <<- PayerFSP: Transaction successful,\nyou should receive 100 USD\nin cash from Payee. You have\npaid 3 USD in fees. +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure31.svg b/docs/technical/api/assets/diagrams/sequence/figure31.svg new file mode 100644 index 000000000..ee320e69b --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure31.svg @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Payer +   + + + +   + Payer + FSP + +   +   + Switch + +   + Payee + FSP + + Payee + (Agent) + + + + Payer + (OTC) + + + + + + + + + + + + + + + I would like to + Cash-Out 100 USD + + + + I would like to receive + 100 USD from Payer + + + + POST /transactionRequest + (amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + POST /transactionRequests + (amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Perform optional validation + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Fee is 2 USD in Payee FSP + to cover agent + commission, agent will + receive 1 USD in commission + + + + PUT /quotes/ + <ID> + (transferAmount=102 USD, + payeeFSPFee=2 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=102 USD, + payeeFSPFee=2 USD) + + + + HTTP 200 + (OK) + + + + + Payer fee is 1 USD in Payer + FSP for Cash-Out, total fees + are 3 USD + + + + Will you approve Cash-out of + 100 USD to Payee? It will + cost you 3 USD in fees. + + + + Perform transaction + + + + + Reserve 103 USD for Payer + account, 102 USD to Switch + account, 1 USD to fee account + + + + POST /transfers + (amount=102 USD) + + + + HTTP 202 + (Accepted) + + + + + Reserve 102 USD from Payer FSP + account to Payee FSP account + + + + POST /transfers + (amount=102 USD) + + + + HTTP 202 + (Accepted) + + + + + Transfer 102 USD from Switch + account, 101 USD to Payee + (1 USD commission), and + 1 USD to fee account + + + + You have received 100 USD + from Payer plus 1 USD in + commission, please give 100 USD + in cash to Payer + + + + Here is your 100 USD in cash + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + Transaction successful, + you should receive 100 USD + in cash from Payee. You have + paid 3 USD in fees. + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure33.plantuml b/docs/technical/api/assets/diagrams/sequence/figure33.plantuml new file mode 100644 index 000000000..188829960 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure33.plantuml @@ -0,0 +1,177 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Merchant-Initiated Merchant Payment example + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer(OTC/Agent) + +' declare actors +actor "<$actor>\nPayer\n" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\n\nSwitch" as Switch +participant "\nPayee\nFSP" as PayeeFSP +actor "<$actor>\nPayee\n(Agent)" as Payee +actor "<$actor>\nPayer\n(OTC)" as PayerOTC + +' start flow +Payee <<- PayerOTC: I would like to buy goods\nor service for 100 USD +PayeeFSP <<- Payee: I would like to receive\n100 USD from Payer +activate PayeeFSP +PayeeFSP ->> Switch: **POST /transactionRequests**\n(amount=100 USD) +activate Switch +PayeeFSP <<-- Switch: **HTTP 202** (Accepted) +PayerFSP <<- Switch: **POST /transactionRequests**\n(amount=100 USD) +activate PayerFSP +PayerFSP -->> Switch: **HTTP 202** (Accepted) +PayerFSP -> PayerFSP: Perform optional validation +PayerFSP ->> Switch: **PUT /transactionRequests/**\n(Receives status) +PayerFSP <<-- Switch: **HTTP 200** (OK) +deactivate PayerFSP +Switch ->> PayeeFSP: **PUT /transactionRequests/**\n(Received status) +Switch <<-- PayeeFSP: **HTTP 200** (OK) +deactivate Switch +deactivate PayeeFSP +PayerFSP ->> Switch: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate PayerFSP +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Fee is 0 USD +Switch <<- PayeeFSP: **PUT /quotes/**\n(transferAmount=100 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch ->> PayerFSP: **PUT /quotes/**\n(transferAmount=100 USD) +Switch <<-- PayerFSP: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Payer fee is 1 USD in Payer\nFSP for Merchant Payment +Payer <<- PayerFSP: Will you approve Merchant Payment\nof 100 USD to Payee? It will\ncost you 1 USD in fees. +deactivate PayerFSP +Payer ->> PayerFSP: Perform transaction +activate PayerFSP +PayerFSP -> PayerFSP: Reserve 101 USD from Payer\naccount, 100 USD to Switch\naccount, 1 USD to fee account +PayerFSP ->> Switch: **POST /transfers**\n(amount=100 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve 100 USD from Payer FSP\naccount to Payee FSP account +Switch ->> PayeeFSP: **POST /transfers**\n(amount=100 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Transfer 100 USD from Switch\naccount to Payee account +PayeeFSP ->> Payee: You have received 100 USD\nfrom Payer. Please give goods\nor service to Payer +Payee ->> PayerOTC: Here is your goods or service +Switch <<- PayeeFSP: **PUT /transfers/** +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch -> Switch: Commit reserved transfer +PayerFSP <<- Switch: **PUT /transfers/** +PayerFSP ->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Commit reserved transfer +Payer <<- PayerFSP: Transaction successful,\nyou have paid 100 USD to Payee\nplus 1 USD in fees. +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure33.svg b/docs/technical/api/assets/diagrams/sequence/figure33.svg new file mode 100644 index 000000000..67ccb5047 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure33.svg @@ -0,0 +1,270 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Payer +   + + + +   + Payer + FSP + +   +   + Switch + +   + Payee + FSP + + Payee + (Agent) + + + + Payer + (OTC) + + + + + + + + + + + + + + + I would like to buy goods + or service for 100 USD + + + + I would like to receive + 100 USD from Payer + + + + POST /transactionRequests + (amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + POST /transactionRequests + (amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Perform optional validation + + + + PUT /transactionRequests/ + <ID> + (Receives status) + + + + HTTP 200 + (OK) + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Fee is 0 USD + + + + PUT /quotes/ + <ID> + (transferAmount=100 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=100 USD) + + + + HTTP 200 + (OK) + + + + + Payer fee is 1 USD in Payer + FSP for Merchant Payment + + + + Will you approve Merchant Payment + of 100 USD to Payee? It will + cost you 1 USD in fees. + + + + Perform transaction + + + + + Reserve 101 USD from Payer + account, 100 USD to Switch + account, 1 USD to fee account + + + + POST /transfers + (amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Reserve 100 USD from Payer FSP + account to Payee FSP account + + + + POST /transfers + (amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Transfer 100 USD from Switch + account to Payee account + + + + You have received 100 USD + from Payer. Please give goods + or service to Payer + + + + Here is your goods or service + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + Transaction successful, + you have paid 100 USD to Payee + plus 1 USD in fees. + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure35.plantuml b/docs/technical/api/assets/diagrams/sequence/figure35.plantuml new file mode 100644 index 000000000..1bbc06eb6 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure35.plantuml @@ -0,0 +1,205 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title ATM-Initiated Cash-Out example + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer(OTC/Agent) + +' declare actors +actor "<$actor>\nPayer\n" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\n\nSwitch" as Switch +participant "\nPayee\nFSP" as PayeeFSP +actor "<$actor>\nPayee\n(ATM)" as PayeeATM +actor "<$actor>\nPayer\n(OTC)" as PayerOTC + +' start flow +Payer -> PayerFSP: Pre-generate OTP for me so that\nI can use it for ATM Cash-Out +activate PayerFSP +PayerFSP -> PayerFSP: Generate OTP +Payer <<-- PayerFSP: "12345 is your OTP" +deactivate PayerFSP +PayeeATM <<- PayerOTC: I would like to\nCash-Out 100 USD +PayeeFSP <<- PayeeATM: I would like to receive\n100 USD from Payer +activate PayeeFSP +PayeeFSP ->> Switch: **POST /transactionRequests**\n(amount=100 USD) +activate Switch +PayeeFSP <<-- Switch: **HTTP 202** (Accepted) +PayerFSP <<- Switch: **POST /transactionRequests**\n(amount=100 USD) +activate PayerFSP +PayerFSP -->> Switch: **HTTP 202** (Accepted) +PayerFSP -> PayerFSP: Perform optional validation +PayerFSP ->> Switch: **PUT /transactionRequests/**\n(Received status) +PayerFSP <<-- Switch: **HTTP 200** (OK) +deactivate PayerFSP +Switch ->> PayeeFSP: **PUT /transactionRequests/**\n(Received status) +Switch <<-- PayeeFSP: **HTTP 200** (OK) +deactivate Switch +deactivate PayeeFSP +PayerFSP ->> Switch: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate PayerFSP +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Payer fee is 1 USD for\nATM Cash-Out +Switch <<- PayeeFSP: **PUT /quotes/**\n(transferAmount=101 USD,\npayeeFspFee=1 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch ->> PayerFSP: **PUT /quotes/**\n(transferAmount=101 USD,\npayeeFspFee=1 USD) +Switch <<-- PayerFSP: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Payer fee is 1 USD in Payer FSP\nfor ATM Cash-Out, total fee 2 USD +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: OTP is pre-generated +Payer <<- PayerFSP: Use you pre-generated OTP to accept\ntransaction of 100 USD, 2 USD\nin fees. +PayerFSP ->> Switch: **GET /authorizations/**\n{TransactionRequestID}\n(amount=100 USD, fees=2 USD,\nretriesLeft=2, type=OTP) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **GET /authorizations/**\n{TransactionRequestID}\n(amount=100 USD, fees=2 USD,\nretriesLeft=2, type=OTP) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP ->> PayeeATM: Total fee for Cash-Out of\n100 USD is 2 USD +PayeeATM ->> PayerOTC: Please enter you OTP\nto confirm Cash-Out of 100 USD,\nfee is 2 USD +PayeeATM <<- PayerOTC: Enters "12345" +PayeeFSP <<- PayeeATM: "12345" is the OTP +Switch <<- PayeeFSP: **PUT /authorizations/**\n{transactionRequestID}\n(otp="12345") +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /authorizations/**\n{transactionRequestID}\n(otp="12345") +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Validate OTP sent by Payee FSP,\nOTP OK +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Reserve 102 USD from Payer\naccount, 101 USD to Switch\naccount, 1 USD to fee account +PayerFSP ->> Switch: **POST /transfers**\n(amount=101 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve 101 USD from Payer FSP\naccount to Payee FSP account +Switch ->> PayeeFSP: **POST /transfers**\n(amount=101 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Transfer 101 USD from Switch\naccount, 100 USD to Payee,\n1 USD to fee account +PayeeFSP ->> PayeeATM: Dispense 100 USD in Cash +PayeeATM ->> PayerOTC: Here is your 100 USD in cash +Switch <<- PayeeFSP: **PUT /transfers/** +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch <- Switch: Commit reserved transfer +Switch ->> PayerFSP: **PUT /transfers/** +Switch <<-- PayerFSP: **HTTP 200** (OK) +deactivate Switch +PayerFSP <- PayerFSP: Commit reserved transfer +Payer <- PayerFSP: Transfer successful,\nyou should receive 100 USD\nin cash from ATM. You have\npaid 2 USD in fees. +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure35.svg b/docs/technical/api/assets/diagrams/sequence/figure35.svg new file mode 100644 index 000000000..7ca43eff6 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure35.svg @@ -0,0 +1,365 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Payer +   + + + +   + Payer + FSP + +   +   + Switch + +   + Payee + FSP + + Payee + (ATM) + + + + Payer + (OTC) + + + + + + + + + + + + + + + + + + Pre-generate OTP for me so that + I can use it for ATM Cash-Out + + + + + Generate OTP + + + + "12345 is your OTP" + + + + I would like to + Cash-Out 100 USD + + + + I would like to receive + 100 USD from Payer + + + + POST /transactionRequests + (amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + POST /transactionRequests + (amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Perform optional validation + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Payer fee is 1 USD for + ATM Cash-Out + + + + PUT /quotes/ + <ID> + (transferAmount=101 USD, + payeeFspFee=1 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=101 USD, + payeeFspFee=1 USD) + + + + HTTP 200 + (OK) + + + + + Payer fee is 1 USD in Payer FSP + for ATM Cash-Out, total fee 2 USD + + + + + OTP is pre-generated + + + + Use you pre-generated OTP to accept + transaction of 100 USD, 2 USD + in fees. + + + + GET /authorizations/ + {TransactionRequestID} + (amount=100 USD, fees=2 USD, + retriesLeft=2, type=OTP) + + + + HTTP 202 + (Accepted) + + + + GET /authorizations/ + {TransactionRequestID} + (amount=100 USD, fees=2 USD, + retriesLeft=2, type=OTP) + + + + HTTP 202 + (Accepted) + + + + Total fee for Cash-Out of + 100 USD is 2 USD + + + + Please enter you OTP + to confirm Cash-Out of 100 USD, + fee is 2 USD + + + + Enters "12345" + + + + "12345" is the OTP + + + + PUT /authorizations/ + {transactionRequestID} + (otp="12345") + + + + HTTP 200 + (OK) + + + + PUT /authorizations/ + {transactionRequestID} + (otp="12345") + + + + HTTP 200 + (OK) + + + + + Validate OTP sent by Payee FSP, + OTP OK + + + + + Reserve 102 USD from Payer + account, 101 USD to Switch + account, 1 USD to fee account + + + + POST /transfers + (amount=101 USD) + + + + HTTP 202 + (Accepted) + + + + + Reserve 101 USD from Payer FSP + account to Payee FSP account + + + + POST /transfers + (amount=101 USD) + + + + HTTP 202 + (Accepted) + + + + + Transfer 101 USD from Switch + account, 100 USD to Payee, + 1 USD to fee account + + + + Dispense 100 USD in Cash + + + + Here is your 100 USD in cash + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + Transfer successful, + you should receive 100 USD + in cash from ATM. You have + paid 2 USD in fees. + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure37.plantuml b/docs/technical/api/assets/diagrams/sequence/figure37.plantuml new file mode 100644 index 000000000..04e62ac13 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure37.plantuml @@ -0,0 +1,196 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Merchant-Initiated Merchant Payment authorized on POS example + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer(OTC/Agent) + +' declare actors +actor "<$actor>\nPayer\n" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\n\nSwitch" as Switch +participant "\nPayee\nFSP" as PayeeFSP +actor "<$actor>\nPayee\n(POS)" as PayeePOS +actor "<$actor>\nPayer\n(OTC)" as PayerOTC + +' start flow +PayeePOS <<- PayerOTC: I would like to buy goods\nor service for 100 USD +PayeeFSP <<- PayeePOS: I would like to receive\n100 USD from Payer +activate PayeeFSP +PayeeFSP ->> Switch: **POST /transactionRequests**\n(amount=100 USD) +activate Switch +PayeeFSP <<-- Switch: **HTTP 202** (Accepted) +activate PayerFSP +PayerFSP <<- Switch: **POST /transactionRequests**\n(amount=100 USD) +PayerFSP -->> Switch: **HTTP 202** (Accepted) +PayerFSP -> PayerFSP: Perform optional validation +PayerFSP ->> Switch: **PUT /transactionRequests/**\n(Received status) +PayerFSP <<-- Switch: **HTTP 200** (OK) +deactivate PayerFSP +Switch ->> PayeeFSP: **PUT /transactionRequests/**\n(Received status) +Switch <<-- PayeeFSP: **HTTP 200** (OK) +deactivate Switch +deactivate PayeeFSP +PayerFSP ->> Switch: **POST /quotes**\n(amount=100 USD,\namountType=RECEIVE) +activate PayerFSP +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amount=100 USD,\namountType=RECEIVE) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: FSP Commission is 1 USD\nin Payee FSP for\nMerchant Payment +Switch <<- PayeeFSP: **PUT /quotes/**\n(transferAmount=99 USD,\npayeeFspCommission=1 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch ->> PayerFSP: **PUT /quotes/**\n(transferAmount=99 USD,\npayeeFspCommission=1 USD) +Switch <<-- PayerFSP: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Payer FSP uses the\nFSP commission as\na transaction fee +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Generate OTP, "12345" +Payer <<- PayerFSP: Use OTP "12345" to accept\ntransaction to Merchant of 100 USD,\n0 USD in fees. +PayerFSP ->> Switch: **GET /authorizations/**\n{TransactionRequestID}\n(amount=100 USD, fees=0 USD,\nretriesLeft=2, type=OTP) +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **GET /authorizations/**\n{TransactionRequestID}\n(amount=100 USD, fees=0 USD,\nretriesLeft=2, type=OTP) +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP ->> PayeePOS: Total amount is 100 USD,\nfee is 0 USD +PayeePOS ->> PayerOTC: Please enter you OTP\nto confirm Merchant Payment\nof 100 USD, fee is 0 USD +PayeePOS <<- PayerOTC: Enters "12345" +PayeeFSP <<- PayeePOS: "12345" is the OTP +Switch <<- PayeeFSP: **PUT /authorizations/***\n{transactionRequestID}\n(otp="12345") +Switch -->> PayeeFSP: **HTTP 200** (OK) +PayerFSP <<- Switch: **PUT /authorizations/***\n{transactionRequestID}\n(otp="12345") +PayerFSP -->> Switch: **HTTP 200** (OK) +PayerFSP -> PayerFSP: Validate OTP sent by Payee FSP,\nOTP OK +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Reserve 100 USD from Payer\naccount, 99 USD to Switch\naccount, 1 USD to fee account +PayerFSP ->> Switch: **POST /transfers**\n(amount=99 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve 99 USD from Payer FSP\naccount to Payee FSP account +Switch ->> PayeeFSP: **POST /transfers**\n(amount=99 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Transfer 99 USD from Switch\naccount, 1 USD from\ncommission account\nto Payee account +PayeeFSP ->> PayeePOS: You have received 100 USD\nfrom Payer. Please give goods\nor service to Payer. +PayeePOS ->> PayerOTC: Here is your goods or service +Switch <<- PayeeFSP: **PUT /transfers/** +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch <- Switch: Commit reserved transfer +Switch ->> PayerFSP: **PUT /transfers/** +Switch <<-- PayerFSP: **HTTP 200** (OK) +deactivate Switch +PayerFSP <- PayerFSP: Commit reserved transfer +Payer <- PayerFSP: Payment successful, you\nhave paid 100 USD to Payee. +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure37.svg b/docs/technical/api/assets/diagrams/sequence/figure37.svg new file mode 100644 index 000000000..ffc7084e2 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure37.svg @@ -0,0 +1,351 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Payer +   + + + +   + Payer + FSP + +   +   + Switch + +   + Payee + FSP + + Payee + (POS) + + + + Payer + (OTC) + + + + + + + + + + + + + + + + I would like to buy goods + or service for 100 USD + + + + I would like to receive + 100 USD from Payer + + + + POST /transactionRequests + (amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + POST /transactionRequests + (amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Perform optional validation + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + POST /quotes + (amount=100 USD, + amountType=RECEIVE) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amount=100 USD, + amountType=RECEIVE) + + + + HTTP 202 + (Accepted) + + + + + FSP Commission is 1 USD + in Payee FSP for + Merchant Payment + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + payeeFspCommission=1 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + payeeFspCommission=1 USD) + + + + HTTP 200 + (OK) + + + + + Payer FSP uses the + FSP commission as + a transaction fee + + + + + Generate OTP, "12345" + + + + Use OTP "12345" to accept + transaction to Merchant of 100 USD, + 0 USD in fees. + + + + GET /authorizations/ + {TransactionRequestID} + (amount=100 USD, fees=0 USD, + retriesLeft=2, type=OTP) + + + + HTTP 202 + (Accepted) + + + + GET /authorizations/ + {TransactionRequestID} + (amount=100 USD, fees=0 USD, + retriesLeft=2, type=OTP) + + + + HTTP 202 + (Accepted) + + + + Total amount is 100 USD, + fee is 0 USD + + + + Please enter you OTP + to confirm Merchant Payment + of 100 USD, fee is 0 USD + + + + Enters "12345" + + + + "12345" is the OTP + + + + PUT /authorizations/ + * + {transactionRequestID} + (otp="12345") + + + + HTTP 200 + (OK) + + + + PUT /authorizations/ + * + {transactionRequestID} + (otp="12345") + + + + HTTP 200 + (OK) + + + + + Validate OTP sent by Payee FSP, + OTP OK + + + + + Reserve 100 USD from Payer + account, 99 USD to Switch + account, 1 USD to fee account + + + + POST /transfers + (amount=99 USD) + + + + HTTP 202 + (Accepted) + + + + + Reserve 99 USD from Payer FSP + account to Payee FSP account + + + + POST /transfers + (amount=99 USD) + + + + HTTP 202 + (Accepted) + + + + + Transfer 99 USD from Switch + account, 1 USD from + commission account + to Payee account + + + + You have received 100 USD + from Payer. Please give goods + or service to Payer. + + + + Here is your goods or service + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + PUT /transfers/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + Payment successful, you + have paid 100 USD to Payee. + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure39.plantuml b/docs/technical/api/assets/diagrams/sequence/figure39.plantuml new file mode 100644 index 000000000..187a75c8a --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure39.plantuml @@ -0,0 +1,162 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Refund example + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer(OTC/Agent) + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +Payer ->> PayerFSP: I would like a Refund\nof my Agent Cash-in of 101 USD +activate PayerFSP +PayerFSP -> PayerFSP: Find original transaction, FSP\ncommission was 1 USD which\nmeans Payer FSP wants 1 USD\nin fee to reverse. +PayerFSP ->> Switch: **POST /quotes**\n(transactionScenario=REFUND\namountType=SEND,\namount=100 USD, fee=1 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202**\n(Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(transactionScenario=REFUND\namountType=SEND,\namount=100 USD, fee=1 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202**\n(Accepted) +PayeeFSP -> PayeeFSP:Find original transaction, 1 USD\nwas received in FSP commission, \ngive back in FSP commission.\nReverse Agent commission. +PayeeFSP ->> Payee:Customer wants a refund of Cash-in,\nyou will lose 1 USD in commission\nand 100 USD will be transfered to\nyour account, please pay customer\n101 USD in cash +PayeeFSP <<- Payee: OK +Switch <<- PayeeFSP: **PUT /quote/**\n(transferAmount=99 USD,\npayeeFspCommission=1 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quote/**\n(transferAmount=99 USD,\npayeeFspCommission=1 USD) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Payer gets fee subsizidized by\nFSP commission. +Payer <<- PayerFSP: By refunding 100 USD to Agent, you\nshould receive 101 USD in cash +deactivate PayerFSP +Payer ->> PayerFSP: Perform transaction +activate PayerFSP +PayerFSP -> PayerFSP: Reverse original transaction by\nreversing 100 USD from Payer\nAccount, 99 USD to Switch account,\n1 USD to commission account +PayerFSP ->> Switch: **POST /transfers**\n(amount=99 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve 99 USD from Payer FSP\naccount to Payee FSP account +Switch ->> PayeeFSP: **POST /transfer/** +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Reverse original transaction by\ntransferring 100 USD to Payee\naccount, 99 USD from Switch\naccount, 1 USD from fee account,\nand 1 USD from fee account to\ninternal commission account +PayeeFSP -> Payee: You have received 100 USD\nfrom Payer in Cash-in refund,\nplease pay customer his 101 USD +Switch <<- PayeeFSP: **POST /transfer/** +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch -> Switch: Commit reserved transfer +PayerFSP <<- Switch: **POST /transfer/** +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Commit reserved transfer +Payer <- PayerFSP: Transaction successful,\nyou have paid 1 USD in fee +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure39.svg b/docs/technical/api/assets/diagrams/sequence/figure39.svg new file mode 100644 index 000000000..c10af8f4f --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure39.svg @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + +   + Switch + + Payee + FSP + + Payee + + + + + + + + + + + + I would like a Refund + of my Agent Cash-in of 101 USD + + + + + Find original transaction, FSP + commission was 1 USD which + means Payer FSP wants 1 USD + in fee to reverse. + + + + POST /quotes + (transactionScenario=REFUND + amountType=SEND, + amount=100 USD, fee=1 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (transactionScenario=REFUND + amountType=SEND, + amount=100 USD, fee=1 USD) + + + + HTTP 202 + (Accepted) + + + + + Find original transaction, 1 USD + was received in FSP commission, + give back in FSP commission. + Reverse Agent commission. + + + + Customer wants a refund of Cash-in, + you will lose 1 USD in commission + and 100 USD will be transfered to + your account, please pay customer + 101 USD in cash + + + + OK + + + + PUT /quote/ + <ID> + (transferAmount=99 USD, + payeeFspCommission=1 USD) + + + + HTTP 200 + (OK) + + + + PUT /quote/ + <ID> + (transferAmount=99 USD, + payeeFspCommission=1 USD) + + + + HTTP 200 + (OK) + + + + + Payer gets fee subsizidized by + FSP commission. + + + + By refunding 100 USD to Agent, you + should receive 101 USD in cash + + + + Perform transaction + + + + + Reverse original transaction by + reversing 100 USD from Payer + Account, 99 USD to Switch account, + 1 USD to commission account + + + + POST /transfers + (amount=99 USD) + + + + HTTP 202 + (Accepted) + + + + + Reserve 99 USD from Payer FSP + account to Payee FSP account + + + + POST /transfer/ + <ID> + + + + HTTP 202 + (Accepted) + + + + + Reverse original transaction by + transferring 100 USD to Payee + account, 99 USD from Switch + account, 1 USD from fee account, + and 1 USD from fee account to + internal commission account + + + You have received 100 USD + from Payer in Cash-in refund, + please pay customer his 101 USD + + + + POST /transfer/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + + POST /transfer/ + <ID> + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + + + Transaction successful, + you have paid 1 USD in fee + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure4.plantuml b/docs/technical/api/assets/diagrams/sequence/figure4.plantuml new file mode 100644 index 000000000..db01171d2 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure4.plantuml @@ -0,0 +1,64 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +' declare title +' title HTTP PATCH call flow + +' Actor Keys: +' participant - Switch and FSP + +' declare actors +participant "Switch" as Switch +participant "FSP" as FSP + +' start flow +activate Switch +activate FSP +Switch ->> FSP: **POST /service/**//// +FSP -->> Switch: **HTTP 202** (Accepted) +FSP ->> FSP: Create object, state of \ncreated object is a \nnon-fiinalized state +FSP ->> Switch: **PUT /service/** \n(Non-finalized state) +Switch -->> FSP: **HTTP 200** (OK) +deactivate FSP +Switch ->> Switch: Handle callback, send\nnotificaction to FSP regarding\nthe object's finalized state +Switch ->> FSP: **PATCH /service/**\n(Finalized state) +activate FSP +FSP -->> Switch: **HTTP 202** (Accepted) +deactivate Switch +FSP ->> FSP: Update object's state\naccording to new\ninformation +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure4.svg b/docs/technical/api/assets/diagrams/sequence/figure4.svg new file mode 100644 index 000000000..4d6eb7612 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure4.svg @@ -0,0 +1,73 @@ + + + + + + + + + + Switch + + FSP + + + + + + + POST /service/ + <ID> + + + + HTTP 202 + (Accepted) + + + + + + Create object, state of + created object is a + non-fiinalized state + + + + PUT /service/ + <ID> + (Non-finalized state) + + + + HTTP 200 + (OK) + + + + + + Handle callback, send + notificaction to FSP regarding + the object's finalized state + + + + PATCH /service/ + <ID> + (Finalized state) + + + + HTTP 202 + (Accepted) + + + + + + Update object's state + according to new + information + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure41.plantuml b/docs/technical/api/assets/diagrams/sequence/figure41.plantuml new file mode 100644 index 000000000..ee5053cd8 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure41.plantuml @@ -0,0 +1,139 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title How to use the services provided by /participants if there is no common Account Lookup System + +' Actor Keys: +' participant - FSP(User's) and FSP +' actor - User + +' declare actors +actor "<$actor>\nUser" as user +participant "User's\nFSP" as userfsp +participant "\nFSP 1" as fsp1 +participant "\nFSP 2" as fsp2 + +' start flow +user ->> userfsp: I would like to pay or receive\nfunds to/from +123456789 +activate userfsp +userfsp -> userfsp: +123456789 is not\nwithin this system,\nask FSP 1 +userfsp ->> fsp1: **GET /participants/MSISDN/123456789** +activate fsp1 +userfsp <<-- fsp1: **HTTP 202** (Accepted) +fsp1 -> fsp1: +123456789 is not\nwithin this system +userfsp <<- fsp1: **PUT /participants/MSISDN/123456789/error** +userfsp -->> fsp1: **HTTP 200** (OK) +deactivate fsp1 +userfsp -> userfsp: Not in FSP 1, ask FSP 2 +userfsp ->> fsp2: **GET /participants/MSISDN/123456789** +activate fsp2 +userfsp <<-- fsp2: **HTTP 202** (Accepted) +fsp2 -> fsp2: +123456789 is\nwithin this system +userfsp <<- fsp2: **PUT /participants/MSISDN/123456789/error** +userfsp -->> fsp2: **HTTP 200** (OK) +deactivate fsp2 +userfsp -> userfsp: +123456789 found\nin FSP 2 +userfsp -[hidden]>fsp2 +deactivate userfsp +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure41.svg b/docs/technical/api/assets/diagrams/sequence/figure41.svg new file mode 100644 index 000000000..cf028451c --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure41.svg @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + User + + + + User's + FSP + +   + FSP 1 + +   + FSP 2 + + + + + + + I would like to pay or receive + funds to/from +123456789 + + + + + +123456789 is not + within this system, + ask FSP 1 + + + + GET /participants/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + + +123456789 is not + within this system + + + + PUT /participants/MSISDN/123456789/error + + + + HTTP 200 + (OK) + + + + + Not in FSP 1, ask FSP 2 + + + + GET /participants/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + + +123456789 is + within this system + + + + PUT /participants/MSISDN/123456789/error + + + + HTTP 200 + (OK) + + + + + +123456789 found + in FSP 2 + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure42.plantuml b/docs/technical/api/assets/diagrams/sequence/figure42.plantuml new file mode 100644 index 000000000..05ba8f242 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure42.plantuml @@ -0,0 +1,128 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title How to use the services provided by /participants if there is no common Account Lookup System + +' Actor Keys: +' participant - FSP(User's) and Account Lookup Service +' actor - User + +' declare actors +actor "<$actor>\nUser" as user +participant "User's\nFSP" as userfsp +participant "Account\nLookup" as ALS + +' start flow +user ->> userfsp: I would like to pay or receive\nfunds to/from +123456789 +activate userfsp +userfsp -> userfsp: +123456789 is not\nwithin this system +userfsp ->> ALS: **GET /participants/MSISDN/123456789** +activate ALS +userfsp <<-- ALS: **HTTP 202** (Accepted) +ALS -> ALS: Lookup which FSP MSISDN\n+123456789 belongs to. +userfsp <<- ALS: **PUT /participants/MSISDN/123456789**\n(FSP ID) +userfsp -->> ALS: **HTTP 200** (OK) +deactivate ALS +deactivate userfsp +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure42.svg b/docs/technical/api/assets/diagrams/sequence/figure42.svg new file mode 100644 index 000000000..1f9cf748e --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure42.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + User + + + + User's + FSP + + Account + Lookup + + + + + + I would like to pay or receive + funds to/from +123456789 + + + + + +123456789 is not + within this system + + + + GET /participants/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + + Lookup which FSP MSISDN + +123456789 belongs to. + + + + PUT /participants/MSISDN/123456789 + (FSP ID) + + + + HTTP 200 + (OK) + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure43.plantuml b/docs/technical/api/assets/diagrams/sequence/figure43.plantuml new file mode 100644 index 000000000..cc7a269f5 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure43.plantuml @@ -0,0 +1,144 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Example process for /parties resource + +' Actor Keys: +' participant - FSP(User's), Switch, Account Lookup and FSP +' actor - Payee/Payer(User) + +' declare actors +actor "<$actor>\nUser" as user +participant "User's\nFSP" as userfsp +participant "Optional\nSwitch" as Switch +participant "Account\nLookup" as ALS +participant "\nFSP 1" as fsp1 + +' start flow +user -> userfsp: I would like to pay or receive\nfunds to/from +123456789 +activate userfsp +userfsp -> userfsp: +123456789 is not\nwithin this system +userfsp ->> Switch: **GET /parties/MSISDN/123456789** +activate Switch +userfsp <<-- Switch: **HTTP 202** (Accepted) +Switch ->> ALS: **GET /participants/MSISDN/123456789** +activate ALS +Switch <<-- ALS: **HTTP 202** (Accepted) +ALS -> ALS: Lookup which FSP MSISDN\n+123456789 belongs to. +Switch <<- ALS: **PUT /participants/MSISDN/123456789**\n(FSP 1) +Switch -->> ALS: **HTTP 200** (OK) +deactivate ALS +Switch ->> fsp1: **GET /parties/MSISDN/123456789** +activate fsp1 +Switch <<-- fsp1: **HTTP 202** (Accepted) +fsp1 -> fsp1: Lookup party information\nfor +123456789 +Switch <<- fsp1: **PUT /parties/MSISDN/123456789**\n(Party information) +Switch -->> fsp1: **HTTP 200** (OK) +deactivate fsp1 +userfsp <<- Switch: **PUT /parties/MSISDN/123456789**\n(Party information) +userfsp -->> Switch: **HTTP 200** (OK) +deactivate Switch +user <- userfsp: Is "name" correct? +deactivate userfsp +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure43.svg b/docs/technical/api/assets/diagrams/sequence/figure43.svg new file mode 100644 index 000000000..0c6980acc --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure43.svg @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + User + + + + User's + FSP + + Optional + Switch + + Account + Lookup + +   + FSP 1 + + + + + + + I would like to pay or receive + funds to/from +123456789 + + + + + +123456789 is not + within this system + + + + GET /parties/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + GET /participants/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + + Lookup which FSP MSISDN + +123456789 belongs to. + + + + PUT /participants/MSISDN/123456789 + (FSP 1) + + + + HTTP 200 + (OK) + + + + GET /parties/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + + Lookup party information + for +123456789 + + + + PUT /parties/MSISDN/123456789 + (Party information) + + + + HTTP 200 + (OK) + + + + PUT /parties/MSISDN/123456789 + (Party information) + + + + HTTP 200 + (OK) + + + Is "name" correct? + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure44.plantuml b/docs/technical/api/assets/diagrams/sequence/figure44.plantuml new file mode 100644 index 000000000..ed8d8bd0e --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure44.plantuml @@ -0,0 +1,137 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title How to use the /transactionRequests service + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee + +' declare actors +participant "Payer\nFSP" as payerfsp +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as payeefsp +actor "<$actor>\nPayee" as Payee + +' start flow +payeefsp <- Payee: I would like to receive\nfunds from +123456789 +activate payeefsp +payeefsp <- payeefsp: Lookup +123456789\n(process not shown her) +Switch <<- payeefsp: **POST /transactionRequests**\n(Payee information,\ntransaction details) +activate Switch +Switch -->> payeefsp: **HTTP 202** (Accepted) +payerfsp <<- Switch: **POST /transactionRequests**\n(Payee information,\ntransaction details) +activate payerfsp +payerfsp -->> Switch: **HTTP 202** (Accepted) +payeefsp -> payeefsp: Perform optional validation +payerfsp ->> Switch: **PUT /transactionRequests/**\n(Received status) +payerfsp <<-- Switch: **HTTP 200** (OK) +deactivate payerfsp +Switch ->> payeefsp: **PUT /transactionRequests/**\n(Received status) +Switch <<-- payeefsp: **HTTP 200** (OK) +deactivate Switch +payeefsp -> payeefsp: Wait for either quote and\ntransfer, or rejected\ntransaction request by Payer +payeefsp <[hidden]- payeefsp +deactivate payeefsp +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure44.svg b/docs/technical/api/assets/diagrams/sequence/figure44.svg new file mode 100644 index 000000000..e073588f1 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure44.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + Payee + + + + + + + + I would like to receive + funds from +123456789 + + + + + Lookup +123456789 + (process not shown her) + + + + POST /transactionRequests + (Payee information, + transaction details) + + + + HTTP 202 + (Accepted) + + + + POST /transactionRequests + (Payee information, + transaction details) + + + + HTTP 202 + (Accepted) + + + + + Perform optional validation + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + + Wait for either quote and + transfer, or rejected + transaction request by Payer + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure45.plantuml b/docs/technical/api/assets/diagrams/sequence/figure45.plantuml new file mode 100644 index 000000000..bcaad8a0d --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure45.plantuml @@ -0,0 +1,131 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Example process in which a transaction request is rejected + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee + +' declare actors +participant "Payer\nFSP" as payerfsp +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as payeefsp +actor "<$actor>\nPayee" as Payee + +' start flow +activate payerfsp +payerfsp -> payerfsp: Transaction request and\nquoting (process not shown) +payerfsp -> payerfsp: User rejection, OTP not correct,\nor automatic rejection +payerfsp ->> Switch: **PUT /transactionRequests/**\n(Rejected state) +activate Switch +payerfsp <<-- Switch: **HTTP 200** (OK) +deactivate payerfsp +Switch ->> payeefsp: **PUT /transactionRequests/**\n(Rejected state) +activate payeefsp +Switch <<-- payeefsp: **HTTP 200** (OK) +deactivate Switch +payeefsp -> Payee: Transaction failed due\nto user rejection +deactivate payeefsp +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure45.svg b/docs/technical/api/assets/diagrams/sequence/figure45.svg new file mode 100644 index 000000000..5b94d8fd5 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure45.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + Payee + + + + + + + + + + Transaction request and + quoting (process not shown) + + + + + User rejection, OTP not correct, + or automatic rejection + + + + PUT /transactionRequests/ + <ID> + (Rejected state) + + + + HTTP 200 + (OK) + + + + PUT /transactionRequests/ + <ID> + (Rejected state) + + + + HTTP 200 + (OK) + + + Transaction failed due + to user rejection + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure47.plantuml b/docs/technical/api/assets/diagrams/sequence/figure47.plantuml new file mode 100644 index 000000000..86deaaefd --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure47.plantuml @@ -0,0 +1,150 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Example process for resource /quotes + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payer/Payee + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP(s)" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +Payer ->> PayerFSP: I would like to pay 100 USD\nto +123456789 +activate PayerFSP +PayerFSP -> PayerFSP: Lookup +123456789\n(process not shown here) +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on fee model) +PayerFSP ->> Switch: **POST /quotes**\n(Transaction details) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(Transaction details) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Rate Payee FSP\nfees/commission,\ngenerate condition +Group #OldLace Optional + hnote left of PayeeFSP #OldLace + Confirm quote + end hnote + PayeeFSP -> Payee: Here is the quote and Payer name + PayeeFSP <- Payee: I confirm +end +Switch <<- PayeeFSP: ** PUT /quotes/**\n(Payee FSP fee/commission, condition) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quotes/**\n(Payee FSP fee/commission, condition) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on fee model) +Payer <- PayerFSP: Present fees and optionally\npayee name +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure47.svg b/docs/technical/api/assets/diagrams/sequence/figure47.svg new file mode 100644 index 000000000..e18393d9b --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure47.svg @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Payee + FSP(s) + + Payee + + + + + + + + + + I would like to pay 100 USD + to +123456789 + + + + + Lookup +123456789 + (process not shown here) + + + + + Rate Payer FSP quote + (depending on fee model) + + + + POST /quotes + (Transaction details) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (Transaction details) + + + + HTTP 202 + (Accepted) + + + + + Rate Payee FSP + fees/commission, + generate condition + + + Optional + + Confirm quote + + + Here is the quote and Payer name + + + I confirm + + + + + PUT /quotes/** + <ID> + (Payee FSP fee/commission, condition) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + (Payee FSP fee/commission, condition) + + + + HTTP 200 + (OK) + + + + + Rate Payer FSP quote + (depending on fee model) + + + Present fees and optionally + payee name + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure49.plantuml b/docs/technical/api/assets/diagrams/sequence/figure49.plantuml new file mode 100644 index 000000000..553dfc514 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure49.plantuml @@ -0,0 +1,156 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Example process for resource /authorizations + +' Actor Keys: +' participant - FSP(Payee) and Switch +' actor - Payee/Payer(POS/ATM) + +' declare actors +'actor "<$actor>\nPayer" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\nOptional\nSwitch" as Switch +participant "\nPayee\nFSP" as PayeeFSP +actor "<$actor>\nPayee\n(POS/ATM)" as Payee + +' start flow +PayeeFSP <- Payee: I would like to receive\nfunds from +123456789 +activate PayeeFSP +PayeeFSP <- PayeeFSP: Lookup +123456789\n(process not shown here) +Switch <<- PayeeFSP: **POST /transactionRequests**\n(Payee information,\ntransaction details) +activate Switch +Switch -->> PayeeFSP: **HTTP 202** (Accepted) +PayerFSP <<- Switch: **POST /transactionRequests**\n(Payee information,\ntransaction details) +activate PayerFSP +PayerFSP ->> Switch: **HTTP 202** (Accepted) +PayerFSP -> PayerFSP: Perform optional validation +PayerFSP ->> Switch: **PUT /transactionRequests/**\n(Received status) +PayerFSP <<- Switch: **HTTP 200** (OK) +deactivate PayerFSP +Switch ->> PayeeFSP: **PUT /transactionRequests/**\n(Received status) +Switch <<-- PayeeFSP: **HTTP 200** (OK) +deactivate Switch +deactivate PayeeFSP +activate PayerFSP +PayerFSP -> PayerFSP: Do quote, generate OTP,\nnotify user (process\nnot shown here) +PayerFSP ->> Switch: **GET /authorizations/**\n\n(Amount including fees) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **GET /authorizations/**\n\n(Amount including fees) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> Payee: Show fees on POS +Payee -> Payee: Payer approves/rejects\ntransaction using OTP +PayeeFSP <<-- Payee: +Switch <<- PayeeFSP: **PUT /authorizations/**\n\n(OTP) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /authorizations/**\n\n(OTP) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Validate OTP sent by Payee FSP +PayerFSP -[hidden]> Switch +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure49.svg b/docs/technical/api/assets/diagrams/sequence/figure49.svg new file mode 100644 index 000000000..3a5ae346a --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure49.svg @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + +   + Payer + FSP + +   + Optional + Switch + +   + Payee + FSP + + Payee + (POS/ATM) + + + + + + + + + + + I would like to receive + funds from +123456789 + + + + + Lookup +123456789 + (process not shown here) + + + + POST /transactionRequests + (Payee information, + transaction details) + + + + HTTP 202 + (Accepted) + + + + POST /transactionRequests + (Payee information, + transaction details) + + + + HTTP 202 + (Accepted) + + + + + Perform optional validation + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + + Do quote, generate OTP, + notify user (process + not shown here) + + + + GET /authorizations/ + <TransactionRequestID> + (Amount including fees) + + + + HTTP 202 + (Accepted) + + + + GET /authorizations/ + <TransactionRequestID> + (Amount including fees) + + + + HTTP 202 + (Accepted) + + + Show fees on POS + + + + + Payer approves/rejects + transaction using OTP + + + + + + + PUT /authorizations/ + <TransactionRequestID> + (OTP) + + + + HTTP 200 + (OK) + + + + PUT /authorizations/ + <TransactionRequestID> + (OTP) + + + + HTTP 200 + (OK) + + + + + Validate OTP sent by Payee FSP + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure5.plantuml b/docs/technical/api/assets/diagrams/sequence/figure5.plantuml new file mode 100644 index 000000000..0b48ee49c --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure5.plantuml @@ -0,0 +1,69 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +' declare title +' title Using the customized HTTP header fields FSPIOP-Destination and FSPIOP-Source + +' Actor Keys: +' participant - FSP, Peer FSP and Optional Switch + +' declare actors +participant "\nFSP" as FSP +participant "Optional\nSwitch" as Switch +participant "Peer\nFSP" as PEERFSP + +' start flow +FSP ->> Switch: **POST /service**\n(**FSPIOP-Source=**FSP,\n**FSPIOP-Destination=**Peer FSP) +activate FSP +activate Switch +FSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Route message according\nto **FSPIOP-Destination** +Switch ->> PEERFSP: **POST /service**\n(**FSPIOP-Source=**FSP,\n**FSPIOP-Destination=**Peer FSP) +activate PEERFSP +Switch <<-- PEERFSP: **HTTP 202** (Accepted) +PEERFSP -> PEERFSP: Optionally validate messages signature\nusing stored certificate for\nFSP in **FSPIOP-Source** +PEERFSP -> PEERFSP: Replace **FSPIOP-Source**\nwith **FSPIOP-Destination**\nand visa versa for routing of callback +Switch <<- PEERFSP: **PUT /service/**////\n(**FSPIOP-Source=**Peer FSP,\n**FSPIOP-Destination=**FSP) +Switch -->> PEERFSP: **HTTP 200** (OK) +Switch -> Switch: Route message according\nto **FSPIOP-Destination** +deactivate PEERFSP +FSP <<- Switch: **PUT /service/**////\n(**FSPIOP-Source=**Peer FSP,\n**FSPIOP-Destination=**FSP) +FSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +deactivate FSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure5.svg b/docs/technical/api/assets/diagrams/sequence/figure5.svg new file mode 100644 index 000000000..54a0efff5 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure5.svg @@ -0,0 +1,112 @@ + + + + + + + + + + +   + FSP + + Optional + Switch + + Peer + FSP + + + + + + + POST /service + ( + FSPIOP-Source= + FSP, + FSPIOP-Destination= + Peer FSP) + + + + HTTP 202 + (Accepted) + + + + + Route message according + to + FSPIOP-Destination + + + + POST /service + ( + FSPIOP-Source= + FSP, + FSPIOP-Destination= + Peer FSP) + + + + HTTP 202 + (Accepted) + + + + + Optionally validate messages signature + using stored certificate for + FSP in + FSPIOP-Source + + + + + Replace + FSPIOP-Source + with + FSPIOP-Destination + and visa versa for routing of callback + + + + PUT /service/ + <ID> + ( + FSPIOP-Source= + Peer FSP, + FSPIOP-Destination= + FSP) + + + + HTTP 200 + (OK) + + + + + Route message according + to + FSPIOP-Destination + + + + PUT /service/ + <ID> + ( + FSPIOP-Source= + Peer FSP, + FSPIOP-Destination= + FSP) + + + + HTTP 200 + (OK) + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure50.plantuml b/docs/technical/api/assets/diagrams/sequence/figure50.plantuml new file mode 100644 index 000000000..29daf6dff --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure50.plantuml @@ -0,0 +1,145 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Payer requests resend of authorization value (OTP) + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payer/Payee(OTC/POS) + +' declare actors +actor "<$actor>\nPayer\n" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\n\nSwitch" as Switch +participant "\nPayee\nFSP" as PayeeFSP +actor "<$actor>\nPayee\n(POS)" as PayeePOS +actor "<$actor>\nPayer\n(OTC)" as PayerOTC + +' start flow +activate PayerFSP +PayerFSP -> PayerFSP: Transaction request and\nquoting process (not shown) +PayerFSP -> PayerFSP: Generate OTP, "12345", Payer FSP\nsets maximum retries to 2 +Payer <<- PayerFSP: Use OTP "12345" to accept\ntransaction to Merchant\nof 100 USD,\n0 USD in fees. +PayerFSP ->> Switch: **GET /authorizations/**\n\n(amount=100 USD, fees=0 USD,\nretriesLeft=2, type=OTP) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **GET /authorizations/**\n\n(amount=100 USD, fees=0 USD,\nretriesLeft=2, type=OTP) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP ->> PayeePOS: Total amount is 100 USD,\nfee is 0 USD +PayeePOS ->> PayerOTC: Please enter your OTP\nto confirm Merchant Payment\nof 100 USD, fee is 0 USD +PayeePOS <<- PayerOTC: OTP not received +PayeeFSP <<- PayeePOS: OTP not received +Switch <<- PayeeFSP: **PUT /authorizations/**\n\n(resend OTP) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /authorizations/**\n\n(resend OTP) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Resend OTP (optionally\nregenerate) as customer\ndid not receive it +Payer <<- PayerFSP: Use OTP "12345" to accept\ntransaction to Merchant\nof 100 USD,\n0 USD in fees. +PayerFSP -> PayerFSP: Resend GET /authorizations\n(not shown here) +PayerFSP -[hidden]> Switch +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure50.svg b/docs/technical/api/assets/diagrams/sequence/figure50.svg new file mode 100644 index 000000000..70b657a1b --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure50.svg @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + Payer +   + + + +   + Payer + FSP + +   +   + Switch + +   + Payee + FSP + + Payee + (POS) + + + + Payer + (OTC) + + + + + + + + + + Transaction request and + quoting process (not shown) + + + + + Generate OTP, "12345", Payer FSP + sets maximum retries to 2 + + + + Use OTP "12345" to accept + transaction to Merchant + of 100 USD, + 0 USD in fees. + + + + GET /authorizations/ + <TransactionRequestID> + (amount=100 USD, fees=0 USD, + retriesLeft=2, type=OTP) + + + + HTTP 202 + (Accepted) + + + + GET /authorizations/ + <TransactionRequestID> + (amount=100 USD, fees=0 USD, + retriesLeft=2, type=OTP) + + + + HTTP 202 + (Accepted) + + + + Total amount is 100 USD, + fee is 0 USD + + + + Please enter your OTP + to confirm Merchant Payment + of 100 USD, fee is 0 USD + + + + OTP not received + + + + OTP not received + + + + PUT /authorizations/ + <TransactionRequestID> + (resend OTP) + + + + HTTP 200 + (OK) + + + + PUT /authorizations/ + <TransactionRequestID> + (resend OTP) + + + + HTTP 200 + (OK) + + + + + Resend OTP (optionally + regenerate) as customer + did not receive it + + + + Use OTP "12345" to accept + transaction to Merchant + of 100 USD, + 0 USD in fees. + + + + + Resend GET /authorizations + (not shown here) + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure51.plantuml b/docs/technical/api/assets/diagrams/sequence/figure51.plantuml new file mode 100644 index 000000000..505e8f947 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure51.plantuml @@ -0,0 +1,160 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Payer enters incorrect authorization value (OTP) + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payer/Payee(OTC/POS) + +' declare actors +actor "<$actor>\nPayer\n" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\n\nSwitch" as Switch +participant "\nPayee\nFSP" as PayeeFSP +actor "<$actor>\nPayee\n(POS)" as PayeePOS +actor "<$actor>\nPayer\n(OTC)" as PayerOTC + +' start flow +activate PayerFSP +PayerFSP -> PayerFSP: Transaction request and\nquoting process (not shown) +PayerFSP -> PayerFSP: Generate OTP, "12345", Payer FSP\nsets maximum retries to 2 +Payer <<- PayerFSP: Use OTP "12345" to accept\ntransaction to Merchant\nof 100 USD,\n0 USD in fees. +PayerFSP ->> Switch: **GET /authorizations/**\n\n(amount=100 USD, fees=0 USD,\nretriesLeft=2, type=OTP) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **GET /authorizations/**\n\n(amount=100 USD, fees=0 USD,\nretriesLeft=2, type=OTP) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP ->> PayeePOS: Total amount is 100 USD,\nfee is 0 USD +PayeePOS ->> PayerOTC: Please enter your OTP\nto confirm Merchant Payment\nof 100 USD, fee is 0 USD +PayeePOS <<- PayerOTC: Enters "12346" +PayeeFSP <<- PayeePOS: "12346" is the OTP +Switch <<- PayeeFSP: **PUT /authorizations/**\n\n(authenticationValue="12346") +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /authorizations/**\n\n(authenticationValue="12346") +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Validate OTP sent by Payee FSP,\nOTP incorrect, decrease retriesLeft +PayerFSP ->> Switch: **GET /authorizations/**\n\n(amount=100 USD, fees=0 USD,\nretriesLeft=1, type=OTP) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **GET /authorizations/**\n\n(amount=100 USD, fees=0 USD,\nretriesLeft=1, type=OTP) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP ->> PayeePOS: Incorrect OTP,\n1 retry left +PayeePOS ->> PayerOTC: Please enter your OTP to\nconfirm Merchant Payment of\n100 USD, fee is 0 USD, last retry +PayeePOS <<- PayerOTC: Enters "12345" +PayeeFSP <<- PayeePOS: "12345" is the OTP +Switch <<- PayeeFSP: **PUT /authorizations/**\n\n(otp="12345") +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /authorizations/**\n\n(otp="12345") +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Validates OTP sent by\nPayee FSP, OTP OK, perform\ntransfer (not shown here) +PayerFSP -[hidden]> Switch +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure51.svg b/docs/technical/api/assets/diagrams/sequence/figure51.svg new file mode 100644 index 000000000..7918e48dc --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure51.svg @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + Payer +   + + + +   + Payer + FSP + +   +   + Switch + +   + Payee + FSP + + Payee + (POS) + + + + Payer + (OTC) + + + + + + + + + + + + Transaction request and + quoting process (not shown) + + + + + Generate OTP, "12345", Payer FSP + sets maximum retries to 2 + + + + Use OTP "12345" to accept + transaction to Merchant + of 100 USD, + 0 USD in fees. + + + + GET /authorizations/ + <TransactionRequestID> + (amount=100 USD, fees=0 USD, + retriesLeft=2, type=OTP) + + + + HTTP 202 + (Accepted) + + + + GET /authorizations/ + <TransactionRequestID> + (amount=100 USD, fees=0 USD, + retriesLeft=2, type=OTP) + + + + HTTP 202 + (Accepted) + + + + Total amount is 100 USD, + fee is 0 USD + + + + Please enter your OTP + to confirm Merchant Payment + of 100 USD, fee is 0 USD + + + + Enters "12346" + + + + "12346" is the OTP + + + + PUT /authorizations/ + <TransactionRequestID> + (authenticationValue="12346") + + + + HTTP 200 + (OK) + + + + PUT /authorizations/ + <TransactionRequestID> + (authenticationValue="12346") + + + + HTTP 200 + (OK) + + + + + Validate OTP sent by Payee FSP, + OTP incorrect, decrease retriesLeft + + + + GET /authorizations/ + <TransactionRequestID> + (amount=100 USD, fees=0 USD, + retriesLeft=1, type=OTP) + + + + HTTP 202 + (Accepted) + + + + GET /authorizations/ + <TransactionRequestID> + (amount=100 USD, fees=0 USD, + retriesLeft=1, type=OTP) + + + + HTTP 202 + (Accepted) + + + + Incorrect OTP, + 1 retry left + + + + Please enter your OTP to + confirm Merchant Payment of + 100 USD, fee is 0 USD, last retry + + + + Enters "12345" + + + + "12345" is the OTP + + + + PUT /authorizations/ + <TransactionRequestID> + (otp="12345") + + + + HTTP 200 + (OK) + + + + PUT /authorizations/ + <TransactionRequestID> + (otp="12345") + + + + HTTP 200 + (OK) + + + + + Validates OTP sent by + Payee FSP, OTP OK, perform + transfer (not shown here) + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure52.plantuml b/docs/technical/api/assets/diagrams/sequence/figure52.plantuml new file mode 100644 index 000000000..a162cad3d --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure52.plantuml @@ -0,0 +1,155 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title How to use the POST /transfers service + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +Payer ->> PayerFSP: I would like to pay 100 USD\nto +123456789 +activate PayerFSP +PayerFSP -> PayerFSP: Lookup +123456789\n(process not shown here) +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Quote\n(process not shown here) +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Reserve transfer from Payer\naccount to Switch account +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP ->> Switch: **POST /transfers**\n(Transfer ID, conditions, ILP Packet\nincluding transaction details,\nexpiry=30 seconds) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve transfer from\nPayer FSP to Payee FSP +Switch ->> PayeeFSP: **POST /transfers**\n(Transfer ID, conditions, ILP Packet\nincluding transaction details,\nexpiry=30 seconds) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Perform transfer from Switch\naccount to Payee account,\ngenerate fulfilment +Switch <<- PayeeFSP: **PUT /transfers/**\n(Fulfilment) +PayeeFSP -> Payee: Transaction notification +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch -> Switch: Commit transfer from\nPayer FSP to Payee FSP +PayerFSP <<- Switch: **PUT /transfers/**\n(Fulfilment) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Commit transfer from Payer\naccount to Payee FSP account +Payer <- PayerFSP: Transaction notification +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure52.svg b/docs/technical/api/assets/diagrams/sequence/figure52.svg new file mode 100644 index 000000000..f66d00cc6 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure52.svg @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + Payee + + + + + + + + + + + + I would like to pay 100 USD + to +123456789 + + + + + Lookup +123456789 + (process not shown here) + + + + + Quote + (process not shown here) + + + + + Reserve transfer from Payer + account to Switch account + + + + POST /transfers + (Transfer ID, conditions, ILP Packet + including transaction details, + expiry=30 seconds) + + + + HTTP 202 + (Accepted) + + + + + Reserve transfer from + Payer FSP to Payee FSP + + + + POST /transfers + (Transfer ID, conditions, ILP Packet + including transaction details, + expiry=30 seconds) + + + + HTTP 202 + (Accepted) + + + + + Perform transfer from Switch + account to Payee account, + generate fulfilment + + + + PUT /transfers/ + <ID> + (Fulfilment) + + + Transaction notification + + + + HTTP 200 + (OK) + + + + + Commit transfer from + Payer FSP to Payee FSP + + + + PUT /transfers/ + <ID> + (Fulfilment) + + + + HTTP 200 + (OK) + + + + + Commit transfer from Payer + account to Payee FSP account + + + Transaction notification + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure53.plantuml b/docs/technical/api/assets/diagrams/sequence/figure53.plantuml new file mode 100644 index 000000000..4d9e48767 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure53.plantuml @@ -0,0 +1,156 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Optional additional clearing check + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +Payer ->> PayerFSP: I would like to pay 100 USD\nto +123456789 +activate PayerFSP +PayerFSP -> PayerFSP: Lookup +123456789\n(process not shown here) +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Quote (process\nnot shown here) +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Reserve transfer from Payer\naccount to Switch account +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP ->> Switch: **POST /transfers**\n(Transfer ID, condition, ILP Packet\nincluding transaction details,\nexpiry=30 seconds) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve transfer from\nPayer FSP to Payee FSP +Switch ->> PayeeFSP: **POST /transfers**\n(Transfer ID, condition, ILP Packet\nincluding transaction details,\nexpiry=20 seconds) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Perform transfer from\nSwitch account to\nPayee account +PayeeFSP -> Payee: Transaction notification +Switch -> Switch: Expiry time reached,\ncancel reservation +PayerFSP <<- Switch: **PUT /transfers/**/**error** +Switch <<- PayeeFSP: **PUT /transfers/**\n(Fulfilment) +PayerFSP -->> Switch: **HTTP 200** (OK) +Switch -->> PayeeFSP: **HTTP 200** (OK) +Switch -> Switch: Mark transfer for\nReconciliation as Payee\nFSP has completed and\nPayer FSP has cancelled +deactivate PayeeFSP +PayerFSP -> PayerFSP: Cancel transfer from Payer\naccount to Switch +deactivate Switch +Payer <- PayerFSP: Transaction failure notification +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure53.svg b/docs/technical/api/assets/diagrams/sequence/figure53.svg new file mode 100644 index 000000000..8eea5e412 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure53.svg @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + Payee + + + + + + + + + + + + I would like to pay 100 USD + to +123456789 + + + + + Lookup +123456789 + (process not shown here) + + + + + Quote (process + not shown here) + + + + + Reserve transfer from Payer + account to Switch account + + + + POST /transfers + (Transfer ID, condition, ILP Packet + including transaction details, + expiry=30 seconds) + + + + HTTP 202 + (Accepted) + + + + + Reserve transfer from + Payer FSP to Payee FSP + + + + POST /transfers + (Transfer ID, condition, ILP Packet + including transaction details, + expiry=20 seconds) + + + + HTTP 202 + (Accepted) + + + + + Perform transfer from + Switch account to + Payee account + + + Transaction notification + + + + + Expiry time reached, + cancel reservation + + + + PUT /transfers/ + <ID> + / + error + + + + PUT /transfers/ + <ID> + (Fulfilment) + + + + HTTP 200 + (OK) + + + + HTTP 200 + (OK) + + + + + Mark transfer for + Reconciliation as Payee + FSP has completed and + Payer FSP has cancelled + + + + + Cancel transfer from Payer + account to Switch + + + Transaction failure notification + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure54.plantuml b/docs/technical/api/assets/diagrams/sequence/figure54.plantuml new file mode 100644 index 000000000..608a813b0 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure54.plantuml @@ -0,0 +1,159 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Optional additional clearing check where commit in Switch failed + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +Payer ->> PayerFSP: I would like to pay 100 USD\nto +123456789 +activate PayerFSP +PayerFSP -> PayerFSP: Lookup +123456789\n(process not shown here) +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Quote (process\nnot shown here) +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Reserve transfer from Payer\naccount to Switch account +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP ->> Switch: **POST /transfers**\n(Transfer ID, condition, ILP Packet\nincluding transaction details,\nexpiry=30 seconds) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve transfer from\nPayer FSP to Payee FSP +Switch ->> PayeeFSP: **POST /transfers**\n(Transfer ID, condition, ILP Packet\nincluding transaction details,\nexpiry=20 seconds) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Reserve transfer from Switch\naccount to Payee account,\ngenerate fulfilment +PayeeFSP -> PayeeFSP: Request commit notification\nfrom Switch by sending transfer\nstate as reserved +Switch <<- PayeeFSP: **PUT /transfers/**\n(Fulfilment,\ntransferState=RESERVED) +Switch -->> PayeeFSP: **HTTP 200** (OK) +Switch -> Switch: Commit transfer from\nPayer FSP to Payee FSP,\nsend commit notification\nto Payee FSP +Switch ->> PayeeFSP: **PATCH /transfers/**\n(transferState=COMMITTED,\ncompletedTimestamp) +Switch <<-- PayeeFSP: **HTTP 200** (OK) +PayerFSP <<- Switch: **PUT /transfers/**\n(Fulfilment) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayeeFSP -> PayeeFSP: Commit reserved transfer\nfrom Switch to Payee +PayeeFSP -> Payee: Transaction notification +deactivate PayeeFSP +PayerFSP -> PayerFSP: Commit transfer from Payer\naccount to Payee FSP account +Payer <- PayerFSP: Transaction notification +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure54.svg b/docs/technical/api/assets/diagrams/sequence/figure54.svg new file mode 100644 index 000000000..3a80063b6 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure54.svg @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + Payee + + + + + + + + + + + + I would like to pay 100 USD + to +123456789 + + + + + Lookup +123456789 + (process not shown here) + + + + + Quote (process + not shown here) + + + + + Reserve transfer from Payer + account to Switch account + + + + POST /transfers + (Transfer ID, condition, ILP Packet + including transaction details, + expiry=30 seconds) + + + + HTTP 202 + (Accepted) + + + + + Reserve transfer from + Payer FSP to Payee FSP + + + + POST /transfers + (Transfer ID, condition, ILP Packet + including transaction details, + expiry=20 seconds) + + + + HTTP 202 + (Accepted) + + + + + Reserve transfer from Switch + account to Payee account, + generate fulfilment + + + + + Request commit notification + from Switch by sending transfer + state as reserved + + + + PUT /transfers/ + <ID> + (Fulfilment, + transferState=RESERVED) + + + + HTTP 200 + (OK) + + + + + Commit transfer from + Payer FSP to Payee FSP, + send commit notification + to Payee FSP + + + + PATCH /transfers/ + <ID> + (transferState=COMMITTED, + completedTimestamp) + + + + HTTP 200 + (OK) + + + + PUT /transfers/ + <ID> + (Fulfilment) + + + + HTTP 200 + (OK) + + + + + Commit reserved transfer + from Switch to Payee + + + Transaction notification + + + + + Commit transfer from Payer + account to Payee FSP account + + + Transaction notification + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure55.plantuml b/docs/technical/api/assets/diagrams/sequence/figure55.plantuml new file mode 100644 index 000000000..b0b15412e --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure55.plantuml @@ -0,0 +1,158 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Commit notification where commit of transfer in Switch failed + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee/Payer + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Switch" as Switch +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +Payer ->> PayerFSP: I would like to pay 100 USD\nto +123456789 +activate PayerFSP +PayerFSP -> PayerFSP: Lookup +123456789\n(process not shown here) +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Quote (process\nnot shown here) +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Reserve transfer from Payer\naccount to Switch account +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP ->> Switch: **POST /transfers**\n(Transfer ID, condition, ILP Packet\nincluding transaction details,\nexpiry=30 seconds) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve transfer from\nPayer FSP to Payee FSP +Switch ->> PayeeFSP: **POST /transfers**\n(Transfer ID, condition, ILP Packet\nincluding transaction details,\nexpiry=20 seconds) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Reserve transfer from Switch\naccount to Payee account,\ngenerate fulfilment +PayeeFSP -> PayeeFSP: Request commit notification\nfrom Switch by sending transfer\nstate as reserved +Switch <<- PayeeFSP: **PUT /transfers/**\n(Fulfilment,\ntransferState=RESERVED) +Switch -->> PayeeFSP: **HTTP 200** (OK) +Switch -> Switch: Commit transfer from\nPayer FSP to Payee FSP\nfailed, notify both FSPs +Switch ->> PayeeFSP: **PATCH /transfers/**\n(transferState=ABORTED,\ncompletedTimestamp) +Switch <<-- PayeeFSP: **HTTP 200** (OK) +PayeeFSP -> PayeeFSP: Rollback reserved transfer\nfrom Switch to Payee +PayerFSP <<- Switch: **PUT /transfers/**/**error** +deactivate PayeeFSP +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Rollback reserved transfer from\nPayer to Switch +Payer <- PayerFSP: Transaction notification +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure55.svg b/docs/technical/api/assets/diagrams/sequence/figure55.svg new file mode 100644 index 000000000..56263ad83 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure55.svg @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Switch + + Payee + FSP + + Payee + + + + + + + + + + + + I would like to pay 100 USD + to +123456789 + + + + + Lookup +123456789 + (process not shown here) + + + + + Quote (process + not shown here) + + + + + Reserve transfer from Payer + account to Switch account + + + + POST /transfers + (Transfer ID, condition, ILP Packet + including transaction details, + expiry=30 seconds) + + + + HTTP 202 + (Accepted) + + + + + Reserve transfer from + Payer FSP to Payee FSP + + + + POST /transfers + (Transfer ID, condition, ILP Packet + including transaction details, + expiry=20 seconds) + + + + HTTP 202 + (Accepted) + + + + + Reserve transfer from Switch + account to Payee account, + generate fulfilment + + + + + Request commit notification + from Switch by sending transfer + state as reserved + + + + PUT /transfers/ + <ID> + (Fulfilment, + transferState=RESERVED) + + + + HTTP 200 + (OK) + + + + + Commit transfer from + Payer FSP to Payee FSP + failed, notify both FSPs + + + + PATCH /transfers/ + <ID> + (transferState=ABORTED, + completedTimestamp) + + + + HTTP 200 + (OK) + + + + + Rollback reserved transfer + from Switch to Payee + + + + PUT /transfers/ + <ID> + / + error + + + + HTTP 200 + (OK) + + + + + Rollback reserved transfer from + Payer to Switch + + + Transaction notification + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure57.plantuml b/docs/technical/api/assets/diagrams/sequence/figure57.plantuml new file mode 100644 index 000000000..615c2acec --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure57.plantuml @@ -0,0 +1,138 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Example transaction process + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payer + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP + +' start flow +Payer -> PayerFSP: I would like to pay 100 USD\nto +123456789 +activate PayerFSP +PayerFSP -> PayerFSP: Lookup +123456789\n(process not shown here) +PayerFSP -> PayerFSP: Perform quote\n(process not shown here) +PayerFSP -> PayerFSP: Perform transfer\n(process not shown here) +PayerFSP ->> Switch: **GET /transactions/** +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **GET /transactions/** +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Lookup transaction\ninformation +Switch <<- PayeeFSP: **PUT /transactions/**\n(Transaction detail) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /transactions/**\n(Transaction detail) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +Payer <- PayerFSP: Transaction notification\nincluding transaction\ndata(e.g. token ID) +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure57.svg b/docs/technical/api/assets/diagrams/sequence/figure57.svg new file mode 100644 index 000000000..98acfada5 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure57.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + + + + + I would like to pay 100 USD + to +123456789 + + + + + Lookup +123456789 + (process not shown here) + + + + + Perform quote + (process not shown here) + + + + + Perform transfer + (process not shown here) + + + + GET /transactions/ + <TransactionID> + + + + HTTP 202 + (Accepted) + + + + GET /transactions/ + <TransactionID> + + + + HTTP 202 + (Accepted) + + + + + Lookup transaction + information + + + + PUT /transactions/ + <TransactionID> + (Transaction detail) + + + + HTTP 200 + (OK) + + + + PUT /transactions/ + <TransactionID> + (Transaction detail) + + + + HTTP 200 + (OK) + + + Transaction notification + including transaction + data(e.g. token ID) + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure59.plantuml b/docs/technical/api/assets/diagrams/sequence/figure59.plantuml new file mode 100644 index 000000000..f90967b30 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure59.plantuml @@ -0,0 +1,147 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Example bulk quote process + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payer + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP(s)" as PayeeFSP + +' start flow +Payer -> PayerFSP: I would like to upload\na file of bulk transactions +activate PayerFSP +PayerFSP -> PayerFSP: Lookup in which FSP each\nPayee is located in, divide\nPayees into FSP separate files\n(process not shown here) +Loop #OldLace + hnote left of PayerFSP #OldLace + For each + created bulk + file per + Payee FSP + end hnote + PayerFSP -> PayerFSP: Rate Payer FSP bulk quote\n(process not shown here) + PayerFSP ->> Switch: **POST /bulkQuotes**\n(Bulk info and list of individual quotes) + activate Switch + PayerFSP <<-- Switch: **HTTP 202** (Accepted) + Switch ->> PayeeFSP: **POST /bulkQuotes**\n(Bulk info and list of individual quotes) + activate PayeeFSP + Switch <<-- PayeeFSP: **HTTP 202** (Accepted) + PayeeFSP -> PayeeFSP: Rate Payee FSP\nfee/commission and\ngenerate condition per\nindividual transfer + Switch <<- PayeeFSP: **PUT /bulkQuotes/**\n(List of individual quote results\nand condition per transfer) + Switch -->> PayeeFSP: **HTTP 200** (OK) + deactivate PayeeFSP + PayerFSP <<- Switch: **PUT /bulkQuotes/**\n(List of individual quote results\nand condition per transfer) + PayerFSP -->> Switch: **HTTP 200** (OK) + deactivate Switch + PayerFSP -> PayerFSP: Rate payer FSP bulk quote\n(depending on fee model) +end Loop +PayerFSP -> PayerFSP: Handle quote results for\nall Payee FSPs +PayerFSP -[hidden]> Switch +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure59.svg b/docs/technical/api/assets/diagrams/sequence/figure59.svg new file mode 100644 index 000000000..558bc47e8 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure59.svg @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Payee + FSP(s) + + + + + + I would like to upload + a file of bulk transactions + + + + + Lookup in which FSP each + Payee is located in, divide + Payees into FSP separate files + (process not shown here) + + + loop + + For each + created bulk + file per + Payee FSP + + + + + Rate Payer FSP bulk quote + (process not shown here) + + + + POST /bulkQuotes + (Bulk info and list of individual quotes) + + + + HTTP 202 + (Accepted) + + + + POST /bulkQuotes + (Bulk info and list of individual quotes) + + + + HTTP 202 + (Accepted) + + + + + Rate Payee FSP + fee/commission and + generate condition per + individual transfer + + + + PUT /bulkQuotes/ + <ID> + (List of individual quote results + and condition per transfer) + + + + HTTP 200 + (OK) + + + + PUT /bulkQuotes/ + <ID> + (List of individual quote results + and condition per transfer) + + + + HTTP 200 + (OK) + + + + + Rate payer FSP bulk quote + (depending on fee model) + + + + + Handle quote results for + all Payee FSPs + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure6.plantuml b/docs/technical/api/assets/diagrams/sequence/figure6.plantuml new file mode 100644 index 000000000..7f28f23c9 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure6.plantuml @@ -0,0 +1,77 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +' declare title +' title Example scenario where FSPIOP-Destination is unknown by FSP + +' Actor Keys: +' participant - FSP, Peer FSP, Optional Switch and Account Lookup + +' declare actors +participant "\nFSP" as FSP +participant "Optional\nSwitch" as Switch +participant "Account\nLookup" as ALS +participant "Peer\nFSP" as PEERFSP + +' start flow +FSP ->> Switch: **GET /parties/msisdn/123456789**\n(**FSPIOP-Source=**FSP) +activate FSP +activate Switch +FSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> ALS: **GET /participants/msisdn/123456789**\n(**FSPIOP-Source=**Switch,\n**FSPIOP-Destination=**Account Lookup) +activate ALS +Switch <<-- ALS: **HTTP 202** (Accepted) +ALS -> ALS: Replace **FSPIOP-Source**\nwith **FSPIOP-Destination**\nand vice versa for\nrouting of callback +Switch <<- ALS: **PUT /participants/msisdn/123456789**\n(**FSPIOP-Source=**Account Lookup,\n**FSPIOP-Destination=**Switch) +Switch -->> ALS: **HTTP 200** (OK) +deactivate ALS +Switch -> Switch: Set **FSPIOP-Destination**\nin original messages according\nto results of **PUT /participants** +Switch ->> PEERFSP: **GET /parties/msisdn/123456789**\n(**FSPIOP-Source=**FSP, **FSPIOP-Destination=**Peer FSP) +activate PEERFSP +Switch <<-- PEERFSP: **HTTP 202** (Accepted) +PEERFSP -> PEERFSP: Optionally validate message\nsignature using stored certificate\nfor FSP in **FSPIOP-Source** +PEERFSP -> PEERFSP: Replace **FSPIOP-Source**\nwith **FSPIOP-Destination** and\nvice versa for routing of callback +Switch <<- PEERFSP: **PUT /parties/msisdn/123456789**\n(**FSPIOP-Source=**Peer FSP, **FSPIOP-Destination=**FSP) +Switch -->> PEERFSP: **HTTP 200** (OK) +deactivate PEERFSP +Switch -> Switch: Route messages according\nto **FSPIOP-Destination** +FSP <<- Switch: **PUT /parties/msisdn/123456789**\n(**FSPIOP-Source=**Peer FSP,\n**FSPIOP-Destination=**FSP) +FSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +deactivate FSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure6.svg b/docs/technical/api/assets/diagrams/sequence/figure6.svg new file mode 100644 index 000000000..c61416d66 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure6.svg @@ -0,0 +1,155 @@ + + + + + + + + + + + + +   + FSP + + Optional + Switch + + Account + Lookup + + Peer + FSP + + + + + + + + GET /parties/msisdn/123456789 + ( + FSPIOP-Source= + FSP) + + + + HTTP 202 + (Accepted) + + + + GET /participants/msisdn/123456789 + ( + FSPIOP-Source= + Switch, + FSPIOP-Destination= + Account Lookup) + + + + HTTP 202 + (Accepted) + + + + + Replace + FSPIOP-Source + with + FSPIOP-Destination + and vice versa for + routing of callback + + + + PUT /participants/msisdn/123456789 + ( + FSPIOP-Source= + Account Lookup, + FSPIOP-Destination= + Switch) + + + + HTTP 200 + (OK) + + + + + Set + FSPIOP-Destination + in original messages according + to results of + PUT /participants + + + + GET /parties/msisdn/123456789 + ( + FSPIOP-Source= + FSP, + FSPIOP-Destination= + Peer FSP) + + + + HTTP 202 + (Accepted) + + + + + Optionally validate message + signature using stored certificate + for FSP in + FSPIOP-Source + + + + + Replace + FSPIOP-Source + with + FSPIOP-Destination + and + vice versa for routing of callback + + + + PUT /parties/msisdn/123456789 + ( + FSPIOP-Source= + Peer FSP, + FSPIOP-Destination= + FSP) + + + + HTTP 200 + (OK) + + + + + Route messages according + to + FSPIOP-Destination + + + + PUT /parties/msisdn/123456789 + ( + FSPIOP-Source= + Peer FSP, + FSPIOP-Destination= + FSP) + + + + HTTP 200 + (OK) + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure61.plantuml b/docs/technical/api/assets/diagrams/sequence/figure61.plantuml new file mode 100644 index 000000000..5f0ab8b64 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure61.plantuml @@ -0,0 +1,153 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Example bulk transfer process + +' Actor Keys: +' participant - FSP(Payer/Payee(s)) and Switch +' actor - Payer/Payee(s) + +' declare actors +actor "<$actor>\nPayer\n" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP(s)" as PayeeFSP +actor "<$actor>\nPayees\n(multiple)" as Payee + +' start flow +Payer -> PayerFSP: I would like to upload\na file of bulk transactions +activate PayerFSP +PayerFSP -> PayerFSP: Lookup in which FSP each\nPayee is located in, divide\nPayees into FSP separate files\n(process not shown here) +PayerFSP -> PayerFSP: Perform bulk quoting per\nPayee FSP\n(process not shown here) +Payer <- PayerFSP: Bulk has finished processing,\npresent fees +Payer -> PayerFSP: Execute my bulk +Loop #OldLace + hnote left of PayerFSP #OldLace + For each + created bulk + file per + Payee FSP + end hnote + PayerFSP -> PayerFSP: Reserve each individual\ntransfer from Payer\naccount to Payee FSP account + PayerFSP ->> Switch: **POST /bulkTransfers**\n(List of individual transfers\nincluding ILP packet and condition) + activate Switch + PayerFSP <<-- Switch: **HTTP 202** (Accepted) + Switch -> Switch: Reserve each individual\ntransfer from Payer FSP\nto Payee FSP + Switch ->> PayeeFSP: **POST /bulkTransfers**\n(List of individual transfers\nincluding ILP packet and condition) + activate PayeeFSP + Switch <<-- PayeeFSP: **HTTP 202** (Accepted) + PayeeFSP -> PayeeFSP: Perform each transfer from \nPayer FSP account to Payee \naccount, generate fulfilments + PayeeFSP -> Payee: Transaction notification\nfor each Payee + Switch <<- PayeeFSP: **PUT /bulkTransfers/**\n(List of fulfilments) + Switch -->> PayeeFSP: **HTTP 200** (OK) + deactivate PayeeFSP + Switch -> Switch: Commit each successful\ntransfer from Payer\nFSP to Payee FSP + PayerFSP <<- Switch: **PUT /bulkTransfers/**\n(List of fulfilments) + PayerFSP -->> Switch: **HTTP 200** (OK) + deactivate Switch + PayerFSP -> PayerFSP: Commit each successful\ntransfer from Payer account\nto Payee account +end Loop +Payer <- PayerFSP: Your bulk has been executed +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure61.svg b/docs/technical/api/assets/diagrams/sequence/figure61.svg new file mode 100644 index 000000000..31fb7c70d --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure61.svg @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + Payer +   + + + + Payer + FSP + + Optional + Switch + + Payee + FSP(s) + + Payees + (multiple) + + + + + + + + I would like to upload + a file of bulk transactions + + + + + Lookup in which FSP each + Payee is located in, divide + Payees into FSP separate files + (process not shown here) + + + + + Perform bulk quoting per + Payee FSP + (process not shown here) + + + Bulk has finished processing, + present fees + + + Execute my bulk + + + loop + + For each + created bulk + file per + Payee FSP + + + + + Reserve each individual + transfer from Payer + account to Payee FSP account + + + + POST /bulkTransfers + (List of individual transfers + including ILP packet and condition) + + + + HTTP 202 + (Accepted) + + + + + Reserve each individual + transfer from Payer FSP + to Payee FSP + + + + POST /bulkTransfers + (List of individual transfers + including ILP packet and condition) + + + + HTTP 202 + (Accepted) + + + + + Perform each transfer from + Payer FSP account to Payee + account, generate fulfilments + + + Transaction notification + for each Payee + + + + PUT /bulkTransfers/ + <ID> + (List of fulfilments) + + + + HTTP 200 + (OK) + + + + + Commit each successful + transfer from Payer + FSP to Payee FSP + + + + PUT /bulkTransfers/ + <ID> + (List of fulfilments) + + + + HTTP 200 + (OK) + + + + + Commit each successful + transfer from Payer account + to Payee account + + + Your bulk has been executed + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure64.plantuml b/docs/technical/api/assets/diagrams/sequence/figure64.plantuml new file mode 100644 index 000000000..589e9e159 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure64.plantuml @@ -0,0 +1,258 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Payer Initiated Transaction pattern using the asynchronous REST binding + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payer/Payee(s) + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Account\nLookup" as ALS +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +autonumber 1 1 "[0]" +Payer -> PayerFSP: I would like to\npay 100 USD\nto +123456789 +activate PayerFSP +autonumber stop +PayerFSP -> PayerFSP: Payee not within\nPayer FSP system +autonumber resume +PayerFSP ->> Switch: **GET /parties/MSISDN/123456789** +activate Switch +autonumber stop +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +autonumber resume +Switch ->> ALS: **GET /participants/MSISDN/123456789** +activate ALS +autonumber stop +Switch <<-- ALS: **HTTP 202** (Accepted) +ALS -> ALS: Lookup which\nFSP MSISDN\n+123456789\nbelongs to +autonumber resume +Switch <<- ALS: **PUT /participants/MSISDN/123456789**\n(FSP ID) +autonumber stop +Switch -->> ALS: **HTTP 200** (OK) +deactivate ALS +autonumber resume +Switch ->> PayeeFSP: **GET /parties/MSISDN/123456789** +activate PayeeFSP +autonumber stop +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Lookup party\ninformation\nRegarding\nMSISDN\n+123456789 +autonumber resume +Switch <<- PayeeFSP: **Put /parties/MSISDN/123456789**\n(Party information) +autonumber stop +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +autonumber resume +PayerFSP <<- Switch: **PUT /parties/MSISDN/123456789**\n(Party information) +autonumber stop +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +deactivate PayerFSP +autonumber resume +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on fee model) +PayerFSP ->> Switch: **POST /quotes**\n(Transaction details) +activate Switch +autonumber stop +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +autonumber resume +Switch ->> PayeeFSP: **POST /quote**\n(Transaction details) +activate PayeeFSP +autonumber stop +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +autonumber resume +PayeeFSP -> PayeeFSP: Rate Payee FSP\nfee/commission,\ngenerate condition +group #OldLace Optional + hnote left of PayeeFSP #OldLace + Confirm quote + end hnote + PayeeFSP -> Payee: Here is the\nquote and\nPayer name + autonumber stop + PayeeFSP <- Payee: I confirm +end +autonumber resume +Switch <<- PayeeFSP: **PUT /quote/**\n(Payee FSP fee/commission,\ncondition) +autonumber stop +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +autonumber resume +PayerFSP <<- Switch: **PUT /quotes/**\n(Payee FSP fee/commission,\ncondition) +autonumber stop +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +autonumber resume +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on fee model) +autonumber stop +Payer <- PayerFSP: Present fees and\noptionally payee name +deactivate PayerFSP +autonumber resume +Payer -> PayerFSP: I approve the\ntransaction +activate PayerFSP +autonumber stop +PayerFSP -> PayerFSP: Reserve transfer from Payer\naccount to Switch account +autonumber resume +PayerFSP -> Switch: **POST /transfers**\n(Transfer ID, condition, ILP packet\nincluding transaction ID) +autonumber stop +activate Switch +PayerFSP <-- Switch: **HTTL 202** (Accepted) +autonumber resume +Switch -> Switch: Reserve transfer from\nPayer FSP to Payee FSP +autonumber stop +Switch ->> PayeeFSP: **POST /transfers**\n(Transfer ID, condition, ILP packet\nincluding transaction ID) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +autonumber resume +PayeeFSP -> PayeeFSP: Perform transfer\nfrom Switch\naccount to Payee\naccount, generate\nfulfilment +autonumber stop +PayeeFSP -> Payee: Transaction notification +autonumber resume +Switch <<- PayeeFSP: **PUT /transfers/**\n(Fulfilment) +autonumber stop +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +autonumber resume +Switch -> Switch: Commit transfer from\nPayer FSP to Payee FSP +autonumber stop +PayerFSP <<- Switch: **PUT /transfers/**\n(Fulfilment) +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +autonumber resume +PayerFSP -> PayerFSP: Commit transfer from Payer\naccount to Switch account +group #OldLace Optional + hnote left of PayerFSP #OldLace + Get transaction data + end hnote + PayerFSP ->> Switch: **GET /transactions/** + activate Switch + autonumber stop + PayerFSP <<-- Switch: **HTTP 202** (Accepted) + autonumber resume + Switch <<- PayeeFSP: **GET /transactions/** + activate PayeeFSP + autonumber stop + Switch -->> PayeeFSP: **HTTP 202** (Accepted) + autonumber resume + PayeeFSP -> PayeeFSP: Lookup\ntransaction\ninformation + Switch <<- PayeeFSP: **PUT /transactions/**\n(Transaction details) + autonumber stop + Switch -->> PayeeFSP: **HTTP 200** (OK) + deactivate PayeeFSP + autonumber resume + PayerFSP <<- Switch: **PUT /transactions/**\n(Transaction details) + autonumber stop + PayerFSP -->> Switch: **HTTP 200** (OK) + deactivate Switch +end +autonumber resume +Payer <- PayerFSP: Transaction notification\nincluding optional\ntransaction data\n(e.g. token ID) +deactivate PayerFSP +autonumber stop +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure64.svg b/docs/technical/api/assets/diagrams/sequence/figure64.svg new file mode 100644 index 000000000..a5fe0d64d --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure64.svg @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Account + Lookup + + Payee + FSP + + Payee + + + + + + + + + + + + + + + + + [1] + I would like to + pay 100 USD + to +123456789 + + + + + Payee not within + Payer FSP system + + + + [2] + GET /parties/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + [3] + GET /participants/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + + Lookup which + FSP MSISDN + +123456789 + belongs to + + + + [4] + PUT /participants/MSISDN/123456789 + (FSP ID) + + + + HTTP 200 + (OK) + + + + [5] + GET /parties/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + + Lookup party + information + Regarding + MSISDN + +123456789 + + + + [6] + Put /parties/MSISDN/123456789 + (Party information) + + + + HTTP 200 + (OK) + + + + [7] + PUT /parties/MSISDN/123456789 + (Party information) + + + + HTTP 200 + (OK) + + + + + [9] + Rate Payer FSP quote + (depending on fee model) + + + + [10] + POST /quotes + (Transaction details) + + + + HTTP 202 + (Accepted) + + + + [11] + POST /quote + (Transaction details) + + + + HTTP 202 + (Accepted) + + + + + [12] + Rate Payee FSP + fee/commission, + generate condition + + + Optional + + Confirm quote + + + [13] + Here is the + quote and + Payer name + + + I confirm + + + + [14] + PUT /quote/ + <ID> + (Payee FSP fee/commission, + condition) + + + + HTTP 200 + (OK) + + + + [15] + PUT /quotes/ + <ID> + (Payee FSP fee/commission, + condition) + + + + HTTP 200 + (OK) + + + + + [16] + Rate Payer FSP quote + (depending on fee model) + + + Present fees and + optionally payee name + + + [17] + I approve the + transaction + + + + + Reserve transfer from Payer + account to Switch account + + + [18] + POST /transfers + (Transfer ID, condition, ILP packet + including transaction ID) + + + HTTL 202 + (Accepted) + + + + + [19] + Reserve transfer from + Payer FSP to Payee FSP + + + + POST /transfers + (Transfer ID, condition, ILP packet + including transaction ID) + + + + HTTP 202 + (Accepted) + + + + + [20] + Perform transfer + from Switch + account to Payee + account, generate + fulfilment + + + Transaction notification + + + + [21] + PUT /transfers/ + <ID> + (Fulfilment) + + + + HTTP 200 + (OK) + + + + + [22] + Commit transfer from + Payer FSP to Payee FSP + + + + PUT /transfers/ + <ID> + (Fulfilment) + + + + HTTP 200 + (OK) + + + + + [23] + Commit transfer from Payer + account to Switch account + + + Optional + + Get transaction data + + + + [24] + GET /transactions/ + <TransactionID> + + + + HTTP 202 + (Accepted) + + + + [25] + GET /transactions/ + <TransactionID> + + + + HTTP 202 + (Accepted) + + + + + [26] + Lookup + transaction + information + + + + [27] + PUT /transactions/ + <TransactionID> + (Transaction details) + + + + HTTP 200 + (OK) + + + + [28] + PUT /transactions/ + <TransactionID> + (Transaction details) + + + + HTTP 200 + (OK) + + + [29] + Transaction notification + including optional + transaction data + (e.g. token ID) + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure64a.plantuml b/docs/technical/api/assets/diagrams/sequence/figure64a.plantuml new file mode 100644 index 000000000..673e1daca --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure64a.plantuml @@ -0,0 +1,212 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Payer-Initiated Transaction + +' Actor Keys: +' participant - FSP(Payer/Payee), Switch and Account Lookup +' actor - Payer/Payee(s) + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Account\nLookup" as ALS +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +autonumber 1 1 "[0]" +Payer -> PayerFSP: I would like to\npay 100 USD\nto +123456789 +activate PayerFSP +PayerFSP -> PayerFSP: Payee not within\nPayer FSP system +autonumber stop +PayerFSP ->> Switch: **Lookup Party Information**\n(MSISDN 123456789) +activate Switch +autonumber resume +Switch ->> ALS: **Lookup Participant Information**\n(MSISDN 123456789) +activate ALS +ALS -> ALS: Lookup which\nFSP MSISDN\n+123456789\nbelongs to +autonumber stop +Switch <<- ALS: **Return Participant Information**\n(FSP ID) +deactivate ALS +autonumber resume +Switch ->> PayeeFSP: **Lookup Party Information**\n(MSISDN 123456789) +activate PayeeFSP +PayeeFSP -> PayeeFSP: Lookup party\ninformation\nregarding\nMSISDN\n+123456789 +autonumber stop +Switch <<- PayeeFSP: **Return Party Information**\n(Party Information) +deactivate PayeeFSP +autonumber resume +PayerFSP <<- Switch: **Return Party Information**\n(Party Information) +deactivate Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on fee model) +PayerFSP ->> Switch: **Calculate Quote**\n(Transaction details) +activate Switch +Switch ->> PayeeFSP: **Calculate Quote**\n(Transaction details) +activate PayeeFSP +PayeeFSP -> PayeeFSP: Rate Payee FSP\nfee/commission,\ngenerate condition +group #OldLace Optional + hnote left of PayeeFSP #OldLace + Confirm quote + end hnote + PayeeFSP -> Payee: Here is the\nquote and\nPayer name + autonumber stop + PayeeFSP <- Payee: I confirm +end +autonumber resume +Switch <<- PayeeFSP: **Return Quote Information**\n(Payee FSP fee/commission,\ncondition) +deactivate PayeeFSP +PayerFSP <<- Switch: **Return Quote Information**\n(Payee FSP fee/commission,\ncondition) +deactivate Switch +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on fee model) +autonumber stop +Payer <- PayerFSP: Present fees and\noptionally payee name +deactivate PayerFSP +autonumber resume +Payer -> PayerFSP: I approve the\ntransaction +activate PayerFSP +autonumber stop +PayerFSP -> PayerFSP: Reserve transfer from Payer\naccount to Switch account +autonumber resume +PayerFSP -> Switch: **Preform Transfers**\n(Transfer ID, condition, ILP packet\nincluding transaction ID) +activate Switch +Switch -> Switch: Reserve transfer from\nPayer FSP to Payee FSP +autonumber stop +Switch ->> PayeeFSP: **Perform Transfer**\n(Transfer ID, condition, ILP packet\nincluding transaction ID) +activate PayeeFSP +autonumber resume +PayeeFSP -> PayeeFSP: Perform transfer\nfrom Switch\naccount to Payee\naccount, generate\nfulfilment +PayeeFSP -> Payee: Transaction notification +autonumber stop +Switch <<- PayeeFSP: **Return Transfer Information**\n(Fulfilment) +deactivate PayeeFSP +autonumber resume +Switch -> Switch: Commit transfer from\nPayer FSP to Payee FSP +autonumber stop +PayerFSP <<- Switch: **Return Transfer Information**\n(Fulfilment) +deactivate Switch +autonumber resume +PayerFSP -> PayerFSP: Commit transfer from Payer\naccount to Switch account +group #OldLace Optional + hnote left of PayerFSP #OldLace + Get transaction data + end hnote + PayerFSP ->> Switch: **Retrieve Transaction Information**\n(Transaction ID) + activate Switch + Switch <<- PayeeFSP: **Retrieve Transaction Information**\n(Transaction ID) + activate PayeeFSP + PayeeFSP -> PayeeFSP: Lookup\ntransaction\ninformation + Switch <<- PayeeFSP: **Return Transaction Information**\n(Transaction details) + deactivate PayeeFSP + PayerFSP <<- Switch: **Return Transaction Information**\n(Transaction details) + deactivate Switch +end +Payer <- PayerFSP: Transaction notification\nincluding optional\ntransaction data\n(e.g. token ID) +deactivate PayerFSP +autonumber stop +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure64a.svg b/docs/technical/api/assets/diagrams/sequence/figure64a.svg new file mode 100644 index 000000000..44df91386 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure64a.svg @@ -0,0 +1,307 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Account + Lookup + + Payee + FSP + + Payee + + + + + + + + + + + + + + + + + [1] + I would like to + pay 100 USD + to +123456789 + + + + + [2] + Payee not within + Payer FSP system + + + + Lookup Party Information + (MSISDN 123456789) + + + + [3] + Lookup Participant Information + (MSISDN 123456789) + + + + + [4] + Lookup which + FSP MSISDN + +123456789 + belongs to + + + + Return Participant Information + (FSP ID) + + + + [5] + Lookup Party Information + (MSISDN 123456789) + + + + + [6] + Lookup party + information + regarding + MSISDN + +123456789 + + + + Return Party Information + (Party Information) + + + + [7] + Return Party Information + (Party Information) + + + + + [9] + Rate Payer FSP quote + (depending on fee model) + + + + [10] + Calculate Quote + (Transaction details) + + + + [11] + Calculate Quote + (Transaction details) + + + + + [12] + Rate Payee FSP + fee/commission, + generate condition + + + Optional + + Confirm quote + + + [13] + Here is the + quote and + Payer name + + + I confirm + + + + [14] + Return Quote Information + (Payee FSP fee/commission, + condition) + + + + [15] + Return Quote Information + (Payee FSP fee/commission, + condition) + + + + + [16] + Rate Payer FSP quote + (depending on fee model) + + + Present fees and + optionally payee name + + + [17] + I approve the + transaction + + + + + Reserve transfer from Payer + account to Switch account + + + [18] + Preform Transfers + (Transfer ID, condition, ILP packet + including transaction ID) + + + + + [19] + Reserve transfer from + Payer FSP to Payee FSP + + + + Perform Transfer + (Transfer ID, condition, ILP packet + including transaction ID) + + + + + [20] + Perform transfer + from Switch + account to Payee + account, generate + fulfilment + + + [21] + Transaction notification + + + + Return Transfer Information + (Fulfilment) + + + + + [22] + Commit transfer from + Payer FSP to Payee FSP + + + + Return Transfer Information + (Fulfilment) + + + + + [23] + Commit transfer from Payer + account to Switch account + + + Optional + + Get transaction data + + + + [24] + Retrieve Transaction Information + (Transaction ID) + + + + [25] + Retrieve Transaction Information + (Transaction ID) + + + + + [26] + Lookup + transaction + information + + + + [27] + Return Transaction Information + (Transaction details) + + + + [28] + Return Transaction Information + (Transaction details) + + + [29] + Transaction notification + including optional + transaction data + (e.g. token ID) + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure65.plantuml b/docs/technical/api/assets/diagrams/sequence/figure65.plantuml new file mode 100644 index 000000000..369c7624a --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure65.plantuml @@ -0,0 +1,283 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Payee Initiated Transaction pattern using the asynchronous REST binding + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payer/Payee(s) + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Account\nLookup" as ALS +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +autonumber 1 1 "[0]" +PayeeFSP <- Payee: I would like\nto receive\n100 USD from\n+123456789 +activate PayeeFSP +PayeeFSP <- PayeeFSP: Payer not\nwithin Payee\nFSP system +autonumber stop +ALS <<- PayeeFSP: **GET /participants/MSISDN/123456789** +activate ALS +ALS -->> PayeeFSP: **HTTP 202** (Accepted) +autonumber resume +ALS -> ALS: Lookup which FSP MSISDN\n+123456789 belongs to +ALS ->> PayeeFSP: **PUT /participants/MSISDN/123456789**\n(FSP ID) +autonumber stop +ALS <<-- PayeeFSP: **HTTP 200** (OK) +deactivate ALS +deactivate PayeeFSP +autonumber resume +Switch <<- PayeeFSP: **Post /transactionRequests**\n(Payee information, transaction details) +activate PayeeFSP +activate Switch +autonumber stop +Switch -->> PayeeFSP: **HTTP 202** (Accepted) +autonumber resume +PayerFSP <<- Switch: **POST /transactionRequests**\n(Payee information,\ntransaction details) +activate PayerFSP +autonumber stop +PayerFSP -->> Switch: **HTTP 202** (Accepted) +deactivate Switch +autonumber resume +PayerFSP -> PayerFSP: Perform optional validation +PayerFSP ->> Switch: **PUT /transactionRequests/**\n(Received status) +autonumber stop +activate Switch +PayerFSP <<-- Switch: **HTTP 200** (OK) +deactivate PayerFSP +autonumber resume +Switch ->> PayeeFSP: **PUT /transactionRequests/**\n(Received status) +autonumber stop +Switch <<-- PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +deactivate Switch +autonumber resume +activate PayerFSP +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on fee model) +PayerFSP ->> Switch: **POST /quotes**\n(Transaction details) +activate Switch +autonumber stop +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +autonumber resume +Switch ->> PayeeFSP: **POST /quotes**\n(Transaction details) +activate PayeeFSP +autonumber stop +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Rate Payee FSP\nfees/commission,\ngenerate condition +group #OldLace Optional + hnote left of PayeeFSP #OldLace + Confirm quote + end hnote + autonumber resume + PayeeFSP -> Payee: Here is the\nquote and\nPayer name + autonumber stop + PayeeFSP <- Payee: I confirm +end +autonumber resume +Switch <<- PayeeFSP: **PUT /quotes/**\n(Payee FSP fee/commission,condition) +autonumber stop +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +autonumber resume +PayerFSP <<- Switch: **PUT /quotes/**\n(Payee FSP\nfee/commission,condition) +autonumber stop +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +autonumber resume +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on the fee model) +Payer <- PayerFSP: Will you approve the\ntransaction request\nfor 100 USD\n(plus fees)\nto Payee? +deactivate PayerFSP +Alt #OldLace Alternatives + hnote over of Payer #OldLace + User rejects + transaction request + end hnote + autonumber resume + Payer -> PayerFSP: I reject the\ntransaction request + activate PayerFSP + PayerFSP ->> Switch: **PUT /transactionRequests/**\n(Rejected state) + activate Switch + autonumber stop + PayerFSP <<-- Switch: **HTTP 200** (OK) + deactivate PayerFSP + autonumber resume + Switch ->> PayeeFSP: **PUT /transactionRequests/**\n(Rejected state) + activate PayeeFSP + autonumber stop + Switch <<-- PayeeFSP: **HTTP 200** (OK) + deactivate Switch + autonumber resume + PayeeFSP -> Payee: Transaction failed\ndue to user\nrejection + deactivate PayeeFSP + autonumber stop +else + hnote over of Payer #OldLace + User approves + transaction request + end hnote + Payer -> PayerFSP: I approve the\ntransaction request + activate PayerFSP + autonumber resume + PayerFSP -> PayerFSP: Reserve transfer from Payer\naccount to Switch account + autonumber stop + PayerFSP ->> Switch: **POST /transfers**\n(Transfer ID, condition, ILP packet\nincluding transaction ID) + activate Switch + PayerFSP <<-- Switch: **HTTP 202** (Accepted) + autonumber resume + Switch -> Switch: Reserve transfer\nfrom Payer\nFSP to Payee FSP + autonumber stop + Switch ->> PayeeFSP: **POST /transfers**\n(Transfer ID, condition, ILP packet\nincluding transaction ID) + activate PayeeFSP + Switch <<-- PayeeFSP: **HTTP 202** (Accepted) + autonumber resume + PayeeFSP -> PayeeFSP: Perform transfer\nfrom Switch account\nto Payee account,\ngenerate fulfilment + PayeeFSP -> Payee: Transaction\nnotification + autonumber stop + Switch <<- PayeeFSP: **PUT /transfers/**\n(Fulfilment) + Switch -->> PayeeFSP: **HTTP 200** (OK) + deactivate PayeeFSP + autonumber resume + Switch -> Switch: Commit transfer\nfrom Payer FSP\nto Payee FSP + autonumber stop + PayerFSP <<- Switch: **PUT /transfers/**\n(Fulfilment) + PayerFSP -->> Switch: **HTTP 200** (OK) + deactivate Switch + autonumber resume + PayerFSP -> PayerFSP: Commit transfer from Payer\naccount to Payee FSP account + group #LightGrey Optional + hnote over PayerFSP #LightGrey + Get transaction data + end hnote + autonumber resume + PayerFSP ->> Switch: **GET /transactions/** + activate Switch + autonumber stop + PayerFSP <<-- Switch: **HTTP 202** (Accepted) + autonumber resume + Switch ->> PayeeFSP: **GET /transactions/** + activate PayeeFSP + autonumber stop + Switch <<-- PayeeFSP: **HTTP 202** (Accepted) + autonumber resume + PayeeFSP -> PayeeFSP: Looksup transaction\ninformation + Switch <<- PayeeFSP: **PUT /transactions/**\n(Transaction details) + autonumber stop + Switch -->> PayeeFSP: **HTTP 200** (OK) + deactivate PayeeFSP + autonumber resume + PayerFSP <<- Switch: **PUT /transactions/**\n(Transaction details) + autonumber stop + PayerFSP -->> Switch: **HTTP 200** (OK) + deactivate Switch + end + autonumber resume + Payer <- PayerFSP: Transaction\nnotification + deactivate PayerFSP +end +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure65.svg b/docs/technical/api/assets/diagrams/sequence/figure65.svg new file mode 100644 index 000000000..e606726df --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure65.svg @@ -0,0 +1,462 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Account + Lookup + + Payee + FSP + + Payee + + + + + + + + + + + + + + + + + + + + + + [1] + I would like + to receive + 100 USD from + +123456789 + + + + + [2] + Payer not + within Payee + FSP system + + + + GET /participants/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + + [3] + Lookup which FSP MSISDN + +123456789 belongs to + + + + [4] + PUT /participants/MSISDN/123456789 + (FSP ID) + + + + HTTP 200 + (OK) + + + + [5] + Post /transactionRequests + (Payee information, transaction details) + + + + HTTP 202 + (Accepted) + + + + [6] + POST /transactionRequests + (Payee information, + transaction details) + + + + HTTP 202 + (Accepted) + + + + + [7] + Perform optional validation + + + + [8] + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + [9] + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + + [10] + Rate Payer FSP quote + (depending on fee model) + + + + [11] + POST /quotes + (Transaction details) + + + + HTTP 202 + (Accepted) + + + + [12] + POST /quotes + (Transaction details) + + + + HTTP 202 + (Accepted) + + + + + Rate Payee FSP + fees/commission, + generate condition + + + Optional + + Confirm quote + + + [13] + Here is the + quote and + Payer name + + + I confirm + + + + [14] + PUT /quotes/ + <ID> + (Payee FSP fee/commission,condition) + + + + HTTP 200 + (OK) + + + + [15] + PUT /quotes/ + <ID> + (Payee FSP + fee/commission,condition) + + + + HTTP 200 + (OK) + + + + + [16] + Rate Payer FSP quote + (depending on the fee model) + + + [17] + Will you approve the + transaction request + for 100 USD + (plus fees) + to Payee? + + + alt + [Alternatives] + + User rejects + transaction request + + + [18] + I reject the + transaction request + + + + [19] + PUT /transactionRequests/ + <ID> + (Rejected state) + + + + HTTP 200 + (OK) + + + + [20] + PUT /transactionRequests/ + <ID> + (Rejected state) + + + + HTTP 200 + (OK) + + + [21] + Transaction failed + due to user + rejection + + + User approves + transaction request + + + I approve the + transaction request + + + + + [22] + Reserve transfer from Payer + account to Switch account + + + + POST /transfers + (Transfer ID, condition, ILP packet + including transaction ID) + + + + HTTP 202 + (Accepted) + + + + + [23] + Reserve transfer + from Payer + FSP to Payee FSP + + + + POST /transfers + (Transfer ID, condition, ILP packet + including transaction ID) + + + + HTTP 202 + (Accepted) + + + + + [24] + Perform transfer + from Switch account + to Payee account, + generate fulfilment + + + [25] + Transaction + notification + + + + PUT /transfers/ + <ID> + (Fulfilment) + + + + HTTP 200 + (OK) + + + + + [26] + Commit transfer + from Payer FSP + to Payee FSP + + + + PUT /transfers/ + <ID> + (Fulfilment) + + + + HTTP 200 + (OK) + + + + + [27] + Commit transfer from Payer + account to Payee FSP account + + + Optional + + Get transaction data + + + + [28] + GET /transactions/ + <TransactionID> + + + + HTTP 202 + (Accepted) + + + + [29] + GET /transactions/ + <TransactionID> + + + + HTTP 202 + (Accepted) + + + + + [30] + Looksup transaction + information + + + + [31] + PUT /transactions/ + <TransactionID> + (Transaction details) + + + + HTTP 200 + (OK) + + + + [32] + PUT /transactions/ + <TransactionID> + (Transaction details) + + + + HTTP 200 + (OK) + + + [33] + Transaction + notification + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure65a.plantuml b/docs/technical/api/assets/diagrams/sequence/figure65a.plantuml new file mode 100644 index 000000000..86398225a --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure65a.plantuml @@ -0,0 +1,234 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Payee Initiated Transaction + +' Actor Keys: +' participant - FSP(Payer/Payee), Switch and Account Lookup +' actor - Payer/Payee(s) + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Account\nLookup" as ALS +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +autonumber 1 1 "[0]" +PayeeFSP <- Payee: I would like\nto receive\n100 USD from\n+123456789 +activate PayeeFSP +PayeeFSP <- PayeeFSP: Payer not\nwithin Payee\nFSP system +autonumber stop +ALS <<- PayeeFSP: **Lookup Participant Information**\n(MSISDN 123456789) +activate ALS +autonumber resume +ALS -> ALS: Lookup which FSP MSISDN\n+123456789 belongs to +ALS ->> PayeeFSP: **Returns Participant Information**\n(FSP ID) +deactivate ALS +deactivate PayeeFSP +Switch <<- PayeeFSP: **Perform Transaction Request**\n(Payee information, transaction details) +activate PayeeFSP +activate Switch +PayerFSP <<- Switch: **Perform Transaction Request**\n(Payee information,\ntransaction details) +deactivate Switch +activate PayerFSP +PayerFSP -> PayerFSP: Perform optional validation +PayerFSP ->> Switch: **Return Transaction**\n**Request Information**\n(Received status) +activate Switch +deactivate PayerFSP +Switch ->> PayeeFSP: **Return Transaction Request Information**\n(Received status) +deactivate PayeeFSP +deactivate Switch +activate PayerFSP +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on fee model) +autonumber stop +PayerFSP ->> Switch: **Calculate Quote**\n(Transaction detail) +activate Switch +autonumber resume +Switch ->> PayeeFSP: **Calculate Quote**\n(Transaction details) +activate PayeeFSP +PayeeFSP -> PayeeFSP: Rate Payee FSP\nfees/commission,\ngenerate condition +group #OldLace Optional + hnote left of PayeeFSP #OldLace + Confirm quote + end hnote + PayeeFSP -> Payee: Here is the\nquote and\nPayer name + autonumber stop + PayeeFSP <- Payee: I confirm +end +autonumber resume +Switch <<- PayeeFSP: **Return Quote Information**\n(Payee FSP fee/commission,condition) +deactivate PayeeFSP +PayerFSP <<- Switch: **Return Quote Information**\n(Payee FSP\nfee/commission,condition) +deactivate Switch +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on the fee model) +Payer <- PayerFSP: Will you approve\ntransaction\nrequest for\n100 USD(plusfees)\nto Payee? +deactivate PayerFSP +Alt #OldLace Alternatives + hnote over of Payer #OldLace + User rejects + transaction request + end hnote + Payer -> PayerFSP: I reject the\ntransaction request + activate PayerFSP + PayerFSP ->> Switch: **Return Transaction**\n**Request Information**\n(Rejected state) + deactivate PayerFSP + activate Switch + Switch ->> PayeeFSP: **Return Transaction Request Information**\n(Rejected state) + deactivate Switch + activate PayeeFSP + PayeeFSP -> Payee: Transaction failed\ndue to user\nrejection + deactivate PayeeFSP + autonumber stop +else + hnote over of Payer #OldLace + User rejects + transaction request + end hnote + Payer -> PayerFSP: I approve the\ntransaction request + activate PayerFSP + autonumber resume + PayerFSP -> PayerFSP: Reserve transfer from Payer\naccount to Switch account + autonumber stop + PayerFSP ->> Switch: **Perform Transfer**\n(Transfer ID, condition, ILP packet\nincluding transaction ID) + activate Switch + autonumber resume + Switch -> Switch: Reserve transfer\nfrom Payer\nFSP to Payee FSP + autonumber stop + Switch ->> PayeeFSP: **Perform Transfer**\n(Transfer ID, condition, ILP packet\nincluding transaction ID) + activate PayeeFSP + autonumber resume + PayeeFSP -> PayeeFSP: Perform transfer\nfrom Switch account\nto Payee account,\ngenerate fulfilment + PayeeFSP -> Payee: Transaction\nnotification + autonumber stop + Switch <<- PayeeFSP: **Retrun Transfer Information**\n(Fulfilment) + deactivate PayeeFSP + autonumber resume + Switch -> Switch: Commit transfer\nfrom Payer FSP\nto Payee FSP + autonumber stop + PayerFSP <<- Switch: **Return Transfer Information**\n(Fulfilment) + deactivate Switch + autonumber resume + PayerFSP -> PayerFSP: Commit transfer from Payer\naccount to Payee FSP account + group #LightGrey Optional + hnote over PayerFSP #LightGrey + Get transaction data + end hnote + PayerFSP ->> Switch: **Retrieve Transaction Information**\n(Transaction ID) + activate Switch + Switch ->> PayeeFSP: **Retrieve Transaction Information**\n(Transaction ID) + activate PayeeFSP + PayeeFSP -> PayeeFSP: Looksup transaction\ninformation + Switch <<- PayeeFSP: **Return Transaction Information**\n(Transaction detail) + deactivate PayeeFSP + PayerFSP <<- Switch: **Return Transaction Information**\n(Transaction detail) + deactivate Switch + end + Payer <- PayerFSP: Transaction\nnotification + deactivate PayerFSP +end +autonumber stop +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure65a.svg b/docs/technical/api/assets/diagrams/sequence/figure65a.svg new file mode 100644 index 000000000..cb9409cac --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure65a.svg @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Account + Lookup + + Payee + FSP + + Payee + + + + + + + + + + + + + + + + + + + + + + [1] + I would like + to receive + 100 USD from + +123456789 + + + + + [2] + Payer not + within Payee + FSP system + + + + Lookup Participant Information + (MSISDN 123456789) + + + + + [3] + Lookup which FSP MSISDN + +123456789 belongs to + + + + [4] + Returns Participant Information + (FSP ID) + + + + [5] + Perform Transaction Request + (Payee information, transaction details) + + + + [6] + Perform Transaction Request + (Payee information, + transaction details) + + + + + [7] + Perform optional validation + + + + [8] + Return Transaction + Request Information + (Received status) + + + + [9] + Return Transaction Request Information + (Received status) + + + + + [10] + Rate Payer FSP quote + (depending on fee model) + + + + Calculate Quote + (Transaction detail) + + + + [11] + Calculate Quote + (Transaction details) + + + + + [12] + Rate Payee FSP + fees/commission, + generate condition + + + Optional + + Confirm quote + + + [13] + Here is the + quote and + Payer name + + + I confirm + + + + [14] + Return Quote Information + (Payee FSP fee/commission,condition) + + + + [15] + Return Quote Information + (Payee FSP + fee/commission,condition) + + + + + [16] + Rate Payer FSP quote + (depending on the fee model) + + + [17] + Will you approve + transaction + request for + 100 USD(plusfees) + to Payee? + + + alt + [Alternatives] + + User rejects + transaction request + + + [18] + I reject the + transaction request + + + + [19] + Return Transaction + Request Information + (Rejected state) + + + + [20] + Return Transaction Request Information + (Rejected state) + + + [21] + Transaction failed + due to user + rejection + + + User rejects + transaction request + + + I approve the + transaction request + + + + + [22] + Reserve transfer from Payer + account to Switch account + + + + Perform Transfer + (Transfer ID, condition, ILP packet + including transaction ID) + + + + + [23] + Reserve transfer + from Payer + FSP to Payee FSP + + + + Perform Transfer + (Transfer ID, condition, ILP packet + including transaction ID) + + + + + [24] + Perform transfer + from Switch account + to Payee account, + generate fulfilment + + + [25] + Transaction + notification + + + + Retrun Transfer Information + (Fulfilment) + + + + + [26] + Commit transfer + from Payer FSP + to Payee FSP + + + + Return Transfer Information + (Fulfilment) + + + + + [27] + Commit transfer from Payer + account to Payee FSP account + + + Optional + + Get transaction data + + + + [28] + Retrieve Transaction Information + (Transaction ID) + + + + [29] + Retrieve Transaction Information + (Transaction ID) + + + + + [30] + Looksup transaction + information + + + + [31] + Return Transaction Information + (Transaction detail) + + + + [32] + Return Transaction Information + (Transaction detail) + + + [33] + Transaction + notification + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure66.plantuml b/docs/technical/api/assets/diagrams/sequence/figure66.plantuml new file mode 100644 index 000000000..179a4e1b1 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure66.plantuml @@ -0,0 +1,346 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' Payee Initiated Transaction using OTP pattern using the asynchronous REST binding + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payer/Payee(s) + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Account\nLookup" as ALS +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +autonumber 1 1 "[0]" +Group #Oldlace Option #1 + hnote left of Payer #Oldlace + User + initiated + OTP + end hnote + Payer -> PayerFSP: Generate\nOTP for me + activate PayerFSP + PayerFSP -> PayerFSP: Generate OTP + Payer <- PayerFSP: Your OTP\nis 12345 + deactivate PayerFSP +end +PayeeFSP <- Payee: I would like\nto receive\n100 USD from\n+123456789 +activate PayeeFSP +autonumber stop +PayeeFSP <- PayeeFSP: MSISDN not within\nPayee FSP system +autonumber resume +ALS <<- PayeeFSP: **GET /participants/MSISDN/123456789** +activate ALS +autonumber stop +ALS -->> PayeeFSP: **HTTP 202** (Accepted) +autonumber resume +ALS <- ALS: Lookup which FSP MSISDN\n+123456789 belongs to +ALS -> PayeeFSP: **PUT /participants/MSISDN/123456789**\n(FSP ID) +autonumber stop +ALS <<-- PayeeFSP: **HTTP 200** (OK) +deactivate ALS +deactivate PayeeFSP +autonumber resume +Switch <<- PayeeFSP: **POST /transactionRequests**\n(Payee information, transaction details, OTP authorization) +activate PayeeFSP +activate Switch +autonumber stop +Switch -->> PayeeFSP: **HTTP 202** (Accepted) +autonumber resume +PayerFSP <<- Switch: **POST /transactionRequests**\n(Payee information,\ntransaction details, OTP authorization) +activate PayerFSP +autonumber stop +PayerFSP -->> Switch: **HTTP 202** (Accepted) +autonumber resume +PayerFSP -> PayerFSP: Perform optional validation +PayerFSP ->> Switch: **Put /transactionRequests/**\n(Received status) +autonumber stop +PayerFSP <<-- Switch: **HTTP 200** (OK) +deactivate PayerFSP +autonumber resume +Switch ->> PayeeFSP: **Put /transactionRequests/**\n(Received status) +autonumber stop +Switch <<-- PayeeFSP: **HTTP 200** (OK) +deactivate Switch +deactivate PayeeFSP +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +autonumber resume +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on fee model) +PayerFSP ->> Switch: **POST /qoutes**\n(Transaction details) +activate Switch +autonumber stop +PayerFSP <<-- Switch: **HTTP 202**\n(Accepted) +autonumber resume +Switch ->> PayeeFSP: **POST /qoutes**\n(Transaction details) +activate PayeeFSP +autonumber stop +Switch <<-- PayeeFSP: **HTTP 202**\n(Accepted) +PayeeFSP -> PayeeFSP: Rate Payee FSP\nfees/commission,\ngenerate condition +Group #Oldlace Optional + hnote left of PayeeFSP #Oldlace + Confirm + quote + end hnote + autonumber resume + PayeeFSP -> Payee: Her is the\nquote and\nPayer name + autonumber stop + PayeeFSP <- Payee: I confirm +end +autonumber resume +Switch <<- PayeeFSP: **PUT /quote/**\n(Payee FSP fee/commission,\ncondition) +autonumber stop +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +autonumber resume +PayerFSP <<- Switch: **PUT /quote/**\n(Payee FSP fee/commission,\ncondition) +autonumber stop +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +autonumber resume +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on fee model) +autonumber stop +PayerFSP -[hidden]> Switch +deactivate PayerFSP +Group #Oldlace Option #2 + hnote left of Payer #Oldlace + Automatic + generated + OTP + end hnote + PayerFSP -[hidden]> Switch + activate PayerFSP + autonumber resume + PayerFSP -> PayerFSP: Generate OTP + Payer <- PayerFSP: Use OTP\nto confirm +end +PayerFSP ->> Switch: **GET /authorizations/**\n(Amount and fees) +activate Switch +autonumber stop +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +autonumber resume +Switch ->> PayeeFSP: **GET /authorizations/**\n(Amount and fees) +activate PayeeFSP +autonumber stop +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +autonumber resume +PayeeFSP -> Payee: Show fees\non POS +Payee -> Payee: Payer\napproves/rejects\ntransaction\nusing OTP +autonumber stop +PayeeFSP <<-- Payee: Entered OTP +autonumber resume +Switch <<- PayeeFSP: **PUT /authorizations/**\n(OTP) +autonumber stop +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +autonumber resume +PayerFSP <<- Switch: **PUT /authorizations/**\n(OTP) +autonumber stop +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +autonumber resume +PayerFSP -> PayerFSP: Validate OTP sent by Payee FSP +autonumber stop +PayerFSP -[hidden]> Switch +deactivate PayerFSP +Group #Oldlace Alternatives + hnote left of Payer #Oldlace + OTP + validation + failed + end hnote + autonumber resume + PayerFSP ->> Switch: **PUT /transactionRequests/**\n(Rejected state) + activate PayerFSP + activate Switch + autonumber stop + PayerFSP <<-- Switch: **HTTP 200** (OK) + deactivate PayerFSP + autonumber resume + Switch ->> PayeeFSP: **PUT /transactionRequests/**\n(Rejected state) + activate PayeeFSP + autonumber stop + Switch <<-- PayeeFSP: **HTTP 200** (OK) + deactivate Switch + autonumber resume + PayeeFSP -> Payee: Transaction\nfailed due to\nincorrect OTP + deactivate PayeeFSP + autonumber stop +else + hnote left of Payer #Oldlace + OTP + validation + successful + end hnote + PayerFSP -[hidden]> Switch + autonumber 33 1 + activate PayerFSP + PayerFSP -> PayerFSP: Reserve transfer from Payer\naccount to Switch account + autonumber stop + PayerFSP ->> Switch: **POST /transfers**\n(Transfer ID, condition,\nILP packet including transaction ID) + activate Switch + PayerFSP <<-- Switch: **HTTP 202** (Accepted) + autonumber resume + Switch -> Switch: Reserve transfer\nfrom Payer FSP\nto Payee FSP + autonumber stop + Switch ->> PayeeFSP: **POST /transfers**\n(Transfer ID, condition, \nILP packet including transaction ID) + activate PayeeFSP + Switch <<-- PayeeFSP: **HTTP 202** (Accepted) + autonumber resume + PayeeFSP -> PayeeFSP: Lookup\ntransaction\ninformation + PayeeFSP -> Payee: Transaction\nnotification + autonumber stop + Switch <<- PayeeFSP: **PUT /transfers/**\n(Fulfilment) + Switch -->> PayeeFSP: **HTTP 200** (OK) + deactivate PayeeFSP + autonumber resume + Switch -> Switch: Commit transfer\nfrom Payer FSP\nto Payee FSP + autonumber stop + PayerFSP <<- Switch: **PUT /transfers/**\n(Fulfilment) + PayerFSP -->> Switch: **HTTP 200** (OK) + deactivate Switch + autonumber resume + PayerFSP -> PayerFSP: Commits transfer from Payer\naccount to Payee FSP account + autonumber stop + PayerFSP -[hidden]> Switch + Group #Lightgrey Optional + hnote left of PayerFSP #Lightgrey + Get transaction + data + end hnote + autonumber resume + PayerFSP ->> Switch: **GET /transactions/** + activate Switch + autonumber stop + PayerFSP <<-- Switch: **HTTP 202** (Accepted) + autonumber resume + Switch ->> PayeeFSP: **GET /transactions/** + activate PayeeFSP + autonumber stop + Switch <<-- PayeeFSP: **HTTP 202** (Accepted) + autonumber resume + PayeeFSP -> PayeeFSP: Lookup\ntransaction\ninformation + autonumber resume + Switch <<- PayeeFSP: **PUT /transactions/**\n(Transaction details) + autonumber stop + Switch -->> PayeeFSP: **HTTP 200** (OK) + deactivate PayeeFSP + autonumber resume + PayerFSP ->> Switch: **PUT /transactions/**\n(Transaction details) + autonumber stop + PayerFSP <<-- Switch: **HTTP 200** (OK) + deactivate Switch + end + autonumber resume + Payer <- PayerFSP: Transaction\nnotification + deactivate PayerFSP +end +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure66.svg b/docs/technical/api/assets/diagrams/sequence/figure66.svg new file mode 100644 index 000000000..10475e8cf --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure66.svg @@ -0,0 +1,568 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Account + Lookup + + Payee + FSP + + Payee + + + + + + + + + + + + + + + + + + + + + + + + + Option #1 + + User + initiated + OTP + + + [1] + Generate + OTP for me + + + + + [2] + Generate OTP + + + [3] + Your OTP + is 12345 + + + [4] + I would like + to receive + 100 USD from + +123456789 + + + + + MSISDN not within + Payee FSP system + + + + [5] + GET /participants/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + + [6] + Lookup which FSP MSISDN + +123456789 belongs to + + + [7] + PUT /participants/MSISDN/123456789 + (FSP ID) + + + + HTTP 200 + (OK) + + + + [8] + POST /transactionRequests + (Payee information, transaction details, OTP authorization) + + + + HTTP 202 + (Accepted) + + + + [9] + POST /transactionRequests + (Payee information, + transaction details, OTP authorization) + + + + HTTP 202 + (Accepted) + + + + + [10] + Perform optional validation + + + + [11] + Put /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + [12] + Put /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + + [13] + Rate Payer FSP quote + (depending on fee model) + + + + [14] + POST /qoutes + (Transaction details) + + + + HTTP 202 + (Accepted) + + + + [15] + POST /qoutes + (Transaction details) + + + + HTTP 202 + (Accepted) + + + + + Rate Payee FSP + fees/commission, + generate condition + + + Optional + + Confirm + quote + + + [16] + Her is the + quote and + Payer name + + + I confirm + + + + [17] + PUT /quote/ + <ID> + (Payee FSP fee/commission, + condition) + + + + HTTP 200 + (OK) + + + + [18] + PUT /quote/ + <ID> + (Payee FSP fee/commission, + condition) + + + + HTTP 200 + (OK) + + + + + [19] + Rate Payer FSP quote + (depending on fee model) + + + Option #2 + + Automatic + generated + OTP + + + + + [20] + Generate OTP + + + [21] + Use OTP + to confirm + + + + [22] + GET /authorizations/ + <TransactionRequestID> + (Amount and fees) + + + + HTTP 202 + (Accepted) + + + + [23] + GET /authorizations/ + <TransactionRequestID> + (Amount and fees) + + + + HTTP 202 + (Accepted) + + + [24] + Show fees + on POS + + + + + [25] + Payer + approves/rejects + transaction + using OTP + + + + Entered OTP + + + + [26] + PUT /authorizations/ + <TransactionRequestID> + (OTP) + + + + HTTP 200 + (OK) + + + + [27] + PUT /authorizations/ + <TransactionRequestID> + (OTP) + + + + HTTP 200 + (OK) + + + + + [28] + Validate OTP sent by Payee FSP + + + Alternatives + + OTP + validation + failed + + + + [29] + PUT /transactionRequests/ + <ID> + (Rejected state) + + + + HTTP 200 + (OK) + + + + [30] + PUT /transactionRequests/ + <ID> + (Rejected state) + + + + HTTP 200 + (OK) + + + [31] + Transaction + failed due to + incorrect OTP + + + OTP + validation + successful + + + + + 33 + Reserve transfer from Payer + account to Switch account + + + + POST /transfers + (Transfer ID, condition, + ILP packet including transaction ID) + + + + HTTP 202 + (Accepted) + + + + + 34 + Reserve transfer + from Payer FSP + to Payee FSP + + + + POST /transfers + (Transfer ID, condition, + ILP packet including transaction ID) + + + + HTTP 202 + (Accepted) + + + + + 35 + Lookup + transaction + information + + + 36 + Transaction + notification + + + + PUT /transfers/ + <ID> + (Fulfilment) + + + + HTTP 200 + (OK) + + + + + 37 + Commit transfer + from Payer FSP + to Payee FSP + + + + PUT /transfers/ + <ID> + (Fulfilment) + + + + HTTP 200 + (OK) + + + + + 38 + Commits transfer from Payer + account to Payee FSP account + + + Optional + + Get transaction + data + + + + 39 + GET /transactions/ + <TransactionID> + + + + HTTP 202 + (Accepted) + + + + 40 + GET /transactions/ + <TransactionID> + + + + HTTP 202 + (Accepted) + + + + + 41 + Lookup + transaction + information + + + + 42 + PUT /transactions/ + <TransactionID> + (Transaction details) + + + + HTTP 200 + (OK) + + + + 43 + PUT /transactions/ + <TransactionID> + (Transaction details) + + + + HTTP 200 + (OK) + + + 44 + Transaction + notification + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure66a.plantuml b/docs/technical/api/assets/diagrams/sequence/figure66a.plantuml new file mode 100644 index 000000000..8e944f64d --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure66a.plantuml @@ -0,0 +1,288 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Payee-Initiated Transaction using OTP + +' Actor Keys: +' participant - FSP(Payer/Payee), Switch and Account Lookup +' actor - Payer/Payee(s) + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Account\nLookup" as ALS +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +autonumber 1 1 "[0]" +Group #Oldlace Option #1 + hnote left of Payer #Oldlace + User + initiated + OTP + end hnote + Payer -> PayerFSP: Generate\nOTP for me + activate PayerFSP + PayerFSP -> PayerFSP: Generate OTP + Payer <- PayerFSP: Your OTP\nis 12345 + deactivate PayerFSP +end +PayeeFSP <- Payee: I would like\nto receive\n100 USD from\n+123456789 +activate PayeeFSP +autonumber stop +PayeeFSP <- PayeeFSP: MSISDN not within\nPayee FSP system +autonumber resume +ALS <<- PayeeFSP: **Lookup Participant Information**\n(MSISDN 123456789) +activate ALS +ALS <- ALS: Lookup which FSP MSISDN\n+123456789 belongs to +ALS -> PayeeFSP: **Return Participant Information**\n(FSP ID) +deactivate ALS +deactivate PayeeFSP +Switch <<- PayeeFSP: **Perform Transaction Request**\n(Payee information, transaction details, OTP authorization) +activate PayeeFSP +activate Switch +PayerFSP <<- Switch: **Perform Transaction Request**\n(Payee information,\ntransaction details, OTP authorization) +activate PayerFSP +autonumber stop +autonumber resume +PayerFSP -> PayerFSP: Perform optional validation +PayerFSP ->> Switch: **Return Transaction**\n**Request Information**\n(Received status) +deactivate PayerFSP +autonumber resume +Switch ->> PayeeFSP: **Return Transaction Request Information**\n(Received status) +deactivate Switch +deactivate PayeeFSP +autonumber stop +PayerFSP -[hidden]> Switch +activate PayerFSP +autonumber resume +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on fee model) +autonumber stop +PayerFSP ->> Switch: **Calculate Quote**\n(Transaction details) +activate Switch +autonumber resume +Switch ->> PayeeFSP: **Calculate Quote**\n(Transaction details) +activate PayeeFSP +PayeeFSP -> PayeeFSP: Rate Payee FSP\nfees/commission,\ngenerate condition +Group #Oldlace Optional + hnote left of PayeeFSP #Oldlace + Confirm + quote + end hnote + autonumber resume + PayeeFSP -> Payee: Her is the\nquote and\nPayer name + autonumber stop + PayeeFSP <- Payee: I confirm +end +autonumber resume +Switch <<- PayeeFSP: **Return Quote Information**\n(Payee FSP fee/commision, condition) +deactivate PayeeFSP +PayerFSP <<- Switch: **Return Quote Information**\n(Payee FSP fee/commission,\ncondition) +deactivate Switch +PayerFSP -> PayerFSP: Rate Payer FSP quote\n(depending on fee model) +autonumber stop +PayerFSP -[hidden]> Switch +deactivate PayerFSP +Group #Oldlace Option #2 + hnote left of Payer #Oldlace + Automatic + generated + OTP + end hnote + PayerFSP -[hidden]> Switch + activate PayerFSP + autonumber resume + PayerFSP -> PayerFSP: Generate OTP + Payer <- PayerFSP: Use OTP\nto confirm +end +PayerFSP ->> Switch: **Perform Authorization**\n(Amount and fees) +activate Switch +Switch ->> PayeeFSP: **Perform Authorization**\n(Amount and fees) +activate PayeeFSP +PayeeFSP -> Payee: Show fees\non POS +Payee -> Payee: Payer\napproves/rejects\ntransaction\nusing OTP +autonumber stop +PayeeFSP <<-- Payee: Entered OTP +autonumber resume +Switch <<- PayeeFSP: **Return Authorization Result**\n(OTP) +deactivate PayeeFSP +PayerFSP <<- Switch: **Return Authorization Result**\n(OTP) +autonumber stop +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +autonumber resume +PayerFSP -> PayerFSP: Validate OTP sent by Payee FSP +autonumber stop +PayerFSP -[hidden]> Switch +deactivate PayerFSP +Group #Oldlace Alternatives + hnote left of Payer #Oldlace + OTP + validation + failed + end hnote + PayerFSP -[hidden]> Switch + activate PayerFSP + autonumber resume + PayerFSP ->> Switch: **Return Transaction Request Information**\n(Rejected state) + activate Switch + deactivate PayerFSP + Switch ->> PayeeFSP: **Return Transaction Request Information**\n(Rejected state) + activate PayeeFSP + deactivate Switch + PayeeFSP -> Payee: Transaction\nfailed due to\nincorrect OTP + deactivate PayeeFSP + autonumber stop +else + hnote left of Payer #Oldlace + OTP + validation + successful + end hnote + PayerFSP -[hidden]> Switch + autonumber 33 1 + activate PayerFSP + PayerFSP -> PayerFSP: Reserve transfer from Payer\naccount to Switch account + autonumber stop + PayerFSP ->> Switch: **Perform Transfer**\n(Transfer ID, condition, ILP packet\nincluding transaction ID) + activate Switch + autonumber resume + Switch -> Switch: Reserve transfer\nfrom Payer FSP\nto Payee FSP + autonumber stop + Switch ->> PayeeFSP: **Perform Transfer**\n(Transfer ID, condition, \nILP packet including transaction ID)\n + activate PayeeFSP + autonumber resume + PayeeFSP -> PayeeFSP: Perform transfer\nfrom Switch account\nto Payee account,\ngenerate fulfilment + PayeeFSP -> Payee: Transaction\nnotification + autonumber stop + Switch <<- PayeeFSP: **Return Transfer Information**\n(Fulfilment) + deactivate PayeeFSP + autonumber resume + Switch -> Switch: Commit transfer\nfrom Payer FSP\nto Payee FSP + autonumber stop + PayerFSP <<- Switch: **Return Transfer Information**\n(Fulfilment) + deactivate Switch + autonumber resume + PayerFSP -> PayerFSP: Commits transfer from Payer\naccount to Payee FSP account + Group #Lightgrey Optional + hnote left of PayerFSP #Lightgrey + Get transaction + data + end hnote + PayerFSP ->> Switch: **Retrieve Transaction Information**\n(Transaction ID) + activate Switch + Switch ->> PayeeFSP: **Retrieve Transaction Information**\n(Transaction ID) + activate PayeeFSP + PayeeFSP -> PayeeFSP: Lookup\ntransaction\ninformation + Switch <<- PayeeFSP: **Return Transaction Information**\n(Transaction details) + deactivate PayeeFSP + PayerFSP ->> Switch: Return Transaction Information**\n(Transaction details) + deactivate Switch + end + Payer <- PayerFSP: Transaction\nnotification + deactivate PayerFSP +end +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure66a.svg b/docs/technical/api/assets/diagrams/sequence/figure66a.svg new file mode 100644 index 000000000..25303cb58 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure66a.svg @@ -0,0 +1,442 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Account + Lookup + + Payee + FSP + + Payee + + + + + + + + + + + + + + + + + + + + + + + + + Option #1 + + User + initiated + OTP + + + [1] + Generate + OTP for me + + + + + [2] + Generate OTP + + + [3] + Your OTP + is 12345 + + + [4] + I would like + to receive + 100 USD from + +123456789 + + + + + MSISDN not within + Payee FSP system + + + + [5] + Lookup Participant Information + (MSISDN 123456789) + + + + + [6] + Lookup which FSP MSISDN + +123456789 belongs to + + + [7] + Return Participant Information + (FSP ID) + + + + [8] + Perform Transaction Request + (Payee information, transaction details, OTP authorization) + + + + [9] + Perform Transaction Request + (Payee information, + transaction details, OTP authorization) + + + + + [10] + Perform optional validation + + + + [11] + Return Transaction + Request Information + (Received status) + + + + [12] + Return Transaction Request Information + (Received status) + + + + + [13] + Rate Payer FSP quote + (depending on fee model) + + + + Calculate Quote + (Transaction details) + + + + [14] + Calculate Quote + (Transaction details) + + + + + [15] + Rate Payee FSP + fees/commission, + generate condition + + + Optional + + Confirm + quote + + + [16] + Her is the + quote and + Payer name + + + I confirm + + + + [17] + Return Quote Information + (Payee FSP fee/commision, condition) + + + + [18] + Return Quote Information + (Payee FSP fee/commission, + condition) + + + + + [19] + Rate Payer FSP quote + (depending on fee model) + + + Option #2 + + Automatic + generated + OTP + + + + + [20] + Generate OTP + + + [21] + Use OTP + to confirm + + + + [22] + Perform Authorization + (Amount and fees) + + + + [23] + Perform Authorization + (Amount and fees) + + + [24] + Show fees + on POS + + + + + [25] + Payer + approves/rejects + transaction + using OTP + + + + Entered OTP + + + + [26] + Return Authorization Result + (OTP) + + + + [27] + Return Authorization Result + (OTP) + + + + HTTP 200 + (OK) + + + + + [28] + Validate OTP sent by Payee FSP + + + Alternatives + + OTP + validation + failed + + + + [29] + Return Transaction Request Information + (Rejected state) + + + + [30] + Return Transaction Request Information + (Rejected state) + + + [31] + Transaction + failed due to + incorrect OTP + + + OTP + validation + successful + + + + + 33 + Reserve transfer from Payer + account to Switch account + + + + Perform Transfer + (Transfer ID, condition, ILP packet + including transaction ID) + + + + + 34 + Reserve transfer + from Payer FSP + to Payee FSP + + + + Perform Transfer + (Transfer ID, condition, + ILP packet including transaction ID) +   + + + + + 35 + Perform transfer + from Switch account + to Payee account, + generate fulfilment + + + 36 + Transaction + notification + + + + Return Transfer Information + (Fulfilment) + + + + + 37 + Commit transfer + from Payer FSP + to Payee FSP + + + + Return Transfer Information + (Fulfilment) + + + + + 38 + Commits transfer from Payer + account to Payee FSP account + + + Optional + + Get transaction + data + + + + 39 + Retrieve Transaction Information + (Transaction ID) + + + + 40 + Retrieve Transaction Information + (Transaction ID) + + + + + 41 + Lookup + transaction + information + + + + 42 + Return Transaction Information + (Transaction details) + + + + 43 + Return Transaction Information** + (Transaction details) + + + 44 + Transaction + notification + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure67.plantuml b/docs/technical/api/assets/diagrams/sequence/figure67.plantuml new file mode 100644 index 000000000..0576dc323 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure67.plantuml @@ -0,0 +1,222 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Bulk Transactions pattern using the asynchronous REST binding + +' Actor Keys: +' participant - FSP(Payer/Payee(s)), Switch and Account Lookup Services (ALS) +' actor - Payer/Payee(s) + +' declare actors +actor "<$actor>\nPayer\n" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\nOptional\nSwitch" as Switch +participant "\nAccount\nLookup" as ALS +participant "\nPayee\nFSP(s)" as PayeeFSP +actor "<$actor>\nPayees\n(multiple)" as Payee + +' start flow +autonumber 1 1 "[0]" +Payer -> PayerFSP: I would like to upload\na file of bulk transactions +activate PayerFSP +Loop #Oldlace + hnote left of PayerFSP #Oldlace + For each + transaction + in bulk file + end hnote + PayerFSP -> PayerFSP: Locate Payee, if not\nwithin Payer FSP\nuse Account Lookup + PayerFSP ->> ALS: **GET /participants/****/** + activate ALS + autonumber stop + PayerFSP <<-- ALS: **HTTP 202** (Accepted) + autonumber resume + ALS -> ALS: Lookup FSP for\nrequested Type/ID + autonumber stop + PayerFSP ->> ALS: **PUT /participants/****/** + PayerFSP <<-- ALS: **HTTP 200** (OK) + deactivate ALS + autonumber resume + PayerFSP -> PayerFSP: Place transaction\nin bulk file\nper Payee FSP + autonumber stop +end Loop +PayerFSP -[hidden]> Switch +deactivate PayerFSP +PayerFSP -[hidden]> Switch +activate PayerFSP +Loop #Oldlace + hnote left of PayerFSP #Oldlace + For each + created bulk + file per + Payee FSP + end hnote + PayerFSP -> PayerFSP: Rate Payer FSP bulk quote\n(depending on fee model) + autonumber resume + PayerFSP ->> Switch: **POST /bulkQuotes**\n(Bulk info and list\nof individual quotes) + autonumber stop + activate Switch + autonumber resume + PayerFSP <<-- Switch: **HTTP 202** (Accepted) + Switch ->> PayeeFSP: **POST /bulkQuotes**\n(Bulk info and list of individual quotes) + activate PayeeFSP + autonumber stop + Switch <<-- PayeeFSP: **HTTP 202** (Accepted) + autonumber resume + PayeeFSP -> PayeeFSP: Rate Payee FSP\nfee/commission and\ngenerate condition per\nindividual transfer + autonumber stop + Switch <<- PayeeFSP: **PUT /bulkQuotes/**\n(List of individual quote results\nand condition per transfer) + Switch -->> PayeeFSP: **HTTP 200** (OK) + deactivate PayeeFSP + autonumber resume + PayerFSP <<- Switch: **PUT /bulkQuotes/**\n(List of individual quote results\nand condition per transfer) + autonumber stop + PayerFSP -->> Switch: **HTTP 200** (OK) + deactivate Switch + autonumber resume + PayerFSP -> PayerFSP: Rate Payer FSP bulk quote\n(depending on fee model) +end Loop + +PayerFSP -> PayerFSP: Calculate total fee for Payer +Payer <- PayerFSP: Bulk has finished processing,\npresent fees +deactivate PayerFSP +Payer -> PayerFSP: Execute my bulk +activate PayerFSP +Loop #Oldlace + hnote left of PayerFSP #Oldlace + For each + created bulk + file per + Payee FSP + end hnote + PayerFSP -> PayerFSP: Reserve each individual\ntransfer from Payer\naccount to Payee FSP account + autonumber stop + PayerFSP ->> Switch: **POST /bulkTransfers**\n(List of individual transfers\nincluding ILP packet and condition) + activate Switch + PayerFSP <<-- Switch: **HTTP 202** (Accepted) + autonumber resume + Switch -> Switch: Reserve each individual\ntransfer from Payer FSP\nto Payee FSP + autonumber stop + Switch ->> PayeeFSP: **POST /bulkTransfers**\n(List of individual transfers\nincluding ILP packet and condition) + activate PayeeFSP + Switch <<-- PayeeFSP: **HTTP 202** (Accepted) + autonumber resume + PayeeFSP -> PayeeFSP: Perform each transaction from\nPayer FSP account to Payee\naccount, generate fulfilments + PayeeFSP -> Payee: Transaction notification\nfor each Payee + Switch <<- PayeeFSP: **PUT /bulkTransfers/**\n(List of fulfilments) + autonumber stop + Switch -->> PayeeFSP: **HTTP 200** (OK) + deactivate PayeeFSP + Switch -> Switch: Commit each successful\ntransfer from Payer\nFSP to Payee FSP + autonumber resume + PayerFSP <<- Switch: **PUT /bulkTransfers/**\n(List of fulfilments) + autonumber stop + PayerFSP -->> Switch: **HTTP 200** (OK) + deactivate Switch + autonumber resume + PayerFSP -> PayerFSP: Commit each successful\ntransfer from Payer account\nto Payee FSP account +end Loop +Payer <- PayerFSP: Your bulk has been executed +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure67.svg b/docs/technical/api/assets/diagrams/sequence/figure67.svg new file mode 100644 index 000000000..7372a33e3 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure67.svg @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Payer +   + + + +   + Payer + FSP + +   + Optional + Switch + +   + Account + Lookup + +   + Payee + FSP(s) + + Payees + (multiple) + + + + + + + + + + + + + [1] + I would like to upload + a file of bulk transactions + + + loop + + For each + transaction + in bulk file + + + + + [2] + Locate Payee, if not + within Payer FSP + use Account Lookup + + + + [3] + GET /participants/ + <PartyIdType> + / + <PartyId> + + + + HTTP 202 + (Accepted) + + + + + [4] + Lookup FSP for + requested Type/ID + + + + PUT /participants/ + <PartyIdType> + / + <PartyId> + + + + HTTP 200 + (OK) + + + + + [5] + Place transaction + in bulk file + per Payee FSP + + + loop + + For each + created bulk + file per + Payee FSP + + + + + Rate Payer FSP bulk quote + (depending on fee model) + + + + [6] + POST /bulkQuotes + (Bulk info and list + of individual quotes) + + + + [7] + HTTP 202 + (Accepted) + + + + [8] + POST /bulkQuotes + (Bulk info and list of individual quotes) + + + + HTTP 202 + (Accepted) + + + + + [9] + Rate Payee FSP + fee/commission and + generate condition per + individual transfer + + + + PUT /bulkQuotes/ + <ID> + (List of individual quote results + and condition per transfer) + + + + HTTP 200 + (OK) + + + + [10] + PUT /bulkQuotes/ + <ID> + (List of individual quote results + and condition per transfer) + + + + HTTP 200 + (OK) + + + + + [11] + Rate Payer FSP bulk quote + (depending on fee model) + + + + + [12] + Calculate total fee for Payer + + + [13] + Bulk has finished processing, + present fees + + + [14] + Execute my bulk + + + loop + + For each + created bulk + file per + Payee FSP + + + + + [15] + Reserve each individual + transfer from Payer + account to Payee FSP account + + + + POST /bulkTransfers + (List of individual transfers + including ILP packet and condition) + + + + HTTP 202 + (Accepted) + + + + + [16] + Reserve each individual + transfer from Payer FSP + to Payee FSP + + + + POST /bulkTransfers + (List of individual transfers + including ILP packet and condition) + + + + HTTP 202 + (Accepted) + + + + + [17] + Perform each transaction from + Payer FSP account to Payee + account, generate fulfilments + + + [18] + Transaction notification + for each Payee + + + + [19] + PUT /bulkTransfers/ + <ID> + (List of fulfilments) + + + + HTTP 200 + (OK) + + + + + Commit each successful + transfer from Payer + FSP to Payee FSP + + + + [20] + PUT /bulkTransfers/ + <ID> + (List of fulfilments) + + + + HTTP 200 + (OK) + + + + + [21] + Commit each successful + transfer from Payer account + to Payee FSP account + + + [22] + Your bulk has been executed + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure67a.plantuml b/docs/technical/api/assets/diagrams/sequence/figure67a.plantuml new file mode 100644 index 000000000..9f4ba3a5d --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure67a.plantuml @@ -0,0 +1,200 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title Bulk Transaction + +' Actor Keys: +' participant - FSP(Payer/Payee(s)), Switch and Account Lookup Services (ALS) +' actor - Payer/Payee(s) + +' declare actors +actor "<$actor>\nPayer\n" as Payer +participant "\nPayer\nFSP" as PayerFSP +participant "\nOptional\nSwitch" as Switch +participant "\nAccount\nLookup" as ALS +participant "\nPayee\nFSP(s)" as PayeeFSP +actor "<$actor>\nPayees\n(multiple)" as Payee + +' start flow +autonumber 1 1 "[0]" +Payer -> PayerFSP: I would like to upload\na file of bulk transactions +activate PayerFSP +Loop #Oldlace + hnote left of PayerFSP #Oldlace + For each + transaction + in bulk file + end hnote + PayerFSP -> PayerFSP: Locate Payee, if not\nwithin Payer FSP\nuse Account Lookup + PayerFSP ->> ALS: **Lookup Participant Information**\n(Payee Party ID Type and Party ID) + activate ALS + ALS -> ALS: Lookup FSP for\nrequested Type/ID + PayerFSP ->> ALS: **Return Participant Information**\n(FSP ID) + autonumber stop + deactivate ALS + PayerFSP -> PayerFSP: Place transaction\nin bulk file\nper Payee FSP + PayerFSP -[hidden]> Switch + deactivate PayerFSP +end Loop +Loop #Oldlace + hnote left of PayerFSP #Oldlace + For each + created bulk + file per + Payee FSP + end hnote + PayerFSP -[hidden]> Switch + activate PayerFSP + PayerFSP -> PayerFSP: Rate Payer FSP bulk quote\n(depending on fee model) + autonumber resume + PayerFSP ->> Switch: **Calculate Bulk Quote**\n(Bulk info and list\nof individual quotes) + Switch ->> PayeeFSP: **Calculate Bulk Quote**\n(Bulk info and list of individual quotes) + activate PayeeFSP + activate Switch + PayeeFSP -> PayeeFSP: Rate Payee FSP\nfee/commission and\ngenerate condition per\nindividual transfer + autonumber stop + Switch <<- PayeeFSP: **Return Bulk Quote Information**\n(List of individual quote results\nand condition per transfer) + deactivate PayeeFSP + autonumber resume + PayerFSP <<- Switch: **Return Bulk Quote Information**\n(List of individual quote results\nand condition per transfer) + deactivate Switch + PayerFSP -> PayerFSP: Rate Payer FSP bulk quote\n(depending on fee model) +end Loop +autonumber resume +PayerFSP -> PayerFSP: Calculate total fee for Payer +Payer <- PayerFSP: Bulk has finished processing,\npresent fees +deactivate PayerFSP +Payer -> PayerFSP: Execute my bulk +activate PayerFSP +Loop #Oldlace + hnote left of PayerFSP #Oldlace + For each + created bulk + file per + Payee FSP + end hnote + PayerFSP -> PayerFSP: Reserve each individual\ntransfer from Payer\naccount to Payee FSP account +autonumber stop + PayerFSP ->> Switch: **Perform Bulk Transfer**\n(List of individual transfers\nincluding ILP packet and condition) + activate Switch +autonumber resume + Switch -> Switch: Reserve each individual\ntransfer from Payer FSP\nto Payee FSP + autonumber stop + Switch ->> PayeeFSP: **Perform Bulk Transfer**\n(List of individual transfers\nincluding ILP packet and condition) + activate PayeeFSP +autonumber resume + PayeeFSP -> PayeeFSP: Perform each transaction from\nPayer FSP account to Payee\naccount, generate fulfilments + PayeeFSP -> Payee: Transaction notification\nfor each Payee + Switch <<- PayeeFSP: **Return Bulk Transfer Information**\n(List of fulfilments) + autonumber stop + deactivate PayeeFSP + Switch -> Switch: Commit each successful\ntransfer from Payer\nFSP to Payee FSP + autonumber resume + PayerFSP <<- Switch: **Return Bulk Transfer Information**\n(List of fulfilments) + deactivate Switch + PayerFSP -> PayerFSP: Commit each successful\ntransfer from Payer account\nto Payee FSP account +end Loop +Payer <- PayerFSP: Your bulk has been executed +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure67a.svg b/docs/technical/api/assets/diagrams/sequence/figure67a.svg new file mode 100644 index 000000000..11e7f3675 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure67a.svg @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Payer +   + + + +   + Payer + FSP + +   + Optional + Switch + +   + Account + Lookup + +   + Payee + FSP(s) + + Payees + (multiple) + + + + + + + + + + + + + [1] + I would like to upload + a file of bulk transactions + + + loop + + For each + transaction + in bulk file + + + + + [2] + Locate Payee, if not + within Payer FSP + use Account Lookup + + + + [3] + Lookup Participant Information + (Payee Party ID Type and Party ID) + + + + + [4] + Lookup FSP for + requested Type/ID + + + + [5] + Return Participant Information + (FSP ID) + + + + + Place transaction + in bulk file + per Payee FSP + + + loop + + For each + created bulk + file per + Payee FSP + + + + + Rate Payer FSP bulk quote + (depending on fee model) + + + + [6] + Calculate Bulk Quote + (Bulk info and list + of individual quotes) + + + + [7] + Calculate Bulk Quote + (Bulk info and list of individual quotes) + + + + + [8] + Rate Payee FSP + fee/commission and + generate condition per + individual transfer + + + + Return Bulk Quote Information + (List of individual quote results + and condition per transfer) + + + + [9] + Return Bulk Quote Information + (List of individual quote results + and condition per transfer) + + + + + [10] + Rate Payer FSP bulk quote + (depending on fee model) + + + + + [11] + Calculate total fee for Payer + + + [12] + Bulk has finished processing, + present fees + + + [13] + Execute my bulk + + + loop + + For each + created bulk + file per + Payee FSP + + + + + [14] + Reserve each individual + transfer from Payer + account to Payee FSP account + + + + Perform Bulk Transfer + (List of individual transfers + including ILP packet and condition) + + + + + [15] + Reserve each individual + transfer from Payer FSP + to Payee FSP + + + + Perform Bulk Transfer + (List of individual transfers + including ILP packet and condition) + + + + + [16] + Perform each transaction from + Payer FSP account to Payee + account, generate fulfilments + + + [17] + Transaction notification + for each Payee + + + + [18] + Return Bulk Transfer Information + (List of fulfilments) + + + + + Commit each successful + transfer from Payer + FSP to Payee FSP + + + + [19] + Return Bulk Transfer Information + (List of fulfilments) + + + + + [20] + Commit each successful + transfer from Payer account + to Payee FSP account + + + [21] + Your bulk has been executed + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure68.plantuml b/docs/technical/api/assets/diagrams/sequence/figure68.plantuml new file mode 100644 index 000000000..2acdac867 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure68.plantuml @@ -0,0 +1,64 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +' declare title +' title Error on server during processing of request + +' Actor Keys: +' participant - Client and Server + + +' declare actors +participant "Client" as client +participant "Server" as server + +' start flow +autonumber 1 1 "[0]" +client ->> server: **POST /service** +activate client +activate server +client <<-- server: **HTTP 202** (Accepted) +autonumber stop +server -> server: Some processing error\noccurs, i.e. the request\ncan not be handled as\nrequested. +autonumber resume +client <<- server: **PUT /service/****/error** +client -->> server: **HTTP 200** (OK) +deactivate server +deactivate client +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure68.svg b/docs/technical/api/assets/diagrams/sequence/figure68.svg new file mode 100644 index 000000000..f1b5d40d1 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure68.svg @@ -0,0 +1,47 @@ + + + + + + + + + Client + + Server + + + + + + [1] + POST /service + + + + [2] + HTTP 202 + (Accepted) + + + + + Some processing error + occurs, i.e. the request + can not be handled as + requested. + + + + [3] + PUT /service/ + <ID> + /error + + + + [4] + HTTP 200 + (OK) + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure69.plantuml b/docs/technical/api/assets/diagrams/sequence/figure69.plantuml new file mode 100644 index 000000000..c1f3ba428 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure69.plantuml @@ -0,0 +1,81 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +' declare title +' title Handling of error callback from POST /transfers + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch + + +' declare actors +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP + +' start flow +autonumber 1 1 "[0]" +activate PayerFSP +PayerFSP -> PayerFSP: Reserve transfer from Payer\naccount to Switch account +PayerFSP ->> Switch: **POST /transfers**\n(Transfer ID, condition, ILP Packet\nincluding transaction details) +activate Switch +autonumber stop +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve transfer from\nPayer FSP to Payee FSP +autonumber resume +Switch ->> PayeeFSP: **POST /transfers**\n(Transfer ID, condition, ILP Packet\nincluding transaction details) +activate PayeeFSP +autonumber stop +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Some processing error occurs,\ne.g. a limit breach +autonumber resume +Switch <<- PayeeFSP: **PUT /transfers/****/error** +autonumber stop +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch -> Switch: Cancel transfer from\nPayer FSP to Payee FSP +autonumber resume +PayerFSP <<- Switch: **PUT /transfers/****/error**\n(Error information) +autonumber stop +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Cancel transfer from Payer\naccount to Payee FSP account +PayerFSP -[hidden]> Switch +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure69.svg b/docs/technical/api/assets/diagrams/sequence/figure69.svg new file mode 100644 index 000000000..c8e47a23b --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure69.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + + + + + + + [1] + Reserve transfer from Payer + account to Switch account + + + + [2] + POST /transfers + (Transfer ID, condition, ILP Packet + including transaction details) + + + + HTTP 202 + (Accepted) + + + + + Reserve transfer from + Payer FSP to Payee FSP + + + + [3] + POST /transfers + (Transfer ID, condition, ILP Packet + including transaction details) + + + + HTTP 202 + (Accepted) + + + + + Some processing error occurs, + e.g. a limit breach + + + + [4] + PUT /transfers/ + <ID> + /error + + + + HTTP 200 + (OK) + + + + + Cancel transfer from + Payer FSP to Payee FSP + + + + [5] + PUT /transfers/ + <ID> + /error + (Error information) + + + + HTTP 200 + (OK) + + + + + Cancel transfer from Payer + account to Payee FSP account + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure70.plantuml b/docs/technical/api/assets/diagrams/sequence/figure70.plantuml new file mode 100644 index 000000000..42f6da819 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure70.plantuml @@ -0,0 +1,81 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +' declare title +' title Handling of error callback from API Service /bulkTransfers + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch + + +' declare actors +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP(s)" as PayeeFSP + +' start flow +autonumber 1 1 "[0]" +activate PayerFSP +PayerFSP -> PayerFSP: Reserve each individual\ntransfer from Payer\naccount to Payee FSP account +PayerFSP ->> Switch: **POST /bulkTransfers**\n(List of individual transfers\nincluding ILP packet and condition) +activate Switch +autonumber stop +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve each individual\ntransfer from Payer FSP\nto Payee FSP +autonumber resume +Switch ->> PayeeFSP: **POST /bulkTransfers**\n(List of individual transfers\nincluding ILP packet and condition) +activate PayeeFSP +autonumber stop +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Some processing error occurs,\ne.g. a validation failure that prevents\nthe bulk transfer to be performed +autonumber resume +Switch <<- PayeeFSP: **PUT /bulkTransfers/****/error**\n(Error information) +autonumber stop +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +Switch -> Switch: Cancel each reserved\ntransfer from Payer\nFSP to Payee FSP +autonumber resume +PayerFSP <<- Switch: **PUT /bulkTransfers/****/error**\n(Error information) +autonumber stop +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Cancel each transfer\nfrom Payer account\nto Payee FSP account +PayerFSP -[hidden]> Switch +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure70.svg b/docs/technical/api/assets/diagrams/sequence/figure70.svg new file mode 100644 index 000000000..bbdcd79ec --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure70.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + Payer + FSP + + Optional + Switch + + Payee + FSP(s) + + + + + + + + [1] + Reserve each individual + transfer from Payer + account to Payee FSP account + + + + [2] + POST /bulkTransfers + (List of individual transfers + including ILP packet and condition) + + + + HTTP 202 + (Accepted) + + + + + Reserve each individual + transfer from Payer FSP + to Payee FSP + + + + [3] + POST /bulkTransfers + (List of individual transfers + including ILP packet and condition) + + + + HTTP 202 + (Accepted) + + + + + Some processing error occurs, + e.g. a validation failure that prevents + the bulk transfer to be performed + + + + [4] + PUT /bulkTransfers/ + <ID> + /error + (Error information) + + + + HTTP 200 + (OK) + + + + + Cancel each reserved + transfer from Payer + FSP to Payee FSP + + + + [5] + PUT /bulkTransfers/ + <ID> + /error + (Error information) + + + + HTTP 200 + (OK) + + + + + Cancel each transfer + from Payer account + to Payee FSP account + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure71.plantuml b/docs/technical/api/assets/diagrams/sequence/figure71.plantuml new file mode 100644 index 000000000..858f8bca1 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure71.plantuml @@ -0,0 +1,70 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +' declare title +' title Error handling from client using resend of request + +' Actor Keys: +' participant - Client and Server + + +' declare actors +participant "Client" as client +participant "Server" as server + +' start flow +autonumber 1 1 "[0]" +client ->> server: **POST /service** +activate client +client -> client: Timeout, resend\nservice request +client ->> server: **POST /service** +activate server +client <<-- server: **HTTP 202** (Accepted) +autonumber stop +client -> client: Timeout, resend\nservice request +autonumber resume +client ->> server: **POST /service** +autonumber stop +client <<-- server: **HTTP 202** (Accepted) +autonumber resume +client <<- server: **PUT /service/** +client -->> server: **HTTP 200** (OK) +deactivate server +deactivate client +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure71.svg b/docs/technical/api/assets/diagrams/sequence/figure71.svg new file mode 100644 index 000000000..155304af7 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure71.svg @@ -0,0 +1,66 @@ + + + + + + + + + Client + + Server + + + + + + [1] + POST /service + + + + + [2] + Timeout, resend + service request + + + + [3] + POST /service + + + + [4] + HTTP 202 + (Accepted) + + + + + Timeout, resend + service request + + + + [5] + POST /service + + + + HTTP 202 + (Accepted) + + + + [6] + PUT /service/ + <ID> + + + + [7] + HTTP 200 + (OK) + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure72.plantuml b/docs/technical/api/assets/diagrams/sequence/figure72.plantuml new file mode 100644 index 000000000..6bf57abd8 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure72.plantuml @@ -0,0 +1,67 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke + +hide footbox + +' declare title +' title Error handling from client using GET request + +' Actor Keys: +' participant - Client and Server + + +' declare actors +participant "Client" as client +participant "Server" as server + +' start flow +autonumber 1 1 "[0]" +client ->> server: **POST /service** +activate client +activate server +client <<-- server: **HTTP 202** (Accepted) +'autonumber stop +client -> client: No update received within\nreasonable time period,\ncheck status +'autonumber resume +client ->> server: **GET /service** +autonumber stop +client <<-- server: **HTTP 202** (Accepted) +autonumber resume +client <<- server: **PUT /service/** +client -->> server: **HTTP 200** (OK) +deactivate server +deactivate client +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure72.svg b/docs/technical/api/assets/diagrams/sequence/figure72.svg new file mode 100644 index 000000000..148863300 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure72.svg @@ -0,0 +1,57 @@ + + + + + + + + + Client + + Server + + + + + + [1] + POST /service + + + + [2] + HTTP 202 + (Accepted) + + + + + [3] + No update received within + reasonable time period, + check status + + + + [4] + GET /service + <ID> + + + + HTTP 202 + (Accepted) + + + + [5] + PUT /service/ + <ID> + + + + [6] + HTTP 200 + (OK) + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure74.plantuml b/docs/technical/api/assets/diagrams/sequence/figure74.plantuml new file mode 100644 index 000000000..752507fa1 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure74.plantuml @@ -0,0 +1,220 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title End-to-end flow, from provision of account holder FSP information to a successful transaction + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payer/Payee(s) + +' declare actors +actor "<$actor>\nMats\nHagman" as Payer +participant "\nBank\nNrOne" as PayerFSP +participant "\n\nSwitch" as Switch +participant "\nMobile\nMoney" as MM +actor "<$actor>\nHenrik\nKarlsson" as Payee + +' start flow +autonumber 1 1 "[0]" +Switch <<- MM: **POST /participants/MSISDN/123456789**\n(fspid=MobileMoney) +activate Switch +activate MM +autonumber stop +Switch -->> MM: **HTTP 202** (Accepted) +autonumber resume +Switch <<-- Switch: Save FSP information for\nMSISDN 123456789 +Switch ->> MM: **PUT /participants/MSISDN/123456789**\n(fspid=MobileMoney) +autonumber stop +Switch <<-- MM: **HTTP 200** (OK) +deactivate MM +deactivate Switch +autonumber resume +Payer -> PayerFSP: I would like MSISDN +123456789\nto receive 100 USD +activate PayerFSP +autonumber stop +PayerFSP -> PayerFSP: MSISDN +123456789\nnot within BankNrOne +autonumber resume +PayerFSP ->> Switch: **GET /parties/MSISDN/123456789** +activate Switch +autonumber stop +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Lookup which FSP MSISDN\n+123456789 belongs to +autonumber resume +Switch ->> MM: **GET /parties/MSISDN/123456789** +activate MM +autonumber stop +Switch <<-- MM: **HTTP 202** (Accepted) +MM -> MM: Lookup party information\nregarding MSISDN +123456789 +autonumber resume +Switch <<- MM: **PUT /Parties/MSISDN/123456789**\n(Party Information) +autonumber stop +Switch -->> MM: **HTTP 200** (OK) +deactivate MM +autonumber resume +PayerFSP <<- Switch: **PUT /Parties/MSISDN/123456789**\n(Party Information) +autonumber stop +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +deactivate PayerFSP +autonumber resume +PayerFSP ->> Switch: **POST /quotes**\n(amountType=RECEIVE, amount=100) +activate PayerFSP +activate Switch +autonumber stop +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +autonumber resume +Switch ->> MM: **POST /quotes**\n(amountType=RECEIVE, amount=100) +activate MM +autonumber stop +Switch <<-- MM: **HTTP 202** (Accepted) +MM -> MM: Internal rating for fees/commission,\n1 USD in FSP commission, generate\nand store fulfilment, generate\ncondition out of fulfilment +autonumber resume +Switch <<- MM: **PUT /quotes/**\n(transferAmount=99 USD\npayeeFspCommission=1 USD) +autonumber stop +Switch -->> MM: **HTTP 200** (OK) +deactivate MM +autonumber resume +PayerFSP <<- Switch: **PUT /quotes/**\n(transferAmount=99 USD\npayeeFspCommission=1 USD) +autonumber stop +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: BankNrOne keeps commission as\nfee, transaction is free for Mats +autonumber resume +Payer <- PayerFSP: Transferring 100 USD to Henrik\nKarlsson will cost 0 USD in fees +deactivate PayerFSP +Payer -> PayerFSP: I approve the transaction +activate PayerFSP +autonumber stop +PayerFSP -> PayerFSP: Reserve 100 USD from Mats\nHagman's account,\n99 USD to Switch and\n1 USD to FSP commission +autonumber resume +PayerFSP ->> Switch: **POST /transfers**\n(amount=99 USD, PayerFsp=BankNrOne\npayeeFsp=MobileMoney) +activate Switch +autonumber stop +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch -> Switch: Reserve 99 USD from\nBankNrOne to MobileMoney +autonumber resume +Switch ->> MM: **POST /transfers**\n(amount=99 USD, PayerFsp=BankNrOne\npayeeFsp=MobileMoney) +activate MM +autonumber stop +Switch <<-- MM: **HTTP 202** (Accepted) +MM -> MM: Perform transfer of 100 USD to\nHenrik Karlsson's account,\n99 USD from Switch\naccount, and 1 USD from FSP\ncommission account +autonumber resume +MM -> MM: Retrieve fulfilment +MM -> Payee: You have received 100 USD\nfrom Mats Hagman +Switch <<- MM: **PUT /transfers/**\n(Fulfilment) +autonumber stop +Switch -->> MM: **HTTP 200** (OK) +deactivate MM +Switch -> Switch: Commit transfer from\nBankNrOne to MobileMoney +autonumber resume +PayerFSP <<- Switch: **PUT /transfers/**\n(Fulfilment) +autonumber stop +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Commit transfer from Mats\nHagman's account to\nSwitch account +autonumber resume +Payer <- PayerFSP: You have transferred 100 USD\nto Henrik Karlsson +autonumber stop +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure74.svg b/docs/technical/api/assets/diagrams/sequence/figure74.svg new file mode 100644 index 000000000..0d00d55c4 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure74.svg @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Mats + Hagman + + + +   + Bank + NrOne + +   +   + Switch + +   + Mobile + Money + + Henrik + Karlsson + + + + + + + + + + + + + + + + + [1] + POST /participants/MSISDN/123456789 + (fspid=MobileMoney) + + + + HTTP 202 + (Accepted) + + + + + + [2] + Save FSP information for + MSISDN 123456789 + + + + [3] + PUT /participants/MSISDN/123456789 + (fspid=MobileMoney) + + + + HTTP 200 + (OK) + + + [4] + I would like MSISDN +123456789 + to receive 100 USD + + + + + MSISDN +123456789 + not within BankNrOne + + + + [5] + GET /parties/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + + Lookup which FSP MSISDN + +123456789 belongs to + + + + [6] + GET /parties/MSISDN/123456789 + + + + HTTP 202 + (Accepted) + + + + + Lookup party information + regarding MSISDN +123456789 + + + + [7] + PUT /Parties/MSISDN/123456789 + (Party Information) + + + + HTTP 200 + (OK) + + + + [8] + PUT /Parties/MSISDN/123456789 + (Party Information) + + + + HTTP 200 + (OK) + + + + [9] + POST /quotes + (amountType=RECEIVE, amount=100) + + + + HTTP 202 + (Accepted) + + + + [10] + POST /quotes + (amountType=RECEIVE, amount=100) + + + + HTTP 202 + (Accepted) + + + + + Internal rating for fees/commission, + 1 USD in FSP commission, generate + and store fulfilment, generate + condition out of fulfilment + + + + [11] + PUT /quotes/ + <ID> + (transferAmount=99 USD + payeeFspCommission=1 USD) + + + + HTTP 200 + (OK) + + + + [12] + PUT /quotes/ + <ID> + (transferAmount=99 USD + payeeFspCommission=1 USD) + + + + HTTP 200 + (OK) + + + + + BankNrOne keeps commission as + fee, transaction is free for Mats + + + [13] + Transferring 100 USD to Henrik + Karlsson will cost 0 USD in fees + + + [14] + I approve the transaction + + + + + Reserve 100 USD from Mats + Hagman's account, + 99 USD to Switch and + 1 USD to FSP commission + + + + [15] + POST /transfers + (amount=99 USD, PayerFsp=BankNrOne + payeeFsp=MobileMoney) + + + + HTTP 202 + (Accepted) + + + + + Reserve 99 USD from + BankNrOne to MobileMoney + + + + [16] + POST /transfers + (amount=99 USD, PayerFsp=BankNrOne + payeeFsp=MobileMoney) + + + + HTTP 202 + (Accepted) + + + + + Perform transfer of 100 USD to + Henrik Karlsson's account, + 99 USD from Switch + account, and 1 USD from FSP + commission account + + + + + [17] + Retrieve fulfilment + + + [18] + You have received 100 USD + from Mats Hagman + + + + [19] + PUT /transfers/ + <ID> + (Fulfilment) + + + + HTTP 200 + (OK) + + + + + Commit transfer from + BankNrOne to MobileMoney + + + + [20] + PUT /transfers/ + <ID> + (Fulfilment) + + + + HTTP 200 + (OK) + + + + + Commit transfer from Mats + Hagman's account to + Switch account + + + [21] + You have transferred 100 USD + to Henrik Karlsson + + diff --git a/docs/technical/api/assets/diagrams/sequence/figure8.plantuml b/docs/technical/api/assets/diagrams/sequence/figure8.plantuml new file mode 100644 index 000000000..69a6186af --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure8.plantuml @@ -0,0 +1,135 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation + +- Name Surname +-------------- +******'/ + +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} +hide footbox + +' declare title +' title Example of non-disclosing receive amount + +' Actor Keys: +' participant - FSP(Payer/Payee) and Optional Switch +' actor - Payee and Payer + +' declare actors +actor "<$actor>\nPayer" as Payer +participant "Payer\nFSP" as PayerFSP +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as PayeeFSP +actor "<$actor>\nPayee" as Payee + +' start flow +Payer ->> PayerFSP: I would like to Payee to\nreceive 100 USD +activate PayerFSP +PayerFSP ->> Switch: **POST /quotes**\n(amountType=RECEIVED,\namount=100 USD) +activate Switch +PayerFSP <<-- Switch: **HTTP 202** (Accepted) +Switch ->> PayeeFSP: **POST /quotes**\n(amountType=RECEIVE,\namount=100 USD) +activate PayeeFSP +Switch <<-- PayeeFSP: **HTTP 202** (Accepted) +PayeeFSP -> PayeeFSP: Rate transaction fee or\ncommission for handeling\ntransaction in Payee FSP => \nFSP commission 1 USD +Switch <<- PayeeFSP: **PUT /quotes/**\n(transferAmount=99 USD,\npayeeFspCommission=1 USD) +Switch -->> PayeeFSP: **HTTP 200** (OK) +deactivate PayeeFSP +PayerFSP <<- Switch: **PUT /quotes/** +PayerFSP -->> Switch: **HTTP 200** (OK) +deactivate Switch +PayerFSP -> PayerFSP: Keep commission\nfee for Payer for\nhandling transaction in\nPayer FSP => total fee 1 USD +PayerFSP ->> Payer: Sending 100 USD to Payee\nwill cost 1 USD in fees +deactivate PayerFSP +@enduml diff --git a/docs/technical/api/assets/diagrams/sequence/figure8.svg b/docs/technical/api/assets/diagrams/sequence/figure8.svg new file mode 100644 index 000000000..7ffa03a23 --- /dev/null +++ b/docs/technical/api/assets/diagrams/sequence/figure8.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + Payer + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + Payee + + + + + + + + + I would like to Payee to + receive 100 USD + + + + POST /quotes + (amountType=RECEIVED, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + POST /quotes + (amountType=RECEIVE, + amount=100 USD) + + + + HTTP 202 + (Accepted) + + + + + Rate transaction fee or + commission for handeling + transaction in Payee FSP => + FSP commission 1 USD + + + + PUT /quotes/ + <ID> + (transferAmount=99 USD, + payeeFspCommission=1 USD) + + + + HTTP 200 + (OK) + + + + PUT /quotes/ + <ID> + + + + HTTP 200 + (OK) + + + + + Keep commission + fee for Payer for + handling transaction in + Payer FSP => total fee 1 USD + + + + Sending 100 USD to Payee + will cost 1 USD in fees + + diff --git a/docs/technical/api/assets/figure1-platforms-layout.svg b/docs/technical/api/assets/figure1-platforms-layout.svg new file mode 100644 index 000000000..8a12de358 --- /dev/null +++ b/docs/technical/api/assets/figure1-platforms-layout.svg @@ -0,0 +1,3 @@ + + +
CA
CA
ALS
ALS
FSP-1
FSP-1
FSP-2
FSP-2
Switch
Switch
FSP-3
FSP-3
FSP-4
FSP-4
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Issuer: CN=CA
O=CA
Subject: CN=CA
O=CA
Issuer: CN=CA...
Legend:
Solid lines indicate TLS-secured communication.
Dashed lines indicate certificate owner.
Legend:...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/docs/technical/api/assets/scheme-rules-figure-1-http-timeout.png b/docs/technical/api/assets/scheme-rules-figure-1-http-timeout.png new file mode 100644 index 000000000..9d3faf74e Binary files /dev/null and b/docs/technical/api/assets/scheme-rules-figure-1-http-timeout.png differ diff --git a/docs/technical/api/assets/scheme-rules-figure-2-callback-timeout.png b/docs/technical/api/assets/scheme-rules-figure-2-callback-timeout.png new file mode 100644 index 000000000..04f5da996 Binary files /dev/null and b/docs/technical/api/assets/scheme-rules-figure-2-callback-timeout.png differ diff --git a/docs/technical/api/assets/sequence-diagram-figure-1.png b/docs/technical/api/assets/sequence-diagram-figure-1.png new file mode 100644 index 000000000..53215785d Binary files /dev/null and b/docs/technical/api/assets/sequence-diagram-figure-1.png differ diff --git a/docs/technical/api/fspiop/README.md b/docs/technical/api/fspiop/README.md new file mode 100644 index 000000000..2211014c5 --- /dev/null +++ b/docs/technical/api/fspiop/README.md @@ -0,0 +1,28 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- + +# FSPIOP API + +The Open API for FSP Interoperability Specification includes the following documents: + +## Logical Documents + +* [Logical Data Model](./logical-data-model.md) +* [Generic Transaction Patterns](./generic-transaction-patterns.md) +* [Use Cases](./use-cases.md) + +## Asynchronous REST Binding Documents + +* API Definition + * [FSPIOP v1.1](./v1.1/api-definition.md) + * [FSPIOP v1.0](./v1.0/api-definition.md) +* [Central Ledger API](#central-ledger-api) +* [JSON Binding Rules](#json-binding-rules) +* [Scheme Rules](./scheme-rules.md) + +## Data Integrity, Confidentiality, and Non-Repudiation + +* [PKI Best Practices](./pki-best-practices.md) +* [Signature](./v1.1/signature.md) +* [Encryption](./v1.1/encryption.md) diff --git a/docs/technical/api/fspiop/definitions.md b/docs/technical/api/fspiop/definitions.md new file mode 100644 index 000000000..e89691b20 --- /dev/null +++ b/docs/technical/api/fspiop/definitions.md @@ -0,0 +1,13 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- + +# FSPIOP API + +## Versions + +|Version|Date|Change Description| +|---|---|---| +|[1.0](./v1.0/api-definition)|2018-03-13|Initial version| +|[1.1](./v1.1/api-definition)|2020-05-19|1. This version contains a new option for a Payee FSP to request a commit notification from the Switch. The Switch should then send out the commit notification using the new request **PATCH /transfers/**_{ID}_. The option to use commit notification replaces the previous option of using the ”Optional Additional Clearing Check”. The section describing this has been replaced with the new section ”Commit Notification”. As the **transfers** resource has been updated with the new **PATCH** request, this resource has been updated to version 1.1. As part of adding the possibility to use a commit notification, the following changes has been made:
a. PATCH has been added as an allowed HTTP Method in Section 3.2.2. b. The call flow for **PATCH** is described in Section 3.2.3.5.
c. Table 6 in Section 6.1.1 has been updated to include **PATCH** as a possible HTTP Method.
d. Section 6.7.1 contains the new version of the **transfers** resource.
e. Section 6.7.2.6 contains the process for using commit notifications
f. Section 6.7.3.3 describes the new **PATCH /transfers**/_{ID}_ request.

2. In addition to the changes mentioned above regarding the commit notification, the following non-API affecting changes has been made:
a. Updated Figure 6 as it contained a copy-paste error.
b. Added Section 6.1.2 to describe a comprehensive view of the current version for each resource.
c. Added a section for each resource to be able to see the resource version history.
d. Minor editorial fixes.

3. The descriptions for two of the HTTP Header fields in Table 1 have been updated to add more specificity and context
a. The description for the **FSPIOP-Destination** header field has been updated to indicate that it should be left empty if the destination is not known to the original sender, but in all other cases should be added by the original sender of a request.
b. The description for the **FSPIOP-URI** header field has been updated to be more specific.

4. The examples used in this document have been updated to use the correct interpretation of the Complex type ExtensionList which is defined in Table 84. This doesn’t imply any change as such.
a. Listing 5 has been updated in this regard.

5. The data model is updated to add an optional ExtensionList element to the **PartyIdInfo** complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 103 has been updated. For consistency, the data model for the **POST /participants/**_{Type}/{ID}_ and **POST /participants/**_{Type}/{ID}/{SubId}_ calls in Table 10 has been updated to include the optional ExtensionList element as well.

6. A new Section 6.5.2.2 is added to describe the process involved in the rejection of a quote.

7. A note is added to Section 6.7.4.1 to clarify the usage of ABORTED state in **PUT /transfers/**_{ID}_ callbacks.| +|**1.1.1**|2021-09-22|This document version only adds information about optional HTTP headers regarding tracing support in [Table 2](#table-2), see _Distributed Tracing Support for OpenAPI Interoperability_ for more information. There are no changes in any resources as part of this version.| \ No newline at end of file diff --git a/docs/technical/api/fspiop/generic-transaction-patterns.md b/docs/technical/api/fspiop/generic-transaction-patterns.md new file mode 100644 index 000000000..8e0828344 --- /dev/null +++ b/docs/technical/api/fspiop/generic-transaction-patterns.md @@ -0,0 +1,1854 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- +# Generic Transaction Patterns + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| + +
+ +## Introduction + +This document introduces the four generic transaction patterns that are supported in a logical version of the Interoperability API. Additionally, all logical services that are part of the API are presented on a high-level. + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](#) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](./json-binding-rules) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](./v1.1/signature) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](./glossary) + +
+ +## Logical API Services + +The Interoperability API consists of a number of logical API resources. Each resource defines one or more services that clients can use to connect to a server that has implemented the API. This section introduces these services. + +**Note:** API services identified in this section may not be relevant to (and therefore may not appear in) the generic transaction patterns identified in [Generic Transaction Patterns](#generic-transaction-patterns). + +For example, some services are used for provisioning of information, are part of error cases, or are for retrieving information that is not necessary in a generic transaction pattern. + +
+ +### Common Functionality + +This section introduces functionality that is used by more than one logical API resource or service. + +#### Party Addressing + +A Party is an entity such as an individual, a business, an organization that has a financial account in one of the FSPs. A party is addressed by a combination of an _ID type_ and an _ID_, and possibly also a _subtype_ or _sub ID_. Some examples of _ID type_ and _ID_ combinations are: + +- _ID type_: **MSISDN**, _ID_: **+123456789** + +- _ID type_: **Email**, _ID_: **john@doe.com** + +#### Interledger + +The API includes basic support for the Interledger Protocol (ILP) by defining a concrete implementation of the Interledger Payment Request protocol[1](https://interledger.org/rfcs/0011-interledger-payment-request)(ILP) in the logical API resources **Quotes** and **Transfers**. More details of the ILP protocol can be found on the Interledger project website[2](https://interledger.org), in the Interledger Whitepaper[3](https://interledger.org/interledger.pdf), and in the Interledger architecture specification[4](https://interledger.org/rfcs/0001-interledger-architecture). + +
+ +### API Resource Participants + +In the API, a _Participant_ is the same as an FSP that is participating in an Interoperability Scheme. The primary purpose of the logical API resource **Participants** is for FSPs to find out in which other FSP a counterparty in an interoperable financial transaction is located. There are also services defined for the FSPs to provision information to a common system. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Lookup Participant Information + +The logical API service request `Lookup Participant Information` is used from an FSP to request from another system, which could be another FSP or a common system, information regarding in which FSP a counterparty in an interoperable financial transaction is located. + +- Successful response: [Return Participant Information](#return-participant-information) + +- Error response: [Return Participant Information Error](#return-participant-information-error) + +##### Create Participant Information + +The logical API service request `Create Participant Information` is used to provision information regarding in which FSP a party is located. + +- Successful response: [Return Participant Information](#return-participant-information) + +- Error response: [Return Participant Information Error](#return-participant-information-error) + +##### Create Bulk Participant Information + +The logical API service request `Create Bulk Participant Information` is used to provision information regarding in which FSP one or more parties are located. + +- Successful response: [Return Bulk Participant Information](#return-bulk-participant-information) + +- Error response: [Return Bulk Participant Information Error](#return-bulk-participant-information-error) + +##### Delete Participant Information + +The logical API service request `Delete Participant Information` is used to remove information regarding in which FSP a party is located. + +- Successful response: [Return Participant Information](#return-participant-information) + +- Error response: [Return Participant Information Error](#return-participant-information-error) + +
+ +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Participant Information + +The logical API service response `Return Participant Information` is used to return information from the requests [Lookup Participant Information](#lookup-participant-information), [Create Participant Information](#create-participant-information) and [Delete Participant Information](#delete-participant-information). + +##### Return Bulk Participant Information + +The logical API service response `Return Bulk Participant Information` is used to return information from the request [Create Bulk Participant Information](#create-bulk-participant-information). + +
+ +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Participant Information Error + +The logical API service error response `Return Participant Information Error` is used to return error information regarding the requests [Lookup Participant Information](#lookup-participant-information), [Create Participant Information](#create-participant-information) and [Delete Participant Information](#delete-participant-information). + +##### Return Bulk Participant Information Error + +The logical API service error response `Return Bulk Participant Information Error` is used to return information from the request [Create Bulk Participant Information](#create-bulk-participant-information). + +
+ +### API Resource Parties + +In the API, a _Party_ is an individual, a business, an organization, or a similar entity, that has a financial account in one of the FSPs. The primary purpose of the logical API resource **Parties** is for FSPs to ascertain information regarding a counterparty in an interoperable financial transaction, such as name and birth date of the Party. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Lookup Party Information + +The logical API service request `Lookup Party Information` is used by an FSP to request from another FSP information regarding a counterparty in an interoperable financial transaction. + +- Successful response: [Return Party Information](#return-party-information). + +- Error response: [Return Party Information Error](#return-party-information-error). + +
+ +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Party Information + +The logical API service response `Return Party Information` is used to return information from the request [Lookup Party Information](#lookup-party-information). + +
+ +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Party Information Error + +The logical API service error response `Return Party Information Error` is used to return error information regarding the request [Lookup Party Information](#lookup-party-information). + +
+ +### API Resource Transaction Requests + +In the API, a _Transaction Request_ is a request from a Payee to a Payer to transfer electronic funds to the Payee, which the Payer can accept or reject. The primary purpose of the logical API resource **Transaction Requests** is for a Payee FSP to send the request to transfer to the Payer FSP. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Perform Transaction Request + +The logical API service request `Perform Transaction Request` is used to send a Transaction Request from a Payee FSP to the Payer FSP; that is, to ask if a Payer will accept or reject a transaction from the Payer to the Payee. + +- Successful response: [Return Transaction Request Information](#return-transaction-request-information) + +- Error response: [Return Transaction Request Information Error](#return-transaction-request-information-error) + +##### Retrieve Transaction Request Information + +The logical API service request `Retrieve Transaction Request Information` is used from a Payee FSP to a Payer FSP to request information regarding a previously-sent Transaction Request. + +- Successful response: [Return Transaction Request Information](#return-transaction-request-information) + +- Error response: [Return Transaction Request Information Error](#return-transaction-request-information-error) + +
+ +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Transaction Request Information + +The logical API service response `Return Transaction Request Information` is used to return information from the requests [Perform Transaction Request](#perform-transaction-request) or [Retrieve Transaction Request Information](#retrieve-transaction-request-information). + +
+ +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Transaction Request Information Error + +The logical API service error response `Return Transaction Request Information Error` is used to return error information regarding the requests [Perform Transaction Request](#perform-transaction-request) or [Retrieve Transaction Request Information](#retrieve-transaction-request-information). + +
+ +### API Resource Quotes + +In the API, a _Quote_ is the price for performing an interoperable financial transaction from the Payer FSP to the Payee FSP. The primary purpose of the logical API resource **Quotes** is for a Payer FSP to request a Payee FSP to calculate the Payee FSP's part of the quote. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Calculate Quote + +The logical API service request `Calculate Quote` is used from a Payer FSP to ask a Payee FSP to calculate the Payee FSP's part of the quote to perform an interoperable financial transaction. The Payee FSP should also create the ILP Packet and the condition (see [Interledger](#interledger) section for links to more information) when receiving the request. + +- Successful response: [Return Quote Information](#return-quote-information) + +- Error response: [Return Quote Information Error](#return-quote-information-error) + +
+ +##### Retrieve Quote Information + +The logical API service request `Retrieve Quote Information` is used by a Payer FSP to request that a Payee FSP ask for information regarding a previously-sent [Calculate Quote](#calculate-quote) request. + +- Successful response: [Return Quote Information](#return-quote-information) + +- Error response: [Return Quote Information Error](#return-quote-information-error) + +
+ +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Quote Information + +The logical API service response `Return Quote Information` is used to return information from the requests [Calculate Quote](#calculate-quote) or [Retrieve Quote Information](#retrieve-quote-information). + +
+ +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Quote Information Error + +The logical API service error response `Return Quote Information Error` is used to return error information regarding the requests [Calculate Quote](#calculate-quote) or [Retrieve Quote Information](#retrieve-quote-information). + +
+ +### API Resource Authorizations + +In the API, an _Authorization_ is an approval from a Payer to perform an interoperable financial transaction by entering the applicable credentials in a Payee FSP system. An example where this kind of approval is used, is when a Payer is using an ATM that is managed by another FSP. The primary purpose of the logical API resource **Authorizations** is for a Payer FSP to request a Payee FSP to ask the Payer to enter the credentials. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Perform Authorization + +The logical API service request `Perform Authorization` is used from a Payer FSP to ask a Payee FSP to enter the applicable credentials to approve an interoperable financial transaction. + +- Successful response: [Return Authorization Result](#return-authorization-result) + +- Error response: [Return Authorization Error](#return-authorization-error) + +
+ +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Authorization Result + +The logical API service response `Return Authorization Result` is used to return information from the request [Perform Authorization](#perform-authorization). + +
+ +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Authorization Error + +The logical API service error response `Return Authorization Error` is used to return error information regarding the request [Perform Authorization](#perform-authorization). + +
+ +### API Resource Transfers + +In the API, a _Transfer_ is hop-to-hop ILP (see [Interledger](#interledger) section for links to more information) transfer of funds. + +The transfer also contains information regarding the end-to-end interoperable financial transaction. The primary purpose of the logical API resource **Transfers** is for an FSP or Switch to request that the next entity in the chain of the ILP Payment perform the transfer involved in the interoperable financial transaction. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Perform Transfer + +The logical API service request `Perform Transfer` is used by an FSP or Switch to request the next entity in the chain of the ILP Payment to reserve the transfer involved in an interoperable financial transaction. + +- Successful response: [Return Transfer Information](#return-transfer-information) + +- Error response: [Return Transfer Information Error](#return-transfer-information-error) + +##### Retrieve Transfer Information + +The logical API service request `Retrieve Transfer Information` is used by an FSP or Switch to request the next entity in the chain of the ILP Payment for information regarding the transfer involved in an interoperable financial transaction. + +- Successful response: [Return Transfer Information](#return-transfer-information) + +- Error response: [Return Transfer Information Error](#return-transfer-information-error) + +
+ +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Transfer Information + +The logical API service response `Return Transfer Information` is used to return information from the requests [Perform Transfer](#perform-transfer) or [Retrieve Transfer Information](#retrieve-transfer-information). On receiving the [Return Transfer Information](#return-transfer-information) response, the FSP or Switch should validate the fulfilment (see [Interledger](#interledger) section for links to more information) and commit the reserved transfer if the validation is successful. + +
+ +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Transfer Information Error + +The logical API service error response `Return Transfer Information Error` is used to return error information regarding the requests [Perform Transfer](#perform-transfer) or [Retrieve Transfer Information](#retrieve-transfer-information). + +
+ +### API Resource Transactions + +In the API, a _Transaction_ is an end-to-end interoperable financial transaction between the Payer FSP and Payee FSP. The primary purpose of the logical API resource **Transactions** is for a Payer FSP to request end-to-end information from the Payee FSP regarding an interoperable financial transaction; for example, in order to get a token or code that the Payer can use to redeem a service or product. + +### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Retrieve Transaction Information + +The logical API service request `Retrieve Transaction Information` is used by a Payer FSP to request that a Payee FSP get information regarding a previously-performed interoperable financial transaction (by using the logical API resource **Transfers**, see [API Resource Tarnsfers](#api-resource-transfers) section). + +- Successful response: [Return Transfer Information](#return-transfer-information) + +- Error response: [Return Transfer Information Error](#return-transfer-information-error) + +
+ +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Transaction Information + +The logical API service response`*Return Transaction Information` is used to return information from the request [Retrieve Transfer Information](#retrieve-transfer-information). + +
+ +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Transaction Information Error + +The logical API service error response `Return Transaction Information Error` is used to return error information regarding the request [Retrieve Transfer Information](#retrieve-transfer-information). + +
+ +### API Resource Bulk Quotes + +In the API, a _Bulk Quote_ is a collection of individual quotes (see [API Resource Quotes](#api-resource-quotes) section for information regarding a single quote) for performing more than one interoperable financial transaction from the Payer FSP to the Payee FSP. + +The primary purpose of the logical API resource **Bulk Quotes** is for a Payer FSP to request a Payee FSP to calculate the Payee FSP's part of the bulk quote. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Calculate Bulk Quote + +The logical API service request `Calculate Bulk Quote` is used by a Payer FSP to request that a Payee FSP calculate the Payee FSP's part of the quotes to perform more than one interoperable financial transaction. + +The Payee FSP should also create the ILP Packet and the condition (see [Interledger](#interledger) section for links to more information) per quote when receiving the request. + +- Successful response: [Return Bulk Quote Information](#return-bulk-quote-information) + +- Error response: [Return Bulk Quote Information Error](#return-bulk-quote-information-error) + +##### Retrieve Bulk Quote Information + +The logical API service request `Retrieve Bulk Quote Information` is used by a Payer FSP to request that a Payee FSP ask for information regarding a previously-sent [Calculate Bulk Quote](#calculate-bulk-quote) request. + +- Successful response: [Return Bulk Quote Information](#return-bulk-quote-information) + +- Error response: [Return Bulk Quote Information Error](#return-bulk-quote-information-error) + +
+ +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Bulk Quote Information + +The logical API service response `Return Bulk Quote Information` is used to return information from the requests [Calculate Bulk Quote](#calculate-bulk-quote) or [Retrieve Bulk Quote Information](#retrieve-bulk-quote-information). + +
+ +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Bulk Quote Information Error + +The logical API service error response `Return Bulk Quote Information Error` is used to return error information regarding the requests [Calculate Bulk Quote](#calculate-bulk-quote) or [Retrieve Bulk Quote Information](#retrieve-bulk-quote-information). + +
+ +### API Resource Bulk Transfers + +In the API, a _Bulk Transfer_ is a collection of hop-to-hop ILP (see [Interledger.](#interledger)section for links to more information) transfers of funds. The transfers also contain information regarding the end-to-end interoperable financial transactions. + +The primary purpose of the logical API resource **Bulk Transfers** is to enable an FSP or Switch to request that the next entity in the chain of the ILP Payment perform the transfers involved in the interoperable financial transactions. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Perform Bulk Transfer + +The logical API service request `Perform Bulk Transfer` is used by an FSP or Switch to request that the next entity in the chain of the ILP Payment reserve the transfer involved in an interoperable financial transaction. + +- Successful response: [Return Bulk Transfer Information](#return-bulk-transfer-information) + +- Error response: [Return Bulk Transfer Information Error](#return-bulk-transfer-information-error) + + +##### Retrieve Bulk Transfer Information + +The logical API service request `Retrieve Bulk Transfer Information` is used from an FSP or Switch to request that the next entity in the chain of the ILP Payment for information regarding the transfer involved in an interoperable financial transaction. + +- Successful response: [Return Bulk Transfer Information](#return-bulk-transfer-information) + +- Error response: [Return Bulk Transfer Information Error](#return-bulk-transfer-information-error) + +
+ +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Bulk Transfer Information + +The logical API service response `Return Bulk Transfer Information` is used to return information from the requests [Perform Bulk Transfer](#perform-bulk-transfer) or [Retrieve Bulk Transfer Information](#retrieve-bulk-transfer-information). + +On receiving the response **Return Bulk Transfer Information**, the FSP or Switch should validate the fulfilments (see [Interledger](#interledger) section for links to more information) and commit the reserved transfers if the validations are successful. + +
+ +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Bulk Transfer Information Error + +The logical API service error response `Return Bulk Transfer Information Error` is used to return error information regarding the requests [Perform Bulk Transfer](#perform-bulk-transfer) or [Retrieve Bulk Transfer Information](#retrieve-bulk-transfer-information). + +
+ +## Generic Transaction Patterns + +This section provides information about the three primary transaction patterns defined in the Interoperability API: + +- [Payer-Initiated Transaction](#payer-initiated-transaction) + +- [Payee-Initiated Transaction](#payee-initiated-transaction) + +- [Bulk Transaction](#bulk-transaction) + +Each transaction pattern defines how funds can be transferred from a Payer located in one Financial Service Provider (FSP) to a Payee located in another FSP. + +Both the [Payer-Initiated Transaction](#payer-initiated-transaction) and the [Payee-Initiated Transaction](#payee-initiated-transaction) patterns are intended for a single transfer of funds from one Payer to one Payee. The significant difference between the two patterns is in which of the participants in the transaction is responsible for the initiation of the transaction. + +The [Bulk Transaction](#bulk-transaction) pattern should be used when a single Payer would like to transfer funds to multiple Payees, possibly in different FSPs, in a single transaction. + +This section also provides information about _Payee-Initiated Transaction using OTP_. which is an alternative to the [Payee-Initiated Transaction](#payee-initiated-transaction). + +Additionally, the section provides high-level information about all logical services that are part of the API. + +
+ +### Payer-Initiated Transaction + +In a _Payer-Initiated Transaction_, the `Payer` initiates the transaction. + +#### Business Process Pattern Description + +The _Payer-Initiated Transaction_ pattern should be used whenever a `Payer` would like to transfer funds to another party whose account is not located in the same FSP. + +In most implementations, `Payee` involvement is limited to receiving a notification in the event of a successful transaction. Exceptions in which the Payee is more involved are: + +- In countries that require the `Payee` to confirm receipt of funds. + +- Cases in which the `Payee` should accept the terms of the transaction (for example, Agent-Initiated Cash-In). + +#### Participants and Roles + +The actors in a _Payer-Initiated Transaction_ are: + +- **Payer** -- The payer of funds in a financial transaction. + +- **Payee** -- The recipient of funds in a financial transaction. + + +The intermediary objects used in a _Payer-Initiated Transaction_ to perform the transaction are: + +- **Payer FSP** -- The FSP in which the Payer's account is located. + +- **Switch (optional)** -- An optional entity used for routing of requests between different FSPs. This object can be removed if requests should be routed directly between a Payer and Payee FSP. + +- **Account Lookup System** -- An entity used for retrieving information regarding accounts or participants. Could be hosted in a separate server, in the Switch, or in the different FSPs. + +- **Payee FSP** -- The FSP in which the Payee's account is located. + + +#### Business Process Sequence Diagram + +Figure 1 shows the UML sequence diagram for a _Payer-Initiated Transaction_. + +![](../assets/diagrams/sequence/figure64a.svg) + +**Figure 1 -- Payer-Initiated Transaction** + +#### Internal Processing Steps + +This section provides descriptions of and assumptions made for all steps in the sequence shown in [Figure 1](#business-process-sequence-diagram). + +##### Lookup Counterparty + +1. **Description** + + The `Payer` initiates the transaction by requesting to send funds to a `Payee`, using the `Payer FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + None. + +2. **Description** + + The `Payer FSP` tries to find the `Payee` within the FSP system. Because the `Payee` cannot be found in the `Payer FSP` system, the request [Lookup Party Information](#lookup-party-information) is sent by the `Payer FSP` to the optional `Switch` to get information regarding the `Payee`, including in which FSP the `Payee` is located. + + **Assumptions** + + The Payee is assumed to be in a different FSP than the `Payer`. Also, a `Switch` is assumed to be placed between the `Payer FSP` and the `Payee FSP` to route the messages between FSPs. The `Switch` is optional in the process, as the request [Lookup Party Information](#lookup-party-information) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. As the `Payer FSP` should not know in which FSP the `Payee` is located if there is no `Switch` present, the request might need to be sent to more than one FSP. + +3. **Description** + + The `Switch` receives the request [Lookup Party Information](#lookup-party-information). The `Switch` then tries to find in which FSP the `Payee` is located by sending the request [Lookup Participant Information](#lookup-participant-information) to the `Account Lookup System`. + + **Assumptions** + + An `Account Lookup System` is assumed to exist in a different server than the `Switch`. It is possible that the `Account Lookup System` is in the same system as the `Switch`. + +4. **Description** + + The `Account Lookup System` receives the request [Lookup Participant Information](#lookup-participant-information). It then performs an internal lookup to find in which FSP the `Payee` is located. When the lookup is completed, the response [Return Participant Information](#return-participant-information) is sent to inform the Switch about which FSP the `Payee` is located in. + + **Assumptions** + + The `Payee` can be found by the `Account Lookup System`. + +5. **Description** + + The `Switch` receives the response [Return Participant Information](#return-participant-information). As the `Switch` now knows in which FSP the `Payee` is located, the `Switch` sends the request [Lookup Participant Information](#lookup-participant-information) to the `Payee FSP` to get more information about the `Payee`. + + **Assumptions** + + None. + +6. **Description** + + The `Payee FSP` receives the request [Lookup Participant Information](#lookup-participant-information). The `Payee FSP` then does an internal lookup to find more information regarding the `Payee` and sends the response [Return Participant Information](#return-participant-information) to the `Switch`. + + **Assumptions** + + None. + +7. **Description** + + The `Switch` receives the response [Return Party Information](#return-party-information). The `Switch` then routes the [Return Party Information](#return-party-information) response to the `Payer FSP` to send the information about the `Payee`. + + **Assumptions** + + None. + +8. **Description** + + The `Payer FSP` receives the response [Return Party Information](#return-party-information) containing information about the `Payee`. + + **Assumptions** + + None. + +
+ +##### Calculate Quote + +9. **Description** + + Depending on the fee model used, the `Payer FSP` rates the transaction internally and includes the quote information in the request [Calculate Quote](#calculate-quote) to a `Switch` to retrieve the full quote for performing the interoperable financial transaction from the `Payer FSP` to the `Payee FSP`. The transaction details are sent in the parameters of the request to allow for the `Payee FSP` to correctly calculate the quote. + + **Assumptions** + + In this sequence, a `Switch` is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The `Switch` is optional in the process, as the request[Calculate Quote](#calculate-quote) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. + +10. **Description** + + The `Switch` receives the [Calculate Quote](#calculate-quote) request. The `Switch` then routes the request to the `Payee FSP`, using the same parameters. + + **Assumptions** + + None. + +11. **Description** + + The `Payee FSP` receives the [Calculate Quote](#calculate-quote) request. The `Payee FSP` then internally calculates the fees or FSP commission for performing the transaction. It then constructs the ILP Packet containing the ILP Address of the `Payee`, the amount that the `Payee` will receive, and the transaction details. The fulfilment and the condition are then generated out of the ILP Packet combined with a local secret. + + **Assumptions** + + None. + + **Optional procedure: Quote Confirmation by Payee** + + a. **Description** + + Depending on the use case and the fee model used, the `Payee` might be informed of the quote in order to confirm the proposed financial transaction. The quote is in that case sent to the `Payee` using a front-end API (outside the scope of this API). The `Payee` receives the quote including information regarding the transaction including fees and optionally `Payer` name. The `Payee` then confirms the quote using a front-end API (outside the scope of this API), and the `Payee FSP` receives the confirmation from the `Payee`. + + **Assumptions** + + The `Payee` is assumed to accept and confirm the quote. If the `Payee` would reject the quote, an error response would be sent from the `Payee` FSP to the `Payer FSP` via the `Switch` to inform about the rejected quote. + + **End of Optional procedure** + +12. **Description** + + The `Payee FSP` uses the response [Return Quote Information](#return-quote-information) to the `Switch` to return information to the `Payer FSP` about the quote, the ILP Packet, and the condition. The quote has an expiration time, to inform the `Payer FSP` until which point in time the quote is valid. + + **Assumptions** + + None. + +13. **Description** + + The `Switch` receives the response [Return Quote Information](#return-quote-information). The `Switch` will then route the response to the `Payer FSP`. + + **Assumptions** + + None. + +14. **Description** + + The `Payer FSP` receives the response[Return Quote Information](#return-quote-information) from the `Switch`. The `Payer FSP` then informs the `Payer` using a front-end API (outside the scope of this API) about the total fees to perform the transaction, along with the `Payee` name. + + **Assumptions** + + The total quote can be calculated by the `Payer FSP`. Also, the `Payee` name was allowed to be sent during the counterparty lookup (depending on regulation on privacy laws). + +15. **Description** + + The `Payer` receives the transaction information including fees, taxes and optionally `Payee` name. If the `Payer` rejects the transaction, the sequence ends here. + + **Assumptions** + + The `Payer` is assumed to approve the transaction in this sequence. If the `Payer` would reject the transaction at this stage, no response regarding the rejection is sent to the `Payee FSP`. The created quote at the `Payee FSP` should have an expiry time, at which time it is automatically deleted. + +
+ +##### Perform Transfer + +16. **Description** + + The `Payer FSP` receives an approval of the interoperable financial transaction using a front-end API (out of scope of this API). The `Payer FSP` then performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on). If the validations are successful, a transfer of funds is reserved from the `Payer`'s account to either a combined `Switch` account or a `Payee FSP` account, depending on setup. After the transfer has been successfully reserved, the request [Perform Transfer](#perform-transfer) is sent to the `Switch` to request the `Switch` to transfer the funds from the `Payer FSP` account in the Switch to the `Payee FSP` account. The request [Perform Transfer](#perform-transfer) includes a reference to the earlier quote, an expiry of the transfer, the ILP Packet, and the condition that was received from the `Payee FSP`. The interoperable financial transaction is now irrevocable from the `Payer FSP`. + + **Assumptions** + + Internal validations and reservation are assumed to be successful. In this sequence, a `Switch` is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The `Switch` is optional in the process, as the request [Perform Transfer](#perform-transfer) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. + +17. **Description** + + The `Switch` receives the request [Perform Transfer](#perform-transfer). The `Switch` then performs all its applicable internal transfer validations (for example, limit checks blacklist check and so on). If the validations are successful, a transfer is reserved from a `Payer FSP` account to a `Payee FSP` account. After the transfer has been successfully reserved, the request [Perform Transfer](#perform-transfer) is sent to the `Payee FSP`, including the same ILP Packet and condition as was received from the `Payer FSP`. The expiry time should be decreased by the `Switch` so that the `Payee FSP` should answer before the `Switch` answers to the `Payer FSP`. The transfer is now irrevocable from the `Switch`. + + **Assumptions** + + Internal validations and reservation are successful. + +18. **Description** + + The `Payee FSP` receives the request [Perform Transfer](#perform-transfer). The `Payee FSP` then performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on). It also verifies that the amount and ILP Address in the ILP Packet are correct and match the amount and `Payee` in the transaction details stored in the ILP Packet. If all the validations are successful, a transfer of funds is performed from either a combined `Switch` account or a `Payer FSP` account to the `Payee`'s account and the fulfilment of the condition is regenerated, using the same secret as in Step 11. After the interoperable financial transaction has been successfully performed, a transaction notification is sent to the `Payee` using a front-end API (out of scope of this API) and the response **Return Transfer Information** is sent to the `Switch`, including the regenerated fulfilment. The transfer is now irrevocable from the `Payee FSP`. + + **Assumptions** + + Internal validations and transfer of funds are successful. + +19. **Description** + + The `Payee` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +20. **Description** + + The `Switch` receives the response [Return Transfer Information](#return-transfer-information). The `Switch` then validates the fulfilment and commits the earlier reserved transfer. The `Switch` then uses the response [Return Transfer Information](#return-transfer-information) to the `Payer FSP`, using the same parameters. + + **Assumptions** + + The fulfilment is assumed to be correctly validated. + +21. **Description** + + The `Payer FSP` receives the response [Return Transfer Information](#return-transfer-information). The `Payer FSP` then validates the fulfilment and commits the earlier reserved transaction. + + **Assumptions** + + The fulfilment is assumed to be correctly validated. + +**Optional fragment: Get Transaction Details** + +22. **Description** + + In case the interoperable financial transaction contains additional information that is useful for the `Payer` or the `Payer FSP`, such as a code or a voucher token, the `Payer FSP` can use the request [Return Transfer Information](#return-transfer-information) to get the additional transaction information. The request [Retrieve Transaction Information](#retrieve-transaction-information) is sent to the `Switch`. + + **Assumptions** + + None. + +23. **Description** + + The `Switch` receives the request [Retrieve Transaction Information](#retrieve-transaction-information). The `Switch` then routes the [Retrieve Transaction Information](#retrieve-transaction-information) request to the `Payee FSP`. + + **Assumptions** + + None. + +24. **Description** + + The `Payee FSP` receives the request [Retrieve Transaction Information](#retrieve-transaction-information). The `Payee FSP` then collects the requested information and sends the response [Return Transaction Information](#return-transaction-information) to the `Switch`. + + **Assumptions** + + The transaction with the provided ID can be found in the `Payee FSP`. + +25. **Description** + + The `Switch` receives the response [Return Transaction Information](#return-transaction-information). The Switch then routes the [Return Transaction Information](#return-transaction-information) response to the `Payer FSP`. + + **Assumptions** + + None. + +26. **Description** + + The `Payer FSP` receives the response [Return Transaction Information](#return-transaction-information). + + **Assumptions** + + None. + + **End of Optional fragment** + +28. **Description** + + The `Payer FSP` sends a transaction notification to the `Payee` using a front-end API (out of scope of this API), optionally including transaction details retrieved from the `Payee FSP`. + + **Assumptions** + + None. + +29. **Description** + + The `Payer` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +
+ +### Payee-Initiated Transaction + +In a _Payee-Initiated Transaction_, the `Payee` (that is, the recipient of electronic funds) initiates the transaction. + +#### Business Process Pattern Description + +The pattern should be used whenever a `Payee` would like to receive funds from another party whose account is not located in the same FSP. + +In all alternatives to this pattern, the `Payer` must in some way confirm the request of funds. Some possible alternatives for confirming the request are: + +- **Manual approval** -- A transaction request is routed from the Payee to the Payer, the Payer can then either approve or reject the transaction. + +- **Pre-approval of Payee** -- A Payer can pre-approve a specific Payee to request funds, used for automatic approval of, for example, school fees or electric bills. + +Another alternative for approval is to use the business pattern [Payee-Initiated Transaction using OTP](#payee-initiated-transaction-using-otp). + +#### Participants and Roles + +The actors in a _Payee-Initiated Transaction_ are: + +- **Payer** -- The payer of funds in a financial transaction. + +- **Payee** -- The recipient of funds in a financial transaction. + +The intermediary objects used in a _Payee-Initiated Transaction_ to perform the transaction are: + +- **Payer FSP** -- The FSP in which the Payer's account is located. + +- **Switch (optional)** -- An optional entity used for routing of requests between different FSPs. This object can be removed if requests should be routed directly between a Payer and Payee FSP. + +- **Account Lookup System** -- An entity used for retrieving information regarding accounts or participants. Could be hosted in a separate server, in the Switch, or in the different FSPs. + +- **Payee FSP** -- The FSP in which the Payee's account is located. + +#### Business Process Sequence Diagram + +Figure 2 shows the UML sequence diagram for a _Payee-Initiated Transaction_. + +![](../assets/diagrams/sequence/figure65a.svg) + +**Figure 2 -- Payee-Initiated Transaction** + +#### Internal Processing Steps + +This section provides descriptions of and assumptions made for all steps in the sequence shown in Figure 2 above. + +##### Lookup Counterparty + +1. **Description** + + The `Payee` initiates the transaction by requesting to receive funds from a `Payer`, using the `Payee FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + None. + +2. **Description** + + The `Payee FSP` tries to find the Payer within the FSP system. Because the `Payer` cannot be found in the `Payee FSP` system, the `Payee FSP` sends the request to the optional `Account Lookup System` to get information regarding in which FSP the `Payer` is located. + + **Assumptions** + + The `Payer` is assumed to be located in a different FSP than the `Payee`. Also, an `Account Lookup System` is assumed to exist. + + The `Account Lookup System` is optional in the process, as the request [Lookup Participant Information](#lookup-participant-information) could also be sent directly to the` Payer FSP` if there is no `Account Lookup System`. As the `Payee FSP` should not know in which FSP the Payer is located if there is no `Account Lookup System` present, the request might need to be sent to more than one FSP. It is also possible that the `Payee FSP` would like more information about the `Payer` before a transaction request is sent; in that case the request [Lookup Participant Information](#lookup-participant-information), either to the Switch or directly to the `Payer FSP`, should be sent instead of [Lookup Participant Information](#lookup-participant-information) to the `Account Lookup System`. + +3. **Description** + + The `Account Lookup System` receives the [Lookup Participant Information](#lookup-participant-information). It then performs an internal lookup to find in which FSP the `Payer` is located. When the lookup is completed, the response [Return Participant Information](#return-participant-information) is sent to inform the `Payee FSP` about which FSP the `Payer` is located. + + **Assumptions** + + The `Payer` can be found by the `Account Lookup System`. + +4. **Description** + + The `Payee FSP` receives the response [Return Participant Information](#return-participant-information). + + **Assumptions** + + None. + + **Transaction Request** + +5. **Description** + + The `Payee FSP` sends the request [Perform Transaction Request](#perform-transaction-request) to the `Switch`. The request contains the transaction details including the amount that the Payee would like to receive. + + **Assumptions** + + In this sequence, a `Switch` is placed between the `Payee FSP` and the `Payer FSP` to route the messages. The `Switch` is optional in the process, as the request [Perform Transaction Request](#perform-transaction-request) could also be sent directly to the `Payer FSP` if there is no Switch in-between. + +6. **Description** + + The `Switch` receives the [Perform Transaction Request](#perform-transaction-request). The `Switch` then routes the request to the `Payer FSP`, using the same parameters. + + **Assumptions** + + None. + +7. **Description** + + The `Payer FSP` receives the request [Perform Transaction Request](#perform-transaction-request). The `Payer FSP` then optionally validates the transaction request (for example, whether the `Payer` exists) and uses the response [Return Transaction Request Information](#return-transaction-request-information) to inform the `Payee FSP` via the `Switch` that the transaction request has been received. + + **Assumptions** + + The optional validation succeeds. + +8. **Description** + + The `Switch` receives the response [Return Transaction Request Information](#return-transaction-request-information). The `Switch` then sends the same response [Return Transaction Request Information](#return-transaction-request-information) to inform the `Payee FSP` about the successfully delivered transaction request to the `Payer FSP`. + + **Assumptions** + + None. + +9. **Description** + + The `Payee FSP` receives the response [Return Transaction Request Information](#return-transaction-request-information) from the `Switch`. + + **Assumptions** + + None. + +
+ +##### Calculate Quote + +10. **Description** + + The `Payer FSP` rates the transaction internally based on the fee model used and includes the quote information in the request[Calculate Quote](#calculate-quote) to a `Switch` to retrieve the full quote for performing the interoperable financial transaction from the `Payer FSP` to the `Payee FSP`. The transaction details, including a reference to the earlier sent transaction request, are sent in the parameters of the request to allow for the `Payee FSP` to correctly calculate the quote. + + **Assumptions** + + In this sequence, a `Switch` is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The `Switch` is optional in the process, as the request [Calculate Quote](#calculate-quote) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. + +11. **Description** + + The `Switch` receives the [Calculate Quote](#calculate-quote) request. The `Switch` then routes the request to the `Payee FSP`. + + **Assumptions** + + None. + +12. **Description** + + The `Payee FSP` receives the [Calculate Quote](#calculate-quote) request. The `Payee FSP` then internally calculates the fees or FSP commission for performing the transaction. It then constructs the ILP Packet containing the ILP Address of the `Payee`, the amount that the `Payee` will receive, and the transaction details. The fulfilment and the condition are then generated out of the ILP Packet combined with a local secret. + + **Assumptions** + + None + +13. **Description** + + Depending on use case and the fee model used, the `Payee` might be informed of the quote so that the `Payee` can confirm the proposed financial transaction. The quote is in that case sent to the `Payee` using a front-end API (outside the scope of this API). The `Payee` receives the quote including information regarding the transaction including fees and optionally Payer name. The `Payee` then confirms the quote using a front-end API (outside the scope of this API). The `Payee FSP` receives the confirmation from the `Payee`. + + **Assumptions** + + The quote is assumed to be sent to the `Payer` for confirmation, and the `Payee` is assumed to accept and confirm the quote. If the `Payee` would reject the quote, an error response would be sent from the `Payee FSP` to the `Payer FSP` via the `Switch` to inform about the rejected quote. + + **End of Optional fragment** + +14. **Description** + + The `Payee FSP` uses the response [Return Quote Information](#return-quote-information) to the `Switch` to return information to the `Payer FSP` about the quote, the ILP Packet, and the condition. The quote has an expiration time, to inform the `Payer FSP` until which point in time the quote is valid. + + **Assumptions** + + None. + +15. **Description** + + The `Switch` receives the response [Return Quote Information](#return-quote-information). The `Switch` then routes the response to the `Payer FSP`. + + **Assumptions** + + None. + +16. **Description** + + The `Payer FSP` receives the response [Return Quote Information](#return-quote-information) from the `Switch`. The `Payer FSP` then informs the `Payer` using a front-end API (outside the scope of this API) about the transaction request from the `Payee`, including the amount and the total fees required to perform the transaction, along with the `Payee` name. + + **Assumptions** + + The total quote can be calculated by the `Payer FSP`. Also, the `Payee` name was allowed to be sent during the counterparty lookup (depending on regulation on privacy laws). + +17. **Description** + + The `Payer` receives the transaction request information including fees, taxes and optionally `Payee` name. + + **Assumptions** + + If the `Payer` rejects the transaction request, the sequence proceeds to Step 18. If the `Payer` approves the transaction request, the sequence proceeds to Step 22. + + **Alternative: Transaction Rejection** + +18. **Description** + + The `Payer FSP` receives the rejection of the transaction request using a front-end API (out of scope of this API). The `Payer FSP` then uses the response [Return Transaction Request Information](#return-transaction-request-information) with a rejected status to inform the `Switch` that the transaction was rejected. + + **Assumptions** + + The `Payer` is assumed to reject the transaction request in Step 17. + +19. **Description** + + The `Switch` receives the response [Return Transaction Request Information](#return-transaction-request-information) from the `Payer FSP`. The `Switch` then routes the response [Return Transaction Request Information](#return-transaction-request-information) to the `Payee FSP`. + + **Assumptions** + + None. + +20. **Description** + + The `Payee FSP` receives the response *[Return Transaction Request Information](#return-transaction-request-information) with a rejected status from the `Switch`. The `Payee FSP` then informs the Payee using a front-end API (outside the scope of this API) about the rejected transaction request. + + **Assumptions** + + None. + +21. **Description** + + The `Payee` receives the notification that the transaction was rejected. The process ends here as the transaction request was rejected and the `Payee` has been informed of the decision. + + **Assumptions** + + None. + + **Alternative: Perform Transfer** + +22. **Description** + + The `Payer FSP` receives an approval of the interoperable financial transaction using a front-end API (out of scope of this API). The `Payer FSP` then performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on). If the validations are successful, a transfer of funds is reserved from the `Payer`'s account to either a combined `Switch` account or a `Payee FSP` account, depending on setup. After the transfer has been successfully reserved, the request [Perform Transfer](#perform-transfer) is sent to the `Switch` to request the `Switch` to transfer the funds from the `Payer FSP` account in the `Switch` to the `Payee FSP` account. The request [Perform Transfer](#perform-transfer) includes a reference to the earlier quote, an expiry of the transfer, the ILP Packet, and the condition that was received from the `Payee FSP`. The interoperable financial transaction is now irrevocable from the `Payer FSP`. + + **Assumptions** + + The `Payer` is assumed to approve the transaction request in Step 17. Internal validations and reservation are assumed to be successful. In this sequence, a `Switch` is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The Switch is optional in the process, as the request [Perform Transfer](#perform-transfer) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. + +23. **Description** + + The `Switch` receives the request [Perform Transfer](#perform-transfer). The `Switch` then performs all its applicable internal transfer validations (for example, limit checks, blacklist check, and so on). If the validations are successful, a transfer is reserved from a `Payer FSP` account to a `Payee FSP` account. After the transfer has been successfully reserved, the request [Perform Transfer](#perform-transfer) is sent to the `Payee FSP`, including the same ILP Packet and condition as was received from the Payer FSP. The expiry time should be decreased by the `Switch`, so that the `Payee FSP` should answer before the `Switch` should answer to the `Payer FSP`. The transfer is now irrevocable from the `Switch`. + + **Assumptions** + + Internal validations and reservation are successful. + +24. **Description** + + The `Payee FSP` receives the request [Perform Transfer](#perform-transfer). The `Payee FSP` then performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on). It also verifies that the amount and ILP Address in the ILP Packet are correct and match the amount and `Payee` in the transaction details stored in the ILP Packet. If all the validations are successful, a transfer of funds is performed from either a combined `Switch` account or a `Payer FSP` account to the `Payee`'s account and the fulfilment of the condition is regenerated, using the same secret as in Step 11. After the interoperable financial transaction has been successfully performed, a transaction notification is sent to the Payee using a front-end API (out of scope of this API) and the response [Return Transfer Information](#return-transfer-information) is sent to the `Switch`, including the regenerated fulfilment. The transfer is now irrevocable from the `Payee FSP`. + + **Assumptions** + + Internal validations and transfer of funds are successful. + +25. **Description** + + The `Payee` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +26. **Description** + + The `Switch` receives the response [Return Transfer Information](#return-transfer-information). The `Switch` then validates the fulfilment and commits the earlier reserved transfer. The `Switch` then uses the response [Return Transfer Information](#return-transfer-information) to the `Payer FSP`, using the same parameters. + + **Assumptions** + + The fulfilment is assumed to be correctly validated. + +27. **Description** + + The `Payer FSP` receives the response [Return Transfer Information](#return-transfer-information). The `Payer FSP` then validates the fulfilment and commits the earlier reserved transaction. + + **Assumptions** + + The fulfilment is assumed to be correctly validated. + + **Optional fragment: Get Transaction Details** + +28. **Description** + + In case the interoperable financial transaction contains additional information that is useful for the `Payer` or the `Payer FSP`; for example, a code or a voucher token, the `Payer FSP` can use the request [Retrieve Transaction Information](#retrieve-transaction-information) to get the additional information. The request [Retrieve Transaction Information](#retrieve-transaction-information) is sent to the `Switch`. + + **Assumptions** + + None. + +29. **Description** + + The `Switch` receives the request [Retrieve Transaction Information](#retrieve-transaction-information). The `Switch` then routes the request [Retrieve Transaction Information](#retrieve-transaction-information) to the `Payee FSP`. + + **Assumptions** + + None. + +30. **Description** + + The `Payee FSP` receives the request [Retrieve Transaction Information](#retrieve-transaction-information). The `Payee FSP` then collects the requested information and uses the response [Retrieve Transaction Information](#retrieve-transaction-information) to the `Switch`. + + **Assumptions** + + The transaction with the provided ID can be found in the Payee FSP. + +31. **Description** + + The `Switch` receives the response [Retrieve Transaction Information](#retrieve-transaction-information). The `Switch` then routes the [Retrieve Transaction Information](#retrieve-transaction-information) response to the `Payer FSP`. + + **Assumptions** + + None. + +32. **Description** + + The `Payer FSP` receives the response [Retrieve Transaction Information](#retrieve-transaction-information) from the `Switch`. + + **Assumptions** + + None. + + **End of Optional fragment** + +33. **Description** + + The `Payer FSP` sends a transaction notification to the `Payee` using a front-end API (out of scope of this API), optionally including transaction details retrieved from the `Payee FSP`. + + **Assumptions** + + None. + +34. **Description** + + The `Payer` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +
+ +### Payee-Initiated Transaction using OTP + +A _Payee-Initiated Transaction using OTP_ is very similar to a [Payee-Initiated Transaction](#payee-initiated-transaction), but the transaction information (including fees and taxes) and approval for the `Payer` is shown/entered on a `Payee` device instead. + +#### Business Process Pattern Description + +The pattern should be used when a `Payee` would like to receive funds from another party whose account is not located in the same FSP, and both the transaction information (including fees and taxes) and approval is shown/entered on a `Payee` device instead. + +- **Approval using OTP** -- A `Payer` can approve a transaction by first creating an OTP in his/her FSP. An alternative to user- initiated creation of OTP is that the OTP is automatically generated and sent by the `Payer FSP`. The same OTP is then entered by the `Payer` in a `Payee` device, usually a POS device or an ATM. The OTP in the transaction request is automatically matched by the `Payer FSP` to either approve or reject the transaction. The OTP does not need to be encrypted as it should only be valid once during a short time period. + +#### Participants and Roles + +The actors in a _Payee-Initiated Transaction using OTP_ are: + +- **Payer** -- The payer of funds in a financial transaction. + +- **Payee** -- The recipient of funds in a financial transaction. + +The intermediary objects used in a _Payee-Initiated Transaction using OTP_ to perform the transaction are: + +- **Payer FSP** -- The FSP in which the Payer's account is located. + +- **Switch (optional)** -- An optional entity used for routing of requests between different FSPs. This object can be removed if requests should be routed directly between a Payer and Payee FSP. + +- **Account Lookup System** -- An entity used for retrieving information regarding accounts or participants. Could be hosted in a separate server, in the Switch, or in the different FSPs. + +- **Payee FSP** -- The FSP in which the Payee's account is located. + +#### Business Process Sequence Diagram + +Figure 3 shows the UML sequence diagram for a _Payee-Initiated Transaction using OTP_. + +![](../assets/diagrams/sequence/figure66a.svg) + +**Figure 3 -- Payee-Initiated Transaction using OTP** + +#### Internal Processing Steps + +This section provides descriptions of and assumptions made for all steps in the sequence shown in Figure 3 above. + +##### Optional fragment: Manual OTP request + +1. **Description** + + The `Payer` requests that an OTP be generated, using the `Payer FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + There are two alternatives for generating an OTP; either it is generated upon request by the `Payer` (this option), or it is automatically generated in Step 19. + +2. **Description** + + The `Payer FSP` receives the request to generate an OTP and returns a generated OTP to the `Payer`, using the `Payer FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + None. + +3. **Description** + + `Payer` receives the generated OTP. The OTP can then be used by the `Payer` in Step 25 for automatic approval. + + **Assumptions** + + None. + + **End of Optional fragment** + +###### Lookup Counterparty + +4. **Description** + + The `Payee` initiates the transaction by requesting to receive funds from a `Payer`, using the `Payee FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + None. + +5. **Description** + + The `Payee FSP` tries to find the `Payer` within the FSP system. Because the `Payer` cannot be found in the `Payee FSP` system, the request **Lookup Participant Information** is sent by the `Payee FSP` to the optional Account Lookup System to get information regarding in which FSP the Payer is located. + + **Assumptions** + + The `Payer` is assumed to be in a different FSP than the `Payee`. Also, an `Account Lookup System` is assumed to exist. The `Account Lookup System` is optional in the process, as the request [Lookup Participant Information](#lookup-participant-information) could also be sent directly to the `Payer FSP` if there is no `Account Lookup System`. As the `Payee FSP` should not know in which FSP the `Payer` is located if there is no `Account Lookup System` present, the request might need to be sent to more than one FSP. It is also possible that the `Payee FSP` would like more information about the Payer before a transaction request is sent; in that case the request [Lookup Party Information](#lookup-party-information), either to the `Switch` or directly to the `Payer FSP`, should be sent instead of [Lookup Participant Information](#lookup-participant-information) to the `Account Lookup System`. + +6. **Description** + + The `Account Lookup System` receives the [Lookup Participant Information](#lookup-participant-information). It then performs an internal lookup to find in which FSP the `Payer` is located. When the lookup is completed, the response [Return Participant Information](#return-participant-information) is sent to inform the `Payee FSP` about which FSP the `Payer` is located in. + + **Assumptions** + + The `Payer` can be found by the `Account Lookup System`. + +7. **Description** + + The `Payee FSP` receives the response [Return Participant Information](#return-participant-information). + + **Assumptions** + + None. + +##### Transaction Request + +8. **Description** + + The Payee FSP sends the request [Perform Transaction Request](#perform-transaction-request) to the `Switch`. The request contains the transaction details including the amount that the `Payee` would like to receive, and that the request should be validated using an OTP (possibly a QR code containing a OTP). + + **Assumptions** + + In this sequence, a `Switch` is placed between the `Payee FSP` and the `Payer FSP` to route the messages. The `Switch` is optional in the process, as the request [Perform Transaction Request](#perform-transaction-request) could also be sent directly to the `Payer FSP` if there is no `Switch` in-between. + +9. **Description** + + The `Switch` receives the request [Perform Transaction Request](#perform-transaction-request). The `Switch` then routes the request to the `Payer FSP`, using the same parameters. + + **Assumptions** + + None. + +10. **Description** + + The `Payer FSP` receives the request [Perform Transaction Request](#perform-transaction-request). The `Payer FSP` then optionally validates the transaction request (for example, whether the `Payer` exists or not) and sends the response [Return Transaction Request Information](#return-transaction-request-information) to inform the `Payee FSP` via the `Switch` that the transaction request has been received. + + **Assumptions** + + The optional validation succeeds. + +11. **Description** + + The `Switch` receives the response [Return Transaction Request Information](#return-transaction-request-information). The `Switch` then uses the same response [Return Transaction Request Information](#return-transaction-request-information) to inform the `Payee FSP` about the successfully delivered transaction request to the `Payer FSP`. + + **Assumptions:** + + None. + +12. **Description** + + The `Payee FSP` receives the response [Return Transaction Request Information](#return-transaction-request-information) from the `Switch`. + + **Assumptions** + + None. + + **Calculate Quote** + +13. **Description** + + The `Payer FSP` rates the transaction internally based on the fee model used and includes the quote information in the request [Calculate Quote](#calculate-quote) to a `Switch` to retrieve the full quote for performing the interoperable financial transaction from the `Payer FSP` to the `Payee FSP`. The transaction details, including a reference to the transaction request, are sent in the parameters of the request to allow for the `Payee FSP` to correctly calculate the quote. + + **Assumptions** + + In this sequence, a `Switch` is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The `Switch` is optional in the process, as the request [Calculate Quote](#calculate-quote) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. + +14. **Description** + + The `Switch` receives the [Calculate Quote](#calculate-quote) request. The `Switch` then routes the request to the `Payee FSP`, using the same parameters. + + **Assumptions** + + None. + +15. **Description** + + The `Payee FSP` receives the [Calculate Quote](#calculate-quote) request. The `Payee FSP` then internally calculates the fees or FSP commission for performing the transaction. It then constructs the ILP Packet containing the ILP Address of the `Payee`, the amount that the `Payee` will receive, and the transaction details. The fulfilment and the condition is then generated out of the ILP Packet combined with a local secret. + + **Assumptions** + + None. + + **Optional fragment: Quote Confirmation by Payee** + +16. **Description** + + Depending on the fee model used and which use case it is, the `Payee` might be informed of the quote to be able to confirm the proposed financial transaction. The quote is in that case sent to the `Payee` using a front- end API (outside the scope of this API. The `Payee` receives the quote including information regarding the transaction including fees and optionally `Payer` name. The `Payee` then confirms the quote using a front-end API (outside the scope of this API). The `Payee FSP` receives the confirmation from the `Payee`. + + **Assumptions** + + The quote is assumed to be sent to the Payer for confirmation, and the `Payee` is assumed to accept and confirm the quote. If the `Payee` would reject the quote, an error response would be sent from the `Payee FSP` to the `Payer FSP` via the `Switch` to inform about the rejected quote. + + **End of Optional fragment** + +17. **Description** + + The `Payee FSP` uses the response [Return Quote Information](#return-quote-information) to the `Switch` to return information to the `Payer FSP` about the quote, the ILP Packet, and the condition. The quote has an expiration time, to inform the `Payer FSP` until which point in time the quote is valid. + + **Assumptions** + + None. + +18. **Description** + + The `Switch` receives the response [Return Quote Information](#return-quote-information). The `Switch` will then route the request to the `Payer FSP`. + + **Assumptions** + + None. + +19. **Description** + + The `Payer FSP` receives the response [Return Quote Information](#return-quote-information) from the Switch. + + **Assumptions** + + The total quote can be calculated by the `Payer FSP`. + + **Optional fragment: Automatic OTP generation** + +20. **Description** + + The `Payer FSP` automatically generates an OTP and sends it to the `Payer`, using the `Payer FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + There are two alternatives for generating the OTP. Either it is generated upon request by the `Payer` (Step 1), or it is automatically generated (this option). + +21. **Description** + + The `Payer` receives the automatically-generated OTP. + + **Assumptions** + + None. + + **End of Optional fragment** + +22. **Description** + + The `Payer FSP` sends the request [Perform Authorization](#perform-authorization) to the `Switch`, to get an authorization to perform the transaction from the Payer via a POS, ATM, or similar payment device, in the `Payee FSP`. The request includes the amount to be withdrawn from the `Payer`'s account, and how many retries are left for the `Payer` to retry the OTP. + + **Assumptions** + + None. + +23. **Description** + + The `Switch` receives the request [Perform Authorization](#perform-authorization) from the `Payer FSP`. The `Switch` then routes the [Perform Authorization](#perform-authorization) to the `Payee FSP`. + + **Assumptions** + + None. + +24. **Description** + + The `Payee FSP` receives the request [Perform Authorization](#perform-authorization) from the `Switch`. The `Payee FSP` sends the authorization request to the `Payee` device (POS, ATM, or similar payment device) using the `Payee FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + None. + +25. **Description** + + The `Payee` device receives the authorization request, and the `Payer` can see the amount that will be withdrawn from his or her account. The `Payer` then uses the OTP received in Step 3 or Step 21, depending on whether the OTP was manually requested or automatically generated. The entered or scanned OTP is then sent to the `Payee FSP` using the `Payee FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + The `Payer` has received the OTP in Step 3 or Step 21. + +26. **Description** + + The `Payee FSP` receives the OTP from the `Payee` device. The `Payee FSP` then sends the response [Return Authorization Result](#return-authorization-result) to the Switch containing the OTP from the Payer. + + **Assumptions** + + None. + +27. **Description** + + The `Switch` receives the request [Return Authorization Result](#return-authorization-result) from the `Payee FSP`. The `Switch` then routes the [Return Authorization Result](#return-authorization-result) to the `Payer FSP`. + + **Assumptions** + + None. + +28. **Description** + + The `Payer FSP` receives the request [Return Authorization Result](#return-authorization-result) to the `Switch`. The `Payer FSP` then validates the OTP received from the OTP generated in Step 2 or Step 20. If the `Payer FSP` is unable to validate the OTP (for example, because the OTP is incorrect) and this was the last remaining retry for the Payer, the sequence continues with Step 29. If the `Payer FSP` correctly validates the OTP, the sequence continues with Step 33. + + **Assumptions** + + None. + + **Alternative: OTP validation failed** + +29. **Description** + + The validation in Step 28 fails and this was the final retry for the Payer. The `Payer FSP` then uses the response [Return Transaction Request Information](#return-transation-request-information) with a rejected state to inform the `Switch` that the transaction was rejected. + + **Assumptions** + + The OTP validation in Step 28 is assumed to fail and no more retries remains for the Payer. + +30. **Description** + + The `Switch` receives the response [Return Transaction Request Information](#return-transation-request-information) from the Payer FSP. The `Switch` then routes the [Return Transaction Request Information](#return-transation-request-information) response to the `Payee FSP`. + + **Assumptions** + + None. + +31. **Description** + + The `Payee FSP` receives the response [Return Transaction Request Information](#return-transation-request-information) with a rejected status from the `Switch`. The `Payee FSP` then informs the `Payee` using a front-end API (outside the scope of this API) about the rejected transaction request. + + **Assumptions** + + None. + +32. **Description** + + The `Payee` receives the notification that the transaction was rejected. The process ends here as the transaction request was rejected and the `Payee` has been informed of the decision. The `Payer` is also assumed to receive the notification via the `Payee` device. + + **Assumptions** + + None. + + **Alternative: OTP validation succeed** + +33. **Description** + + The validation in Step 28 is successful. The `Payer FSP` then performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on). If the validations are successful, a transfer of funds is reserved from the `Payer`'s account to either a combined Switch account or a `Payee FSP` account, depending on setup. After the transfer has been successfully reserved, the request [Perform Transfer](#perform-transfer) is sent to the `Switch` to request the `Switch` to transfer the funds from the `Payer FSP` account in the `Switch` to the `Payee FSP` account. The request [Perform Transfer](#perform-transfer) includes a reference to the earlier quote, an expiry of the transfer, the ILP Packet, and the condition that was received from the `Payee FSP`. The interoperable financial transaction is now irrevocable from the `Payer FSP`. + + **Assumptions** + + The OTP validation in Step 28 is assumed to be successful. Internal validations and reservation are assumed to be successful. In this sequence, a Switch is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The Switch is optional in the process, as the request [Perform Transfer](#perform-transfer) could also be sent directly to the `Payee FSP` if there is no Switch in-between. + + 34. **Description** + + The `Switch` receives the request [Perform Transfer](#perform-transfer). The `Switch` then performs all its applicable internal transfer validations (for example, limit checks, blacklist check, and so on). If the validations are successful, a transfer is reserved from a `Payer FSP` account to a `Payee FSP` account. After the transfer has been successfully reserved, the request [Perform Transfer](#perform-transfer) is sent to the Payee FSP, including the same ILP Packet and condition as was received from the Payer FSP. The expiry time should be decreased by the Switch so that the `Payee FSP` should answer before the Switch should answer to the `Payer FSP`. The transfer is now irrevocable from the `Switch`. + + **Assumptions** + + Internal validations and reservation are successful. + +35. **Description** + + The `Payee FSP` receives the [Perform Transfer](#perform-transfer). The `Payee FSP` then performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on). It also verifies that the amount and ILP Address in the ILP Packet are correct, and match the amount and `Payee` in the transaction details stored in the ILP Packet. If all the validations are successful, a transfer of funds is performed from either a combined `Switch` account or a Payer FSP account to the `Payee`'s account and the fulfilment of the condition is regenerated, using the same secret as in Step 11. After the interoperable financial transaction has been successfully performed, a transaction notification is sent to the `Payee` using a front-end API (out of scope of this API) and the response [Return Transfer Information](#return-transfer-information) is sent to the `Switch`, including the regenerated fulfilment. The transfer is now irrevocable from the `Payee FSP`. + + **Assumptions** + + Internal validations and transfer of funds are successful. + +36. **Description** + + The `Payee` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +37. **Description** + + The `Switch` receives the response [Return Transfer Information](#return-transfer-information). The `Switch` then validates the fulfilment and commits the earlier reserved transfer. The `Switch` will then use the response [Return Transfer Information](#return-transfer-information) to the `Payer FSP`, using the same parameters. + + **Assumptions** + + The fulfilment is assumed to be correctly validated. + +38. **Description** + + The `Payer FSP` receives the response [Return Transfer Information](#return-transfer-information). The` Payer FSP` then validates the fulfilment and commits the earlier reserved transaction. + + **Assumptions** + + The fulfilment is assumed to be correctly validated. + + **Optional fragment: Get Transaction Details** + +39. **Description** + + In case the interoperable financial transaction contains additional information that is useful for the `Payer` or the `Payer FSP`, such as a code or a voucher token, the `Payer FSP` can use the request [Retrieve Transaction Information](#retrieve-transaction-information) to get the additional information. The request [Retrieve Transaction Information](#retrieve-transaction-information) is sent to the Switch. + + **Assumptions** + + None. + +40. **Description** + + The `Switch` receives the request [Retrieve Transaction Information](#retrieve-transaction-information). The `Switch` then routes the request[Retrieve Transaction Information](#retrieve-transaction-information) to the `Payee FSP`. + + **Assumptions** + + None. + +41. **Description** + + The `Payee FSP` receives the request *[Retrieve Transaction Information](#retrieve-transaction-information). The `Payee FSP` then collects the requested information and uses the response [Return Transaction Information](#return-transaction-information) to the `Switch`. + + **Assumptions** + + The transaction with the provided ID can be found in the `Payee FSP`. + +42. **Description** + + The `Switch` receives the response [Return Transaction Information](#return-transaction-information). The `Switch` then routes the [Return Transaction Information](#return-transaction-information) response to the `Payer FSP`. + + **Assumptions** + + None. + +43. **Description** + + The `Payer FSP` receives the response [Return Transaction Information](#return-transaction-information) from the `Switch`. + + **Assumptions** + + None. + + **End of Optional fragment** + +44. **Description** + + The `Payer FSP` sends a transaction notification to the `Payee` using a front-end API (out of scope of this API), optionally including transaction details retrieved from the `Payee FSP`. + + **Assumptions** + + None. + +45. **Description** + + The `Payer` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +
+ +### Bulk Transactions + +In a _Bulk Transaction_, the `Payer` (that is, the sender of funds) initiates multiple transactions to multiple Payees, potentially located in different FSPs. + +#### Business Process Pattern Description + +The pattern should be used whenever a `Payer` would like to transfer funds to multiple Payees in the same transaction. The Payees can potentially be located in different FSPs. + +#### Participants and Roles + +The actors in a _Bulk Transaction_ are: + +- **Payer** -- The sender of funds. + +- **Payees** -- The recipients of funds. There should be multiple Payees in a _Bulk Transaction_. + +The intermediary objects used in a _Bulk Transaction_ to perform the transaction are: + +- **Payer FSP** -- The FSP in which the Payer's account is located. + +- **Switch (optional)** -- An optional entity used for routing of transactions between different FSPs. This object can be removed if transactions should be routed directly between a Payer and `Payee FSP`. + +- **Account Lookup System** -- An entity used for retrieving information regarding accounts or participants. Could be hosted in a separate server, in the Switch, or in the different FSPs. + +- **Payee FSP** -- The FSP in which a Payee's account is located. There may be multiple Payee FSPs in a _Bulk Transaction_. + +#### Business Process Sequence Diagram + +Figure 4 below shows the UML sequence diagram for a _Bulk Transaction_. + +![](../assets/diagrams/sequence/figure67a.svg) + +**Figure 4 -- Bulk Transaction** + +#### Internal Processing Steps + +This section provides descriptions of and assumptions made for all steps in the sequence shown in Figure 4. + +##### Lookup Counterparties + +1. **Description** + + The `Payer` initiates the bulk transaction process by uploading a bulk file to the `Payer FSP`, using the `Payer FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + None. + + **Loop for each Transaction in bulk file** + +2. **Description** + + `Payer FSP` tries to find the Payee within the `Payer FSP` system. + + **Assumptions** + + The `Payee` is assumed to be located in a different FSP than the `Payer`. If the `Payee` is within the `Payer FSP`, the transaction can be handled internally in the `Payer FSP` (outside the scope of this API). + +3. **Description** + + The `Payer FSP` sends the request [Lookup Participant Information](#lookup-participant-information) to the optional `Account Lookup System` to get information regarding in which FSP the `Payer` is present in. + + **Assumptions** + + The `Payee` is assumed to in a different FSP than the `Payer`. Also, an `Account Lookup System` is assumed to exist. The `Account Lookup System` is optional in the process, as the request [Lookup Participant Information](#lookup-participant-information) could also be sent directly to the `Payee FSP`s if there is no `Account Lookup System`. As the `Payer FSP `should not know in which FSP the `Payee` is located in if there is no `Account Lookup System` present, the request might need to be sent to more than one FSP. It is also possible that the `Payer FSP` would like more information about the `Payee` before a bulk transaction is executed; for example, for additional verification purposes of the `Payee` name. In that case, the request [Lookup Party Information](#lookup-party-information), either to the `Switch` or directly to the `Payee FSP`, should be sent instead of the request [Lookup Participant Information](#lookup-participant-information) to the `Account Lookup System`. + +4. **Description** + + The `Account Lookup System` receives the request [Lookup Participant Information](#lookup-participant-information) It then performs an internal lookup to find in which FSP the `Payee` is located. When the lookup is completed, the response [Return Participant Information](#return-participant-information) is sent to inform the Payer FSP about which FSP the `Payee` is located in. + + **Assumptions** + + The `Payee` can be found by the `Account Lookup System`. + +5. **Description** + + The `Payer FSP` receives the response [Return Participant Information](#return-participant-information). The `Payee` and the related transaction is then placed in a new bulk file separated per `Payee FSP`. + + **Assumptions** + + None. + + **End of loop for each Transaction** + +##### Calculate Bulk Quote + + **Loop for each `Payee FSP` to Calculate Bulk Quote** + +6. **Description** + + The `Payer FSP` uses the request [Calculate Bulk Quote](#calculate-bulk-quote) on a `Switch` to retrieve a quote for performing the bulk transaction from the `Payer FSP` to the `Payee FSP`. The request contains details for each individual transaction in the bulk transaction. + + **Assumptions** + + In this sequence, a `Switch` is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The Switch is optional in the process, as the request [Calculate Bulk Quote](#calculate-bulk-quote) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. + +7. **Description** + + The `Switch` receives the [Calculate Bulk Quote](#calculate-bulk-quote) request. The `Switch` then routes the request to the `Payee FSP`, using the same parameters. + + **Assumptions** + + None. + +8. **Description** + + The `Payee FSP` receives the [Calculate Bulk Quote](#calculate-bulk-quote) request. The `Payee FSP` then internally calculates the fees or FSP commission for performing each individual transaction in the bulk transaction. For each individual transaction, the `Payee FSP` then constructs an ILP Packet containing the ILP Address of the `Payee`, the amount that the `Payee` will receive, and the transaction details. The fulfilment and the condition is then generated out of the ILP Packet combined with a local secret. It then uses the response [Return Bulk Quote Information](#return-bulk-quote-information) to the `Switch` to inform the `Payer FSP` about the fees involved in performing the bulk transaction and the ILP Packet and condition. The bulk quote has an expiration date and time, to inform the `Payer FSP` until which time the bulk quote is valid. + + **Assumptions** + + The bulk quote can be calculated by the `Payee FSP`. + +9. **Description** + + The Switch receives the response [Return Bulk Quote Information](#return-bulk-quote-information). The `Switch` then routes the response to the Payer FSP. + + **Assumptions** + + None. + +10. **Description** + + The `Payer FSP` receives the response [Return Bulk Quote Information](#return-bulk-quote-information) from the `Switch`. + + **Assumptions** + + None. + + **End of loop for each `Payee FSP`** + +11. **Description** + + The `Payer FSP` calculates any internal bulk fees and taxes, and informs the `Payer` using a front-end API (outside the scope of this API) about the total fees and taxes to perform the bulk transaction. + + **Assumptions** + + None. + +12. **Description** + + The `Payer` receives the notification about the completed processing of the bulk transaction and the fees and taxes to perform the bulk transaction. The `Payer` then decides to execute the bulk transaction. + + **Assumptions** + + The `Payer` is assumed to execute the bulk transaction. If the `Payer` would reject the bulk transaction at this stage, no response is sent to the `Payee FSP`. The created bulk quote at the `Payee FSP`s should have an expiry date; that is, at which time it's automatically deleted. + +##### Perform Bulk Transfer** + +13. **Description** + + The `Payer FSP` receives the request to execute the bulk transaction from the `Payer`. + + **Assumptions** + + None. + + **Loop for each `Payee FSP` to perform Bulk Transfer** + +14. **Description** + + The `Payer FSP` performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on) for the bulk transaction to the `Payee FSP`. If the validations are successful, a transfer of funds is reserved from the Payer's account to either a combined `Switch` account or a `Payee FSP` account, depending on setup. After the transfer has been successfully reserved, the request [Perform Bulk Transfer](#perform-bulk-transfer) is sent to the `Switch`. The request [Perform Bulk Transfer](#perform-bulk-transfer) includes a reference to the earlier bulk quote, an expiry of the bulk transfer, and the ILP Packets and condition per transfer that was received from the `Payee FSP`. The interoperable financial transaction is now irrevocable from the Payer FSP. The interoperable bulk transaction is now irrevocable from the Payer FSP. + + **Assumptions** + + In this sequence, a Switch is placed between the `Payer FSP `and the `Payee FSP` to route the messages. The `Switch` is optional in the process, as the request *[Perform Bulk Transfer](#perform-bulk-transfer) could also be sent directly to the `Payee FSP` if there is no Switch in-between. + +15. **Description** + + The Switch receives the request [Perform Bulk Transfer](#perform-bulk-transfer). The Switch then performs all applicable internal transfer validations (such as limit checks, blacklist check, and so on). If the validations are successful, a transfer is reserved from a Payer FSP account to a `Payee FSP` account. After the transfer has been successfully reserved, the request [Perform Bulk Transfer](#perform-bulk-transfer) is sent to the `Payee FSP`, including the same ILP Packets and conditions for each transfer that were received from the `Payer FSP`. The expiry time should be decreased by the Switch so that the `Payee FSP` should answer before the Switch should answer to the `Payer FSP`. The bulk transfer is now irrevocable from the `Switch`. + + **Assumptions** + + Internal validations and reservation are successful. + +16. **Description** + + The `Payee FSP` receives the request [Perform Bulk Transfer](#perform-bulk-transfer). The `Payee FSP` then performs all applicable internal transaction validations (such as limit checks, and blacklist checks) for each individual transaction in the bulk transaction. If the validations are successful, a transfer of funds is performed from either a combined Switch account or a `Payer FSP` account, depending on setup, to each of the Payees' accounts and the fulfilment of each condition is regenerated, using the same secret as in Step 8. After each transfer to a `Payee` has been successfully performed, a transaction notification is sent to the `Payee` using a front-end API (out of scope of this API). After each of the individual transactions in the bulk transaction has been completed, the response [Return Bulk Transfer Information](#return-bulk-transfer-information) is sent to the Switch to inform the Switch and the Payer FSP of the result including each fulfilment. The transactions in the bulk transaction are now irrevocable from the `Payee FSP`. + + **Assumptions** + + Internal validations and transfers of funds are successful. + +17. **Description** + + Each `Payee` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +18. **Description** + + The `Switch` receives the response [Return Bulk Transfer Information](#return-bulk-transfer-information). The `Switch` then validates the fulfilments and commits the earlier reserved transfers. The `Switch` then uses the response [Return Bulk Transfer Information](#return-bulk-transfer-information) to the `Payer FSP`, using the same parameters. + + **Assumptions** + + Each individual transaction in the bulk transaction is assumed to be successful in the `Payee FSP`, and the validation of the fulfilments is also assumed to be correct. If one or more of the transactions in the bulk transaction were unsuccessful, the earlier reserved, now unsuccessful, transfer or transfers in the `Switch` would need to be cancelled. + +19. **Description** + + The `Payer FSP` receives the response [Return Bulk Transfer Information](#return-bulk-transfer-information). The `Payer FSP` then commits the earlier reserved transfers. After the bulk transaction has been successfully committed, a transaction notification is sent to the `Payer` using a front-end API (out of scope of this API). + + **Assumptions** + + Each individual transaction in the bulk transaction is assumed to be successful in the `Payee FSP`, and the validation of the fulfilments is also assumed to be correct. If one or more of the transactions in the bulk transaction were unsuccessful, the earlier reserved transfer in the `Payer FSP` would need to be updated with the total amount of all successful transactions before being committed. + + **End of loop for each `Payee FSP`** + +20. **Description** + + After each of the `Payee FSP`s has executed their part of the bulk transaction, a response is sent to the Payer using a front- end API (out of scope for this API). + + **Assumptions** + + None. + +21. **Description** + + The `Payer` receives a bulk transaction notification containing information about the successfully performed bulk transaction. + + **Assumptions** + + None. + +## References + +1 [https://interledger.org/rfcs/0011-interledger-payment-request/ - Interledger Payment Request (IPR)](https://interledger.org/rfcs/0011-interledger-payment-request) + +2 [https://interledger.org/ - Interledger](https://interledger.org) + +3 [https://interledger.org/interledger.pdf - A Protocol for Interledger Payments](https://interledger.org/interledger.pdf) + +4 [https://interledger.org/rfcs/0001-interledger-architecture/ - Interledger Architecture](https://interledger.org/rfcs/0001-interledger-architecture) + + + +**List of Figures** + +[Figure 1 -- Payer-Initiated Transaction](#443-business-process-sequence-diagram) + +[Figure 2 -- Payee-Initiated Transaction](#423-business-process-sequence-diagram) + +[Figure 3 -- Payee-Initiated Transaction using OTP](#433-business-process-sequence-diagram) + +[Figure 4 -- Bulk Transaction](#443-business-process-sequence-diagram) diff --git a/docs/technical/api/fspiop/glossary.md b/docs/technical/api/fspiop/glossary.md new file mode 100644 index 000000000..cce7b8bf7 --- /dev/null +++ b/docs/technical/api/fspiop/glossary.md @@ -0,0 +1,286 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- + +# Glossary + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information. + +| **Type of Information** | **Convention** | **Example** | +| :--- | :--- | :--- | +| **Elements of the API, such as resources** | Boldface | **/authorization** | +| **Variables** | Italics within curled brackets | _{ID}_ | +| **Glossary** | Italics on first occurrence; defined in _Glossary_ | The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of **terms** electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP. | +| **Library documents** | Italics | User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +| **Version** | **Date** | **Change Description** | +| :--- | :--- | :--- | +| **1.0** | 2018-03-13 | Initial version | + +
+ +## Introduction + +This document provides the glossary for the Open API for FSP Interoperability Specification. Terms have been compiled from three sources: + +- ITU-T Digital Financial Services Focus Group Glossary (ITU-T)[ITU-T Digital Financial Services Focus Group Glossary (ITU-T)](https://www.itu.int/dms_pub/itu-t/opb/tut/T-TUT-ECOPO-2018-PDF-E.pdf), + +- Feedback from Technology Service Providers (TSPs) in the Product Development Partnership (PDP) work groups, and + +- Feedback from the L1P IST Reference Implementation team (RI). + +Information is shared in accordance with Creative Commons Licensing[LICENSE](https://github.com/mojaloop/mojaloop-specification/blob/master/LICENSE.md). + + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](./logical-data-model) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](./json-binding-rules) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](./v1.1/signature) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](#) + +
+ + +## API Glossary + +| **Term** | **Alternative and Related Terms** | **Definition** | **Source** | +| --- | --- | --- | --- | +| **Access Channel** | POS ("Point of Sale"), Customer Access Point, ATM, Branch, MFS Access Point | Places or capabilities that are used to initiate or receive a payment. Access channels can include bank branch offices, ATMs, terminals at the POS, agent outlets, mobile phones, and computers. | ITU-T | +| **Account ID** | | A unique identifier assigned by the FSP that created the account. | PDP | +| **Account Lookup System** | | Account Lookup System is an abstract entity used for retrieving information regarding in which FSP an account, wallet, or identity is hosted. The Account Lookup System itself can be hosted in its own server, as part of a financial switch, or in the different FSPs. | PDP | +| **Active User** | | A term used by many providers in describing how many of their account holders are frequent users of their service. | +| **Agent** | Agent Til , Agent Outlet | An entity authorized by the provider to handle various functions such as customer enrollment, cash-in and cash-out using an agent til . | ITU-T | +| **Agent Outlet** | Access Point | A physical location that carries one or more agent tills, enabling it to perform enrollment, cash-in, and cash-out transactions for customers on behalf of one or more providers. National law defines whether an agent outlet may remain exclusive to one provider. Agent outlets may have other businesses and support functions. | ITU-T | +| **Agent Till** | Registered Agent | An agent till is a provider-issued registered “line”, either a special SIM card or a POS machine, used to perform enrollment, cash-in and cash-out transactions for clients. National law dictates which financial service providers can issue agent tills. | ITU-T | +| **Aggregator** | Merchant Aggregator | A specialized form of a merchant services provider, who typically handles payment transactions for a large number of small merchants. Scheme rules often specify what aggregators are allowed to do. | ITU-T | +| **Anti-Money Laundering** | AML; also "Combating the Financing of Terrorism", or CFT | Initiatives to detect and stop the use of financial systems to disguise the use of funds that have been criminally obtained. | ITU-T | +| **API** | Application Programming Interface | A set of clearly defined methods of communication to allow interaction and sharing of data between different software programs. |PDP | +| **Arbitration** | | The use of an arbitrator, rather than courts, to resolve disputes. | ITU-T | +| **Authentication** | Verification, Validation | The process of ensuring that a person or a transaction is valid for the process (account opening, transaction initiation, and so on) being performed. | ITU-T | +| **Authorization** | | A process used during a "pull" payment (such as a card payment), in which the payee requests (through their provider) confirmation from the payer's bank that the transaction is good. | ITU-T | +| **Authorized /institution entity** | | Non-financial institutions that have followed the appropriate authorization by State Bank and/or relevant regulatory authorities to partake in the provisioning of mobile financial services. | PDP | +| **Automated Clearing House** | ACH | An electronic clearing system in which payment orders are exchanged among payment service providers, primarily via magnetic media or telecommunications networks, and then cleared amongst the participants. All operations are handled by a data processing center. An ACH typically clears credit transfers and debit transfers, and in some cases also cheques. | ITU-T | +| **Bank** | Savings Bank, Credit Union, Payments Bank | A chartered financial system within a country that has the ability to ITU-T accept deposits and make and receive payments into customer accounts. | ITU-T | +| **Bank Accounts and Transaction Services** | Mobile Banking, Remote Banking, Digital Banking| A transaction account held at a bank. This account may be accessible by ITU-T a mobile phone, in which case it is sometimes referred to as "mobile banking".| ITU-T | +| **Bank-Led Model** | Bank-Centric Model| A reference to a system in which banks are the primary providers of digital financial services to end users. National law may require this. | ITU-T | +| **Basic Phone** | | Minimum device required to use digital financial services. | PDP | +| **Bill Payment** | C2B, Utility Payments, School Payments | Making a payment for a recurring service, either in person ("face to face") or remotely. | ITU-T | +| **Biometric Authentication** | | The use of a physical characteristic of a person (fingerprint, IRIS, and so on) to authenticate that person. | ITU-T | +| **Biometric Authentication** | | Any process that validates the identity of a user who wishes to sign into a system by measuring some intrinsic characteristic of that user. | ITU-T | +| **Blacklist** | | A list or register of entities (registered users) that are being denied/blocked from a particular privilege, service, mobility, access or recognition. Entities on the list will not be accepted, approved and or recognized. It is the practice of identifying entities that such entities are denied, unrecognized, or ostracized. Where entities are registered users (or user accounts, if granularity allows) and services are informational (for example, balance check), transactional (for example, debit/credit) payments services or lifecycle (for example, registration, closure) services. | PDP | +| **Blockchain** | Digital Currency, Cryptocurrency, Distributed Ledger Technology| The technology underlying bitcoin and other cryptocurrencies—a shared digital ledger, or a continually updated list of all transactions.| ITU-T | +| **Borrowing** | | Borrowing money to finance a short-term or long-term need. | ITU-T | +| **Bulk Payments** | G2C, B2C, G2P, Social Transfers| Making and receiving payments from a government to a consumer: benefits, cash transfers, salaries, pensions, and so on | ITU-T | +| **Bulk Payment Services** | | A service which allows a government agency or an enterprise to make payments to a large number of payees - typically consumers but can be businesses as well | ITU-T | +| **Bulk upload service** | | A service allowing the import of multiple transactions per session, most often via a bulk data transfer file which is used to initiate payments. Example: salary payment file. | ITU-T | +| **Bundling** | Packaging, Tying | A business model in which a provider which groups a collection of services into one product which an end user agrees to buy or use.| ITU-T | +| **Business** | | Entity such as a public limited or limited company or corporation that uses mobile money as a service; for example, making and accepting bill payments and disbursing salaries.| PDP | +| **Cash Management** | Agent Liquidity Management | Management of cash balances at an agent. | ITU-T | +| **Cash-In** | CICO (Cash-In Cash-Out) | Receiving eMoney credit in exchange for physical cash - typically done at an agent. | ITU-T | +| **Cash-Out** | CICO (Cash-In Cash-Out) | Receiving physical cash in exchange for a debit to an eMoney account - typically done at an agent. | ITU-T | +| **Certificate Signing Request** | CSR | Message sent from an applicant to a Certificate Authority in order to apply for a digital identity certificate. | | +| **Chip Card** | EMV Chip Card, Contactless Chip Card | A chip card contains a computer chip: it may be either contactless or contact (requires insertion into terminal). Global standards for chip cards are set by EMV. | ITU-T | +| **Clearing** | | The process of transmitting, reconciling, and, in some cases, confirming transactions prior to settlement, potentially including the netting of transactions and the establishment of final positions for settlement. Sometimes this term is also used (imprecisely) to cover settlement. For the clearing of futures and options, this term also refers to the daily balancing of profits and losses and the daily calculation of collateral requirements. | RI | +| **Clearing House** | | A central location or central processing mechanism through which financial institutions agree to exchange payment instructions or other financial obligations (for example, securities). The institutions settle for items exchanged at a designated time based on the rules and procedures of the clearinghouse. In some cases, the clearinghouse may assume significant counterparty, financial, or risk management responsibilities for the clearing system.| ITU-T | +| **Client Authentication** | TLS | A client authentication certificate is a certificate used to authenticate clients during an SSL handshake. It authenticates users who access a server by exchanging the client authentication certificate. ... This is to verify that the client is who they claim to be (Source: Techopedia). | | +| **Closed-Loop** | | A payment system used by a single provider, or a very tightly constrained group of providers.| ITU-T | +| **Combatting Terrorist Financing** | | Initiatives to detect and stop the use of financial systems to transfer funds to terrorist organizations or people. | ITU-T | +| **Commission** | | An incentive payment made, typically to an agent or other intermediary who acts on behalf of a DFS provider. Provides an incentive for agent. | ITU-T | +| **Commit** | | Part of a 2-phase transfer operation in which the funds that were reserved to be transferred, are released to the payee; the transfer is completed between the originating/payer and destination/payee accounts. | PDP | +| **Condition** | | In the Interledger protocol, a cryptographic lock used when a transfer is reserved. Usually in the form of a SHA-256 hash of a secret preimage. When provided as part of a transfer request the transfer must be reserved such that it is only committed if the fulfillment of the condition (the secret preimage) is provided. | PDP | +| **Counterparty** | Payee, Payer, Borrower, Lender | The other side of a payment or credit transaction. A payee is the counterparty to a payer, and vice-versa. | ITU-T | +| **Coupon** | | A token that entitles the holder to a discount or that may be exchanged for goods or services.| PDP | +| **Credit History** | Credit Bureaus, Credit Files | A set of records kept for an end user reflecting their use of credit, including borrowing and repayment. | ITU-T | +| **Credit Risk Management** | | Tools to manage the risk that a borrower or counterparty will fail to meet its obligations in accordance with agreed terms. | ITU-T | +| **Credit Scoring** | | A process which creates a numerical score reflecting credit worthiness. | ITU-T | +| **Cross Border Trade Finance Services** | | Services which enable one business to sell or buy to businesses or individuals in other countries; may include management of payments transactions, data handling, and financing. | ITU-T | +| **Cross-FX Transfer** | | Transfer involving multiple currencies including a foreign exchange calculation.| PDP | +| **Customer Database Management** | | The practices that providers do to manage customer data: this may be enabled by the payment platform the provider is using. | ITU-T | +| **Customer Financial Data** | Customer Financial Data | Means a set of financial information of the customer, which includes account balances, deposits and data relating to financial transactions, and so on | PDP | +| **Data Controller** | Data Controller | Data Controller shall mean any person, public authority, agency or any other body which alone or jointly with others determines the purposes and means of the processing of personal data; where the purposes and means of processing are determined by national or Community laws or regulations, the controller or the specific criteria for his nomination may be designated by national or Community law. Also, Data Controller is responsible for providing a secure infrastructure in support of the data, including, but not limited to, providing physical security, backup and recovery processes, granting authorized access privileges and implementing and administering controls. | PDP | +| **Data Portability** | Data Portability | Data Portability shall mean a data subject’s ability to request a copy of personal data being processed in a format usable by this person and be able to transmit it electronically to another processing system | PDP | +| **Data Protection** | PCI-DSS | The practices that enterprises do to protect end user data and credentials. "PCI-DSS" is a card industry standard for this. | ITU-T | +| **Deposit Guarantee System** | Deposit Insurance | A fund that insures the deposits of account holders at a provider; often a government function used specifically for bank accounts. | ITU-T | +| **Diffie-Hellman solution** | | A secure mechanism for exchanging a shared symmetric key between two anonymous peers. | | +| **Digital Financial Services** | DFS, Mobile Financial Services | Digital financial services include methods to electronically store and transfer funds; to make and receive payments; to borrow, save, insure and invest; and to manage a person's or enterprise's finances. | ITU-T | +| **Digital Liquidity** | | A state in which a consumer willing to leave funds (eMoney or bank deposits) in electronic form, rather than performing a "cash-out". | ITU-T | +| **Digital Payment** | Mobile Payment, Electronic Funds Transfer | A broad term including any payment which is executed electronically. Includes payments which are initiated by mobile phone or computer. Card payments in some circumstances are considered to be digital payments. The term "mobile payment" is equally broad and includes a wide variety of transaction types which in some way use a mobile phone. | ITU-T | +| **Dispute Resolution** | | A process specified by a provider or by the rules of a payment scheme to resolve issues between end users and providers, or between an end user and its counter party. | ITU-T | +| **Electronic consent** | Electronic consent |Any sound, symbol, or process which is:
1. Related to technology
    a. Having electrical, digital, magnetic, wireless, optical, electromagnetic, or similar capabilities, including (but not limited to) mobile telephone, facsimile and internet and
    b. Which may only be accessed through a security access code, and


2. Logically associated with a legally binding agreement or authorization and executed or adopted by a person with the intent to be bound by such agreement or authorization.
| PDP | +| **Electronic Invoicing, ERP, Digital Accounting, Supply Chain Solutions, Services, Business Intelligence** | | Services which support merchant or business functions relating to DFS services. | ITU-T | +| **eMoney** |eFloat, Float, Mobile Money, Electronic Money, Prepaid Cards, Electronic Funds | A record of funds or value available to a consumer stored on a payment device such as chip, prepaid cards, mobile phones or on computer systems as a non-traditional account with a banking or non-banking entity. | ITU-T | +| **eMoney Accounts and Transaction Services** | Digital Wallet, Mobile Wallet, Mobile Money Account |A transaction account held at a non-bank. The value in such an account is referred to as eMoney. | ITU-T | +| **eMoney Issuer** | Issuer, Provider | A provider (bank or non-bank) who deposits eMoney into an account they establish for an end user. eMoney can be created when the provider receives cash ("cash-in") from the end user (typically at an agent location) or when the provider receives a digital payment from another provider. | ITU-T | +| **Encryption** |Decryption | The process of encoding a message so that it can be read only by the sender and the intended recipient. | ITU-T | +| **End User** |Consumer, Customer, Merchant, Biller | The customer of a digital financial services provider: the customer may be a consumer, a merchant, a government, or another form of enterprise. | ITU-T | +| **External Account** | | An account hosted outside the FSP, regularly accessible by an external provider interface API. | PDP | +| **FATF** | | The Financial Action Task Force is an intergovernmental organization to combat money laundering and to act on terrorism financing. | ITU-T | +| **Feature Phone** | |A mobile telephone without significant computational . | ITU-T | +| **Fees** | | The payments assessed by a provider to their end user. This may either be a fixed fee, a percent-of-value fee, or a mixture. A Merchant Discount Fee is a fee charged by a Merchant Services Provider to a merchant for payments acceptance. Payments systems or schemes, as well as processors, also charge fees to their customer (typically the provider.) | ITU-T | +| **Financial Inclusion** | | The sustainable provision of affordable digital financial services that bring the poor into the formal economy.| ITU-T | +| **Financial Literacy** | |Consumers and businesses having essential financial skills, such as preparing a family budget or an understanding of concepts such as the time value of money, the use of a DFS product or service, or the ability to apply for such a service. | ITU-T | +| **FinTech** | |A term that refers to the companies providing software, services, and products for digital financial services: often used in reference to newer technologies. | ITU-T | +| **Float** | |This term can mean a variety of different things. In banking, float is created when one party's account is debited or credited at a different time than the counterparty to the transaction. eMoney, as an obligation of a non-bank provider, is sometimes referred to as float. | ITU-T | +| **Fraud** | Fraud Management, Fraud Detection, Fraud Prevention | Criminal use of digital financial services to take funds from another individual or business, or to damage that party in some other way. | ITU-T | +| **Fraud Risk Management** | | Tools to manage providers' risks, and at times user's risks (for example, for merchants or governments) in providing and/or using DFS services. | ITU-T | +| **FSP** | Provider, Financial Service Provider (FSP), Payment Service Provider, Digital Financial Services Provider (DFSP) | The entity that provides a digital financial service to an end user (either a consumer, a business, or a government.) In a closed-loop payment system, the Payment System Operator is also the provider. In an open- loop payment system, the providers are the banks or non-banks which participate in that system. | ITU-T | +| **FSP On-boarding** | | The process of adding a new FSP to this financial network. | RI | +| **Fulfillment** | | In the Interledger protocol, a secret that is the preimage of a SHA-256 hash, used as a condition on a transfer. The preimage is required in the commit message to trigger the transfer to be committed.| PDP | +| **FX** | | Foreign Exchange | PDP | +| **Government Payments Acceptance Services** | | Services which enable governments to collect taxes and fees from individuals and businesses. | ITU-T | +| **HCE** | | Host Card Emulation. A communication technology that enables payment data to be safely stored without using the Secure Element in the phone. | ITU-T | +| **Identity** | National Identity, Financial Identity, Digital Identity |A credential of some sort that identifies an end user. National identities are issued by national governments. In some countries a financial identity is issued by financial service providers. | ITU-T | +| **Immediate Funds Transfer** | Real Time | A digital payment which is received by the payee almost immediately upon the payer having initiated the transaction | ITU-T | +| **Insurance Products** | | A variety of products which allow end user to insure assets or lives that they wish to protect.| ITU-T | +| **Insuring Lives or assets** | | Paying to protect the value of a life or an asset. | ITU-T | +| **Interchange** | Swipe Fee, Merchant Discount Fee | A structure within some payments schemes which requires one provider to pay the other provider a fee on certain transactions. Typically used in card schemes to effect payment of a fee from a merchant to a consumer's card issuing bank. | ITU-T | +| **Interledger** | | The Interledger protocol is a protocol for transferring monetary value across multiple disconnected payment networks using a choreography of conditional transfers on each network. | PDP | +| **International Remittance** | P2P; Remote Cross-Border Transfer of Value, Cross-Border Remittance | Making and receiving payments to another person in another country. | ITU-T | +| **Interoperability** | Interconnectivity | When payment systems are interoperable, they allow two or more proprietary platforms or even different products to interact seamlessly. The result is the ability to exchange payments transactions between and among providers. This can be done by providers participating in a scheme, or by a variety of bilateral or multilateral arrangements. Both technical and business rules issues need to be resolved for interoperability to work. | ITU-T | +| **Interoperability Service for Transfers (IST)** | Switch | An entity which receives transactions from one provider and routes those transactions on to another provider. A switch may be owned or hired by a scheme or be hired by individual providers. A switch may connect to a settlement system for inter-participant settlement and could also implicitly host other services - such as a common account locator service. | ITU-T | +| **Interoperability settlement bank** | | Entity that facilitates the exchange of funds between the FSPs. The settlement bank is one of the main entities involved in any inter-FSP transaction. | PDP | +| **Investment Products** | | A variety of products which allow end users to put funds into investments other than a savings account.| ITU-T | +| **Irrevocable** | |A transaction that cannot be "called back" by the payer; an irrevocable payment, once received by a payee, cannot be taken back by the payer. | ITU-T | +| **JSON** | JavaScript Object Notation | JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999 (Source: www.json.org). | | +| **Know Your Customer** | KYC, Agent and Customer Due Diligence, Tiered KYC, Zero Tier | The process of identifying a new customer at the time of account opening, in compliance with law and regulation. The identification requirements may be lower for low value accounts ("Tiered KYC"). The term is also used in connection with regulatory requirements for a provider to understand, on an ongoing basis, who their customer is and how they are using their account. | ITU-T | +| **Liability** | Agent Liability, Issuer Liability, Acquirer Liability | A legal obligation of one party to another; required by either national law, payment scheme rules, or specific agreements by providers. Some scheme rules transfer liabilities for a transaction from one provider to another under certain conditions. | ITU-T | +| **Liquidity** | Agent Liquidity | The availability of liquid assets to support an obligation. Banks and non-bank providers need liquidity to meet their obligations. Agents need liquidity to meet cash-out transactions by consumers and small merchants.| ITU-T | +| **Loans** | Microfinance, P2P Lending, Factoring, Cash Advances, Credit, Overdraft, Facility | Means by which end users can borrow money. | ITU-T | +| **M2C** | | Merchant to Customer or Consumer. | PDP | +| **mCommerce** | eCommerce | Refers to buying or selling in a remote fashion: by phone or tablet (mCommerce) or by computer (eCommerce). | ITU-T | +| **Merchant** | Payments Acceptor | An enterprise which sells goods or services and receives payments for such goods or services. | ITU-T | +| **Merchant Acquisition** | Onboarding | The process of enabling a merchant for the receipt of electronic payments.| ITU-T | +| **Merchant payment - POS** | C2B, Proximity Payments | Making a payment for a good or service in person ("face to face"); includes kiosks and vending machines. | ITU-T | +| **Merchant payment - Remote** |C2b, eCommerce Payment, Mobile Payment | Making a payment for a good or service remotely; transacting by phone, computer, and so on | ITU-T | +| **Merchant Payments Acceptance Services** | Acquiring Services | A service which enables a merchant or other payment acceptor to accept one or more types of electronic payments. The term "acquiring" is typically used in the card payments systems. | ITU-T | +| **Merchant Service Provider** | Acquirer | A provider (bank or non-bank) who supports merchants or other payments acceptors requirements to receive payments from customers. The term "acquirer" is used specifically in connection with acceptance of card payments transactions. | ITU-T | +| **Mobile Network Operator** | MNO | An enterprise which sells mobile phone services, including voice and data communication. | ITU-T | +| **Money Transfer Operator** | | A specialized provider of DFS who handles domestic and/or international remittances. | ITU-T | +| **MSISDN** | | Number uniquely identifying a subscription in a mobile phone network. These numbers use the E.164 standard that defines numbering plan for a world-wide public switched telephone network (PSTN).| RI | +| **Mutual Authentication** | TLS | Mutual authentication or two-way authentication refers to two parties authenticating each other at the same time, being a default mode of authentication in some protocols (IKE, SSH) and optional in others (TLS) (Source: Wikipedia). | | +| **Near Field Communication** | NFC | A communication technology used within payments to transmit payment data from an NFC equipped mobile phone to a capable terminal.| ITU-T | +| **Netting** | | The offsetting of obligations between or among participants in the settlement arrangement, thereby reducing the number and value of payments or deliveries needed to settle a set of transactions.| RI | +| **Non-Bank** | Payments Institution, Alternative Lender | An entity that is not a chartered bank, but which is providing financial services to end users. The requirements of non-banks to do this, and the limitations of what they can do, are specified by national law| ITU-T | +| **Non-Bank-Led Model** | MNO-Led Model | A reference to a system in which non-banks are the providers of digital financial services to end users. Non-banks typically need to meet criteria established by national law and enforced by regulators.| ITU-T | +| **Non-repudiation** | | Ability to prove the authenticity of a transaction, such as by validating a digital signature.| PDP | +| **Nostro Account** | | From the Payer's perspective: Payer FSP funds/accounts held/hosted at Payee FSP.| PDP | +| **Notification** | | Notice to a payer or payee regarding the status of transfer. |PDP | +| **Off-Us Payments** | Off-Net Payments | Payments made in a multiple-participant system or scheme, where the payer's provider is a different entity as the payee's provider. | ITU-T | +| **On-Us Payments** | On-Net Payments | Payments made in a multiple-participant system or scheme, where the payer's provider is the same entity as the payee's provider. | ITU-T | +| **Open-Loop** | | A payment system or scheme designed for multiple providers to participate in. Payment system rules or national law may restrict participation to certain classes of providers.| ITU-T | +| **Operations Risk Management** | | Tools to manage providers' risks in operating a DFS system. | ITU-T | +| **Organization** | Business | An entity such as a business, charity or government department that uses mobile money as a service; for example, taking bill payments, making bill payments and disbursing salaries. | PDP | +| **OTP** | One-Time Password | OTP is a credential which by definition can only be used once. It is generated and later validated by the same FSP for automatic approval. The OTP is usually tied to a specific Payer in a Payment. The generated OTP is usually a numeric between 4 and 6 digits. | PDP | +| **Over The Counter Services** | OTC, Mobile to Cash | Services provided by agents when one end party does not have an eMoney account: the (remote) payer may pay the eMoney to the agent's account, who then pays cash to the non- account holding payee. | ITU-T | +| **P2P** | Domestic Remittance, Remote Domestic Transfer of Value| Making and receiving payments to another person in the same country. | ITU-T | +| **Participant** | | A provider who is a member of a payment scheme, and subject to that scheme's rules.| ITU-T | +| **Partner Bank** | | Financial institution supporting the FSP and giving it access to the local banking ecosystem. | PDP | +| **Payee** | Receiver | The recipient of electronic funds in a payment transaction. | ITU-T | +| **Payee FSP** | | Payee's Financial Service Provider. | PDP | +| **Payer** | Sender | The payer of electronic funds in a payment transaction. | ITU-T | +| **Payer FSP** | | Payer's Financial Service Provider. | PDP | +| **Paying for Purchases** | C2B - Consumer to Business | Making payments from a consumer to a business: the business is the "payment acceptor” or merchant. | ITU-T | +| **Payment Device** | ATM (Automated Teller Machine), POS (Point of Sale), Access Point, Point of Sale Device | Payment device is the abstract notion of an electronic device, other than the Payer’s own device, that is capable of letting a Payer accept a transaction through the use of a credential (some kind of OTP). Examples of (Payment) Devices are ATM and POS. | PDP | +| **Payment Instruction** | Payment Instruction | An instruction by a sender to a sender’s payment service provider, transmitted orally, electronically, or in writing, to pay, or to cause another payment service provider to pay, a fixed or determinable amount of money to a payee if:
a) The instruction does not state a condition of payment to the payee other than time of payment; and

b) The instruction is transmitted by the sender directly to the sender’s payment service provider or to an agent, electronic fund transfers system or communication system for transmittal to the sender’s payment service provider.
| PDP | +| **Payment System** | Payment Network, Money Transfer System | ncompasses all payment-related activities, processes, mechanisms, infrastructure, institutions and users in a country or a broader region (for example a common economic area). | ITU-T | +| **Payment System Operator** | Mobile Money Operator, Payment Service Provider | The entity that operates a payment system or scheme. | ITU-T | +| **Peer FSP** | | The counterparty financial service provider. | PDP | +| **PEP** | | Politically Exposed Person. Someone who has been entrusted with a prominent public function. A PEP generally presents a higher risk for potential involvement in bribery and corruption by virtue of their position and the influence that they may hold (for example, ‘senior foreign political figure', 'senior political figure', foreign official', and so on).| PDP | +| **Platform** | Payment Platform, Payment Platform Provider, Mobile Money Platform |A term used to describe the software or service used by a provider, a scheme, or a switch to manage end user accounts and to send and receive payment transactions. | ITU-T | +| **Posting** | Clearing | The act of the provider of entering a debit or credit entry into the end user's account record. | ITU-T | +| **Pre-approval** |Debit Authorization, Mandate |Pre-approval means that a Payer is allowing a specific Payee to withdraw funds without the Payer having to manually accept the payment transaction. The pre-approval can be valid one time, valid during a specific time period or valid until the Payer cancels the pre-approval.| PDP | +| **Prefunding** | | The process of adding funds to Vostro/Nostro accounts. | PDP | +| **Prepaid Cards** | |eMoney product for general purpose use where the record of funds is stored on the payment card (on magnetic stripe or the embedded integrated circuit chip) or a central computer system, and which can be drawn down through specific payment instructions to be issued from the bearer’s payment card. | ITU-T | +| **Processing of Personal/Consumer Data** | Processing of Personal/Consumer Data | Processing of personal/consumer data shall mean any operation or set of operations which is performed upon personal/consumer data, whether or not by automatic means, such as collection, recording, organization, storage, adaptation or alteration, retrieval, consultation, use, disclosure by transmission, dissemination or otherwise making available, alignment or combination, blocking, erasure or destruction. | PDP | +| **Processor** | Gateway | An enterprise that manages, on an out-sourced basis, various functions for a digital financial services provider. These functions may include transaction management, customer database management, and risk management. Processors may also do functions on behalf of payments systems, schemes, or switches. | ITU-T | +| **Promotion** | | FSP marketing initiative offering the user a transaction/service fee discount on goods or services. May be implemented through the use of a coupon. | PDP | +| **Pull Payments** | | A payment type which is initiated by the payee: typically, a merchant or payment acceptor, whose provider "pulls" the funds out of the payer's account at the payer's provider. | ITU-T | +| **Push Payments** | |A payment type which is initiated by the payer, who instructs their provider to debit their account and "push" the funds to the receiving payee at the payee's provider. | ITU-T | +| **Quote** | | Quote can be seen as the price for performing a hypothetical financial transaction. Some factors that can affect a Quote are Fees, FX rate, Commission, and Taxes. A Quote is usually guaranteed a short time period, after that the Quote expires and is no longer valid. | PDP | +| **Reconciliation** | | Cross FSP Reconciliation is the process of ensuring that two sets of records, usually the balances of two accounts, are in agreement between FSPs. Reconciliation is used to ensure that the money leaving an account matches the actual money transferred. This is done by making sure the balances match at the end of a particular accounting period. | PDP | +| **Recourse** | | Rights given to an end user by law, private operating rules, or specific agreements by providers, allowing end users the ability to do certain things (sometimes revoking a transaction) in certain circumstances. | ITU-T | +| **Refund** | | A repayment of a sum of money (i.e. repayment, reimbursement or rebate) to a customer returning the goods/services bought. | PDP | +| **Registration** | Enrollment, Agent Registration, User Creation, User On- Boarding | The process of opening a provider account. Separate processes are used for consumers, merchants’ agents, and so on | ITU-T | +| **Regulator** | | A governmental organization given power through national law to set and enforce standards and practices. Central Banks, Finance and Treasury Departments, Telecommunications Regulators, and Consumer Protection Authorities are all regulators involved in digital financial services. | ITU-T | +| **Reserve** | Prepare | Part of a 2-phase transfer operation in which the funds to be transferred are locked (the funds cannot be used for any purpose until either rolled back or committed). This is usually done for a predetermined duration, the expiration of which results in the reservation being rolled back.| PDP | +| **Reversal** | | The process of reversing a completed transfer. | PDP | +| **Risk Management** | Fraud Management | The practices that enterprises do to understand, detect, prevent, and manage various types of risks. Risk management occurs at providers, at payments systems and schemes, at processors, and at many merchants or payments acceptors.| ITU-T | +| **Risk-based Approach** | | A regulatory and/or business management approach that creates different levels of obligation based on the risk of the underlying transaction or customer. | ITU-T | +| **Roll back** | Reject | Roll back means that the electronic funds that were earlier reserved are put back in the original state. The financial transaction is cancelled. The electronic funds are no longer locked for usage.| PDP | +| **Rollback** | | The process of reversing a transaction - restoring the system (i.e. account balances affected by the transaction) to a previously defined state, typically to recover from an error and via an administrator-level user action. | PDP | +| **Rules** | | The private operating rules of a payments scheme, which bind the direct participants (either providers, in an open-loop system, or end users, in a closed-loop system). | ITU-T | +| **Saving and Investing** | | Keeping funds for future needs and financial return. | ITU-T | +| **Savings Products** | | An account at either a bank or non-bank provider, which stores funds with the design of helping end users save money. | ITU-T | +| **Scheme** | | A set of rules, practices and standards necessary for the functioning of payment services. | ITU-T | +| **Secure Element** | | A secure chip on a phone that can be used to store payment data. | ITU-T | +| **Security Access Code** | Security Access Code | A personal identification number (PIN), password/one-time password (OTP), biometric recognition, code or any other device providing a means of certified access to a customer’s account for the purposes of, among other things, initiating an electronic fund transfer. | PDP | +| **Security Level** | | Security specification of the system which defines effectiveness of risk protection. | ITU-T | +| **Sensitive Consumer Data** | Sensitive Consumer Data |Consumer Sensitive Data means any or all information that is used by a consumer to authenticate identity and gain authorization for performing mobile banking services, including but not limited to User ID, Password, Mobile PIN, Transaction PIN. Also includes data relating to religious or other beliefs, sexual orientation, health, race, ethnicity, political views, trades union membership, criminal record. | PDP | +| **Settlement** | Real Time Gross Settlement (RTGS) | An act that discharges obligations in respect of funds or securities transfers between two or more parties. | RI | +| **Settlement Instruction** | | Means an instruction given to a settlement system by a settlement system participant or by a payment clearing house system operator on behalf of a Central Bank settlement system participant to effect settlement of one or more payment obligations, or to discharge any other obligation of one system participant to another system participant.| PDP | +| **Settlement Obligation** | | Means an indebtedness that is owed by one settlement system participant to another as a result of one or more settlement instructions. | PDP | +| **Settlement System** | Net Settlement, Gross Settlement, RTGS | A system used to facilitate the settlement of transfers of funds, assets or financial instruments. Net settlement system: a funds or securities transfer system which settles net settlement positions during one or more discrete periods, usually at pre-specified times in the course of the business day. Gross settlement system: a transfer system in which transfer orders are settled one by one. | ITU-T | +| **Short Message Service** | | A service for sending short messages between mobile phones. | ITU-T | +| **SIM Card** | SIM ToolKit, Thin SIM | A smart card inside a cellular phone, carrying an identification number unique to the owner, storing personal data, and preventing operation if removed. A SIM Tool Kit is a standard of the GSM system which enables various value-added services. A "Thin SIM" is an additional SIM card put in a mobile phone. | ITU-T | +| **Smart Phone** | | A device that combines a mobile phone with a computer. | ITU-T | +| **Standards Body** | EMV, ISO, ITU, ANSI, GSMA | An organization that creates standards used by providers, payments schemes, and payments systems. | ITU-T | +| **Stored Value Account** | SVA | Account in which funds are kept in a secure, electronic format. May be a bank account or an eMoney account. | PDP | +| **Storing Funds** | Account, Wallet, Cash-In, Deposit | Converting cash into electronic money and keeping funds in secure electronic format. May be a bank account or an eMoney account. | PDP | +| **Super-Agent** | Master Agent | In some countries, agents are managed by Super Agents or Master Agents who are responsible for the actions of their agents to the provider. | ITU-T | +| **Supplier Payment** | B2B - Business to Business, B2G - Business to Government | Making a payment from one business to another for supplies, and so on: may be in-person or remote, domestic or cross border. Includes cross- border trade. | ITU-T | +| **Suspicious Transaction Report** | Suspicious Transaction Report | If a financial institution notes something suspicious about a transaction or activity, it may file a report with the Financial Intelligence Unit that will analyze it and cross check it with other information. The information on an STR varies by jurisdiction. | PDP | +| **Systemic Risk** | | In payments systems, the risk of collapse of an entire financial system or entire market, as opposed to risk associated with any one individual provider or end user. | ITU-T | +| **Tax Payment** | C2G, B2G |Making a payment from a consumer to a government, for taxes, fees, and so on | ITU-T | +| **Tokenization** | | The use of substitute a token ("dummy numbers") in lieu of "real" numbers, to protect against the theft and misuse of the "real" numbers. Requires a capability to map the token to the "real" number. | ITU-T | +| **Trading** | International Trade | The exchange of capital, goods, and services across international borders or territories. | ITU-T | +| **Transaction Accounts** | | Transaction account: broadly defined as an account held with a bank or other authorized and/or regulated service provider (including a non- bank) which can be used to make and receive payments. Transaction accounts can be further differentiated into deposit transaction accounts and eMoney accounts. Deposit transaction account: deposit account held with banks and other authorized deposit-taking financial institutions that can be used for making and receiving payments. Such accounts are known in some countries as current accounts, chequing accounts or other similar terms. | ITU-T | +| **Transaction Cost** | | The cost to a DFS provider of delivering a digital financial service. This could be for a bundle of services (for example, a "wallet") or for individual transactions. | ITU-T | +| **Transaction Request** | Payment Request | Transaction Request is a request sent by a Payee, meant for a Payer to transfer electronic funds to the Payee. The Transaction Request usually requires manual approval by the Payer to perform the financial transaction, but the Payee can also be pre-approved or a credential (usually OTP) can be sent as part of the transaction request for automatic validation and approval. | PDP | +| **Transfer** | | Generic term to describe any financial transaction where value is transferred from one account to another. | PDP | +| **Transfer Funds** | Sending or Receiving Funds | Making and receiving payments to another person. | ITU-T | +| **Transport Layer Security** | TLS, client authentication, mutual authentication | Transport Layer Security (TLS) is a cryptographic protocol that provides communications security over a computer network, used to secure point to point communication (Source: Wikipedia). | | +| **Trust Account** | Escrow, Funds Isolation, Funds Safeguarding, Custodian Account, Trust Account | A means of holding funds for the benefit of another party. eMoney Issuers are usually required by law to hold the value of end users' eMoney accounts at a bank, typically in a Trust Account. This accomplishes the goals of funds isolation and funds safeguarding. | ITU-T | +| **Trusted Execution Environment** | | A development execution environment that has security capabilities and meets certain security-related requirements. | ITU-T | +| **Ubiquity** | | The ability of a payer to reach any (or most) payees in their country, regardless of the provider affiliation of the receiving payee. Requires some type of interoperability. | ITU-T | +| **Unbanked** | Underbanked, Underserved| Unbanked people do not have a transaction account. Underbanked people may have a transaction account but do not actively use it. Underserved is a broad term referring to people who are the targets of financial inclusion initiatives. It is also sometimes used to refer to a person who has a transaction account but does not have additional DFS services. | ITU-T | +| **User ID** | | A unique identifier of a user. This may be an MSISDN, bank account, some form of DFSP-provided ID, national ID, and so on. In a transaction, money is generally addressed to a user ID and not directly to an account ID. | PDP | +| **USSD** | | A communication technology that is used to send text between a mobile phone and an application program in the network. | ITU-T | +| **Vostro Account** | | From the Payee's perspective: Payer FSP funds/accounts held/hosted at Payee FSP. | PDP | +| **Voucher** | | A monetary value instrument commonly used to transfer funds to customers (Payees) who do not have an account at the Payer's FSP. This could be Payees with no account or account at another FSP. | ITU-T | +| **Wallet** | eWallet | Repository of funds for an account. Relationship of Wallet to Account can be many to one. | PDP | +| **Whitelist** | | A list or register of entities (registered users) that are being provided a particular privilege, service, mobility, access or recognition, especially those that were initially blacklisted. Entities on the list will be accepted, approved and/or recognized. Whitelisting is the reverse of blacklisting, the practice of identifying entities that are denied, unrecognized, or ostracized. Where entities are registered users (or user accounts, if granularity allows) and services are informational (for example, balance check), transactional (for example, debit/credit) payments services or lifecycle (for example, registration, closure) services. | PDP | +| **'x'-initiated** | | Used when referring to the side that initiated a transaction; for example, agent-initiated cash-out vs. user-initiated cash-out. | PDP | diff --git a/docs/technical/api/fspiop/json-binding-rules.md b/docs/technical/api/fspiop/json-binding-rules.md new file mode 100644 index 000000000..915a0dba6 --- /dev/null +++ b/docs/technical/api/fspiop/json-binding-rules.md @@ -0,0 +1,1287 @@ +--- +showToc: true +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- +# JSON Binding Rules + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| + +## Introduction + +The purpose of this document is to express the data model used by the Open API for FSP Interoperability (hereafter cited as "the API") in the form of JSON Schema binding rules, along with the validation rules for their corresponding instances. + +This document adds to and builds on the information provided in _Open API for FSP Interoperability Specification._ The contents of the Specification are listed in [FSPIOP API Overview](/). + +The types used in the PDP API fall primarily into three categories: + +- Basic data types and Formats used + +- Element types + +- Complex types + +The various types used in _API Definition_, _Data Model_ and the _Open API Specification_, as well as the JSON transformation rules to which their instances must adhere, are identified in the following sections. + +
+ +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](./logical-data-model) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](#) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](./v1.1/signature) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](./glossary) + +
+ +## Keywords and Usage + +The _keywords_ used in the JSON Schemas and rules are derived from _JSON Schema Specification_[1](http://json-schema.org/documentation.html). The types of keywords used are identified in [Validation Keywords](#validation-keywords), [Metadata Keywords](#metadata-keywords) and [Instance-and-$ref](#instance-and-$ref) sections. As discussed in detail later, some of these keywords specify validation parameters whereas others are more descriptive, such as Metadata. The description that follows specifies details such as whether a field MUST[2](https://www.ietf.org/rfc/rfc2119.txt) be present in the definition and whether a certain field is associated with a particular data type. + +### Validation Keywords + +This section[3](http://json-schema.org/latest/json-schema-validation.html) provides descriptions of the keywords used for validation in _API Definition_. Validation keywords in a schema impose requirements for successful validation of an instance. + +#### maxLength + +The value of this keyword MUST be a non-negative integer. A string instance is valid against this keyword if its length is less than, or equal to, the value of this keyword. The length of a string instance is defined as the number of its characters as defined by RFC 7159[RFC7159]. + +#### minLength + +The value of this keyword MUST be a non-negative integer. A string instance is valid against this keyword if its length is greater than, or equal to, the value of this keyword. The length of a string instance is defined as the number of its characters as defined by RFC 7159[RFC7159]. Omitting this keyword has the same behaviour as assigning it a value of **0**. + +#### pattern + +The value of this keyword MUST be a string. This string SHOULD be a valid regular expression, according to the ECMA 262 regular expression dialect. A string instance is considered valid if the regular expression matches the instance successfully. Recall: regular expressions are not implicitly anchored. + +#### items + +The value of `items` MUST be either a valid JSON Schema or an array of valid JSON Schemas. This keyword determines how child instances validate for arrays; it does not directly validate the immediate instance itself. If `items` is a schema, validation succeeds if all elements in the array successfully validate against that schema. If `items` is an array of schemas, validation succeeds if each element of the instance validates against the schema at the same position, if such a schema exists. Omitting this keyword has the same behaviour as specifying an empty schema. + +#### maxItems + +The value of this keyword MUST be a non-negative integer. An array instance is valid against `maxItems` if its size is less than, or equal to, the value of this keyword. + +#### minItems + +The value of this keyword MUST be a non-negative integer. An array instance is valid against `minItems` if its size is greater than, or equal to, the value of this keyword. Omitting this keyword has the same behaviour as a value of **0**. + +#### required + +The value of this keyword MUST be an array. Elements of this array (if there are any) MUST be strings and MUST be unique. An object instance is valid against this keyword if every item in the array is the name of a property in the instance. Omitting this keyword results in the same behaviour as does having the array be empty. + +#### properties + +The value of `properties` MUST be an object. Each value of this object MUST be a valid JSON Schema. This keyword determines how child instances validate for objects; it does not directly validate the immediate instance itself. Validation succeeds if, for each name that appears in both the instance and as a name within this keyword's value, the child instance for that name successfully validates against the corresponding schema. Omitting this keyword results in the same behaviour as does having an empty object. + +#### enum + +The value of this keyword MUST be an array. This array SHOULD have at least one element. Elements in the array SHOULD be unique. An instance validates successfully against this keyword if its value is equal to one of the elements in this keyword's array value. Elements in the array might be of any value, including null. + +#### type + +The value of this keyword MUST be either a string or an array. If it is an array, elements of the array MUST be strings and MUST be unique. String values MUST be one of the six primitive types (null, boolean, object, array, number, or string), or integer which matches any number with a zero-fractional part. An instance validates if and only if the instance is in any of the sets listed for this keyword. + +This specification uses string type for all basic types and element types, but enforces restrictions using regular expressions as `patterns`. Complex types are of object type and contain properties that are either element or object types in turn. Array types are used to specify lists, which are currently only used as part of complex types. + +### Metadata Keywords + +This section provides descriptions of the fields used in the JSON definitions of the types used. The description specifies whether a field MUST be present in the definition and specifies whether a certain field is associated with a primary data type. Validation keywords in a schema impose requirements for successful validation of an instance. + +#### definitions + +This keyword's value MUST be an object. Each member value of this object MUST be a valid JSON Schema. This keyword plays no role in validation. Its role is to provide a standardized location for schema authors to incorporate JSON Schemas into a more general schema. + +#### title and description + +The value of both keywords MUST be a string. Both keywords can be used to provide a user interface with information about the data produced by this user interface. A title will preferably be short, whereas a description will provide explanation about the purpose of the instance described in this schema. + +### Instance and $ref + +Two keywords, **Instance** and **$ref** are used in either the JSON Schema definitions or the transformation rules in this document, which are described in [Instance](#instance) and [Schema References with $ref](#schema-references-with-$ref-keyword) sections. `Instance` is not used in the Open API Specification; this term is used in this document to describe validation and transformation rules. `$ref` contains a URI value as a reference to other types; it is used in the Specification. + +#### Instance + +JSON Schema interprets documents according to a data model. A JSON value interpreted according to this data model is called an `instance`[4](http://json-schema.org/latest/json-schema-core.html\#rfc.section.4.2). An instance has one of six primitive types, and a range of possible values depending on the type: + +- **null**: A JSON `null` production. + +- **boolean**: A `true` or `false` value, from the JSON `true` or `false` productions. + +- **object**: An unordered set of properties mapping a string to an instance, from the JSON `object` production. + +- **array**: An ordered list of instances, from the JSON `array` production. + +- **number**: An arbitrary-precision, base-10 decimal number value, from the JSON `number` production. + +- **string**: A string of Unicode code points, from the JSON `string` production. + +Whitespace and formatting concerns are outside the scope of the JSON Schema. Since an object cannot have two properties with the same key, behaviour for a JSON document that tries to define two properties (the `member` production) with the same key (the `string` production) in a single object is undefined. + +#### Schema references with $ref keyword + +The `$ref`[5](http://json-schema.org/latest/json-schema-core.html\#rfc.section.8) keyword is used to reference a schema and provides the ability to validate recursive structures through self- reference. An object schema with a `$ref` property MUST be interpreted as a `"$ref"` reference. The value of the `$ref` property MUST be a URI Reference. Resolved against the current URI base, it identifies the URI of a schema to use. All other properties in a `"$ref"` object MUST be ignored. + +The URI is not a network locator, only an identifier. A schema need not be downloadable from the address if it is a network- addressable URL, and implementations SHOULD NOT assume they should perform a network operation when they encounter a network-addressable URI. A schema MUST NOT be run into an infinite loop against a schema. For example, if two schemas "#alice" and "#bob" both have an "allOf" property that refers to the other, a naive validator might get stuck in an infinite recursive loop trying to validate the instance. Schemas SHOULD NOT make use of infinite recursive nesting like this; the behavior is undefined. + +It is used with the syntax `"$ref"` and is mapped to an existing definition. From the syntax, the value part of `_$ref_`, `#/definitions/`, indicates that the type being referenced is from the Definitions section of the Open API Specification (Typically, an Open API Specification has sections named Paths, Definitions, Responses and Parameters.). An example for this can be found in [Listing 26](#listing-26), where the types for properties _authentication_ and _authenticationValue_ are provided by using references to `Authenticationtype` and `AuthenticationValue` types, respectively. + +### JSON Definitions and Examples + +JSON definitions and examples are provided after most sections defining the transformation rules, where relevant. These are provided in JSON form, taken from the JSON version of the Open API Specification. The Regular Expressions in the examples may have minor differences (sometimes having an additional '**\\**' symbol) when compared to the ones in rules and descriptions because the regular expressions in the examples are taken from the JSON version whereas the rules and descriptions are from the standard Open API (Swagger) Specification. They are provided in the relevant section as a numbered Listing. For example, [Listing 1](#listing-1) provides the JSON representation of the definition of data type `Amount`. + +For each of the data types, a description of the JSON Schema from the Open API Specification and (where relevant) an example of that type are provided. Following the Schema description are transformation rules that apply to an instance of that particular type. + +
+ +## Element and Basic Data Types + +This section contains the definitions of and transformation rules for the basic formats and _element_ types used by the API as specified in _API Definition_ and _API Data Model_. These definitions are basic in the context of the API specification, but *not* the Open API Technical Specification. Often, these basic data types are derived from the basic types supported by Open API Specification standards, such as string type. + +### Data Type Amount + +This section provides the JSON Schema definition for the data type `Amount`. [Listing 1](#listing-1) provides a JSON Schema for the `Amount` type. + +- JSON value pair with Name "**title**" and Value "**Amount**" + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**pattern**" and Value "**^(\[0\]\|(\[1-9\]\[0-9\]{0,17}))(\[.\]\[0-9\]{0,3}\[1-9\])?\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type Amount is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons. This pattern does not allow any trailing zeroes at all, but allows an amount without a minor currency unit. It also only allows four digits in the minor currency unit; a negative value is not allowed. Using more than 18 digits in the major currency unit is not allowed.**" + +##### Listing 1 + + +```JSON +"Amount": { + "title": "Amount", + "type": "string", + "pattern": + "^([0]|([1-9][0-9]{0,17}))([.][0-9]{0,3}[1-9])?$", + "maxLength": 32, + "description": "The API data type Amount is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons." +} +``` +**Listing 1 -- JSON Schema for Data type Amount** + +The transformation rules for an instance of Amount data type are as follows: + +- A given Instance of `Amount` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^(\[0\]\|(\[1-9\]\[0-9\]{0,17}))(\[.\]\[0-9\]{0,3}\[1-9\])?\$** + +- The length of this instance is restricted by the regular expression above as 23, with 18 digits in the major currency unit and four digits in the minor currency unit. Valid example values for Amount type: **124.45**, **5, 5.5, 4.4444, 0.5, 0, 181818181818181818** + +### Data Type BinaryString + +This section provides the JSON Schema definition for the data type BinaryString. [Listing 2](#listing-2) provides a JSON Schema for the BinaryString type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**BinaryString**" + +- JSON value pair with Name "**pattern**" and Value "**^\[A-Za-z0-9-\_\]+\[=\]{0,2}\$**" + +- JSON value pair with Name "**description**" and Value the content of Property **description** + +##### Listing 2 + +```JSON +"BinaryString":{ + "title":"BinaryString", + "type":"string", + "pattern":"^[A-Za-z0-9-_]+[=]{0,2}$", + "description":"The API data type BinaryString is a JSON String. The string is the base64url encoding of a string of raw bytes, where padding (character '=') is added at the end of the data if needed to ensure that the string is a multiple of 4 characters. The length restriction indicates the allowed number of characters. +} +``` +**Listing 2 -- JSON Schema for Data type BinaryString** + +The section on [BinaryString Type IlpPacket](#binarystring-type-ilppacket) gives an example for `BinaryString` type. + +The transformation rules for an instance of `BinaryString` data type are as follows: + +- A given Instance of `BinaryString` type MUST be of string type. +- The instance MUST be a match for the regular expression **^\[A-Za-z0-9-\_\]+\[=\]{0,2}\$** + +An example value for `BinaryString` type is + +``` +AYIBgQAAAAAAAASwNGxldmVsb25lLmRmc3AxLm1lci45T2RTOF81MDdqUUZERmZlakgyOVc4bXFmNEpLMHlGTFGCAUBQU0svMS4wCk5vbmNlOiB1SXlweUYzY3pYSXBFdzVVc05TYWh3CkVuY3J5cHRpb246IG5vbmUKUGF5bWVudC1JZDogMTMyMzZhM2ItOGZhOC00MTYzLTg0NDctNGMzZWQzZGE5OGE3CgpDb250ZW50LUxlbmd0aDogMTM1CkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbgpTZW5kZXItSWRlbnRpZmllcjogOTI4MDYzOTEKCiJ7XCJmZWVcIjowLFwidHJhbnNmZXJDb2RlXCI6XCJpbnZvaWNlXCIsXCJkZWJpdE5hbWVcIjpcImFsaWNlIGNvb3BlclwiLFwiY3JlZGl0TmFtZVwiOlwibWVyIGNoYW50XCIsXCJkZWJpdElkZW50aWZpZXJcIjpcIjkyODA2MzkxXCJ9Ig +``` + +#### BinaryString Type IlpPacket + +This section provides the JSON Schema definition for the `BinaryString` type `IlpPacket`. [Listing 3](listing-3) provides a JSON Schema for the IlpPacket type. The transformation rules for an instance of `IlpPacket` are the same as those of data type `BinaryString`. + + - JSON value pair with Name "**title**" and Value "**IlpPacket**" + + - JSON value pair with Name "**type**" and Value "**string**" + + - JSON value pair with Name "**pattern**" and Value "**^\[A-Za-z0-9-\_\]+\[=\]{0,2}\$**" + + - JSON value pair with Name "**minLength**" and Value **1** + + - JSON value pair with Name "**pattern**" and Value **32768** + + - JSON value pair with Name "**description**" and Value "**Information for recipient (transport layer information).**" + +##### Listing 3 + +```json +"IlpPacket":{ + "title":"IlpPacket", + "type":"string", + "pattern":"^[A-Za-z0-9-_]+[=]{0,2}$", + "minLength":1 + "maxLength":32768 + "description":"Information for recipient (transport layer information)." +} +``` + +**Listing 3 -- JSON Schema for BinaryString type IlpPacket** + +### Data Type BinaryString32 + +This section provides the JSON Schema definition for the data type `BinaryString32`. [Listing 4](#listing-4) provides a JSON Schema for the `BinaryString32` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**BinaryString32**" + +- JSON value pair with Name "**pattern**" and Value "**^\[A-Za-z0-9-\_\]{43}\$**" + +- JSON value pair with Name "**description**" and Value the content of Property **description** + +##### Listing 4 + +```json +"BinaryString32":{ + "title":"BinaryString32", + "type":"string", + "pattern":"^[A-Za-z0-9-_]{43}$", + "description":"The API data type BinaryString32 is a fixed size version of the API data type BinaryString, where the raw underlying data is always of 32 bytes. The data type BinaryString32 should not use a padding character as the size of the underlying data is fixed." +} +``` + +**Listing 4 -- JSON Schema for Data type BinaryString32** + +The section on [BinaryString32 Type IlpCondition](#binarystring32-type-ilpcondition) gives an example for `BinaryString32` type. Another example in the API of `BinaryString32` type is `IlpFulfilment`. The transformation rules for an instance of `BinaryString32` data type are as follows: + +- A given Instance of `BinaryString32` type MUST be of string type. + +- The instance MUST be a match for the regular expression "**^\[A-Za-z0-9-\_\]{43}\$**". + +An example value for `BinaryString32` type is: + +``` +AYIBgQAAAAAAAASwNGxldmVsb25lLmRmc3AxLm1lci45T2RTOF81MDdqUUZERmZlakgyOVc4bXFmNEpLMHlGTFGCAUBQU0svMS4wCk5vbmNlOiB1SXlweUYzY3pYSXBFdzVVc05TYWh3CkVuY3J5cHRpb246IG5vbmUKUGF5bWVudC1JZDogMTMyMzZhM2ItOGZhOC00MTYzLTg0NDctNGMzZWQzZGE5OGE3CgpDb250ZW50LUxlbmd0aDogMTM1CkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbgpTZW5kZXItSWRlbnRpZmllcjogOTI4MDYzOTEKCiJ7XCJmZWVcIjowLFwidHJhbnNmZXJDb2RlXCI6XCJpbnZvaWNlXCIsXCJkZWJpdE5hbWVcIjpcImFsaWNlIGNvb3BlclwiLFwiY3JlZGl0TmFtZVwiOlwibWVyIGNoYW50XCIsXCJkZWJpdElkZW50aWZpZXJcIjpcIjkyODA2MzkxXCJ9IgA +``` + +#### BinaryString32 Type IlpCondition + +This section provides the JSON Schema definition for the `BinaryString32` type `IlpCondition`. [Listing 5](#listing-5) provides a JSON Schema for the `IlpCondition` type. The transformation rules for an instance of `IlpCondition` are the same as those of data type `BinaryString32`. + +- JSON value pair with Name "**title**" and Value "**IlpCondition**" + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**pattern**" and Value "**^\[A-Za-z0-9-\_\]{43}\$**" + +- JSON value pair with Name "**maxLength**" and Value **48** + +- JSON value pair with Name "**description**" and Value "**Condition that must be attached to the transfer by the Payer.**" + +##### Listing 5 + +```json +"IlpCondition":{ + "title":"IlpCondition", + "type":"string", + "pattern":"^[A-Za-z0-9-_]{43}$", + "maxLength":48, + "description":"Condition that must be attached to the transfer by the Payer." +} +``` + +**Listing 5 -- JSON Schema for BinaryString32 type IlpCondition** + +### Data Type BopCode + +This section provides the JSON Schema definition for the data type `BopCode`. [Listing 6](#listing-6) provides a JSON Schema for the `BopCode` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**BalanceOfPayments**" + +- JSON value pair with Name "**pattern**" and Value "**^\[1-9\]\\d{2}\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type BopCode is a JSON String of 3 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. [https://www.imf.org/external/np/sta/bopcode/](https://www.imf.org/external/np/sta/bopcode/).**" + +#### Listing 6 + +```json +"BalanceOfPayments":{ + "title":"BalanceOfPayments", + "type":"string", + "pattern":"^[1-9]\d{2}$", + "description":"(BopCode) The API data type BopCode is a JSON String of 3 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. https://www.imf.org/external/np/sta/bopcode/" +} +``` + +**Listing 6 -- JSON Schema for Data type BopCode** + +The transformation rules for an instance of `BopCode` data type are as follows: + +- A given Instance of `BopCode` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[1-9\]\\d{2}\$**. + +An example value for `BopCode` type is **124**. + +### Data Type Enum + +This section provides the JSON Schema definition for the data type `Enum`. These are generic characteristics of an `Enum` type, alternately known as `CodeSet`. [Listing 8](#listing-8) provides an example JSON Schema for the data type Enumeration (CodeSet). + +- CodeSet.Name is the name of the JSON object. + +- JSON value pair with Name "**title**" and Value "**CodeSet.Name**" + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**enum**" and Value the array containing all the CodeSetLiteral values of the CodeSet + +- If Property description is not empty, JSON value pair with Name "**description**" and Value the content of Property description An example for Enum/CodeSet type -- "AmountType" can found in the [Enumeration AmountType](#enumeration-amounttype) section. [Listing 7](#listing-7) lists the other Enum types defined and used in the API. + +##### Listing 7 + +``` +AuthenticationType, AuthorizationResponse, BulkTransferState, Currency, PartyIdentifier, PartyIdType, PartySubIdOrType , PersonalIdentifierType, TransactionInitiator, TransactionInitiatorType, TransactionRequestState, TransactionScenario, TransactionState, TransferState. +``` + +**Listing 7 -- List of Enum types specified and used in the API** + +The transformation rules for an instance of Enum data type are as +follows: + +- A given Instance of `Enum` type MUST be of string type. + +- The instance MUST be one of the values specified in the `CodeSetLiteral` values. + +#### Enumeration AmountType + +This section provides the JSON Schema definition for the Enum type `AmountType`. [Listing 8](#listing-8) provides a JSON Schema for the `AmountType` type. + +- CodeSet.Name "**AmountType**" + +- JSON value pair with Name "**title**" and Value "**AmountType**" + +- JSON value pair with Name "**type**"and Value "**string**" + +- JSON value pair with Name **description** and Value "**_Below are the allowed values for the enumeration AmountType_** + - **_SEND The amount the Payer would like to send, i.e. the amount that should be withdrawn from the Payer account including any fees._** + - **_RECEIVE The amount the Payer would like the Payee to receive, i.e. the amount that should be sent to the receiver exclusive fees._**" + +- JSON value pair with Name **enum** and Value the array containing the values: + + → **SEND** + + → **RECEIVE** + +###### Listing 8 + +```json +"AmountType":{ + "title":"AmountType", + "type":"string", + "enum":[ + "SEND", + "RECEIVE" + ], + "description":"Below are the allowed values for the enumeration AmountType - SEND The amount the Payer would like to send, i.e. the amount that should be withdrawn from the Payer account including any fees. - RECEIVE The amount the Payer would like the Payee to receive, i.e. the amount that should be sent to the receiver exclusive fees." +} +``` + +**Listing 8 -- JSON Schema for Enumeration Type AmountType** + +The transformation rules for an instance of `AmountType` data type are as follows (same as those of Data Type Enum, but listing the rules here to demonstrate a valid set of literal values): + +- A given Instance of AmountType type MUST be of string type. + +- The instance MUST be one of the values defined in the set: {"**SEND**", "**RECEIVE**"}. + +An example value for `AmountType` type is "**SEND**". + +### Data Type Date + +This section provides the JSON Schema definition for the data type `Date`. [Listing 9](#listing-9) provides a JSON Schema for the `Date` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**Date**" + +- JSON value pair with Name "**pattern**" and Value "**^(?:\[1-9\]\\d{3}-(?:(?:0\[1-9\]\|1\[0-2\])-(?:0\[1-9\]\|1\\d\|2\[0- 8\])\|(?:0\[13-9\]\|1\[0-2\])-(?:29\|30)\|(?:0\[13578\]\|1\[02\])-31)\|(?:\[1- 9\]\\d(?:0\[48\]\|\[2468\]\[048\]\|\[13579\]\[26\])\|(?:\[2468\]\[048\]\|\[13579\]\[26\])00)-02-29)\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type Date is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. This format is according to ISO 8601 containing a date only. A more readable version of the format is "yyyy-MM-dd", e.g. "1982-05-23" or "1987-08- 05"**." + +##### Listing 9 + +```json +"Date": { + "title": "Date", + "type": "string", + "pattern": "^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$", + "description": "The API data type Date is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. This format is according to ISO 8601 containing a date only. A more readable version of the format is “yyyy-MM-dd”, e.g. "1982-05-23" or "1987-08-05”." +} +``` + +**Listing 9 -- JSON Schema for Data type Date** + +The transformation rules for an instance of `Date` data type are as follows: + +- A given Instance of `Date` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^(?:\[1-9\]\\d{3}-(?:(?:0\[1-9\]\|1\[0-2\])-(?:0\[1-9\]\|1\\d\|2\[0- 8\])\|(?:0\[13-9\]\|1\[0-2\])-(?:29\|30)\|(?:0\[13578\]\|1\[02\])-31)\|(?:\[1- 9\]\\d(?:0\[48\]\|\[2468\]\[048\]\|\[13579\]\[26\])\|(?:\[2468\]\[048\]\|\[13579\]\[26\])00)-02-29)\$**. + +An example value for `Date` type is **1971-12-25**. + +#### Data Type DateOfBirth + +This section provides the JSON Schema definition for the Date type `DateOfBirth`. [Listing 10](#listing-10) provides a JSON Schema for the `DateOfBirth` type. The transformation rules for an instance of `DateOfBirth` are the same as those of data type `Date`. + +- JSON value pair with Name "**title**" and Value "**DateOfBirth (type Date)**" + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**description**" and Value "**Date of Birth for the Party**" + +- JSON value pair with Name "**pattern**" and Value "**^(?:\[1-9\]\\d{3}-(?:(?:0\[1-9\]\|1\[0-2\])-(?:0\[1-9\]\|1\\d\|2\[0- 8\])\|(?:0\[13-9\]\|1\[0-2\])-(?:29\|30)\|(?:0\[13578\]\|1\[02\])-31)\|(?:\[1- 9\]\\d(?:0\[48\]\|\[2468\]\[048\]\|\[13579\]\[26\])\|(?:\[2468\]\[048\]\|\[13579\]\[26\])00)-02-29)\$**" + +##### Listing 10 + +```json +"DateOfBirth": { + "title": "DateOfBirth (type Date)", + "type": "string", + "pattern": "^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$", + "description": "Date of Birth for the Party." +} +``` + +**Listing 10 -- JSON Schema for Date type DateOfBirth** + +### Data Type DateTime + +The JSON Schema definition for this section provides the JSON Schema definition for the data type `DateTime`. [Listing 11](#listing-11) provides a JSON Schema for the `DateTime` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**DateTime**" + +- JSON value pair with Name "**pattern**" and Value "**^(?:\[1-9\]\\d{3}-(?:(?:0\[1-9\]\|1\[0-2\])-(?:0\[1-9\]\|1\\d\|2\[0- 8\])\|(?:0\[13-9\]\|1\[0-2\])-(?:29\|30)\|(?:0\[13578\]\|1\[02\])-31)\|(?:\[1- 9\]\\d(?:0\[48\]\|\[2468\]\[048\]\|\[13579\]\[26\])\|(?:\[2468\]\[048\]\|\[13579\]\[26\])00)-02-29)T(?:\[01\]\\d\|2\[0-3\]):\[0-5\]\\d:\[0-5\]\\d(?:(\\.\\d{3}))(?:Z\|\[+-\]\[01\]\\d:\[0-5\]\\d)\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type DateTime is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. This format is according to ISO 8601, expressed in a combined date, time and time zone format. A more readable version of the format is "yyyy-MM-ddTHH:mm:ss.SSS\[-HH:MM\]", e.g. \"2016-05-24T08:38:08.699-04:00\" or \"2016-05-24T08:38:08.699Z\" (where Z indicates Zulu time zone, same as UTC)**." + +##### Listing 11 + +```json +"DateTime": { + "title":"DateTime", + "type": "string", + "pattern": "^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01\d|2[0-3]):[0-5]\d:[0-5]\d(?:(\.\d{3}))(?:Z|[+-][01]\d:[0-5]\\d)$", + "description": "The API data type DateTime is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. This format is according to ISO 8601, expressed in a combined date, time and time zone format. A more readable version of the format is “yyyy-MM-ddTHH:mm:ss.SSS[-HH:MM]”, e.g. "2016-05-24T08:38:08.699-04:00" or "2016-05-24T08:38:08.699Z" (where Z indicates Zulu time zone, same as UTC)." +} +``` + +**Listing 11 -- JSON Schema for Data type DateTime** + +The transformation rules for an instance of DateTime data type are as follows: + +- A given Instance of type `DateTime` MUST be of string type. + +- The instance MUST be a match for the regular expression **^(?:\[1-9\]\\d{3}-(?:(?:0\[1-9\]\|1\[0-2\])-(?:0\[1-9\]\|1\\d\|2\[0-8\])\|(?:0\[13-9\]\|1\[0-2\])-(?:29\|30)\|(?:0\[13578\]\|1\[02\])-31)\|(?:\[1-9\]\\d(?:0\[48\]\|\[2468\]\[048\]\|\[13579\]\[26\])\|(?:\[2468\]\[048\]\|\[13579\]\[26\])00)-02-29)T(?:\[01\]\\d\|2\[0-3\]):\[0-5\]\\d:\[0-5\]\\d(?:(\\.\\d{3}))(?:Z\|\[+-\]\[01\]\\d:\[0-5\]\\d)\$**. + +An example value for `DateTime` type is **2016-05-24T08:38:08.699-04:00**. + +### Data Type ErrorCode + +This section provides the JSON Schema definition for the data type `ErrorCode`. [Listing 12](#listing-12) provides a JSON Schema for the `ErrorCode` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**ErrorCode**" + +- JSON value pair with Name "**pattern**" and Value "**^\[1-9\]\\d{3}\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type ErrorCode is a JSON String of 4 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. Specific error number in the form _{C}{E}{SS}_ where _{C}_ is a one-digit category _{E}_ is a one-digit error within the category _{SS}_ is a scheme defined two-digit sub-error within the error. Please refer to x.x for the list of the possible category/error codes**". + +##### Listing 12 + +```json +"ErrorCode": { + "title": "ErrorCode", + "type": "string", + "pattern": "^[1-9]\d{3}$", + "description": "The API data type ErrorCode is a JSON String of 4 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. Specific error number in the form {C}{E}{SS} where {C} is a one-digit category {E} is a one-digit error within the category {SS} is a scheme defined two-digit sub-error within the error. Please refer to x.x for the list of the possible category/error codes" +} +``` + +**Listing 12 -- JSON Schema for Data type ErrorCode** + +The transformation rules for an instance of `ErrorCode` data type are as follows: + +- A given Instance of `ErrorCode` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[1-9\]\d{3}\$**. + +An example value for `ErrorCode` type is **5100**. + +### Data Type Integer + +This section provides the JSON Schema definition for the data type `Integer`. [Listing 13](#listing-13) provides a JSON Schema for the Integer type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**Integer**" + +- JSON value pair with Name "**pattern**" and Value "**^\[1-9\]\d\*\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type Integer is a JSON String consisting of digits only. Negative numbers and leading zeroes are not allowed. The data type is always limited by a number of digits.**" + +##### Listing 13 + +```json +"Integer": { + "title": "Integer", + "type": "string", + "pattern": "^[1-9]\d*$", + "description": "The API data type Integer is a JSON String consisting of digits only. Negative numbers and leading zeroes are not allowed. The data type is always limited by a number of digits." +} +``` + +**Listing 13 -- JSON Schema for Data type Integer** + +The transformation rules for an instance of `Integer` data type are as follows: + +- A given Instance of Integer type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[1-9\]\d\*\$**. + +An example value for `Integer` type is **12345**. + +### Data Type Latitude + +This section provides the JSON Schema definition for the data type `Latitude`. [Listing 14](#listing-14) provides a JSON Schema for the `Latitude` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**Latitude**" + +- JSON value pair with Name "**pattern**" and Value "**^(\\+\|-)?(?:90(?:(?:\\.0{1,6})?)\|(?:\[0-9\]\|\[1-8\]\[0-9\])(?:(?:\\.\[0-9\]{1,6})?))\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type Latitude is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons**". + +##### Listing 14 + +```json +"Latitude": { + "title": "Latitude", + "type": "string", + "pattern": "^(\+|-)?(?:90(?:(?:\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\.[0-9]{1,6})?))$", + "description": "The API data type Latitude is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons." +} +``` + +**Listing 14 -- JSON Schema for Data type Latitude** + +The transformation rules for an instance of `Latitude` data type are as follows: + +- A given Instance of `Latitude` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^(\\+\|-)?(?:90(?:(?:\\.0{1,6})?)\|(?:\[0-9\]\|\[1-8\]\[0-9\])(?:(?:\\.\[0-9\]{1,6})?))\$**. + +An example value for `Latitude` type is **+45.4215**. + +### Data Type Longitude + +This section provides the JSON Schema definition for the data type `Longitude`. [Listing 15](#listing-15) provides a JSON Schema for the `Longitude` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**Longitude**" + +- If Property pattern is not empty, JSON value pair with Name "**pattern**" and Value "**^(\\+\|-)?(?:180(?:(?:\\.0{1,6})?)\|(?:\[0-9\]\|\[1-9\]\[0-9\]\|1\[0-7\]\[0-9\])(?:(?:\\.\[0-9\]{1,6})?))\$**". + +- JSON value pair with Name "**description**" and Value "**The API data type Longitude is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons.**" + +##### Listing 15 + +```json +"Longitude": { + "title": "Longitude", + "type": "string", + "pattern": "^(\+|-)?(?:180(?:(?:\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.[0-9]{1,6})?))$", + "description": "The API data type Longitude is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons." +} +``` + +**Listing 15 -- JSON Schema for Data type Longitude** + +The transformation rules for an instance of `Longitude` data type are as follows: + +- A given Instance of `Longitude` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^(\\+\|-)?(?:180(?:(?:\\.0{1,6})?)\|(?:\[0-9\]\|\[1-9\]\[0-9\]\|1\[0-7\]\[0-9\])(?:(?:\\.\[0-9\]{1,6})?))\$**. + +An example value for `Longitude` type is **+75.6972**. + +### Data Type MerchantClassificationCode + +This section provides the JSON Schema definition for the data type `MerchantClassificationCode`. [Listing 16](#listing-16) provides a JSON Schema for the `MerchantClassificationCode` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**MerchantClassificationCode**" + +- JSON value pair with Name "**pattern**" and Value "**^\[\\d\]{1,4}\$**". + +- JSON value pair with Name "**description**" and Value "**A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, etc.**" + +##### Listing 16 + +```json +"MerchantClassificationCode": { + "title": "MerchantClassificationCode", + "type": "string", + "pattern": "^[\d]{1,4}$", + "description": "A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, etc." +} +``` + +**Listing 16 -- JSON Schema for Data type MerchantClassificationCode** + +The transformation rules for an instance of `MerchantClassificationCode` data type are as follows: + +- A given Instance of `MerchantClassificationCode` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[\\d\]{1,4}\$**. + +An example value for `MerchantClassificationCode` type is **99**. + +### Data Type Name + +This section provides the JSON Schema definition for the data type `Name`. [Listing 17](#listing-17) provides the JSON Schema for a `Name` type. [Name Type Firstname](#name-type-firstname) contains an example of `Name` type -- "First Name". Other Name types used in the API are "Middle Name" and "Last Name". + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**Name**" + +- JSON value pair with Name "**minLength**" and Value the content of Property **minLength** + +- JSON value pair with Name "**maxLength**" and Value the content of Property **maxLength** + +- JSON value pair with Name "**pattern**" and Value "**^(?!\\\\s\*\$)\[\\\\w .,'-\]+\$**". + +- JSON value pair with Name "**description**" and Value "**The API data type Name is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. The restriction will not allow a string consisting of whitespace only, all Unicode characters should be allowed, as well as the characters ".", "'" (apostrophe), "-", "," and " " (space). Note - In some programming languages, Unicode support needs to be specifically enabled. As an example, if Java is used the flag UNICODE\_CHARACTER\_CLASS needs to be enabled to allow Unicode characters.**" + +##### Listing 17 + +```json +"Name": { + "title": "Name", + "type": "string", + "pattern": "^(?!\\s*$)[\\w .,'-]+$", + "description": "The API data type Name is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. The restriction will not allow a string consisting of whitespace only, all Unicode characters should be allowed, as well as the characters ".", "'" (apostrophe), "- ", "," and " " (space). Note - In some programming languages, Unicode support needs to be specifically enabled. As an example, if Java is used the flag UNICODE_CHARACTER_CLASS needs to be enabled to allow Unicode characters." +} +``` + +**Listing 17 -- JSON Schema for Data type Name** + +The transformation rules for an instance of `Name` data type are as follows: + +- A given Instance of `Name` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^(?!\\\\s\*\$)\[\\\\w .,'-\]+\$**. + +An example value for `Name` type is **Bob**. + +#### Name Type FirstName + +This section provides the JSON Schema definition for the `Name` type `FirstName`. [Listing 18](#listing-18) provides a JSON Schema for the `FirstName` type. The transformation rules for an instance of `FirstName` are the same as those of data type `Name`. + +- JSON value pair with Name "**title**" and Value "**FirstName**" + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**pattern**" and Value "**^(?!\\s\*\$)\[\\w .,\'-\]+\$**" + +- JSON value pair with Name "**maxLength**" and Value **128** + +- JSON value pair with Name "**minLength**" and Value **1** + +- JSON value pair with Name "**description**" and Value "**First name of the Party (Name type).**" + +##### Listing 18 + +```json +"FirstName": { + "title": "FirstName", + "type": "string", + "minLength": 1, + "maxLength": 128, + "pattern": "^(?!\s*$)[\w .,'-]+$", + "description": "First name of the Party (Name Type)." +} +``` + +**Listing 18 -- JSON Schema for Name type FirstName** + +### Data Type OtpValue + +This section provides the JSON Schema definition for the data type `OtpValue`. [Listing 19](#listing-19) provides a JSON Schema for the `OtpValue` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**OtpValue**" + +- JSON value pair with Name "**pattern**" and Value "**^\\d{3,10}\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type OtpValue is a JSON String of 3 to 10 characters, consisting of digits only. Negative numbers are not allowed. One or more leading zeros are allowed.**" + +##### Listing 19 + +```json +"OtpValue": { + "title": "OtpValue", + "type": "string", + "pattern": "^\d{3,10}$", + "description": "The API data type OtpValue is a JSON String of 3 to 10 characters, consisting of digits only. Negative numbers are not allowed. One or more leading zeros are allowed." +} +``` + +**Listing 19 -- JSON Schema for Data type OtpValue** + +The transformation rules for an instance of `OtpValue` data type are as follows: + +- A given Instance of `OtpValue` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\\d{3,10}\$**. + +An example value for `OtpValue` type is **987345**. + +### Data Type String + +This section provides the JSON Schema definition for the data type `String`. [Listing 21](#listing-21) provides an example JSON Schema for a `String` type. + +- **String.Name** is the name of the JSON object. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**String.Name**" + +- JSON value pair with Name "**minLength**" and Value the content of Property "**minLength**" + +- JSON value pair with Name "**maxLength**" and Value the content of Property "**maxLength**" + +- If Property pattern is not empty, JSON value pair with Name **pattern** and Value the content of Property **pattern**. + +- JSON value pair with Name "**description**" and Value the content of Property **description**. [Below](#string-type-errordescription), is an example for Stri`ng type, `ErrorDescription`. [Listing 20](#listing-20) has other `String` types specified and used in the API. + +##### Listing 20 + +``` +AuthenticationValue, ExtensionKey, ExtensionValue, FspId, Note, PartyName, QRCODE, RefundReason, TransactionSubScenario. +``` + +**Listing 20 -- String types specified and used in the API** + +The transformation rules for an instance of `String` data type are as follows: + +- A given Instance of `String` type MUST be of string type. + +- The length of this instance MUST not be greater than the **maxLength** specified. + +- The length of this instance MUST not be less than the **minLength** specified. + +- The instance MUST be a match for the regular expression specified by a **pattern** property if one is specified. + +An example value for `String` type is **Financial Services for the Poor**. + +### String Type ErrorDescription + +This section provides the JSON Schema definition for the `String` type `ErrorDescription`. [Listing 21](#listing-21) provides a JSON Schema for the `ErrorDescription` type. + +- JSON value pair with Name "**title**" and Value "**ErrorDescription**" + +- JSON value pair with Name "**type**" and Value "**ErrorDescription**" + +- JSON value pair with Name "**description**" and Value "**Error description string**" + +- JSON value pair with Name "**minLength**" and Value **1** + +- JSON value pair with Name "**maxLength**" and Value **128** + +##### Listing 21 + +```json +"ErrorDescription": { + "title": "ErrorDescription", + "type": "string", + "minLength": 1, + "maxLength": 128, + "description": "Error description string." +} +``` + +**Listing 21 -- JSON Schema for Data type ErrorDescription** + +The transformation rules for an instance of `ErrorDescription` data type are as follows (same as those of `Data` Type String, but listing the rules here to demonstrate a valid set of values for length properties): + +- A given Instance of `ErrorDescription` type MUST be of String Type. + +- The length of this instance MUST not be greater than 128. + +- The length of this instance MUST not be less than 1. + +An example value for `ErrorDescription` type is **This is an error description**. + +### Data Type TokenCode + +This section provides the JSON Schema definition for the data type `TokenCode`. [Listing 22](#listing-22) provides a JSON Schema for the `TokenCode` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**TokenCode**" + +- JSON value pair with Name "**pattern**" and Value "**^\[0-9a-zA-Z\]{4,32}\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type TokenCode is a JSON String between 4 and 32 characters, consisting of digits or characters from a to z (case insensitive).**" + +##### Listing 22 + +```json +"TokenCode": { + "title": "TokenCode", + "type": "string", + "pattern": "^[0-9a-zA-Z]{4,32}$", + "description": "The API data type TokenCode is a JSON String between 4 and 32 characters, consisting of digits or characters from a to z (case insensitive)." +} +``` + +**Listing 22 -- JSON Schema for Data type TokenCode** + +The transformation rules for an instance of `TokenCode` data type are as follows: + +- A given Instance of `TokenCode` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[0-9a-zA-Z\]{4,32}\$**. + +An example value for `TokenCode` type is **Test-Code**. + +#### TokenCode Type Code + +This section provides the JSON Schema definition for the `TokenCode` type `Code`. [Listing 23](#listing-23) provides a JSON Schema for the `Code` type. The transformation rules for an instance of `Code` are the same as those of Data Type `TokenCode`. + +- JSON value pair with Name "**title**" and Value "**Code**" + +- JSON value pair with Name "**type**" and Value "**String**" + +- JSON value pair with Name "**pattern**" and Value "**^\[0-9a-zA-Z\]{4,32}\$**" + +- JSON value pair with Name "**description**" and Value "**Any code/token returned by the Payee FSP (TokenCode type).**" + +##### Listing 23 + +```json +"Code": { + "title": "Code", + "type": "string", + "pattern": "^[0-9a-zA-Z]{4,32}$", + "description": "Any code/token returned by the Payee FSP (TokenCode Type)." +} +``` + +**Listing 23 -- JSON Schema for TokenCode type Code** + +### Data Type UndefinedEnum + +This section provides the JSON Schema definition for the data type `UndefinedEnum`. [Listing 24](#listing-24) provides the JSON Schema for the data type `UndefinedEnum` (Enumeration). + +- JSON value pair with Name "**title**" and Value "**UndefinedEnum**" + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**pattern**" and Value "**^\[A-Z\_\]{1,32}\$**" + +- If Property description is not empty, JSON value pair with Name "**description**" and Value "**The API data type UndefinedEnum is a JSON String consisting of 1 to 32 uppercase characters including "\_" (underscore).**" + +##### Listing 24 + +```json +"UndefinedEnum": { + "title": "UndefinedEnum", + "type": "string", + "pattern": "^[A-Z_]{1,32}$", + "description": "The API data type UndefinedEnum is a JSON String consisting of 1 to 32 uppercase characters including "_" (underscore)." +} +``` + +**Listing 24 -- JSON Schema for Data type UndefinedEnum** + +The transformation rules for an instance of `UndefinedEnum` data type are as follows: + +- A given Instance of UndefinedEnum type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[A-Z\_\]{1,32}\$**. + +An example value for `UndefinedEnum` type depends on the list of values specified. + +### Data Type UUID + +This section provides the JSON Schema definition for the data type `UUID`. [Listing 25](#listing-25) provides a JSON Schema for `CorrelationId` which is of `UUID` type. Since `CorrelationId` is an element type in the *API Definition*, it is being used interchangeably with `UUID` in the Open API Specification version. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and "**Value CorrelationId**" + +- JSON value pair with Name "**pattern**" and Value "**^\[0-9a-f\]{8}-\[0-9a-f\]{4}-\[1-5\]\[0-9a-f\]{3}-\[89ab\]\[0-9a-f\]{3}-\[0-9a- f\]{12}\$**" + +- JSON value pair with Name "**description**" and Value "**Identifier that correlates all messages of the same sequence. The API data type UUID (Universally Unique Identifier) is a JSON String in canonical format, conforming to RFC 4122, that is restricted by a regular expression for interoperability reasons. An example of a UUID is "b51ec534-ee48-4575-b6a9-ead2955b8069". An UUID is always 36 characters long, 32 hexadecimal symbols and 4 dashes ("-").**" + +##### Listing 25 + +```json +"CorrelationId": { + "title": "CorrelationId", + "type": "string", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a- f]{12}$", + "description": "Identifier that correlates all messages of the same sequence. The API data type UUID (Universally Unique Identifier) is a JSON String in canonical format, conforming to RFC 4122, that is restricted by a regular expression for interoperability reasons. An example of a UUID is "b51ec534-ee48-4575-b6a9- ead2955b8069". An UUID is always 36 characters long, 32 hexadecimal symbols and 4 dashes ("-")." +} +``` + +**Listing 25 -- JSON Schema for Data type UUID** + +The transformation rules for an instance of `UUID` data type are as follows: + +- A given Instance of `UUID` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[0-9a-f\]{8}-\[0-9a-f\]{4}-\[1-5\]\[0-9a-f\]{3}-\[89ab\]\[0-9a- f\]{3}-\[0-9a-f\]{12}\$**. + +An example value for `UUID` type is **b51ec534-ee48-4575-b6a9-ead2955b8069**. + +## Complex Types + +This section contains definitions of and transformation characteristics for complex types that are used by the API. Along with the complex types defined in the [API Definition]() and [Data Model]() documents, there are other complex types defined in the PDP Open API Specification based on the objects present in several requests and responses in the **body** section. These are discussed in the [Types of Objects in Requests or Responses](#types-of-objects-in-requests-or-responses) section. + +### Complex Type Definition, Transformation + +This section provides the JSON Schema definition for a complex type. [Listing 26](#listing-26) provides an example JSON Schema for a complex type, `AuthenticationInfo`. Transformation rules specific to a complex type are listed [here](#complex-type-authenticationinfo). + +- JSON value pair with Name "**type**" and Value "**object**" + +- JSON value pair with Name "**title**" and Value "**complextype.Name**" + +- If Property **description** is not empty, JSON value pair with Name "**description**" and Value the content of Property **description**. + +- An array with Name "**required**" and Value the list of properties that MUST be present in an instance of complex type. + +- A JSON object **properties** with the following content: + + - A list of key, value pairs with Name **key.Name** and Value of element, complex or Array type + + - JSON value pair with Name **$ref** and as Value the concatenation of **#/definitions/** with **key.Type** type. An example for a complex type is provided under the [Complex Type AuthenticationInfo](#complex-type-authenticationinfo) section. + +#### Complex Type AuthenticationInfo + +This section provides the JSON Schema definition for the complex type `AuthenticationInfo` can be expressed as follows. [Listing 26](#listing-26) provides the JSON Schema for `AuthenticationInfo`. + +- JSON value pair with Name "**type**" and Value "**object**" + +- JSON value pair with Name "**title**" and Value "**AuthenticationInfo**" + +- JSON value pair with Name "**description**" and Value "**complex type AuthenticationInfo**" + +- An array with Name "**required**" and as Value a list with elements "**authentication**" and "**authenticationValue**" + +- A JSON object **properties** with the following content: + + - A JSON object **authentication** with the following content: + + - JSON value pair with Name "**$ref**" and as Value the concatenation of **#/definitions/** with Authenticationtype type. + + - A JSON object **authenticationValue** with the following content: + + - JSON value pair with Name "**$ref**" and as Value the concatenation of **#/definitions/** with AuthenticationValue type. + +##### Listing 26 + +```json +"AuthenticationInfo": { + "title": "AuthenticationInfo", + "type": "object", + "description": "complex type AuthenticationInfo", + "properties": { + "authentication": { + "$ref": "#/definitions/AuthenticationType", + "description": "The type of authentication." + }, + "authenticationValue":\ { + "$ref": "#/definitions/AuthenticationValue", + "description": " The authentication value." + } + }, + "required": [ + "authentication", + "authenticationValue" + ] +} +``` + +**Listing 26 -- JSON Schema for complex type AuthenticationInfo** + +The transformation rules for an instance of `AuthenticationInfo` complex type are as follows: + +- A given Instance of AuthenticationInfo type MUST be of `Object` type. + +- The instance MUST contain a property with name **authentication**. + +- The JSON object titled **authentication** MUST be an instance of AuthenticationType type, provided in the definitions. + +- The instance MUST contain a property with name **authenticationValue**. + +- The JSON object titled **authenticationValue** MUST be an instance of AuthenticationValue type, provided in the definitions. An example instance for AuthenticationInfo complex type is given in [Listing 27](#listing-27). + +##### Listing 27 + +```json +"authenticationInfo": { + "authentication": "OTP", + "authenticationValue": "1234" +} +``` + +**Listing 27 -- Example instance of AuthenticationInfo complex type** + +#### Complex Types in the API + +The examples for complex type from the API appear in [Listing 28](#listing-28). The list includes complex types defined in [API Definition]() and [Data Model]() documents and does not contain the complex types defined only in the Open API version of the specification which captures the objects in Requests and Reponses. + +##### Listing 28 + +``` +ErrorInformation, Extension, ExtensionList, GeoCode, IndividualQuote, IndividualQuoteResult, IndividualTransfer, IndividualTransferResult, Money, Party, PartyComplexName, PartyIdInfo, PartyPersonalInfo, PartyResult, Refund, Transaction, TransactionType. +``` + +**Listing 28 -- Complex type Examples** + +### Types of Objects in Requests or Responses + +This section contains the definitions and transformation characteristics of the complex types that are used in the API Specification of the PDP API to capture objects in Requests and Responses. These have the same characteristics as the complex data types discussed in the Complex Type section. + +#### Complex Type AuthorizationsIDPutResponse + +This section provides the JSON Schema definition for the complex type `AuthorizationsIDPutResponse`. [Listing 29](#listing-29) provides a JSON Schema for complex type `AuthorizationsIDPutResponse`. + +- JSON value pair with Name "**type**" and Value "**object**" + +- JSON value pair with Name "**title**" and Value "**AuthorizationsIDPutResponse**". + +- JSON value pair with Name "**description**" and Value "**PUT /authorizations/{ID} object**". + +- A JSON object "**properties**" with the following content: + + - If Property "**authenticationInfo**" is present, a JSON object "**authenticationInfo**" with the following content: + + - JSON value pair with Name "**$ref**" and as Value the definition of AuthenticationInfo type, located under **definitions** as indicated by **#/definitions/** + + - A JSON object **responseType** with the following content: + + - JSON value pair with Name "**$ref**" and as Value the definition of AuthorizationResponse type, located under **definitions** as indicated by "**#/definitions/**". + +- An array **required** and as Value a list with single element "**responseType**" + +##### Listing 29 + +```json +"AuthorizationsIDPutResponse": { + "title": "AuthorizationsIDPutResponse", + "type": "object", + "description": "PUT /authorizations/{ID} object", + "properties": { + "authenticationInfo": { + "$ref": "#/definitions/AuthenticationInfo", + "description": "OTP or QR Code if entered, otherwise empty." + } + "responseType": { + "$ref": "#/definitions/AuthorizationResponse", + "description": "Enum containing response information; if the customer entered the authentication value, rejected the transaction, or requested a resend of the authentication value." + } + }, + "required ": [ + "responseType" + ] +} +``` + +**Listing 29 -- JSON Schema for complex type AuthorizationsIDPutResponse** + +The transformation rules for an instance of `AuthorizationsIDPutResponse` complex type are as follows: + +- A given Instance of `AuthorizationsIDPutResponse` type MUST be of object type. + +- The instance MUST contain a property with name "**authenticationInfo**". + +- The JSON object titled "**authenticationInfo**" MUST be an instance of AuthenticationInfo type, provided in the definitions. + +- The instance MUST contain a property with name "**responseType**". + +- The JSON object titled "**responseType**" MUST be an instance of AuthorizationReponse type, provided in the definitions. + +An example instance for `AuthorizationsIDPutResponse` complex type is given in [Listing 30](#listing-30). + +##### Listing 30 + +```json +{ + "authenticationInfo": { + "authentication": "OTP", + "authenticationValue": "1234" + }, + "responseType": "ENTERED" +} +``` + +**Listing 30 -- Example instance of AuthorizationsIDPutResponse complex type** + +**5.2.2 Other Complex types in Requests and Responses** + +Other complex type examples from the API used in Requests or Responses can be found in [Listing 31](#listing-31). + +##### Listing 31 + +``` +BulkQuotesPostRequest, BulkQuotesIDPutResponse, BulkTransfersPostRequest, BulkTransfersIDPutResponse, ErrorInformationObject, ErrorInformationResponse, ParticipantsTypeIDSubIDPostRequest, ParticipantsTypeIDPutResponse, ParticipantsIDPutResponse, ParticipantsPostRequest, QuotesPostRequest, QuotesIDPutResponse, TransactionRequestsIDPutResponse, TransactionsIDPutResponse, TransfersPostRequest, TransactionRequestsPostRequest, TransfersIDPutResponse. +``` + +**Listing 31 -- Complex type Examples for Objects in Requests and Responses in the API** + +## References + +1 The link for this is: [http://json-schema.org/documentation.html](http://json-schema.org/documentation.html) + +2 MUST, MAY, OPTIONAL in this document are to be interpreted as described\ in [RFC2119](https://www.ietf.org/rfc/rfc2119.txt) + +3 Most of the items in this section and the next one, "Metadata Keywords" are taken from: [http://json-schema.org/latest/json-schema-validation.html](http://json-schema.org/latest/json-schema-validation.html). Some changes are made based on Open API limitations or constraints. Also, only relevant keywords are referenced. + +4 The description for "Instance" keyword is taken from: [http://json-schema.org/latest/json-schema-core.html\#rfc.section.4.2](http://json-schema.org/latest/json-schema-core.html\#rfc.section.4.2) + +5 Meaning and usage of \$ref as specified here: [http://json-schema.org/latest/json-schema-core.html\#rfc.section.8](http://json-schema.org/latest/json-schema-core.html\#rfc.section.8) + + + +## Table of Listings + +[Listing 1 -- JSON Schema for Data type Amount](#listing-1) + +[Listing 2 -- JSON Schema for Data type BinaryString](#listing-2) + +[Listing 3 -- JSON Schema for BinaryString type IlpPacket](#listing-3) + +[Listing 4 -- JSON Schema for Data type BinaryString32](#listing-4) + +[Listing 5 -- JSON Schema for BinaryString32 type IlpCondition](#listing-5) + +[Listing 6 -- JSON Schema for Data type BopCode](#listing-6) + +[Listing 7 -- List of Enum types specified and used in the API](#listing-7) + +[Listing 8 -- JSON Schema for Enumeration Type AmountType](#listing-8) + +[Listing 9 -- JSON Schema for Data type Date](#listing-9) + +[Listing 10 -- JSON Schema for Date type DateOfBirth](#listing-10) + +[Listing 11 -- JSON Schema for Data type DateTime](#listing-11) + +[Listing 12 -- JSON Schema for Data type ErrorCode](#listing-12) + +[Listing 13 -- JSON Schema for Data type Integer](#listing-13) + +[Listing 14 -- JSON Schema for Data type Latitude](#listing-14) + +[Listing 15 -- JSON Schema for Data type Longitude](#listing-15) + +[Listing 16 -- JSON Schema for Data type MerchantClassificationCode](#listing-16) + +[Listing 17 -- JSON Schema for Data type Name](#listing-17) + +[Listing 18 -- JSON Schema for Name type FirstName](#listing-18) + +[Listing 19 -- JSON Schema for Data type OtpValue](#listing-19) + +[Listing 20 -- String types specified and used in the API](#listing-20) + +[Listing 21 -- JSON Schema for Data type ErrorDescription](#listing-21) + +[Listing 22 -- JSON Schema for Data type TokenCode](#listing-22) + +[Listing 23 -- JSON Schema for TokenCode type Code](#listing-23) + +[Listing 24 -- JSON Schema for Data type UndefinedEnum](#listing-24) + +[Listing 25 -- JSON Schema for Data type UUID](#listing-25) + +[Listing 26 -- JSON Schema for complex type AuthenticationInfo](#listing-26) + +[Listing 27 -- Example instance of AuthenticationInfo complex type](#listing-27) + +[Listing 28 -- Complex type Examples](#listing-28) + +[Listing 29 -- JSON Schema for complex type AuthorizationsIDPutResponse](#listing-29) + +[Listing 30 -- Example instance of AuthorizationsIDPutResponse complex type](#listing-30) + +[Listing 31 -- Complex type Examples for Objects in Requests and Responses in the API](#listing-31) \ No newline at end of file diff --git a/docs/technical/api/fspiop/logical-data-model.md b/docs/technical/api/fspiop/logical-data-model.md new file mode 100644 index 000000000..146f85b40 --- /dev/null +++ b/docs/technical/api/fspiop/logical-data-model.md @@ -0,0 +1,2440 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- + +# Logical Data Model + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| + +
+ +## Introduction + +This document specifies the logical data model used by Open API (Application Programming Interface) for FSP (Financial Service Provider) Interoperability (hereafter cited as “the API”). + +The [Services Elements](#api-services-elements) section lists elements used by each service. + +The [Supporting Data Model](#api-supporting-data-model) section describes the data model in terms of basic elements, simple data types and complex data types. + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](#) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](./json-binding-rules) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](./v1.1/signature) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](./glossary) + +
+ +## API Services Elements + +The section identifies and describes elements used by each service. + +### API Resource Participants + +This section describes the data model of services for the resource **Participants**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Participants**. +
+ +##### Lookup Participant Information + +Table 1 contains the data model for _Lookup Participant Information_. + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartyIdSubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party.| + +**Table 1 – Lookup Participant Information data model** + +
+ +##### Create Participant Information + +Table 2 below contains the data model for _Create Participant Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) |The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartyIdSubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party. | +| **fspId** | 1 | [FspId](#fspid-element) | FSP Identifier that the Party belongs to. | +| **currency** | 0..1 | [Currency](#currency-element) | Indicate that the provided Currency is supported by the Party. | + +**Table 2 – Create Participant Information data model** + +
+ +##### Create Bulk Participant Information + +Table 3 below contains the data model for _Create Bulk Participant Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **requestId** | 1 | [CorrelationId](#correlationid-element) | The ID of the request, determined by the client. Used for identification of the callback from the server. | +| **partyList** | 1..10000 | [PartyIdInfo](#partyidinfo) | List of Party elements that the Client would like to update or create FSP information about. | +| **currency** | 0..1 | [Currency](#currency-enum) | Indicate that the provided Currency is supported by each PartyIdInfo in the list. | + +**Table 3 – Create Bulk Participant Information data model** + +
+ +##### Delete Participant Information + +Table 4 below contains the data model for _Delete Participant Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartyIdSubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party. | + +**Table 4 – Delete Participant Information data model** + +
+ +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Participants**. + +##### Return Participant Information + +Table 5 below contains the data model for _Return Participant Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartyIdSubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party. | +| **fspId** | 0..1 | [FspId](#fspid-element) | FSP Identifier that the Party belongs to. | + +**Table 5 – Return Participant Information data model** + +
+ +##### Return Bulk Participant Information + +Table 6 below contains the data model for _Return Bulk Participant Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **requestId** | 1 | [CorrelationId](#correlationid-element) | The ID of the request, determined by the client. Used for identification of the callback from the server. | +| **partyList** | 1..10000 | [PartyResult](#partyresult) | List of PartyResult elements for which creation was attempted (and either succeeded or failed). | +| **Currency** | 0..1 | [Currency](#currency-element) | Indicates that the provided Currency was set to be supported by each successfully added PartyIdInfo. | + +**Table 6 – Return Bulk Participant Information data model** + +
+ +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Participants**. + +##### Return Participant Information Error + +Table 7 below contains the data model for _Return Participant Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartyIdSubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 7 – Return Participant Information Error data model** + +
+ +##### Return Bulk Participant Information Error + +Table 8 below contains the data model for _Return Bulk Participant Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **requestId** | 1 | [CorrelationId](#correlationid-element) | The ID of the request, determined by the client. Used for identification of the callback from the server. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 8 – Return Bulk Participant Information Error data model** + +
+ +### API Resource Parties + +This section describes the data model of services for the resource **Parties**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Parties**. + +##### Lookup Party Information + +Table 9 below contains the data model for _Lookup Party Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartyIdSubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party. | + +**Table 9 – Lookup Party Information data model** + +
+ +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Parties**. + +##### Return Party Information + +Table 10 below contains the data model for _Return Party Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartySubIdOrType](#partysuboridtype-element) | A sub-identifier or sub-type for the Party. | +| **party** | 1 | [Party](#party) | Information regarding the requested Party. | + + +**Table 10 – Return Party Information data model** + + +
+ +#### Error Responses + +##### Return Party Information Error + +Table 11 below contains the data model for _Return Party Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartySubIdOrType](#partysuboridtype-element) | A sub-identifier or sub-type for the Party. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 11 – Return Party Information Error data model** + +
+ +### API Resource Transaction Requests + +This section describes the data model of services for the resource **Transaction Requests**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Transaction Requests**. + +##### Retrieve Transaction Request + +Table 12 below contains the data model for _Retrieve Transaction Request_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionRequestId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the transaction request object, determined by the Payee FSP. The ID should be re-used for re-sends of the same transaction request. A new ID should be generated for each new transaction request. | + +**Table 12 – Retrieve Transaction Request data model** + + +
+ +##### Perform Transaction Request Information + +Table 13 below contains the data model for _Perform Transaction Request Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionRequestId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the transaction request object, determined by the Payee FSP. The ID should be re-used for resends of the same transaction request. A new ID should be generated for each new transaction request. | +| **payee** | 1 | [Party](#party) | Information about the Payee in the proposed financial transaction. | +| **payer** | 1 | [PartyIdInfo](#partyidinfo) | Information about the Payer type, id, subtype/id, FSP Id in the proposed financial transaction. +| **amount** | 1 | [Money](#money) | The requested amount to be transferred from the Payer to Payee. | +| **transactionType** | 1 | [TransactionType](#transactiontype) | The type of transaction. | +| **note** | 0..1 | [Note](#note-element) | Reason for the transaction request, intended to the Payer. | +| **geoCode** | 0..1 | [GeoCode](#geocode) | Longitude and Latitude of the initiating party.

Can be used to detect fraud.

| +| **authenticationType** | 0..1 | [AuthenticationType](#authenticationtype-element) | OTP or QR Code, otherwise empty. | +| **expiration** | 0..1 | [DateTime](#datetime) | Expiration is optional. It can be set to get a quick failure in case the peer FSP takes too long to respond. Also useful for notifying Consumer, Agent, Merchant that their request has a time limit. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 13 – Perform Transaction Request Information data model** + +
+ +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Transaction Requests**. + + +##### Return Transaction Request Information + +Table 14 below contains the data model for _Return Transaction Request Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionRequestId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the transaction request object, determined by the Payee FSP. The ID should be re-used for re-sends of the same transaction request. A new ID should be generated for each new transaction request. | +| **transactionId** | 0..1 | [CorrelationId](#correlationid-element) | Identifies related /transactions (if a transaction has been created). | +| **transactionRequestState** | 1 | [TransactionRequestState](#transactionrequeststate-element) | The state of the transaction request. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 14 – Return Transaction Request Information data model** + +
+ +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Transaction Requests**. + +##### Return Transaction Request Information Error + +Table 15 below contains the data model for _Return Transaction Request Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionRequestId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the transaction request object, determined by the Payee FSP. The ID should be re-used for resends of the same transaction request. A new ID should be generated for each new transaction request. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 15 – Return Transaction Request Information Error data model** + +
+ +### API Resource Quotes + +This section describes the data model of services for the resource **Quotes**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Quotes**. + +##### Retrieve Quote Information + +Table 16 bleow contains the data model for _Retrieve Quote Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | Identifies quote message.| + +**Table 16 – Retrieve Quote Information data model** + +
+ +##### Calculate Quote + +Table 17 below contains the data model for _Calculate Quote_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | Identifies quote message. | +| **transactionId** | 1 | [CorrelationId](#correlationid-element) | Identifies transaction message. | +| **transactionRequestId** | 1 | [CorrelationId](#correlationid-element) | Identifies transactionRequest message. | +| **payee** | 1 | [Party](#party) | Information about the Payee in the proposed financial transaction. | +| **payer** | 1 | [Party](#party) | Information about the Payer in the proposed financial transaction. | +| **amountType** | 1 | [AmountType](#amounttype-element) | SEND for sendAmount, RECEIVE for receiveAmount. | +| **amount** | 1 | [Money](#money) | Depending on amountType:
If SEND: The amount the Payer would like to send, that is, the amount that should be withdrawn from the Payer account including any fees. The amount is updated by each participating entity in the transaction.

If RECEIVE: The amount the Payee should receive, that is, the amount that should be sent to the receiver exclusive any fees. The amount is not updated by any of the participating entities.
| +| **fees** | 0..1 | [Money](#money) | The fees in the transaction.
  • The fees element should be empty if fees should be non-disclosed.
  • The fees element should be non-empty if fees should be disclosed.
| +| **transactionType** | 1 | [TransactionType](#transactiontype) | The type of transaction for which the quote is requested. | +| **geoCode** | 0..1 | [GeoCode](#geocode) | Longitude and Latitude of the initiating party. Can be used to detect fraud. | +| **note** | 0..1 | [Note](#note-element) | A memo that will be attached to the transaction. | +| **expiration** | 0..1 | [DateTime](#datetime) | Expiration is optional. It can be set to get a quick failure in case the peer FSP takes too long to respond. Also useful for notifying Consumer, Agent, Merchant that their request has a time limit. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 17 – Calculate Quote data model** + +
+ +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Quotes**. + +##### Return Quote Information + +Table 18 below contains the data model for _Return Quote Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | Identifies quote message. | +| **transferAmount** | 1 | [Money](#money) | The amount of money that the Payer FSP should transfer to the Payee FSP. | +| **payerReceiveAmount** | 1 | [Money](#money) | The amount of money that the Payee should receive in the end-to-end transaction. Optional, as the Payee FSP might not want to disclose any optional Payee fees. | +| **payeeFspFee** | 0..1 | [Money](#money) | Payee FSP’s part of the transaction fee. | +| **payeeFspCommission** | 0..1 | [Money](#money) | Transaction commission from the Payee FSP. | +| **expiration** | 1 | [DateTime](#datetime) | Date and time until when the quotation is valid and can be honored when used in the subsequent transaction. | +| **geoCode** | 0..1 | [GeoCode](#geocode) | Longitude and Latitude of the Payee. Can be used to detect fraud. | +| **ilpPacket** | 1 | [IlpPacket](#ilppacket-element) | The ILP Packet that must be attached to the transfer by the Payer. | +| **condition** | 1 | [IlpCondition](#ilpcondition-element) | The condition that must be attached to the transfer by the payer. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment | + +**Table 18 – Return Quote Information data model** + +
+ +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Quotes**. + +##### Return Quote Information Error + +Table 19 below contains the data model for _Return Quote Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | Identifies quote message. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 19 – Return Quote Information Error data model** + +
+ +### API Resource Authorizations + +This section describes the data model of services for the resource **Authorizations**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Authorizations**. + +##### Perform Authorization + +Table 20 below contains the data model for _Perform Authorization_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **authorizationId** | 1 | [CorrelationId](#correlationid-element) | Identifies authorization message. | +| **authenticationType** | 0..1 | [AuthenticationType](#authenticationtype-element) | The type of authentication. | +| **retriesLeft** | 0..1 | [NrOfRetries](#nrofretries-element) | Number of retries left. | +| **amount** | 0..1 | [Money](#money) | The authorization amount. | +| **currency** | 0..1 | [CurrencyCode](#currencycode-enum) | The authorization currency. | + +**Table 20 – Perform Authorization data model** + +
+ +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Authorizations**. + +##### Return Authorization Result + +Table 21 below contains the data model for _Return Authorization Result_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **authorizationId** | 1 | [CorrelationId](#correlationid-element) | Identifies authorization message. | +| **authenticationInfo** | 0..1 | [AuthenticationInfo](#authenticationinfo) | OTP or QR Code if entered, otherwise empty. | +| **responseType** | 1 | [AuthorizatonResponse](#authorizationresponse-element) | Enum containing response information, if the customer entered the authentication value, rejected the transaction, or requested a resend of the authentication value. | + +**Table 21 – Return Authorization Result data model** + +
+ +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Authorizations**. + +##### Return Authorization Error + +Table 22 below contains the data model for _Return Authorization Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **authorizationId** | 1 | [CorrelationId](#correlationid-element) | Identifies authorization message. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 22 – Return Authorization Error data model** + +
+ +### API Resource Transfers + +This section describes the data model of services for the resource **Transfers**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Transfers**. + +##### Retrieve Transfer Information + +Table 23 below contains the data model for _Retrieve Transfer Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same transfer. A new ID should be generated for each new transfer. | + +**Table 23 – Retrieve Transfer Information data model** + +
+ +##### Perform Transfer + +Table 24 below contains the data model for _Perform Transfer_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same transfer. A new ID should be generated for each new transfer. | +| **payeeFsp** | 1 | [FspId](#fspid-element) | Payee FSP in the proposed financial transaction. | +| **payerFsp** | 1 | [FspId](#fspid-element) | Payer FSP in the proposed financial transaction. | +| **amount** | 1 | [Money](#money) | The transfer amount to be sent. | +| **ilpPacket** | 1 | [IlpPacket](#ilppacket-element) | The ILP Packet containing the amount delivered to the payee and the ILP Address of the payee and any other end-to-end data. | +| **condition** | 1 | [IlpCondition](#ilpcondition-element) | The condition that must be fulfilled to commit the transfer. | +| **expiration** | 1 | [DateTime](#datetime) | Expiration can be set to get a quick failure Expiration of the transfer. The transfer should be rolled back if no fulfilment is delivered before this time. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 24 – Perform Transfer data model** + +
+ +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Transfers**. + +##### Return Transfer Information + +Table 25 below contains the data model for _Return Transfer Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same transfer. A new ID should be generated for each new transfer. | +| **fulfilment** | 0..1 | [IlpFulfilment](#ilpfulfilment-element) | The fulfilment of the condition specified with the transaction. Mandatory if transfer has completed successfully. | +| **completedTimestamp** | 0..1 | [DateTime](#datetime) | The time and date when the transaction was completed. | +| **transferState** | 1 | [TransferState](#transferstate-enum) | The state of the transfer. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 25 – Return Transfer Information data model** + +
+ +#### Error Responses + +This section describes the data model of error responses used by the server in the API for services provided by the resource **Transfers**. + +##### Return Transfer Information Error + +Table 26 below contains the data model for _Return Transfer Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the transfer object, determined by the Payer FSP. The ID should be reused for re-sends of the same transfer. A new ID should be generated for each new transfer. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 26 – Return Transfer Information Error data model** + +
+ +### API Resource Transactions + +This section describes the data model of services for the resource **Transactions**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Transactions**. + +##### Retrieve Transaction Information + +Table 27 below contains the data model for **Retrieve Transaction Information**. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionId** | 1 | [CorrelationId](#correlationid-element) | Identifies transaction message. | + +**Table 27 – Retrieve Transaction Information data model** + +
+ +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Transactions**. + +##### Return Transaction Information + +Table 28 below contains the data model for _Return Transaction Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionId** | 1 | [CorrelationId](#correlationid-element) | Identifies transaction message. | +| **completedTimestamp** | 0..1 | [DateTime](#datetime) | The time and date when the transaction was completed. | +| **transactionState** | 1 | [TransactionState](#transactionstate-element) | The state of the transaction. | +| **code** | 0..1 | [Code](#code-element) | Optional redemption information provided to Payer after transaction has been completed. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 28 – Return Transaction Information data model** + +
+ +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Transactions**. + +##### Return Transaction Information Error + +Table 29 below contains the data model for _Return Transaction Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionId** | 1 | [CorrelationId](#correlationid-element) | Identifies transaction message. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 29 – Return Transaction Information Error data model** + +
+ +### API Resource Bulk Quotes + +This section describes the data model of services for the resource **Bulk Quotes**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Bulk Quotes**. + +##### Retrieve Bulk Quote Information + +Table 30 below contains the data model for _Retrieve Bulk Quote Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkQuoteId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the bulk quote object, determined by the Payer FSP. The ID should be reused for re-sends of the same bulk quote. A new ID should be generated for each new bulk quote. | + +**Table 30 – Retrieve Bulk Quote data model** + +
+ +##### Calculate Bulk Quote + +Table 31 contains the data model for _Calculate Bulk Quote_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkQuoteId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the bulk quote object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk quote. A new ID should be generated for each new bulk quote. payer 1 PartyIdInfo Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction. | +| **GeoCode** | 0..1 | [GeoCode](#geocode) | Longitude and Latitude of the initiating Party. Can be used to detect fraud. | +| **expiration** | 0..1 | [DateTime](#datetime) | Proposed expiration of the quote. | +| **individualQuotes** | 1..1000 | [IndividualQuote](#individualquote) | List of `IndividualQuote` elements. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 31 – Calculate Bulk Quote data model** + +
+ +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Bulk Quotes**. + +##### Return Bulk Quote Information + +Table 32 below contains the data model for _Return Bulk Quote Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkQuoteId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the bulk quote object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk quote. A new ID should be generated for each new bulk quote. | +| **individualQuoteResults** | 0..1000 | [IndividualQuoteResult](#individualquoteresult) | Fees for each individual transaction (if any are charged per transaction). expiration 1 DateTime Date and time until when the quotation is valid and can be honored when used in the subsequent transaction request. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 32 – Return Bulk Quote Information data model** + +
+ +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Bulk Quotes**. + +##### Return Bulk Quote Information Error + +Table 33 below contains the data model for _Return Bulk Quote Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkQuoteId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the bulk quote object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk quote. A new ID should be generated for each new bulk quote. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 33 – Return Bulk Quote Information Error data model** + +
+ +### API Resource Bulk Transfers + +This section describes the data model of services for the resource **Bulk Transfers**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Bulk Transfers**. + +##### Retrieve Bulk Transfer Information + +Table 34 below contains the data model for _Retrieve Bulk Transfer Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkTransferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the bulk transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk transfer. A new ID should be generated for each new bulk transfer. | + +**Table 34 – Retrieve Bulk Transfer Information data model** + +
+ +##### Perform Bulk Transfer + +Table 35 contains the data model for _Perform Bulk Transfer_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkTransferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the bulk transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk transfer. A new ID should be generated for each new bulk transfer. | +| **bulkQuoteId** | 1 | [CorrelationId](#correlationid-element) | This identifies previous quotation request. The fees specified in the previous quotation will have to be honored in the transfer. | +| **payeeFsp** | 1 | [FspId](#fspid-element) | Payee FSP identifier. | +| **payerFsp** | 1 | [FspId](#fspid-element) | Information about the Payer in the proposed financial transaction. | +| **individualTransfers** | 1..1000 | [IndividualTransfer](#individualtransfer) | List of `IndividualTransfer` elements. | +| **expiration** | 1 | [DateTime](#datetime) | Expiration time of the transfers. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 35 – Perform Bulk Transfer data model** + +
+ +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Bulk Transfers**. + +##### Return Bulk Transfer Information + +Table 36 below contains the data model for _Return Bulk Transfer Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkTransferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the bulk transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk transfer. A new ID should be generated for each new bulk transfer. | +| **completedTimestamp** | 0..1 | [DateTime](#datetime) | The time and date when the bulk transfer was completed. | +| **individualTransferResults** | 0..1000 | [IndividualTransferResult](#individualtransferresult) | List of `IndividualTransferResult` elements. | +| **bulkTransferState** | 1 | [BulkTransferState](#bulktransferstate-enum) | The state of the bulk transaction. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 36 – Return Bulk Transfer Information data model** + +
+ +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Bulk Transfers**. + +##### Return Bulk Transfer Information Error + +Table 37 below contains the data model for _Return Bulk Transfer Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkTransferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the bulk transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk transfer. A new ID should be generated for each new bulk transfer. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 37 – Return Bulk Transfer Information Error data model** + +
+ +## API Supporting Data Model + +This section defines the data model and contains the following sub-sections: + +- [Length Specification](#length-specification) introduces the formats used for the element data types used by the API. + +- [Element Data Type Formats](#element-data-type-formats) defines the element data types used by the API. + +- [Element Defintions](#element-defintions) defines the elements types used by the API. + +- [Complex Types](#complex-types) identifies the complex types used by the API. + +- [Enumerations](#enumerations) identifies the enumerations used by the API. + +
+ +### Length Specification +All element data types have both a minimum and maximum length. These lengths are indicated by one of the following: + +- A minimum and maximum length +- An exact length +- A regular expression limiting the element such that only a specific length or lengths can be used. + +#### Minimum and Maximum Length + +If a minimum and maximum length is used, this will be indicated after the data type in parentheses: First the minimum value (inclusive value), followed by two period characters (..), and then the maximum value (inclusive value). + +Examples: + +- `String(1..32)` – A String that is minimum one character and maximum 32 characters long. +- `Integer(3..10)` - An Integerr that is minimum 3 digits, but maximum 10 digits long. + +#### Exact Length + +If an exact length is used, this will be indicated after the data type in parentheses containing only one exact value. Other lengths are not allowed. + +Examples: + +- `String(3)` – A String that is exactly three characters long. +- `Integer(4)` – An Integer that is exactly four digits long. + +#### Regular Expressions + +Some element data types are restricted using regular expressions. The regular expressions in this document use the standard for syntax and character classes established by the programming language Perl[1](https://perldoc.perl.org/perlre.html#Regular-Expressions). + +
+ +### Element Data Type Formats + +This section contains the definition of element data types used by the API. + +#### String + +The API data type `String` is a normal JSON String[2](https://tools.ietf.org/html/rfc7159#section-7), limited by a minimum and maximum number of characters. + +##### Example Format I + +`String(1..32)` – A String that is minimum *1* character and maximum *32* characters long. + +An example of `String(1..32)` appears below: + +- _This String is 28 characters_ + +##### Example Format II + +`String(1..128)` – A String that is minimum *1* character and maximum *128* characters long. + +An example of `String(32..128)` appears below: + +- _This String is longer than 32 characters, but less than 128_ + +
+ +#### Enum + +The API data type `Enum` is a restricted list of allowed JSON [String](#string)) values; an enumeration of values. Other values than the ones defined in the list are not allowed. + +##### Example Format + +`Enum of String(1..32)` – A String that is minimum one character and maximum 32 characters long and restricted by the allowed list of values. The description of the element contains a link to the enumeration. + +
+ +#### UndefinedEnum + +The API data type `UndefinedEnum` is a JSON String consisting of one to 32 uppercase characters including an underscore character ( _) . + +##### Regular Expression + +The regular expression for restricting the `UndefinedEnum` type appears in Listing 1 below: + +``` +^[A-Z_]{1,32}$ +``` +**Listing 1 – Regular expression for data type UndefinedEnum** + +
+ +#### Name + +The API data type `Name` is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. + +##### Regular Expression + +The regular expression for restricting the `Name` type is shown in Listing 2 below. The restriction will not allow a string consisting of whitespace only, all Unicode[3](http://www.unicode.org/) characters should be allowed, as well as period (.), apostrophe (“), dash (-), comma (,) and space ( ) characters. The maximum number of characters in the **Name** is 128. + +**Note:** In some programming languages, Unicode support needs to be specifically enabled. As an example, if Java is used the flag `UNICODE_CHARACTER_CLASS` needs to be enabled to allow Unicode characters. + +``` +^(?!\s*$)[\w .,'-]{1,128}$ +``` + +**Listing 2 – Regular expression for data type Name** + +
+ +#### Integer + +The API data type `Integer` is a JSON String consisting of digits only. Negative numbers and leading zeroes are not allowed. The data type is always limited by a number of digits. + +##### Regular Expression + +The regular expression for restricting an `Integer` is shown in Listing 3 below. + +``` +^[1-9]\d*$ +``` + +**Listing 3 – Regular expression for data type Integer** + +##### Example Format + +`Integer(1..6)` – An `Integer` that is at minimum one digit long, maximum six digits. + +An example of `Integer(1..6)` appears below: + +- _123456_ + +
+ +#### OtpValue + +The API data type `OtpValue` is a JSON String of three to 10 characters, consisting of digits only. Negative numbers are not allowed. One or more leading zeros are allowed. + +##### Regular Expression + +The regular expression for restricting the `OtpValue` type appears in Listing 4 below. + +``` +^\d{3,10}$ +``` + +**Listing 4 – Regular expression for data type OtpValue** + +
+ +#### BopCode + +The API data type `BopCode` is a JSON String of three characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. + +##### Regular Expression + +The regular expression for restricting the `BopCode` type appears in Listing 5 below. +``` +^[1-9]\d{2}$ +``` + +**Listing 5 – Regular expression for data type BopCode** + +
+ +#### ErrorCode + +The API data type `ErrorCode` is a JSON String of four characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. + +##### Regular Expression + +The regular expression for restricting the `ErrorCode` type appears in Listing 6 below. + +``` +^[1-9]\d{3}$ +``` + +**Listing 6 – Regular expression for data type ErrorCode** + +
+ +#### TokenCode + +The API data type `TokenCode` is a JSON String between four and 32 characters, consisting of digits or upper or lowercase characters from **a** to **z**. + +##### Regular Expression + +The regular expression for restricting the `TokenCode` type appears in Listing 7 below. + +``` +^[0-9a-zA-Z]{4,32}$ +``` + +**Listing 7 – Regular expression for data type TokenCode** + +
+ +#### MerchantClassificationCode + +The API data type `MerchantClassificationCode` is a JSON String consisting of one to four digits. + +##### Regular Expression + +The regular expression for restricting the `MerchantClassificationCode` type appears in Listing 8 below. + +``` +^[\d]{1,4}$ +``` + +**Listing 8 - Regular expression for data type MerchantClassificationCode** + +
+ +#### Latitude + +The API data type `Latitude` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting the `Latitude` type appears in Listing 9 below. + +``` +^(\+|-)?(?:90(?:(?:\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\.[0-9]{1,6})?))$ +``` + +**Listing 9 – Regular expression for data type Latitude** + +
+ +#### Longitude + +The API data type `Longitude` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting the `Longitude` type is shown in Listing 10 below. + +``` +^(\+|-)?(?:180(?:(?:\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.[0- +9]{1,6})?))$ +``` + +**Listing 10 – Regular expression for data type Longitude** + +
+ +#### Amount + +The API data type `Amount` is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting the `Amount` type appears in Listing 11 below. This pattern: + +- Does not allow trailing zeroes. +- Allows an amount without a minor currency unit. +- Allows only four digits in the minor currency unit; a negative value is not allowed. +- Does not allow more than 18 digits in the major currency unit. + +The regular expression for restricting the `Amount` type is shown in Listing 11 below. + +``` +^([0]|([1-9][0-9]*))([.][0-9]{0,3}[1-9])?$ +``` + +**Listing 11 – Regular expression for data type Amount** + +##### Examples + +See [table](#results-for-validated-amount-values) below for validation results for some example `Amount` values using the [regular expression](#regular-expression-11) defined above. + +##### Results for validated Amount values + +| Value | Validation result | +| --- | --- | +| _5_ | Accepted | +| _5.0_ | Rejected | +| _5._ | Rejected | +| _5.00_ | Rejected | +| _5.5_ | Accepted | +| _5.50_ | Rejected | +| _5.5555_ | Accepted | +| _5.55555_ | Rejected | +| _555555555555555555_ | Accepted | +| _5555555555555555555_ | Rejected | +| _-5.5_ | Rejected | +| _0.5_ | Accepted | +| _.5_ | Rejected | +| _00.5_ | Rejected | +| _0_ | Accepted | + +**Table 38 – Example results for different values for Amount type** + +
+ +#### DateTime + +The API data type `DateTime` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting `DateTime` appears in Listing 12 below. The format is according to ISO 8601[4](https://www.iso.org/iso-8601-date-and-time-format.html) , expressed in a combined date, time and time format. A more readable version of the format is `yyyy-MM-dd'T'HH:mm:ss.SSS[-HH:MM]` + +``` +^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])- +(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1- +9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02- +29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:(\.\d{3}))(?:Z|[+-][01]\d:[0-5]\d)$ +``` + +**Listing 12 – Regular expression for data type DateTime** + +##### Examples + +Two examples of the `DateTime` type appear below: + +- _2016-05-24T08:38:08.699-04:00_ + +- _2016-05-24T08:38:08.699Z_ (where **Z** indicates Zulu time zone, which is the same as UTC). + +
+ +#### Date + +The API data type `Date` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting the `Date` type appears in Listing 13 below. This format, as specified in ISO 8601, contains a date only. A more readable version of the format is `yyyy-MM-dd`. + +``` +^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])- +(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1- +9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$ +``` + +**Listing 13 – Regular expression for data type Date** + +##### Examples + +Two examples of the `Date` type appear below: + +- _1982-05-23_ + +- _1987-08-05_ + +
+ +#### UUID + +The API data type `UUID` (Universally Unique Identifier) is a JSON String in canonical format, conforming to RFC 4122[5](https://tools.ietf.org/html/rfc4122), that is restricted by a regular expression for interoperability reasons. A `UUID` is always 36 characters long, 32 hexadecimal symbols and four dashes (-). + +##### Regular Expression + +The regular expression is shown in Listing 14 below. + +``` +^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ +``` + +**Listing 14 – Regular expression for data type UUID** + +##### Example + +An example of a `UUID` type appears below: + +- _a8323bc6-c228-4df2-ae82-e5a997baf898_ + +
+ +#### BinaryString + +The API data type `BinaryString` is a JSON String. The String is the base64url[6](https://tools.ietf.org/html/rfc4648#section-5) encoding of a string of raw bytes. The length restrictions for the `BinaryString` type apply to the underlying binary data, indicating the allowed number of bytes. For data types with a fixed size no padding character is used. + +##### Regular Expression + +The regular expression for restricting the **BinaryString** type appears in Listing 15 below. + +``` +^[A-Za-z0-9-_]+[=]?$ +``` + +**Listing 15 – Regular expression for data type BinaryString** + +##### Example Format + +`BinaryString(32)` –32 bytes of data base64url encoded. + +An example of a `BinaryString(32..256)` appears below. Note that a padding character, `'='` has been added to ensure that the string is a multiple of four characters. + +- _QmlsbCAmIE1lbGluZGEgR2F0ZXMgRm91bmRhdGlvbiE=_ + + +
+ +#### BinaryString32 + +The API data type _BinaryString32_ is a fixed size variation of the API data type `BinaryString` defined [here](#binarystring), in which the raw underlying data is always of 32 bytes. The data type _BinaryString32_ should not use a padding character because the size of the underlying data is fixed. + +##### Regular Expression +The regular expression for restricting the _BinaryString32_ type appears in Listing 16 below. + +``` +^[A-Za-z0-9-_]{43}$ +``` + +**Listing 16 – Regular expression for data type BinaryString32** + +##### Example Format +`BinaryString(32)` – 32 bytes of data base64url encoded. + +An example of a `BinaryString32` appears below. Note that this is the same binary data as the example shown in the [Example Format](#example-format-3) of the `BinaryString` type, but due to the underlying data being fixed size, the padding character `'='` is excluded. + +``` +QmlsbCAmIE1lbGluZGEgR2F0ZXMgRm91bmRhdGlvbiE +``` + +
+ +### Element Definitions + +This section contains the definition of the elements types that are used by the API. + +#### AmountType element + +Table 39 below contains the data model for the element `AmountType`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **AmountType** | 1 | [Enum](#enum) of [String(1..32)](#string) | This element contains the amount type. See [AmountType](#amounttype-enum) enumeration for more information on allowed values. | + +**Table 39 – Element AmountType** + +
+ +#### AuthenticationType element + +Table 40 below contains the data model for the element `AuthenticationType`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Authentication** | 1 | [Enum](#enum) of [String(1..32)](#string) | This element contains the authentication type. See [AuthenticationType](#authenticationtype-enum) enumeration for possible enumeration values. | + +**Table 40 – Element AuthenticationType** + +
+ +#### AuthenticationValue element + +Table 41 below contains the data model for the element `AuthenticationValue`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **AuthenticationValue** | 1 | Depends on [AuthenticationType](#authenticationtype-element).

If `OTP`: type is [Integer(1..6)](#integer). For example:**123456**

OtpValue
If `QRCODE`: type is [String(1..64)](#string) | This element contains the authentication value. The format depends on the authentication type used in the [AuthenticationInfo](#authenticationinfo) complex type. | + +**Table 41 – Element AuthenticationValue** + +
+ +#### AuthorizationResponse element + +Table 42 below contains the data model for the element `AuthorizationResponse`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **AuthorizationResponse** | 1 | [Enum](#enum) of [String(1..32)](#string) | This element contains the authorization response. See [AuthorizationResponse](#authorizationresponse-enum) enumeration for possible enumeration values. | + +**Table 42 – Element AuthorizationResponse** + +
+ +#### BalanceOfPayments element + +Table 43 below contains the data model for the element `BalanceOfPayment`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **BalanceOfPayments** | 1 | [BopCode](#bopcode) | The possible values and meaning are defined in [https://www.imf.org/external/np/sta/bopcode/](https://www.imf.org/external/np/sta/bopcode/) | + +**Table 43 – Element BalanceOfPayments** + +
+ +#### BulkTransferState element + +Table 44 below contains the data model for the element `BulkTransferState`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **BulkTransferState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [BulkTransferState](#bulktransferstate-enum) enumeration for information on allowed values| + +**Table 44 – Element BulkTransferState** + +
+ +#### Code element + +Table 45 below contains the data model for the element `Code`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Code** | 1 | [TokenCode](#tokencode) | Any code/token returned by the Payee FSP. | + +**Table 45 – Element Code** + +
+ +#### CorrelationId element + +Table 46 below contains the data model for the element `CorrelationId`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **CorrelationId** | 1 |[UUID](#uuid) | Identifier that correlates all messages of the same sequence. | + + +**Table 46 – Element CorrelationId** + +
+ +#### Currency element + +Table 47 below contains the data model for the element `Currency`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Currency** | 1 | [Enum](#enum) of [String(3)](#string) | See [Currency](#currencycode-enum) enumeration for information on allowed values | + +**Table 47 – Element Currency** + +
+ +#### DateOfBirth element + +Table 48 below contains the data model for the element `DateOfBirth`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **DateOfBirth** | 1 | Examples

Two examples of the [DateTime](#datetime) type appear below:

2016-05-24T08:38:08.699-04:00

2016-05-24T08:38:08.699Z (where Z indicates Zulu time zone, which is the same as UTC).

Date

| Date of Birth of the Party.| + +**Table 48 – Element DateOfBirth** + +
+ +#### ErrorCode element + +Table 49 below contains the data model for the element `ErrorCode`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ErrorCode** | 1 | [ErrorCode](#errorcode) | Four digit error code, see section on [Error Codes](#error-codes) for more information. | + +**Table 49 – Element ErrorCode** + +
+ +#### ErrorDescription element + +Table 50 below contains the data model for the element `ErrorDescription`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ErrorDescription** | 1 | [String(1..128)](#string) | Error description string. | + +**Table 50 – Element ErrorDescription** + +
+ +#### ExtensionKey element + +Table 51 below contains the data model for the element `ExtensionKey`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ExtensionKey** | 1 | [String(1..32)](#string) | The extension key. | + +**Table 51 – Element ExtensionKey** + +
+ +#### ExtensionValue element + +Table 52 below contains the data model for the element `ExtensionValue`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ExtensionValue** | 1 | [String(1..128)](#string) | The extension value. | + +**Table 52 – Element ExtensionValue** + +
+ +#### FirstName element +Table 53 below contains the data model for the element `FirstName`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **FirstName** | 1 | [Name](#name) | First name of the Party | + +**Table 53 – Element FirstName** + +
+ +#### FspId element + +Table 54 below contains the data model for the element `FspId`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **FspId** | 1 | [String(1..32)](#string)| The FSP identifier. | + +**Table 54 – Element FspId** + +
+ +#### IlpCondition element + +Table 55 below contains the data model for the element `IlpCondition`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **IlpCondition** | 1 | [BinaryString32](#binarystring32) | The condition that must be attached to the transfer by the Payer. | + +**Table 55 – Element IlpCondition** + +
+ +#### IlpFulfilment element + +Table 56 below contains the data model for the element `IlpFulfilment`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **IlpFulfilment** | 1 | [BinaryString32](#binarystring32) | The fulfilment that must be attached to the transfer by the Payee. | + +**Table 56 – Element IlpFulfilment** + +
+ +#### IlpPacket element + +Table 57 below cntains the data model for the element `IlpPacket`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **IlpPacket** | 1 | Example

An example of a [UUID](#uuid) type appears below:

a8323bc6-c228-4df2-ae82-e5a997baf898

[BinaryString(1..32768)](#binarystring)

| Information for recipient (transport layer information). | + +**Table 57 – Element IlpPacket** + +
+ +#### LastName element + +Table 58 below contains the data model for the element `LastName`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **LastName** | 1 | [Name](#name) | Last name of the Party (ISO 20022 definition). | + +**Table 58 – Element LastName** + +
+ +#### MerchantClassificationCode element + +Table 59 below contains the data model for the element `MerchantClassificationCode`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **MerchantClassificationCode** | 1 | [MerchantClassificationCode](#merchantclassificationcode) | A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, and so on. | + +**Table 59 – Element MerchantClassificationCode** + +
+ +#### MiddleName element + +Table 60 below contains the data model for the element `MiddleName`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **MiddleName** | 1 | [Name](#name) | Middle name of the Party (ISO 20022 definition). | + +**Table 60 – Element MiddleName** + +
+ +#### Note element + +Table 61 below contains the data model for the element `Note`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Note** | 1 | [String(1..128)](#string) | Memo assigned to transaction. | + +**Table 61 – Element Note** + +
+ + +#### NrOfRetries element + +Table 62 below contains the data model for the element `NrOfRetries`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **NrOfRetries** | 1 | [Integer(1..2)](#integer) | Number of retries. | + +**Table 62 – Element NrOfRetries** + +
+ +#### PartyIdentifier element + +Table 63 below contains the data model for the element `PartyIdentifier`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartyIdentifier** | 1 | [String(1..128)](#string) | Identifier of the Party.| + +**Table 63 – Element PartyIdentifier** + +
+ +#### PartyIdType element + +Table 64 below contains the data model for the element `PartyIdType`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartyIdType** | 1 | Enum of [String(1..32)](#string) | See [PartyIdType](#partyidtype-enum) enumeration for more information on allowed values. | + +**Table 64 – Element PartyIdType** + +
+ +#### PartyName element + +Table 65 below contains the data model for the element `PartyName`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartyName** | 1 | `Name` | Name of the Party. Could be a real name or a nickname. | + +**Table 65 – Element PartyName** + +
+ +#### PartySubIdOrType element + +Table 66 below contains the data model for the element `PartySubIdOrType`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartySubIdOrType** | 1 | [String(1..128)](#string) | Either a sub-identifier of a [PartyIdentifier](#partyidentifier-element), or a sub-type of the [PartyIdType](#partyidtype-element), normally a `PersonalIdentifierType`. | + +**Table 66 – Element PartySubIdOrType** + +
+ +#### RefundReason element + +Table 67 below contains the data model for the element `RefundReason`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **RefundReason** | 1 | [String(1..128)](#string) | Reason for the refund. | + +**Table 67 – Element RefundReason** + +
+ +#### TransactionInitiator element + +Table 68 below contains the data model for the element `TransactionInitiator`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionInitiator** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionInitiator](#transactioninitiator-enum) enumeration for more information on allowed values. | + +**Table 68 – Element TransactionInitiator** + +
+ +#### TransactionInitiatorType element + +Table 69 below contains the data model for the element `TransactionInitiatorType`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionInitiatorType** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionInitiatorType](#transactioninitiatortype-enum) enumeration for more information on allowed values. | + +**Table 69 – Element TransactionInitiatorType** + +
+ +#### TransactionRequestState element + +Table 70 below contains the data model for the element `TransactionRequestState`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionRequestState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionRequestState](#transactionrequeststate-enum) enumeration for more information on allowed values. | + + +**Table 70 – Element TransactionRequestState** + +
+ +#### TransactionScenario element + +Table 71 below contains the data model for the element `TransactionScenario`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionScenario** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionScenario](#transactionscenario-enum) enumeration for more information on allowed values. | + +**Table 71 – Element TransactionScenario** + +
+ +#### TransactionState element + +Table 72 below contains the data model for the element `TransactionState`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionState](#transactionstate-enum) enumeration for more information on allowed values. | + +**Table 72 – Element TransactionState** + +
+ +#### TransferState element + +Table 73 below contains the data model for the element `TransferState`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransferState](#transferstate-enum) enumeration for more information on allowed values. | + +**Table 73 – Element TransferState** + +
+ +#### TransactionSubScenario element + +Table 74 below contains the data model for the element `TransactionSubScenario`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionSubScenario** | 1 | [UndefinedEnum](#undefinedenum) | Possible sub-scenario, defined locally within the scheme.| + +**Table 74 – Element TransactionSubScenario** + +
+ +### Complex Types + +This section contains the complex types that are used by the API. + +#### AuthenticationInfo + +Table 75 below contains the data model for the complex type `AuthenticationInfo`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **authentication** | 1 | [AuthenticationType](#authenticationtype-element) | The type of authentication. | +| **authenticationValue** | 1 | [AuthenticationValue](#authenticationvalue-element) | The authentication value. | + +**Table 75 – Complex type AuthenticationInfo** + +
+ +#### ErrorInformation + +Table 76 below contains the data model for the complex type `ErrorInformation`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **errorCode** | 1 | [ErrorCode](#errorcode) | Specific error number. | +| **errorDescription** | 1 | [ErrorDescription](#errordescription-element) | Error description string. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional list of extensions, specific to deployment. | + +**Table 76 – Complex type ErrorInformation** + +
+ +#### Extension + +Table 77 below contains the data model for the complex type `Extension`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **key** | 1 | [ExtensionKey](#extensionkey-element) | The extension key. | +| **value** | 1 | [ExtensionValue](#extensionvalue-element) | The extension value. | + +**Table 77 – Complex type Extension** + +
+ +#### ExtensionList + +Table 78 below contains the data model for the complex type `ExtensionList`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **extension** | 1..16 | [Extension](#extension) | A number of Extension elements. | + +**Table 78 – Complex type ExtensionList** + +
+ +#### IndividualQuote + +Table 79 below contains the data model for the complex type `IndividualQuote`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | Identifies quote message. | +| **transactionId** | 1 | [CorrelationId](#correlationid-element) | Identifies transaction message. | +| **payee** | 1 | [Party](#party) | Information about the Payee in the proposed financial transaction. | +| **amountType** | 1 | [AmountType](#amounttype-element) | `SEND_AMOUNT` for _sendAmount_,

`RECEIVE_AMOUNT` for _receiveAmount_.

+| **amount** | 1 | [Money](#money) | Depending on amountType:

If `SEND`: The amount the Payer would like to send, that is, the amount that should be withdrawn from the Payer account including any fees. The amount is updated by each participating entity in the transaction.

If `RECEIVE`: The amount the Payee should receive, that is, the amount that should be sent to the receiver exclusive any fees. The amount is not updated by any of the participating entities. | +| **fees** | 0..1 | [Money](#money) | The fees in the transaction.
  • The fees element should be empty if fees should be non-disclosed.
  • The fees element should be non-empty if fees should be disclosed.
+| **transactionType** | 1 | [TransactionType](#transactiontype) | The type of transaction that the quote is requested for. | +| **note** | 0..1 | [Note](#note-element) | A memo that will be attached to the transaction. This is sent in the quote so it can be included in the ILP Packet. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 79 – Complex type IndividualQuote** + +
+ +#### IndividualQuoteResult + +Table 80 below contains the data model for the complex type `IndividualQuoteResult`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | Identifies the quote message. | +| **payeeReceiveAmount** | 0..1 | [Money](#money) | Amount that the Payee should receive in the end-toend transaction. Optional as the Payee FSP might not want to disclose any optional Payee fees. | +| **payeeFspFee** | 0..1 | [Money](#money) | Payee FSP’s part of the transaction fee. | +| **payeeFspCommission** | 0..1 | [Money](#money) | Transaction commission from the Payee FSP. | +| **ilpPacket** | 0..1 | [IlpPacket](#ilppacket-element) | The ILP Packet that must be attached to the transfer by the payer. | +| **condition** | 0..1 | [IlpCondition](#ilpcondition-element) | The condition that must be attached to the transfer by the payer. | +| **errorInformation** | 0..1 | [ErrorInformation](#errorinformation) | Error code, category description.

Note: If errorInformation is set, the following are not set:

  • receiveAmount
  • payeeFspFee
  • payeeFspCommission
  • ilpPacket
  • condtion
| +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment | + +**Table 80 – Complex type IndividualQuoteResult** + +
+ +#### IndividualTransfer + +Table 81 below contains the data model for the complex type `IndividualTransfer`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transferId** | 1 | [CorrelationId](#correlationid-element) | Identifies messages related to the same /transfers sequence. | +| **transferAmount** | 1 | [Money](#money) | The transaction amount to be sent. | +| **ilpPacket** | 1 | [IlpPacket](#ilppacket-element) | The ILP Packet containing the amount delivered to the payee and the ILP Address of the payee and any other end-to-end data. | +| **condition** | 1 | [IlpCondition](#ilpcondition-element) | The condition that must be fulfilled to commit the transfer. +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 81 – Complex type IndividualTransfer** + +
+ +#### IndividualTransferResult + +Table 82 below contains the data model for the complex type `IndividualTransferResult`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transferId** | 1 | [CorrelationId](#correlationid-element) | Identifies messages related to the same /transfers sequence. | +| **fulfilment** | 0..1 | [IlpFulfilment](#ilpfulfilment-element) | The fulfilment of the condition specified with the transaction.

Note: Either fulfilment is set or errorInformation is set, not both.

+| **errorInformation** | 0..1 | [ErrorInformation](#errorinformation) | If transactionState is `REJECTED`, error information may be provided.

Note: Either fulfilment is set or errorInformation is set, not both.

+| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 82 – Complex type IndividualTransferResult** + +#### GeoCode + +Table 83 below contains the data model for the complex type `GeoCode`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **latitude** | 1 | [Latitude](#latitude) | The Latitude of the service initiating Party. | +| **longitude** | 1 | [Longitude](#longitude) | The Longitude of the service initiating Party. | + +**Table 83 – Complex type GeoCode** + +
+ +#### Money + +Table 84 below contains the data model for the complex type `Money`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **currency** | 1 | [Currency](#currency-element) | The currency of the Amount. | +| **amount** | 1 | [Amount](#amount) | The amount of Money. | + +**Table 84 – Complex type Money** + +
+ +#### Party + +Table 85 below contains the data model for the complex type `Party`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdInfo** | 1 | [PartyIdInfo](#partyidinfo) | Party Id type, id, sub ID or type, and FSP Id. | +| **merchantClassificationCode** | 0..1 | [MerchantClassificationCode](#merchantclassificationcode) | Optional: Used in the context of Payee Information, where the Payee happens to be a merchant accepting merchant payments. | +| **name** | 0..1 | [PartyName](#partyname-element) | The name of the party, could be a real name or a nick name. | +| **personalInfo** | 0..1 | [PartyPersonalInfo](#partypersonalinfo) | Personal information used to verify identity of Party such as first, middle, last name and date of birth. | + +**Table 85 – Complex type Party** + +
+ +#### PartyComplexName + +Table 86 below contains the data model for the complex type `PartyComplexName`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **firstName** | 0..1 | [FirstName](#firstname-element) | First name. | +| **middleName** | 0..1 | [MiddleName](#middlename-element) | Middle name. | +| **lastName** | 0..1 | [LastName](#lastname-element) | Last name. | + +**Table 86 – Complex type PartyComplexName** + +
+ +#### PartyIdInfo + +Table 87 below contains the data model for the complex type `PartyIdInfo`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartySubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party. | +| **fspId** | 0..1 | [FspId](#fspid-element) | The FSP ID (if known) | + +**Table 87 – Complex type PartyIdInfo** + +
+ +#### PartyPersonalInfo + +Table 88 below contains the data model for the complex type `PartyPersonalInfo`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **complexName** | 0..1 | [PartyComplexName](#partycomplexname) | First, middle and last name. | +| **dateOfBirth** | 0..1 | [DateOfBirth](#dateofbirth-element) | Date of birth. | + +**Table 88 – Complex type PartyPersonalInfo** + +
+ +#### PartyResult + +Table 89 below contains the data model for the complex type `PartyResult`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyId** | 1 | [PartyIdInfo](#partyidinfo) | Party Id type, id, sub ID or type, and FSP Id. | +| **errorInformation** | 0..1 | [ErrorInformation](#errorinformation) | If the Party failed to be added, error information should be provided. Otherwise, this parameter should be empty to indicate success. | + +**Table 89 – Complex type PartyPersonalInfo** + +
+ +#### Refund + +Table 90 below contains the data model for the complex type `Refund`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **originalTransactionId** | 1 | [CorrelationId](#correlationid-element) | Reference to the original transaction ID that is requested to be refunded.| +| **refundReason** | 0..1 | [RefundReason](#refundreason-element) | Free text indicating the reason for the refund. | + +**Table 90 – Complex type Refund** + +
+ +#### Transaction + +Table 91 below contains the data model for the complex type `Transaction`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionId** | 1 | [CorrelationId](#correlationid-element) | ID of the transaction, the ID is determined by the Payer FSP during the creation of the quote. | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | ID of the quote, the ID is determined by the Payer FSP during the creation of the quote. | +| **payee** | 1 | [Party](#party) | Information about the Payee in the proposed financial transaction. | +| **payer** | 1 | [Party](#party) | Information about the Payer in the proposed financial transaction. | +| **amount** | 1 | [Money](#money) | The transaction amount to be sent. | +| **transactionType** | 1 | [TransactionType](#transactiontype) | The type of the transaction. | +| **note** | 0..1 | [Note](#note-element) | Memo associated to the transaction,intended to the Payee. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 91 – Complex type Transaction** + +#### TransactionType + +Table 92 below contains the data model for the complex type `TransactionType`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **scenario** | 1 | [TransactionScenario`](#transactionscenario-element) | Deposit, withdrawal, refund, … | +| **subScenario** | 0..1 | [TransactionSubScenario](#transactionsubscenario-element) | Possible sub-scenario, defined locally within the scheme. | +| **initiator** | 1 | [TransactionInitiator](#transactioninitiator-enum) | Who is initiating the transaction: payer or payee | +| **initiatorType** | 1 | [TransactionInitiatorType](#transactioninitiatortype-enum) | Consumer, agent, business, … | +| **refundInfo** | 0..1 | [Refund](#refund) | Extra information specific to a refund scenario. Should only be populated if scenario is `REFUND`. | +| **balanceOfPayments** | 0..1 | [BalanceOfPayments](#balanceofpayments-element) | Balance of Payments code. | + +**Table 92 – Complex type TransactionType** + +
+ + +### Enumerations + +This section contains the enumerations used by the API. + +#### AmountType enum + +Table 93 below contains the allowed values for the enumeration `AmountType`. + +| Name | Description | +| --- | --- | +| **SEND** | The amount the Payer would like to send, that is, the amount that should be withdrawn from the Payer account including any fees. | +| **RECEIVE** | The amount the Payer would like the Payee to receive, that is, the amount that should be sent to the receiver exclusive fees. | + +**Table 93 – Enumeration AmountType** + +
+ +#### AuthenticationType enum + +Table 94 below contains the allowed values for the enumeration `AuthenticationType`. + +| Name | Description | +| --- | ---| +| **OTP** | One-time password, either chosen by the Party, or generated by the Party’s FSP. | +| **QRCODE** | QR code used as One Time Password. | + +**Table 94 – Enumeration AuthenticationType** + +
+ +#### AuthorizationResponse enum + +Table 95 below contains the allowed values for the enumeration `AuthorizationResponse`. + +| Name | Description | +| --- | --- | +| **ENTERED** | Consumer entered the authentication value. | +| **REJECTED** | Consumer rejected the transaction. | +| **RESEND** | Consumer requested to resend the authentication value. | + +**Table 95 – Enumeration AuthorizationResponse** + +
+ +#### BulkTransferState + +Table 96 below contains the allowed values for the enumeration `BulkTransferState`. + +| Name | Description | +| --- | --- | +| **RECEIVED** | Payee FSP has received the bulk transfer from the Payer FSP. | +| **PENDING** | Payee FSP has validated the bulk transfer. | +| **ACCEPTED** | Payee FSP has accepted to process the bulk transfer. | +| **PROCESSING** | Payee FSP has started to transfer fund to the Payees. | +| **COMPLETED** | Payee FSP has completed transfer of funds to the Payees. | +| **REJECTED** | Payee FSP has rejected to process the transfer. | + +**Table 96 – Enumeration BulkTransferState** + +
+ +#### CurrencyCode enum + +The currency codes defined in ISO 4217[7](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic codes are used as the standard naming representation for currencies. The currency codes from ISO 4217 are not is shown in this document, implementers are instead encouraged to use the information provided by the ISO 4217 standard directly. + +
+ +#### PartyIdType enum + +Table 97 below contains the allowed values for the enumeration `PartyIdType`. + +| Name | Description | +| --- | ---| +| **MSISDN** | Used when an MSISDN (Mobile Station International Subscriber Directory Number, that is, the phone number) is used as reference to a participant. The MSISDN identifier should be in international format according to the ITU-T E.164 standard. Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix. | +| **EMAIL** | Used when an email should be used as reference to a participant. The format of the email should be according to the informational RFC 3696. | +| **PERSONAL_ID** | Used when some kind of personal identifier should be used as reference to a participant. Examples of personal identification can be passport number, birth certificate number, national registration number or similar. The identifier number shall be added in the PartyIdentifier element. The personal identifier type shall be added in the PartySubIdOrType element. | +| **BUSINESS** | Used when a specific Business (for example, an Organization or a Company) should be used as reference to a participant. The Business identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the PartySubIdOrType element should be used. | +| **DEVICE** | Used when a specific Device (for example, a POS or ATM) ID connected to a specific Business or Organization should be used as reference to a Party. To use a specific device under a specific Business or Organization, the PartySubIdOrType element should be used. | +| **ACCOUNT_ID** | Used when a bank account number or FSP account ID should be used as reference to a participant. The `ACCOUNT_ID` identifier can be in any format, as formats can greatly differ depending on country and FSP. | +| **IBAN** | Used when a bank account number or FSP account ID should be used as reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without any whitespace. | +| **ALIAS** | Used when an alias should be used as reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias can be username in the FSP system. The `ALIAS` identifier can be in any format. It is also possible to use the PartySubIdOrType element for identifying an account under an Alias defined by the PartyIdentifier. | + +**Table 97 – Enumeration PartyIdType** + +
+ +#### PersonalIdentifierType enum + +Table 98 below contains the allowed values for the enumeration `PersonalIdentifierType`. + +| Name | Description | +| --- | --- | +| **PASSPORT** | Used when a passport number should be used as reference to a Party | +| **NATIONAL_REGISTRATION** | Used when a national registration number should be used as reference to a Party | +| **DRIVING_LICENSE** | Used when a driving license should be used as reference to a Party | +| **ALIEN_REGISTRATION** | Used when an alien registration number should be used as reference to a Party | +| **NATIONAL_ID_CARD** | Used when a national ID card number should be used as reference to a Party | +| **EMPLOYER_ID** | Used when a tax identification number should be used as reference to a Party | +| **TAXI_ID_NUMBER** | Used when a tax identification number should be used as reference to a Party. | +| **SENIOR_CITIZENS_CARD** | Used when a senior citizens card number should be used as reference to a Party | +| **MARRIAGE_CERTIFICATE** | Used when a marriage certificate number should be used as reference to a Party | +| **HEALTH_CARD** | Used when a health card number should be used as reference to a Party | +| **VOTERS_ID** | Used when a voters identification number should be used as reference to a Party | +| **UNITED_NATIONS** | Used when an UN (United Nations) number should be used as reference to a Party | +| **OTHER_ID** | Used when any other type of identification type number should be used as reference to a Party | + +**Table 98 – Enumeration PersonalIdentifierType** + +
+ +#### TransactionInitiator enum + +Table 99 below contains the allowed values for the enumeration `TransactionInitiator`. + +| Name | Description | +| --- | --- | +| **PAYER** | The sender of funds is initiating the transaction. The account to send from is either owned by the Payer or is connected to the Payer in some way. | +| **PAYEE** | The recipient of the funds is also initiating the transaction by sending a transaction request. The Payer must approve the transaction, either automatically by a pre-generated OTP, pre-approval of the Payee, or by manually approving in his or her own Device. | + +**Table 99 – Enumeration TransactionInitiator** + +
+ +#### TransactionInitiatorType enum + +Table 100 below contains the allowed values for the enumeration `TransactionInitiatorType`. + +| Name | Description | +| --- | --- | +| **CONSUMER** | Consumer is the initiator of the transaction. | +| **AGENT** | Agent is the initiator of the transaction. | +| **BUSINESS** | Business is the initiator of the transaction. | +| **DEVICE** | Device is the initiator of the transaction. | + +**Table 100 – Enumeration TransactionInitiatorType** + +
+ +#### TransactionRequestState enum + +Table 101 below contains the allowed values for the enumeration `TransactionRequestState`. + +| Name | Description | +| --- | --- | +| **RECEIVED** | Payer FSP has received the transaction from the Payee FSP. | +| **PENDING** | Payer FSP has sent the transaction request to the Payer. | +| **ACCEPTED** | Payer has approved the transaction. | +| **REJECTED** | Payer has rejected the transaction. | + +**Table 101 – Enumeration TransactionRequestState** + +
+ +#### TransactionScenario enum + +Table 102 below contains the allowed values for the enumeration `TransactionScenario`. + +| Name | Description | +| --- | --- | +| **DEPOSIT** | Used for performing a Cash-In (deposit) transaction, where in the normal case electronic funds are transferred from a Business account to a Consumer account, and physical cash is given from the Consumer to the Business User. | +| **WITHDRAWAL** | Used for performing a Cash-Out (withdrawal) transaction, where in the normal case electronic funds are transferred from a Consumer’s account to a Business account, and physical cash is given from the Business User to the Consumer. | +| **TRANSFER** | Used for performing a P2P (Peer to Peer, or Consumer to Consumer) transaction. | +| **PAYMENT** | Typically used for performing a transaction from a Consumer to a Merchant/Organization, but could also be for a B2B (Business to Business) payment. The transaction could be online to purchase in an Internet store, in a physical store where both the Consumer and Business User are present, a bill payment, a donation, and so on. | +| **REFUND** | Used for performing a refund of transaction. | + +**Table 102 – Enumeration TransactionScenario** + +
+ +#### TransactionState enum + +Table 103 below contains the allowed values for the enumeration `TransactionState`. + +| Name | Description | +| --- | --- | +| **RECEIVED** | Payee FSP has received the transaction from the Payer FSP. | +| **PENDING** | Payee FSP has validated the transaction. | +| **COMPLETED** | Payee FSP has successfully performed the transaction. | +| **REJECTED** | Payee FSP has failed to perform the transaction. | + +**Table 103 – Enumeration TransactionState** + +
+ +#### TransferState enum + +Table 104 below contains the allowed values for the enumeration `TransferState`. + +| Name | Description | +| --- | --- | +| **RECEIVED** | The next ledger has received the transfer. | +| **RESERVED** | The next ledger has reserved the transfer. | +| **COMMITTED** | The next ledger has successfully performed the transfer. | +| **ABORTED** | The next ledger has aborted the transfer due a rejection or failure to perform the transfer. | + +**Table 104 – Enumeration TransferState** + +
+ +### Error Codes + +Each error code in the API is a four-digit number, such as **1234**, where the first number (**1** in the example) represents the highlevel error category, the second number (**2** in the example) represents the low-level error category, and the last two numbers (**34** in the example) represents the specific error. Figure 1 shows the structure of an error code. The following sub-sections contains information and defined error codes per high-level error category. + +![Figure 1 - Error code structure](../assets/sequence-diagram-figure-1.png) + +**Figure 1 – Error code structure** + +Each defined high- and low-level category combination contains a generic error (_x_**0**_xx_), which can be used if there is no specific error, or if the server would not like to return information which is considered private. + +All specific errors below _xx_**40**, that is, _xx_**00** to _xx_**39**, are reserved for future use by the API. All specific errors above and including _xx40_, can be used for scheme-specific errors. If a client receives an unknown scheme-specific error, the unknown scheme-specific error should be interpreted as a generic error for the high- and low-level category combination instead (_xx_**00**). + +#### Communication Errors – 1xxx + +All possible communication or network errors that could arise that cannot be represented by an HTTP status code should use +the high-level error code 1 (error codes **1**_xxx_). Because all services in the API are asynchronous, these error codes should generally be used by a Switch in the Callback to the client FSP if the Peer FSP could not be reached, or if a callback is not received from the Peer FSP within an agreed timeout. + +Low level categories defined under Communication Errors: + +- **Generic Communication Error – 10**_xx_ + +See Table 105 below for all communication errors defined in the API. + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **1000** | Communication error | Generic communication error. | X | X | X | X | X | X | X | X | X | +| **1001** | Destination communication error | The Destination of the request failed to be reached. This usually indicates that a Peer FSP failed to respond from an intermediate entity. | X | X | X | X | X | X | X | X | X | + +**Table 105 – Communication errors – 1xxx** + +
+ +#### Server Errors – 2xxx + +All errors occurring in the server in which the server failed to fulfil an apparently valid request from the client should use the high-level error code 2 (error codes **2**_xxx_). These error codes should indicate that the server is aware that it has encountered an error or is otherwise incapable of performing the requested service. + +Low-level categories defined under server Errors: + +- **Generic server Error – 20**_xx_ + +See Table 106 below for all server errors defined in the API. + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **2000** | Generic server error | Generic server error to be used for not disclosing information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **2001** | Internal server error | A generic unexpected exception. This usually indicates a bug or unhandled error case. | X | X | X | X | X | X | X | X | X | +| **2002** | Not implemented | Service requested is not supported by the server. | X | X | X | X | X | X | X | X | X | +| **2003** | Service currently unavailable | Service requested is currently unavailable on the server. This could be because maintenance is taking place, or because of a temporary failure. | X | X | X | X | X | X | X | X | X | +| **2004** | Server timed out | A time out has occurred, meaning the next Party in the chain did not send a callback in time. This could be because a timeout is set too low or because something took longer than it should. | X | X | X | X | X | X | X | X | X | +| **2005** | Server busy | Server is rejecting requests due to overloading. Try again later. | X | X | X | X | X | X | X | X | X | + +**Table 106 – Server errors – 2xxx** + +
+ +#### Client Errors – 3xxx** + +All possible errors occurring in the server where the server’s opinion is that the client have sent one or more erroneous parameters should use the high-level error code 3 (error codes **3**_xxx_). These error codes should indicate that the server could not perform the service according to the request from the client. The server should provide an explanation why the service could not be performed. + +Low level categories defined under client Errors: +- **Generic Client Error – 30**_xx_ + - See Table 107 for the generic client errors defined in the API. +- **Validation Error – 31**_xx_ + - See Table 108 for the validation errors defined in the API. +- **Identifier Error – 32**_xx_ + - See Table 109 for the identifier errors defined in the API. +- **Expired Error – 33**_xx_ + - See Table 110 for the expired errors defined in the API. + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **3000** | Generic client error | Generic client error, to be used for not disclosing information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **3001** | Unacceptable version requested | Client requested to use a protocol version which is not supported by the server. | X | X | X | X | X | X | X | X | X | +| **3002** | Unknown URI | The provided URI was unknown by the server. | | | | | | | | | | +| **3003** | Add Party information error | An error occurred while adding or updating information regarding a Party. | X | | | | | | | | | | + +**Table 107 – Generic client errors – 30xx** + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **3100** | Generic validation error | Generic validation error to be used for not disclosing information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **3101** | Malformed syntax | The format of the parameter is not valid. For example, amount set to 5.ABC. The error description field should specify which element is erroneous. |X | X | X | X | X | X | X | X | X | +| **3102** | Missing mandatory element | A mandatory element in the data model was missing. | X | X | X | X | X | X | X | X | X | +| **3103** | Too many elements | The number of elements of an array exceeds the maximum number allowed. | X | X | X | X | X | X | X | X | X | +| **3104** | Too large payload | The size of the payload exceeds the maximum size. | X | X | X | X | X | X | X | X | X | +| **3105** | Invalid signature | Some parameters have changed in the message, making the signature invalid. This may indicate that the message may have been modified maliciously. |X | X | X | X | X | X | X | X | X | +| **3106** | Modified request | A request with the same ID has previously been processed where the parameters are not the same. | | | X | X | | X | | X | X | +| **3107** | Missing mandatory extension parameter |A scheme mandatory extension parameter was missing. | | | X | X | X | X | X | X | X | + +**Table 108 – Validation Errors – 31xx** + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **3200** | Generic ID not found | Generic ID error provided by the client. | X | X | X | X | X | X | X | X | X | +| **3201** | Destination FSP Error| The Destination FSP does not exist or cannot be found. | X | X | X | X | X | X | X | X | X | +| **3202** | Payer FSP ID not found | The provided Payer FSP ID not found. | | | | | | X | | X | X | +| **3203** | Payee FSP ID not found | The provided Payer FSP ID not found. | | | | | | X | | X | X | +| **3204** | Party not found | The Party with the provided identifier, identifier type, and optional sub id or type was not found. | X | X | X | X | | | | | | +| **3205** | Quote ID not found | The provided Quote ID was not found in the server. | | | | X | | X | | | | +| **3206** | Transaction request ID not found | The provided Transaction Request ID was not found in the server. | | | X | | | X | | | | +| **3207** | Transaction ID not found | The provided Transaction ID was not found in the server. | | | | | | | X | | | +| **3208** | Transfer ID not found | The provided Transfer ID was not found in the server. | | | | | | X | | | | +| **3209** | Bulk quote ID not found | The provided Bulk Quote ID was not found in the server. | | | | | | | | X | X | +| **3210** | Bulk transfer ID not found | The provided Bulk Transfer ID was not found in the server. | | | | | | | | | X | + +**Table 109 – Identifier Errors – 32xx** + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **3300** |Generic expired error | Generic expired object error, to be used for not disclosing information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **3301** | Transaction request expired | Client requested to use a transaction request that has already expired. | | | | X | | | | | | +| **3302** | Quote expired | Client requested to use a quote that has already expired. | | | | | X | | | X | X | +| **3303** | Transfer expired | Client requested to use a transfer that has already expired. | X | X | X | X | X | X | X | X | X | + +**Table 110 – Expired Errors – 33xx** + +
+ +#### Payer Errors – 4xxx + +All possible errors occurring in the server when the Payer or the Payer FSP is the cause of an error should use the high-level error code 4 (error codes **4**_xxx_). These error codes should indicate that there was no error in the server or in the request from the client, but the request failed for some reason due to the Payer or the Payer FSP. The server should provide an explanation why the service could not be performed. + +Low level categories defined under Payer Errors: +- **Generic Payer Error – 40**_xx_ +- **Payer Rejection Error – 41**_xx_ +- **Payer Limit Error – 42**_xx_ +- **Payer Permission Error – 43**_xx_ +- **Payer Blocked Error – 44**_xx_ + +See Table 111 below for all Payer errors defined in the API. + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **4000** | Generic Payer error | Generic error due to the Payer or Payer FSP, to be used for not disclosing information that may be considered private. | | | X | X | X | X | X | X | X | +| **4001** | Payer FSP insufficient liquidity | The Payer FSP has insufficient liquidity to perform the transfer. | | | | | | X | | | | +| **4100** | Generic Payer rejection | Payer or Payer FSP rejected the request. | | | X | X | X | X | X | X | X | +| **4101** | Payer rejected transaction request | Payer rejected the transaction request from the Payee. | | | X | | | | | | | +| **4102** | Payer FSP unsupported transaction type | The Payer FSP does not support or rejected the requested transaction type | | | X | | | | | | | +| **4103** | Payer unsupported currency | Payer doesn’t have an account which supports the requested currency. | | | X | | | | | | | +| **4200** | Payer limit error | Generic limit error, for example, the Payer is making more payments per day or per month than they are allowed to, or is making a payment that is larger than the allowed maximum per transaction. | | | X | X | | X | | X | X | +| **4300** | Payer permission Error | Generic permission error, the Payer or Payer FSP doesn’t have the access rights to perform the service. | | | X | X | X | X | X | X | X | +| **4400** | Generic Payer blocked error | Generic Payer blocked error, the Payer is blocked or has failed regulatory screenings. | | | X | X | X | X | X | X | X | + +**Table 111 – Payer errors – 4xxx** + + +
+ +#### Payee Errors – 5xxx + +All possible errors occurring in the server when the Payee or the Payee FSP is the cause of an error should use the high-level error code 5 (error codes **5**_xxx_). These error codes should indicate that there was no error in the server or in the request from the client, but the request failed for some reason due to the Payee or the Payee FSP. The server should provide an explanation for why the service could not be performed. + +Low level categories defined under Payee Errors: + +- **Generic Payee Error – 50**_xx_ +- **Payee Rejection Error – 51**_xx_ +- **Payee Limit Error – 52**_xx_ +- **Payee Permission Error – 53**_xx_ +- **Payee Blocked Error – 54**_xx_ + +See Table 112 below for all Payee errors defined in the API. + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **5000** |Generic Payee error |Generic error due to the Payer or Payer FSP, to be used for not disclosing information that may be considered private. | | | X | X | X | X | X | X | X | +| **5001** | Payee FSP insufficient liquidity | The Payee FSP has insufficient liquidity to perform the transfer. | | | | | | X | | | | +| **5100** | Generic Payee rejection | Payee or Payee FSP rejected the request. | | | X | X | X | X | X | X | X | +| **5101** | Payee rejected quote | Payee does not want to proceed with the financial transaction after receiving a quote. | | | | X | | | | X | | +| **5102** | Payee FSP unsupported transaction type | The Payee FSP either does not support or rejected the requested transaction type. | | | | X | | | | X | | +| **5103** | Payee FSP rejected quote | Payee doesn’t want to proceed with the financial transaction after receiving a quote. | | | | X | | | | X | | +| **5104** | Payee rejected transaction | Payee rejected the financial transaction. | | | | | | X | | | X | +| **5105** | Payee FSP rejected transaction | Payee FSP rejected the financial transaction. | | | | | | X | | | X | +| **5106** | Payee unsupported currency | Payee doesn’t have an account which supports the requested currency. | | | | X | | X | | X | X | +| **5200** | Payee limit error | Generic limit error, for example, the Payee is receiving more payments per day or per month than they are allowed to, or is receiving a payment which is larger than the allowed maximum per transaction. | | | X | X | | X | | X | X | +| **5300** | Payee permission error | Generic permission error; the Payee or Payee FSP does not have the access rights to perform the service. | | | X | X | X | X | X | X | X | +| **5400** | Generic Payee blocked error | Generic Payee Blocked error, the Payee is blocked or has failed regulatory screenings. | | | X | X | X | X | X | X | X | + +**Table 112 – Payee errors – 5xxx** + + +
+ +## References + +1 [https://perldoc.perl.org/perlre.html#Regular-Expressions](https://perldoc.perl.org/perlre.html#Regular-Expressions) - perlre - Perl regular expressions + +2 [https://tools.ietf.org/html/rfc7159#section-7](https://tools.ietf.org/html/rfc7159#section-7) – The JavaScript Object Notation (JSON) Data Interchange Format - Strings + +3 [http://www.unicode.org/](http://www.unicode.org/) - The Unicode Consortium + +4 [https://www.iso.org/iso-8601-date-and-time-format.html](https://www.iso.org/iso-8601-date-and-time-format.html) - Date and time format - ISO 8601 + +5 [https://tools.ietf.org/html/rfc4122](https://tools.ietf.org/html/rfc4122) - A Universally Unique IDentifier (UUID) URN Namespace + +6 [https://tools.ietf.org/html/rfc4648#section-5](https://tools.ietf.org/html/rfc4648#section-5) - The Base16, Base32, and Base64 Data Encodings - Base 64 Encoding with URL +and Filename Safe Alphabet + +7 [https://www.iso.org/iso-4217-currency-codes.html](https://www.iso.org/iso-4217-currency-codes.html) - Currency codes - ISO 4217 + + + + +## List of Figures + +- [Figure 1](#error-codes) – Error code structure + +## List of Tables + +- [Table 1](#lookup-participant-information) – Lookup Participant Information data model +- [Table 2](#create-participant-information) – Create Participant Information data model +- [Table 3](#create-bulk-participant-information) – Create Bulk Participant Information data model +- [Table 4](#delete-participant-information) – Delete Participant Information data model +- [Table 5](#return-participant-information) – Return Participant Information data model +- [Table 6](#return-bulk-participant-information) – Return Bulk Participant Information data model +- [Table 7](#return-participant-information-error) – Return Participant Information Error data model +- [Table 8](#return-bulk-participant-information-error) – Return Bulk Participant Information Error data model +- [Table 9](#lookup-party-information) – Lookup Party Information data model +- [Table 10](#return-party-information) – Return Party Information data model +- [Table 11](#return-party-information-error) – Return Party Information Error data model +- [Table 12](#retrieve-transaction-request) – Retrieve Transaction Request data model +- [Table 13](#perform-transaction-request-information) – Perform Transaction Request Information data model +- [Table 14](#return-transaction-request-information) – Return Transaction Request Information data model +- [Table 15](#return-transaction-request-information-error) – Return Transaction Request Information Error data model +- [Table 16](#retrieve-quote-information) – Retrieve Quote Information data model +- [Table 17](#calculate-quote) – Calculate Quote data model +- [Table 18](#return-quote-information) – Return Quote Information data model +- [Table 19](#return-quote-information-error) – Return Quote Information Error data model +- [Table 20](#perform-authorization) – Perform Authorization data model +- [Table 21](#return-authorization-result) – Return Authorization Result data model +- [Table 22](#return-authorization-error) – Return Authorization Error data model +- [Table 23](#retrieve-transfer-information) – Retrieve Transfer Information data model +- [Table 24](#perform-transfer) – Perform Transfer data model +- [Table 25](#return-transfer-information) – Return Transfer Information data model +- [Table 26](#return-transfer-information-error) – Return Transfer Information Error data model +- [Table 27](#retrieve-transaction-information) – Retrieve Transaction Information data model +- [Table 28](#return-transaction-information) – Return Transaction Information data model +- [Table 29](#return-transaction-information-error) – Return Transaction Information Error data model +- [Table 30](#retrieve-bulk-quote-information) – Retrieve Bulk Quote data model +- [Table 31](#calculate-bulk-quote) – Calculate Bulk Quote data model +- [Table 32](#return-bulk-quote-information) – Return Bulk Quote Information data model +- [Table 33](#return-bulk-quote-information-error) – Return Bulk Quote Information Error data model +- [Table 34](#retrieve-bulk-transfer-information) – Retrieve Bulk Transfer Information data model +- [Table 35](#perform-bulk-transfer) – Perform Bulk Transfer data model +- [Table 36](#return-bulk-transfer-information) – Return Bulk Transfer Information data model +- [Table 37](#return-bulk-transfer-information-error) – Return Bulk Transfer Information Error data model +- [Table 38](#results-for-validated-amount-values) – Example results for different values for Amount type +- [Table 39](#amounttype-element) – Element AmountType +- [Table 40](#authenticationtype-element) – Element AuthenticationType +- [Table 41](#authenticationvalue-element) – Element AuthenticationValue +- [Table 42](#authorizationresponse-element) – Element AuthorizationResponse +- [Table 43](#balanceofpayments-element) – Element BalanceOfPayments +- [Table 44](#bulktransferstate-element) – Element BulkTransferState +- [Table 45](#code-element) – Element Code +- [Table 46](#correlationid-element) – Element CorrelationId +- [Table 47](#currency-element) – Element Currency +- [Table 48](#dateofbirth-element) – Element DateOfBirth +- [Table 49](#errorcode-element) – Element ErrorCode +- [Table 50](#errordescription-element) – Element ErrorDescription +- [Table 51](#extensionkey-element) – Element ExtensionKey +- [Table 52](#extensionvalue-element) – Element ExtensionValue +- [Table 53](#firstname-element) – Element FirstName +- [Table 54](#fspid-element) – Element FspId +- [Table 55](#ilpcondition-element) – Element IlpCondition +- [Table 56](#ilpfulfilment-element) – Element IlpFulfilment +- [Table 57](#ilppacket-element) – Element IlpPacket +- [Table 58](#lastname-element) – Element LastName +- [Table 59](#merchantclassificationcode-element) – Element MerchantClassificationCode +- [Table 60](#middlename-element) – Element MiddleName +- [Table 61](#note-element) – Element Note +- [Table 62](#nrofretries-element) – Element NrOfRetries +- [Table 63](#partyidentifier-element) – Element PartyIdentifier +- [Table 64](#partyidtype-element) – Element PartyIdType +- [Table 65](#partyname-element) – Element PartyName +- [Table 66](#partysubidortype-element) – Element PartySubIdOrType +- [Table 67](#refundreason-element) – Element RefundReason +- [Table 68](#transactioninitiator-element) – Element TransactionInitiator +- [Table 69](#transactioninitiatortype-element) – Element TransactionInitiatorType +- [Table 70](#transactionrequeststate-element) – Element TransactionRequestState +- [Table 71](#transactionscenario-element) – Element TransactionScenario +- [Table 72](#transactionstate-element) – Element TransactionState +- [Table 73](#transferstate-element) – Element TransferState +- [Table 74](#transactionsubscenario-element) – Element TransactionSubScenario +- [Table 75](#authenticationinfo) – Complex type AuthenticationInfo +- [Table 76](#errorinformation) – Complex type ErrorInformation +- [Table 77](#extension) – Complex type Extension +- [Table 78](#extensionlist) – Complex type ExtensionList +- [Table 79](#individualquote) – Complex type IndividualQuote +- [Table 80](#individualquoteresult) – Complex type IndividualQuoteResult +- [Table 81](#individualtransfer) – Complex type IndividualTransfer +- [Table 82](#individualtransferresult) – Complex type IndividualTransferResult +- [Table 83](#geocode) – Complex type GeoCode +- [Table 84](#money) – Complex type Money +- [Table 85](#party) – Complex type Party +- [Table 86](#partycomplexname) – Complex type PartyComplexName +- [Table 87](#partyidinfo) – Complex type PartyIdInfo +- [Table 88](#partypersonalinfo) – Complex type PartyPersonalInfo +- [Table 89](#partyresult) – Complex type PartyResult +- [Table 90](#refund) – Complex type Refund +- [Table 91](#transaction) – Complex type Transaction +- [Table 92](#transactiontype) – Complex type TransactionType +- [Table 93](#amounttype-enum) – Enumeration AmountType +- [Table 94](#authenticationtype-enum) – Enumeration AuthenticationType +- [Table 95](#authorizationresponse-enum) – Enumeration AuthorizationResponse +- [Table 96](#bulktransferstate-enum) – Enumeration BulkTransferState +- [Table 97](#partyIdtype-enum) – Enumeration PartyIdType +- [Table 98](#personalidentifiertype-enum) – Enumeration PersonalIdentifierType +- [Table 99](#transactioninitiator-enum) – Enumeration TransactionInitiator +- [Table 100](#transactioninitiatortype-enum) – Enumeration TransactionInitiatorType +- [Table 101](#transactionrequeststate-enum) – Enumeration TransactionRequestState +- [Table 102](#transactionscenario-enum) – Enumeration TransactionScenario +- [Table 103](#transactionstate-enum) – Enumeration TransactionState +- [Table 104](#transferstate-enum) – Enumeration TransferState +- [Table 105](#461-communication-errors-–-1xxx) – Communication errors – 1xxx +- [Table 106](#462-server-errors-–-2xxx) – Server errors – 2xxx +- [Table 107](#client-errors-–-3xxx) – Generic client errors – 30xx +- [Table 108](#client-errors-–-3xxx) – Validation Errors – 31xx +- [Table 109](#client-errors-–-3xxx) – Identifier Errors – 32xx +- [Table 110](#client-errors-–-3xxx) – Expired Errors – 33xx +- [Table 111](#463-payer-errors-–-4xxx) – Payer errors – 4xxx +- [Table 112](#464-payee-errors-–-5xxx) – Payee errors – 5xxx + + +## Table of Listings +- [Listing 1](#regular-expression) – Regular expression for data type UndefinedEnum +- [Listing 2](#regular-expression-2) – Regular expression for data type Name +- [Listing 3](#regular-expression-3) – Regular expression for data type Integer +- [Listing 4](#regular-expression-4) – Regular expression for data type OtpValue +- [Listing 5](#regular-expression-5) – Regular expression for data type BopCode +- [Listing 6](#regular-expression-6) – Regular expression for data type ErrorCode +- [Listing 7](#regular-expression-7) – Regular expression for data type TokenCode +- [Listing 8](#regular-expression-8) - Regular expression for data type MerchantClassificationCode +- [Listing 9](#regular-expression-9) – Regular expression for data type Latitude +- [Listing 10](#regular-expression-10) – Regular expression for data type Longitude +- [Listing 11](#regular-expression-11) – Regular expression for data type Amount +- [Listing 12](#regular-expression-12) – Regular expression for data type DateTime +- [Listing 13](#regular-expression-13) – Regular expression for data type Date +- [Listing 14](#regular-expression-14) – Regular expression for data type UUID +- [Listing 15](#regular-expression-15) – Regular expression for data type BinaryString +- [Listing 16](#regular-expression-16) – Regular expression for data type BinaryString32 diff --git a/docs/technical/api/fspiop/pki-best-practices.md b/docs/technical/api/fspiop/pki-best-practices.md new file mode 100644 index 000000000..5de85cb0d --- /dev/null +++ b/docs/technical/api/fspiop/pki-best-practices.md @@ -0,0 +1,707 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- + +# Public Key Infrastructure Best Practices + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| + +## Introduction + +This document explains _Public Key Infrastructure_ (PKI)1 best practices to apply in an _Open API for FSP Interoperability_ (hereafter cited as “the API”) deployment. See [PKI Background](#pki-background) section for more information about PKI. + +The API should be implemented in an environment that consists of either: + +- _Financial Service Providers_ (FSPs) that communicate with other FSPs (in a bilateral setup) or + +- A _Switch_ that acts as an intermediary platform between FSP platforms. There is also an _Account Lookup System_ (ALS) available to identify in which FSP an account holder is located. + +For more information about the environment, see [Network Topology](#network-topology) section. [Certificate Authority PKI Management Strategy](#certificate-authority-pki-management-strategy) and [Platform PKI Management Strategy](#platform-pki-management-strategy) identify management strategies for the CA and for the platform. + +Communication between platforms is performed using a REST (REpresentational State Transfer)-based HTTP protocol (for more information, see _API Definition_). Because this protocol does not provide a means for ensuring either integrity or confidentiality between platforms, extra security layers must be added to protect sensitive information from alteration or exposure to unauthorized parties. + +
+ +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](./logical-data-model) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](./json-binding-rules) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](#) + +- [Signature](./v1.1/signature) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](./glossary) + +
+ + +## PKI Background + +Public Key Infrastructure (PKI) is a set of standards, procedures, and software for implementing authentication using public key cryptography. PKI is used to request, install, configure, manage and revoke digital certificates. PKI offers authentication using digital certificates; these digital certificates are signed and provided by _Certificate Authorities_ (CA). + +PKI uses public key cryptography and works with X.509 standard certificates. It also provides features such as: + +- User authentication + +- Certificate production and distribution + +- Certificate maintenance, management, and revocation + +PKI consists of a number of components that enable the infrastructure to work; it is not a single process or algorithm. In addition to authentication, PKI also enables the provision of integrity, non-repudiation and encryption. + +To obtain a public key, a company must obtain a digital certificate. It should request this certificate from a CA or a _Registration Authority_ (RA) - an organization that processes requests on behalf of a CA. All participants must trust the CA to manage and maintain certificates. The CA requires the company to supply a number of details (_Common Name_ (CN), _Organization_ (O), _Country_ (C) and so on) and validate their request before it provides a certificate. This certificate is proof that the company is who it says it is in the digital world (like a passport in the real world). + +PKI combines well with a _Diffie-Hellman solution_ (a secure mechanism for exchanging a shared symmetric key between two anonymous peers) in providing secure key exchanges. Because Diffie-Hellman does not provide authentication, PKI is used with additional protocols, such as _Pretty Good Privacy_ (PGP) and _Transport Layer Security_ (TLS). + +### Layered Protection + +The API should be used with protection at both the transport- and application-level. + +#### Transport-Level Protection + +To protect the transport level, _Transport Layer Security_2 (TLS) should be used. TLS is a fundamental technique used for securing point-to-point communication. It has been proven to be stable and secure when using strong algorithms with the most recent versions of TLS, and is widely used around the world. TLS is a secure mechanism for exchanging a shared symmetric key between two anonymous peers, with identity verification (that is, trusted certificates). It provides _confidentiality_ (no one has read the content) and _integrity_ (no one has changed the content). Using TLS efficiently as-is requires certificate management. + +#### Application-Level Protection + +This layer provides end-to-end integrity and confidentiality. The API uses the JSON Web Signature3 (JWS) standard for integrity and _non-repudiation_ (provide proof of the integrity and origin of data), and the JSON Web Encryption (JWE) 4 standard for confidentiality. An extended version of JWE is used to support field level encryption. + +Using these standards requires certificate management; therefore, _Certificate Authorities_ (CA) and related PKI techniques are needed. For more information, see PKI Background. + +## Network Topology + +This section identifies the platforms that constitute the API. + +### Platforms Point-to-Point Layout + +Figure 1 shows an example platform point-to-point layout. + +![Figure1 Platforms Layout](../assets/figure1-platforms-layout.svg) + +**Figure 1 - Platforms layout** + +All communication between platforms must be TLS-secured using _client authentication_, also known as _mutual authentication_. + +### Platform Roles + +#### Certificate Authority (CA) + +The CA performs the following functions: + +- Sign _Certificate Signing Requests_ (CSRs) - CSRs is a secure mechanism for exchanging a shared symmetric key between two anonymous peers. The CA signs different types of certificates (for example, TLS, Content signature, Content encryption). + +- Revoke certificates – Mark one or more certificates as invalid. + +- Support CRLs – Maintain and provide certificate revocation lists (CRLs) to be downloaded by clients so that they can see which certificates have been revoked. + +- Support Online Certificate Status Protocol (OCSP) – Provide real-time certificate revocation checks. + +#### Account Lookup System (ALS) + +- Holds basic information about account holders. + +- Answer questions like “Where should I send my financial transaction request for account holder with **MSISDN 0123456**?” + +#### Financial Services Provider (FSP) + +Has account holders to which or from which money is transferred. + +#### Switch + +- Relays transaction information to other platforms. + +- Can perform financial services, as specified in _API Definition_. + +## Certificate Authority PKI Management Strategy + +This section describes the PKI management strategy for Certificate Authorities. + +### Certificate Authority Importance and Selection Criteria + +The Certificate Authority (CA) role is important because: + +- The CA provides a single legal entity that is trustworthy for all platforms. + +- The point-to-point TLS protocol depends on certificates. + +- The end-to-end protocols JWS and JWE depend on certificates for proof of non-repudiation and confidentiality. + +#### Reasons Not to Use a Public CA + +- A public CA can revoke the intermediate certificate used for signing our certificates, thus effectively shutting down all communication between platforms. + +- A public CA also signs certificates which are not part of the _Open API for FSP Interoperability_ setup. Because you trust the certificate the CA signed for you, you then trust all certificates signed by that CA. + +- There is no service in the _Open API for FSP Interoperability_ setup that is open to the public, so there is no reason to have a public CA already trusted by public clients (such as web browsers). + +#### Private CA Options + +- Build your own CA from scratch + +- Build a CA using existing tools (for example, _openssl_) + +- Use a full-featured CA (for example, the open source product _EJBCA_) + +### Trusted Certificate Chain + +A centralized CA makes certificate management easier for the involved platforms. By trusting the same CA certificate, each platform need only trust one certificate; the CA’s self-signed root certificate. + +Thus, the CA should sign all types of certificates (TLS, signature, and encryption), but only for the participants in the _Open API for FSP Interoperability_ setup. + +No intermediate CA certificates are required, because a segmented layout is not used in the _Open API for FSP Interoperability_ setup. + +### CA Root Certificate + +- The CA must create a self-signed root certificate to be used for signing all supported types of certificates (TLS, signing, and encryption). + +- The minimum key length of the asymmetric RSA key pair is 4096 bits, and the signature algorithm should be sha512WithRSAEncryption. + +- The _X.509 Basic Constraints_ must have the attribute **CA** set to **TRUE**. + +- The time validity of the CA root certificate should be ten years. After eight years, a new self-signed root certificate should be created by the CA; the asymmetric RSA key pair must be recreated, not reused. This certificate becomes the certificate to use for signing the platforms CSRs. However, the old CA root certificate must still be active until it expires. This gives the platforms a window of two years to change the CA root certificate without disturbing their ongoing secured communication. + +### Signing Platforms CSRs + +The CA must provide a mechanism for the platforms to get their CSRs signed. Common signing methods are by email and by a web page. The chosen solution and policy must be known to the platforms. + +The CA signs three types of platform certificates; TLS (for communication), JWS (for signature) and JWE (for encryption). Common requirements for these certificates are: + +- The minimum key length of the asymmetric RSA key pair is 2048 bits, and the signature algorithm should be sha256WithRSAEncryption. + +- The _X.509 Basic Constraints_ must have the attribute **CA** set to **FALSE**. + +- The subject distinguished names must contain at least the following attributes: + + - _Common Name_ (CN) – This must be the hostname of the platform which has created the certificate. A N can never be the same for two different platforms or organizations. + + - _Organization_ (O) – The name of the organization. + + - _Country_ (C) – The country of the organization. + +- The URL for platforms to download CRLs must be present. + +- The URL for platforms to send OCSP requests must be present. + +- The time validity should be two years. + +Depending on the type of certificate to sign, the _X.509 Key Usage_ and X.509 Extended Key Usage of the platform’s certificate will differ; see Table 1 for more information. + +| Certificate Type | X.509 Key Usage | X.509 Extended Key Usage | +| --- | --- | --- | +| **TLS Certificates** | Digital Signature, Key Encipherment | TLS Web Server Authentication, TLS Web Client Authentication | +| **Signature Certificates** | Digital Signature | | +| **Encryption Certificates** | Key Encipherment | | + +**Table 1 – Certificate type and key usage** + +### Revoking Certificates + +- The CA must be able to revoke a platform’s certificates. Revoking a certificate means that it will no longer be trusted by any party. It will be marked as invalid by the CA and its revocation status published to the platforms, either in a revocation list (CRL) to be downloaded by platforms, or through a real-time HTTP query using _Online Certificate Status Protocol_ (OCSP) requested by platforms. + +- The CA should support both CRL downloads and OCSP queries. + +- The CA should update and sign the CRL daily and should provide (daily) a HTTP URL to the platforms that points to the CRL to be downloaded. The URL should be stored in the _CRL Distribution Points_ for each signed certificate. + +- The OCSP URL should be stored in the _Authority Information Access_ for each signed certificate. An OCSP response must be signed. Nonce values in an OCSP request should be supported to prevent reply attacks. + +- The CA has the right to revoke certificates, but no obligation to inform the platforms about such revocations. The platforms do not have the right to revoke certificates, but they do have an obligation to check regularly for a certificate’s revocation status. + +### Certificate Enrollment and Renewal + +The CA does not support enrollment or renewal of certificates for which an asymmetric key pair is reused. For increased security, the asymmetric key pairs must be recreated every time a certificate is enrolled or renewed through a new CSR. + +## Platform PKI Management Strategy + +This section describes the PKI management strategy for platforms. + +### Keys, Certificates, and Stores + +A certificate provides the identity of its owner through a trusted CA that has signed the certificate. This can be validated through its signed certificate chain. It also provides the technical means to ensure integrity (signature) and confidentiality (encryption) of data using its asymmetric key pair (known as a _public key and private key_). The public key is within the signed certificate, but its corresponding private key must be kept private and protected. A common solution for handling certificates and private keys is to put them into a protected storage area known as a store. A store can be a file, directory, or something else that provides access and confidentiality. + +A single private key and its associated certificate can be used for all cryptographic purposes, but to enhance security, the following set of keys and certificates is required for each platform: + +- One private key and certificate for TLS communication + +- One private key and certificate for end-to-end integrity using JWS + +- One private key and certificate for end-to-end confidentiality using JWE + +Different keys and types of certificates can all be in the same store, but a more common setup is the following: + +- For TLS communication: + + - One protected key store to hold the private key, its associated certificate, and certificate chain. These items are used for server- and client authentication in TLS. + + - One protected certificate store to hold all trusted TLS certificates. These certificates will be trusted by your platform during a TLS handshake, meaning that they will allow secure communication with the owners of the certificates. Since all participants trust the same CA, it is sufficient to keep only the CA’s root certificate here. + +- For signature and encryption: + + - One protected key store to hold your private keys, their associated certificates, and certificate chains used for signatures and encryption. + + - One private key and certificate chain used for signing using JWS, and one private key and certificate chain used for encryption using JWE. + + - One protected certificate store to hold all trusted signature and encryption certificates from other platforms. Here you must store the certificates (signature and encryption certificates) for each platform that you want to trust for end-to-end integrity and confidentiality. + +### Creating a CSR and Obtaining CA Signature + +To be able to communicate with other platforms, you must create a key store (if one does not already exist), an asymmetric key pair, and an associated certificate that identifies your platform. This unsigned certificate must be signed by the CA before it can be trusted by other platforms. The procedure of getting a certificate signed by a CA begins with a CSR (_Certificate Signing Request_). + +When you create your keys, certificates, and CSRs, the following requirements apply: + +- The minimum key length of the asymmetric RSA key pair is 2048 bits, and the signature algorithm is sha256WithRSAEncryption. + +- The following attributes in the subject distinguished names are mandatory: + + - Common Name (CN) – This must be the hostname of the platform who created the certificate. A CN can never be the same for two different platforms or organizations. + + - Organization (O) – The name of the organization. + + - Country (C) – The country of the organization. + +**For examples of how to create a store, certificate, and CSR, see Appendix C – Common PKI Tasks** + +How to create a store, certificate, and CSR. + +Create your CSR and send it to your CA according to their instructions. + +**Note:** The same procedure must be performed for all your different keys and certificates (TLS, signature, and encryption). + +### Importing a Signed CSR + +After signing your CSR, you will have two certificates in your response from the CA. The first certificate is your own signed certificate. The second is the CA’s own root certificate, which was used for signing your certificate. That certificate must now be trusted by you. + +First you must import your signed certificate into your key store. It must replace your unsigned certificate. For examples, see How to import a signed certificate into your key store. + +Then you must import the CA’s root certificate into the same key store to complete the chain between your certificate and the CA. For examples, see How to import the CA certificate into your key store. + +#### TLS Certificates + +For TLS certificates, you must also import the CA’s root certificate into your TLS trust store to automatically trust the other platforms when establishing new communication channels with them. For examples, see How to import the CA certificate into TLS trust store. + +The above procedure should be performed for each of your signed CSRs. Remember to send your signed certificate and the CA’s root certificate to all other platforms with which you need to communicate. + +The CA will create a validity period of two years for your signed certificate. After 18 months, you should create a new CSR to be signed by the same CA. Your newly signed certificate and the CA’s root certificate should once again be imported into your stores and sent to the other platforms. This will give you and your peers a window of six months to make sure that your new signed certificate works. After two years, the old expired certificate can be deleted. + +### Trusting Certificates from Other Platforms + +Just as your peers must have your certificates to be able to trust you, they must send their certificates to you for you to trust them. + +Make sure that you always receive at least two certificates from a trusted peer: + +- The signed certificate of the peer to trust. + +- The root certificate of the CA that signed the peer’s certificate. + +**Note:** A peer’s CA certificate can differ from yours. This can happen if the CA has created a new CA root certificate when the old one is about to expire. + +You should always view a peer’s certificates (check CN, validity period, and so on) and validate the certificate chain (that is, that each certificate is correctly signed by the given CA) before you import them into your trust store. + +For examples, see How to view a certificate. + +Next, import the peer’s certificate and its CA root certificate into your trust store. For examples, see How to import a trusted certificate. + +### Checking Certificate Revocation Status + +Certificates can be revoked by the CA. A revoked certificate is considered not trusted and should be removed from the trust store. A certificate can also be _on hold_, which means that it is in pending state due to investigation and should not be removed. + +All platforms should perform revocation checks on a regular basis. There are two common ways to find out which certificates have been revoked; either through viewing a revocation list (CRL) to be downloaded by platforms, or through a real-time HTTP query (OCSP) requested by platforms. + +#### Certificate Revocation List + +This is a file maintained by a CA. It contains a list of certificate serial numbers that have been revoked by the CA. This file can be downloaded by any platform at any time. The URL to the CRL file to be downloaded is included in the certificate itself and can be found in _CRL Distribution Points_. A CRL is signed by the CA and should be validated. + +A CRL should be downloaded once per day and cached by the platform. + +For examples, see How to verify a certificate through a CRL. + +#### Online Certificate Status Protocol + +The status of a certificate can be retrieved by sending an OCSP request to an _OCSP Responder_ (which can be the CA). The request contains the serial number of the certificate to be checked. The responder sends back a signed response including the status of the certificate. + +The request should contain a nonce value, which the responder will put in the response, for the platform to validate on receipt. This is to prevent reply attacks. + +An OCSP request/response is considered very fast and can be executed for each received client certificate operation, but depending on the load towards the responder, it might have to be cached by the platform as well. + +The OCSP URL is included in the certificate itself and can be found in _Authority Information Access_. + +For examples, see How to verify a certificate through an OCSP request. + +### Renewing Certificates + +Do not renew certificates for which an asymmetric key pair is reused. For increased security, the asymmetric key pairs must be recreated every time through a new CSR. + +## Transport Layer Protection + +This section describes transport layer protection. + +### TLS + +TLS provides point-to-point integrity and confidentiality, and is used for all communication between peers. + +The setup requires both _server authentication_ - meaning that the server presents itself through its own TLS certificate - and _client authentication_ (also known as mutual authentication) in which the client presents itself through its own TLS certificate. + +#### TLS Protocol Versions + +The TLS protocol version used must be 1.2 or higher. + +#### TLS Cipher Suites + +The following cipher suites should be used: + +- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + +- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + +- TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + +- TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + +- TLS_RSA_WITH_AES_256_GCM_SHA384 + +- TLS_RSA_WITH_AES_128_GCM_SHA256 + +## Application Layer Protection + +This section describes the application layer protection. + +### JSON Web Signature + +The _JSON Web Signature_ (JWS) standard is used for providing end-to-end integrity and non-repudiation; that is, to guarantee that the sender is who it claims to be, and that the message was not tampered with. + +The use of JWS is mandatory and certificates should be used. For more information, see _API Signature_. + +### JSON Web Encryption + +The _JSON Web Encryption_ (JWE) standard is used for providing end-to-end confidentiality; that is, to protect data from being read by unauthorized parties. + +The use of JWE is optional and is applied to specific fields. This is to fulfill regulatory requirements that might exist for certain type of data in certain countries. + +For more information about how to apply JWE to fields in messages, see the extended JWE standard specification _API Encryption_. + + +## List of Appendices + +### Appendix A - Key Lengths and Algorithms + +Table 2 contains the required key length and algorithm for each entity. + +| Entity | Algorithm | Key length/hash size | +| --- | --- | --- | +| CA asymmetric keys | RSA | 4096 bits | +| CA signing algorithm | RSA with SHA2 | >= 256 bits | +| TLS asymmetric keys | RSA | 2048 bits | +| TLS signing algorithm | RSA with SHA2 | >= 256 bits | +| Signature asymmetric keys | RSA | 2048 bits | +| Signature algorithm | RSA with SHA2 | >= 256 bits | +| Encryption asymmetric keys | RSA | 2048 bits | +| HMAC | SHA2 - AES | >= 256 bits| +| Symmetric keys | AES | 256 bits | +| Hashing | SHA2 | >= 256 bits | + +**Table 2 – Key lengths and algorithms** + +### Appendix B - Terminology + +| | | +| --- | --- | +| PKI | Public Key Infrastructure +| API | Application Program Interface +| TLS | Transport Layer Security +| JWS | JSON Web Signature +| JWE | JSON Web Encryption +| FSP | Financial Service Provider +| AL | Account Lookup +| CA | Certificate Authority +| CSR | Certificate Signing Request +| CRL | Certificate Revocation List +| OCSP | Online Certificate Status Protocol +| PEM | Privacy Enhanced Mail +| RSA | Rivest, Shamir, & Adleman +| HMA | Hashed Message Authentication Code +| AES | Advanced Encryption Standard +| SHA | Secure Hash Algorithm + +### Appendix C - Common PKI Tasks + +#### Appendix C.1 - How to create a store, certificate, and CSR + +**Using the Java keytool** + +Use the following command to create an asymmetric RSA key pair and associated certificate information to be signed by the +CA. It will automatically create a JKS key store if the given one does not exist: + +``` +keytool -genkey -dname "CN=" -alias -keyalg RSA - +keystore -keysize 2048 +``` + +**Example** + +``` +keytool -genkey -dname "CN=bank-fsp" -alias tlscert -keyalg RSA -keystore +tlskeystore.jks -keysize 2048 +``` + +**Notes:** + +1. The certificate attribute CN specifies the hostname of the host who identifies itself using this certificate during a TLS session. +2. When asked for password, use the same password for the key as the key store. + +Use the following command to create the actual CSR to be signed by the CA: + +``` +keytool -certreq -alias -keystore –file .csr +``` + +**Example** + +``` +keytool -certreq -alias tlscert -keystore tlskeystore.jks -file tlscert.csr +``` + +**Using openssl** + +Use the following command to create an asymmetric RSA key pair, and CSR to be signed by the CA: + +``` +openssl req -new -newkey rsa:2048 -nodes -subj "/CN=" -out +.csr -keyout .key +``` + +**Example** + +``` +openssl req -new -newkey rsa:2048 -nodes -subj "/CN=bank-fsp" -out tlscert.csr - +keyout tlscert.key +``` + +**Note:** The certificate attribute CN specifies the hostname of the host who identifies itself using this certificate during a TLS session. + +Important to note is that the created private key is stored unencrypted. Use the following command to encrypt it: + +``` +openssl rsa -aes256 -in -out +``` + +**Example** + +``` +openssl rsa -aes256 -in tlscert.key -out tlscert_encrypted.key +``` + +#### Appendix C.2 - How to import a signed certificate into your key store + +**Using the Java keytool** + +Import your signed certificate into your key store. This certificate should replace the old unsigned one, so make sure that you use the correct alias. + +``` +keytool -importcert -alias -file -keystore +``` + +**Example** + +``` +keytool -importcert -alias tlscert -file bank-fsp.pem -keystore tlskeystore.jks +``` + +**Using openssl** + +Remove your old CSR file and replace it with the new signed certificate. + +#### Appendix C.3 - How to import the CA certificate into your key store + +**Using Java keytool** + +Import the CA certificate into your key store: + +``` +keytool -importcert -alias -file -keystore +``` + +**Example:** + +``` +keytool -importcert -alias rootca -file rootca.pem -keystore tlskeystore.jks +``` + +When you are asked to trust the imported certificated, answer **yes**: + +``` +Trust this certificate? [no]: yes +Certificate was added to keystore +``` + +**Using openssl** + +Put the CA certificate with your other certificate files + +#### Appendix C.4 - How to import the CA certificate into TLS trust store + +**Using Java keytool** + +Import the CA certificate into your trust store: + +``` +keytool -importcert -alias -file -keystore +``` + +**Example:** + +``` +keytool -importcert -alias rootca -file rootca.pem -keystore tlstruststore.jks +``` + +When you are asked to trust the imported certificated, answer **yes**: + +``` +Trust this certificate? [no]: yes +Certificate was added to keystore +``` +**Using openssl** + +Put the CA certificate with your other certificate files. + +#### Appendix C.5 - How to view a certificate + +**Using Java keytool** + +Use this command to list all certificates stored in a key store in readable format: + +``` +keytool -list -keystore -v +``` + +**Example:** + +``` +keytool -list -keystore tlskeystore.jks -v +``` + +**Using openssl** + +Use this command to show the content of a PEM encoded certificate in readable format: + +``` +openssl x509 -in -text -nout +``` + +**Example:** + +``` +openssl x509 -in rootca.pem -text -nout +``` + +#### Appendix C.6 - How to import a trusted certificate + +**Using Java keytool** + +Import the certificate into your trust store: + +``` +keytool -importcert -alias -file -keystore +``` + +**Example:** + +``` +keytool -importcert -alias trustedcert -file cert.pem -keystore truststore.jks +``` + +When you are asked to trust the imported certificated, answer **yes**: + +``` +Trust this certificate? [no]: yes +Certificate was added to keystore +``` + +**Using openssl** + +Put the trusted certificate with your other certificate files. + +#### Appendix C.7 - How to verify a certificate through a CRL + +**Using Java** + +You can use a specific security library for this (for example, Bouncy Castle), or use the in-built support for it, see: +[https://stackoverflow.com/questions/10043376/java-x509-certificate-parsing-and-validating/10068006#10068006](#https://stackoverflow.com/questions/10043376/java-x509-certificate-parsing-and-validating/10068006#10068006) + +**Using openssl** + +A good example is found at the following link: +[https://raymii.org/s/articles/OpenSSL_manually_verify_a_certificate_against_a_CRL.html](#https://raymii.org/s/articles/OpenSSL_manually_verify_a_certificate_against_a_CRL.html) + +#### Appendix C.8 - How to verify a certificate through an OCSP request + +**Using Java** + +Some Java examples is found in the following link: +[https://stackoverflow.com/questions/5161504/ocsp-revocation-on-client-certificate](#https://stackoverflow.com/questions/5161504/ocsp-revocation-on-client-certificate) + +**Using openssl** + +A good example is found at the following link: +[https://raymii.org/s/articles/OpenSSL_Manually_Verify_a_certificate_against_an_OCSP.html](#https://raymii.org/s/articles/OpenSSL_Manually_Verify_a_certificate_against_an_OCSP.html) + + +1 This term, and other italicized terms, are defined in Glossary for Open API for FSP Interoperability Specification. + +2 [https://tools.ietf.org/html/rfc5246](#https://tools.ietf.org/html/rfc5246) - The Transport Layer Security (TLS) Protocol - Version 1.2 + +3 [https://tools.ietf.org/html/rfc7515](#https://tools.ietf.org/html/rfc7515) - JSON Web Signature (JWS) + +4 [https://tools.ietf.org/html/rfc7516](#https://tools.ietf.org/html/rfc7516) - JSON Web Encryption (JWE) + +
+ +## Table of Figures + +- [Figure 1 - Platforms layout](#platforms-point-to-point-layout) + +
+ +## Table of Tables + +- [Table 1 – Certificate type and key usage](#Table-1–Certificate-type-and-key-usage) + +- [Table 2 – Key lengths and algorithms](#Table-2-Key-lengths-and-algorithms) \ No newline at end of file diff --git a/assets/.gitkeep b/docs/technical/api/fspiop/sandbox.md similarity index 100% rename from assets/.gitkeep rename to docs/technical/api/fspiop/sandbox.md diff --git a/docs/technical/api/fspiop/scheme-rules.md b/docs/technical/api/fspiop/scheme-rules.md new file mode 100644 index 000000000..7c1639b48 --- /dev/null +++ b/docs/technical/api/fspiop/scheme-rules.md @@ -0,0 +1,219 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- +# Scheme Rules + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| + +## Introduction + +This document defines scheme rules for Open API for FSP Interoperability (hereafter cited as the API) in three categories. + +1. Business Scheme Rules: + + a. These business rules should be governed by FSPs and an optional regulatory authority implementing the API within a scheme. + + b. The regulatory authority or implementing authority should identify valid values for these business scheme rules in their API policy document. + +2. API implementation Scheme Rules: + + a. These API parameters should be agreed on by FSPs and the optional Switch. These parameters should be part of the implementation policy of a scheme. + + b. All participants should configure these API parameters as indicated by the API-level scheme rules for the implementation with which they are working. + +3. Security and Non-Functional Scheme Rules. + + a. Security and non-functional scheme rules should be determined and identified in the implementation policy of a scheme. + +
+ +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](./logical-data-model) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](./json-binding-rules) + +- [Scheme Rules](#) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](./v1.1/signature) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](./glossary) + +
+ +## Business Scheme Rules + +This section describes the business scheme rules. The data model for the parameters in this section can be found in _API Definition._ + +#### Authentication Type + +The authentication type scheme rule controls the authentication types OTP and QR code. It lists the various authentication types available for _Payer_ authentication. A scheme can choose to support all the authentication types mentioned in “AuthenticationTypes” in _API Definition_ or a subset thereof. + +#### Consumer KYC Identification Required + +A scheme can mandate verification of consumer KYC (Know Your Customer) identification by Agent or Merchant at the time of transaction (for example, cash-out, cash-in, merchant payment). The API cannot control this scheme rule; therefore, it should be documented in scheme policy so that it is followed by all participants in a scheme. The scheme can also decide on the valid KYC proof of identification that should be accepted by all FSPs. + +#### Currency + +A scheme may recommend allowing transactions in more than one currency. This scheme may define the list of valid currencies in which transactions can be performed by participants; however, this is not required. A Switch may work as transaction router and doesn’t validate the transaction currency. If a scheme does not define the list of valid currencies, then the Switch works as transaction router and the participating FSP can accept or reject the transaction based on its supported currencies. Foreign exchange is not supported; that is, the transaction currency for the Payer and the _Payee_ should be the same. + +#### FSP ID Format + +A scheme may determine the format of the FSP ID. The FSP ID should be of string type. Each participant will be issued a unique FSP ID by the scheme. Each FSP should prepend the FSP ID to a merchant code (a unique identifier for a merchant) so that the merchant code is unique across all the participants (that is, across the scheme). The scheme can also determine an alternate strategy to ensure that FSP IDs and merchant codes are unique across participating FSPs. + +#### Interoperability Transaction Type + +The API supports the use cases documented in _Use Cases_. A scheme may recommend implementation of all the supported usecases or a subset thereof. A scheme may also recommend to rollout the use cases in phases. Two or more FSPs in the scheme might decide to implement additional use-cases supported by the API. A Switch may work as a transaction router and does not validate transaction type; the FSP can accept or reject the transaction based on its supported transaction types. If a participant FSP initiates a supported API transaction type due to incorrect configuration on the Payer end, then the transaction must be rejected by the peer FSP if the peer FSP doesn’t support the specific transaction type. + +#### Geo-Location Required + +The API supports geolocation of the Payer and the Payee; however, this is optional. A scheme can mandate the geolocation of transactions. In this case, all participants must send the geolocation of their respective party. + +#### Extension Parameters + +The API supports one or more extension parameters. A scheme can recommend that the list of extension parameters be supported. All participants must agree with the scheme rule and support the scheme-mandatory extension parameters. + +#### Merchant Code Format + +The API supports merchant payment transaction. Typically, a consumer either enters or scans a merchant code to initiate merchant payment. In case of merchant payment, the merchant code should be unique across all the schemes. Currently, the merchant code is not unique in the way that mobile numbers or email addresses are unique. Therefore, it is recommended to prepend a prefix or suffix (FSP ID) to the merchant code so that the merchant code is unique across the FSPs. + +#### Max Size Bulk Payments + +The API supports the Bulk Payment use-case. The scheme can define the maximum number of transactions in a bulk payment. + +#### OTP Length + +The API supports One-time Password (OTP) as authentication type. A scheme can define the minimum and maximum length of OTP to be used by all FSPs. + +#### OTP Expiration Time + +An OTP’s expiration time is configured by each FSP. A scheme can recommend it to be uniform for all schemes so that users from different FSPs have a uniform user experience. + +#### Party ID Types + +The API supports account lookup system. An account lookup can be performed based on valid party ID types of a party. A scheme can choose which party ID types to support from **PartyIDType** in API Definition. + +#### Personal Identifier Types + +A scheme can choose the valid or supported personal identifier types mentioned in **PersonalIdentifierType** in API Definition. + +#### QR Code Format + +A scheme should standardize the QR code format in the following two scenarios as indicated. + +##### Payer-Initiated transaction + +Payer scans the QR code of Payee (Merchant) to initiate a Payer-Initiated Transaction. In this case, the QR code should be standardized to include the Payee information, transaction amount, transaction type and transaction note, if any. The scheme should standardize the format of QR code for Payee. + +##### Payee-Initiated Transaction + +Payee scans the QR code of Payer to initiate Payee-Initiated transaction. For example: Merchant scans the QR code of Payer to initiate a Merchant Payment. In this case, the QR code should be standardized to locate the Payer without using the account lookup system. The scheme should standardize the format of QR code; that is, FSP ID, Party ID Type and Payer ID, or only Party ID Type and Party ID. + +## API Implementation Scheme Rules + +This section describes API implementation scheme rules. + +#### API Version + +API version information must be included in all API calls as defined in _API Definition_. A scheme should recommend that all FSPs implement the same version of the API. + +#### HTTP or HTTPS + +The API supports both HTTP and HTTPS. A scheme should recommend that the communication is secured using TLS (see [Communication Security](#communication-security) section). + +#### HTTP Timeout + +FSPs and Switch should configure HTTP timeout. If FSP doesn’t get HTTP response (either **HTTP 202** or **HTTP 200**) for the **POST** or **PUT** request then FSP should timeout. Refer to the diagram in Figure 1 for the **HTTP 202** and **HTTP 200** timeouts shown in dashed lines. + +###### Figure-1 + +![Figure 1 HTTP Timeout](../assets/scheme-rules-figure-1-http-timeout.png) + +**Figure 1 – HTTP Timeout** + +#### Callback Timeouts + +The FSPs and the Switch should configure callback timeouts. The callback timeouts of the initiating FSP should be greater than the callback timeout of the Switch. A scheme should determine callback timeout for the initiating FSP and the Switch. Refer to the diagram in Figure 2 for the callback timeouts highlighted in red. + +###### Figure-2 + +![Figure 1 Callback Timeout](../assets/scheme-rules-figure-2-callback-timeout.png) + + +**Figure 2 – Callback Timeout** + +## Security and Non-Functional Requirements Scheme Rules + +This section describes the scheme rules for security, environment and other network requirements. + +#### Clock Synchronization + +It is important to synchronize clocks between FSPs and Switches. It is recommended that an NTP server or servers be used for clock synchronization. + +#### Data Field Encryption + +Data fields that need to be encrypted will be determined by national and local laws, and any standard that must be complied with. Encryption should follow _Encryption_. + +#### Digital Signing of Message + +A scheme can decide that all messages must be signed as described in _Signature_. Response messages need not to be signed. + +#### Digital Certificates + +To use the signing and encryption features detailed in _Signature_ and _Encryption_ in a scheme, FSPs and Switches must obtain digital certificates as specified by the scheme-designated _CA_ (Certificate Authority). + +#### Cryptographic Requirement + +All parties must support the encoding and encryption ciphers as specified in _Encryption_, if encryption features are to be used in the scheme. + +#### Communication Security + +A scheme should require that all HTTP communication between parties is secured using TLS[1](https://tools.ietf.org/html/rfc5246) version 1.2 or later. + +1 [https://tools.ietf.org/html/rfc5246](https://tools.ietf.org/html/rfc5246) - The Transport Layer Security (TLS) Protocol - Version 1.2 + + +### Table of Figures + +[Figure 1 – HTTP Timeout](#figure-1) + +[Figure 2 – Callback](#figure-2) \ No newline at end of file diff --git a/docs/technical/api/fspiop/use-cases.md b/docs/technical/api/fspiop/use-cases.md new file mode 100644 index 000000000..33058d029 --- /dev/null +++ b/docs/technical/api/fspiop/use-cases.md @@ -0,0 +1,1102 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- + +# Use Cases + + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| + +
+ +## Introduction + +The purpose of this document is to define a set of use cases that can be implemented using the Open API for FSP interoperability (hereafter cited as the API). The use cases referenced within this document provide an overview of transaction processing flows and business rules of each transaction step as well as relevant error conditions. + +The primary purpose of the API is to support the movement of financial transactions between one _Financial Services Provider_ (FSP) and another. + +It should be noted that the API is only responsible for message exchange between FSPs and a Switch when a cross-FSP transaction is initiated by an _End User_ in one of the FSPs. This can occur in either of two scenarios: + +- A bilateral scenario in which FSPs communicate with each other + +- A Switch based scenario in which all communication goes through a Switch + +Reconciliation, clearing and settlement after real time transactions is out of scope for the API. Additionally, account lookup is supported by the API, but it relies on the implementation in a local market in which a third party or Switch would provide such services. Therefore, the need for effective on-boarding processes and appropriate scheme rules must be considered when implementing use cases. + +
+ +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### General Documents + +- _Glossary_ + +#### Logical Documents + +- _Logical Data Model_ + +- _Generic Transaction Patterns_ + +- _Use Cases_ + +#### Asynchronous REST Binding Documents + +- _API Definition_ + +- _JSON Binding Rules_ + +- _Scheme Rules_ + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- _PKI Best Practices_ + +- _Signature_ + +- _Encryption_ + +
+ +## Use Case Summaries + +The following generic transaction patterns are introduced in [Generic Transaction Patterns]() to reduce duplication of each use case description. These patterns summarize the common transaction process flows and shared function of the relevant use cases. + +- **Payer-Initiated Transaction** + - In a _Payer-Initiated Transaction_, it is the _Payer_ (that is, the payer of electronic funds) who initiates the transaction. + + The pattern should be used whenever a Payer would like to transfer funds to another party whose account is not located in the same FSP. + +- **Payee-Initiated Transaction** + + - In a _Payee-Initiated Transaction_, it is the _Payee_ (that is, the recipient of electronic funds) who initiates the transaction. + + This pattern should be used whenever a Payee would like to receive funds from another party whose account is not located in the same FSP. + +- **Payee-Initiated Transaction using OTP** + + - A _Payee-Initiated Transaction using One-Time Password (OTP)_ is like a _Payee-Initiated Transaction_, but the transaction information (including fees and taxes) and approval for the Payer is shown or entered on a Payee device instead. + + - This pattern should be used when a Payee would like to receive funds from another party whose account is not located in the same FSP, and both the transaction information (including fees and taxes) and approval is shown or entered on a Payee device instead. + +- **Bulk Transactions** + + - In a _Bulk Transaction_, it is the Payer (that is, the sender of funds) who initiates multiple transactions to multiple Payees, potentially located in different FSPs. + + - The pattern should be used whenever a Payer would like to transfer funds to multiple Payees in the same transaction. The Payees can potentially be in different FSPs. + +It is recommended to read all Generic Transaction Patterns before reading the use cases. For more information, see [Generic Transaction Patterns](). + +Each use case describes variations on and special considerations for the generic transaction pattern to which it refers. The use cases are introduced in [Table 1](#table-1) below: + +##### Table 1 + +| Use Case Name | Description | +| --- | --- | +| P2P |This use case describes the business process and business rules in which an individual End User initiates a transaction to send money to another individual End User who doesn’t belong to the same FSP as the Payer.

This is usually a remote transaction in which Payer and Payee are not in the same location. | +| Agent-Initiated Cash-In | This use case describes the business process and business rules in which a customer requests an agent of a different FSP to cash-in (deposit funds) to their account.

This is typically a face-to-face transaction in which the customer and the agent are in the same location. | +| Agent-Initiated Cash-Out | This use case describes the business process and business rules in which a customer requests that an agent of a different FSP to cash-out (withdraw funds) from their account.

This is typically a face-to-face transaction in which the customer and the agent are in the same location. | +| Agent-Initiated Cash-Out
Authorized on POS
| This use case describes the business process and business rules in which a customer requests an agent of a different FSP to cash-out (withdraw funds) from their account. In this use case, the agent initiates the transaction through a point-of-sale (_POS_) and the customer inputs OTP on POS to authorize the transaction. Alternatively, the agent can use POS to scan a QR code generated by a customer’s mobile app to initiate the transaction. | +| Customer-Initiated Cash-Out | This use case describes the business process and business rules in which a registered customer initiates a transaction to cash-out (withdraw funds) using an agent who doesn’t belong to the customer’s FSP.

This is typically a face-to-face transaction in which the customer and the agent are in the same location. | +| Customer-Initiated Merchant
Payment
| This use case describes the business process and business rules in which an individual End User initiates a purchase transaction to pay a merchant who does not belong to the same FSP as the customer.

This is usually a face to face transaction when a customer buys goods or services at a merchant store.

A variant of this use case is online payment, in which the online shopping system generates a QR code and displays it on a web page, and the consumer then scans the QR code by handset and completes the payment transaction. | +| Merchant-Initiated Merchant
Payment
| This use case describes the business process and business rules in which a merchant initiates a request for payment to the customer; the customer reviews the transaction amount in the request and confirms the request by providing authentication on their own handset. | +| Merchant-Initiated Merchant
Payment Authorized on POS
| This use case describes the business process and business rules in which merchant initiates a request for payment from the customer; the customer reviews the payment request on a merchant device and authorizes the payment by OTP or QR code on the merchant device. The customer authentication information is sent from _Payee FSP_ to _Payer FSP_ for authentication by Payer FSP. | +| ATM-Initiated Cash-Out | This use case describes the business process and business rules in which an ATM initiates a cash-out request from a customer account. Customer pregenerates an OTP for cash-out and uses this OTP on the ATM device to initiate ATM cash-out. The Payer FSP validates the OTP received in the ATM-Initiated Cash-Out request for authentication purposes. | +| Bulk Payments | _Bulk Payments_ is used when an organization or business is paying out funds – for example, aid or salary to multiple Payees who have accounts located in the different FSPs. The organization or business can group transactions together to make it easier for uploading and validating individual transactions in bulk before the bulk transaction is executed. It is also possible for the organization to follow up the result of the individual transactions in the bulk transaction after the bulk transaction is executed. | +| Refund | This use case describes the business flow how to refund a completed interoperability transaction. | + +**Table 1 – Use Case Summary** + +
+ +## Use Cases + +This section demonstrates ways in which the API can be used through the use cases identified in [Table 1](#table-1) – _Use Case Summary_. + +For each use case, the following is presented: +- Use Case Description +- Reference to Generic Pattern +- Actors and Roles +- Addition to Generic Transaction Pattern +- Relevant Error Conditions + +### P2P + +#### Use Case Description + +This section describes the business process and business rules for a use case in which an individual End User initiates a transaction to send money to another individual End User who doesn’t belong to the same FSP as the Payer. + +This is usually a remote transaction in which Payer and Payee are not in the same location. + +There are four steps necessary to complete a _P2P_ Transfer transaction from one FSP user to another FSP user. + +##### Step 1 + +Payer initiates a transaction to their FSP, and Payer FSP then locates Payee FSP through an API call to the Account Lookup System or by the agreed-upon _scheme_ rules. + +##### Step 2 + +Payer FSP calculates the transaction fee applied to Payer. Payer FSP sends a quote request through an API call to Payee FSP. + +##### Step 3 + +Payer FSP presents the total transaction fee and Payee name (optional) to the Payer to confirm the transaction. + +##### Step 4 + +Payer accepts the transaction and Payer FSP performs the transaction through an API call to the Switch or to Payee FSP. The transaction completes and notifications are sent to both Payer and Payee; or the Payer rejects the transaction and the transaction ends. + +
+ +### Reference to Generic Pattern + +_Payer-Initiated Transaction_ + +#### Actors and Roles + +The actors and roles for P2P are described in [Table 2](#table-2) below: + +##### Table 2 + +| Role | Map to Generic Transaction Pattern | Description | +| --- | --- | --- | +| Customer | Payer | An individual who is a registered customer of an FSP who initiates a transaction to send money to another individual. | +| Customer | Payee | The person who will receive money from Payer.

Payee could be a registered customer of Payee FSP or, if the scheme rules allow it, an unregistered customer who will be registered during the transaction process, which is determined by the design of Payee FSP. + +**Table 2 – P2P Actors and Roles** + +#### Addition to Generic Transaction Pattern + +##### Step 2 + +The Payee FSP ID could be determined by the scheme rule without any dependence on the API. Otherwise, **Lookup Party Information** request is an option for determining in which FSP a Payee is located. + +Payer FSP will use the request **Lookup Party Information** to retrieve details of Payee from Payee FSP directly if there is no Switch between Payer FSP and Payee FSP. + +##### Steps 9 – Step 15 + +In the current version of the API, the **Calculate Quote** request to Payee FSP is mandatory even if a wholesale fee is agreed upon in the scheme. Payee FSP needs to receive transaction details from the **Calculate Quote** request to generate the condition for this transaction. + +Payer FSP can use information from response **Return Quote Information** from Payee FSP to calculate the transaction fee it will apply on Payer. The business rules for how Payer FSP calculates the transaction fee could be defined by the scheme rules; this is out of scope for the API. + +In P2P Transfer case, it is the common practice that Payer pays the entire transaction fee, and Payee is free of charge in the transaction. + +##### Step 16 + +There are several ways to push a confirmation message to Payer to authorize the transaction. For example, USSD Push Message, or SMSC notification; then Payer opens the USSD menu to query and confirm the pending transaction + +The interaction between Payer and Payer FSP is designed by each FSP, and is out-of-scope for the API. + +##### Step 19 + +The Quote ID applied in the previous step is verified in the transaction processing step. If the quote is expired, Payee FSP will reject the transaction. + +##### Step 20 + +A notification is sent to the Payee once the transaction is performed by Payee FSP. + +##### Step 28 + +Payer FSP sends notification to Payer to indicate the transaction result. + +#### Relevant Error Conditions +[Table 3](#table-3) below describes relevant errors and recommended follow-up actions for this use case. + +##### Table 3 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +|2 | Timeout | **Lookup Party Information** request timed out | Retry | +|4 | Payee is unreachable | Account Lookup System fails to locate Payee| Cancel the transaction | +|6 | Currency is not supported | The transaction currency is not supported. | Initiate a new transaction with supported currency by Payee FSP | +| 9 | Timeout | **Calculate Quote** request timed out | Retry with the same ID | +|11 | Wrong quote | Payee FSP cannot provide quote due to internal business rule validation failure or system error.

For example, invalid account status of Payee, wrong fee configuration or database error | Cancel the transaction | +|17 | Timeout | **Perform Transfer** request timed out | Query transaction status and decide to complete or retry

The retry policy will be defined by the scheme rules. For example, retry times and period | +|19 | Transaction failed | Transaction failed at Payee FSP.
Possible reasons:
  • Limit breach
  • Payer or Payee is blacklisted
  • Quote is expired
  • Invalid account status of Payee
  • Payee FSP internal system error

  • | Cancel the transaction | +|22 | Funds reservation timed out | Funds reservation at Payer FSP is timed out and the transaction fails at Payer FSP but succeeds at Payee FSP. | Reconcile according to the scheme rules + +**Table 3 – P2P Relevant Error Conditions** + +
    + +### Agent-Initiated Cash-In + +#### Use Case Description + +This section describes the business process and business rules for the use case in which a customer requests an agent of a different FSP to cash-in (deposit funds) to their account. This is a two-step transaction: Agent initiates a cash-in transaction from their handset or POS and then receives transaction information including possible fees. Agent can either approve or reject the transaction. Once transaction is completed, the customer gives cash to the agent. + +Agent-Initiated Cash-In is typically a face-to-face transaction in which the customer and the agent are in the same location. + +#### Reference to Generic Pattern + +_Payer-Initiated Transaction_ + +#### Actors and Roles + +The actors and roles for Agent-Initiated Cash-In are described in [Table 4](#table-4) below: + +| Role | Map to Generic Transaction Pattern | Description | +| --- | --- | --- | +|Agent | Payer | Payer is an agent (individual or organization) who will receive cash from the customer and transfer money to the customer’s account.

    Agent is a registered party with Payer FSP. | +| Customer | Payee | Customer is an individual who would like to deposit cash into their account.

    Customer is a registered individual in Payee FSP. | + +**Table 4 – Agent-Initiated Cash-In: Actors and Roles** + +#### Addition to Generic Transaction Pattern + +##### Step 1 + +Customer requests that an agent cash-in to their account. + +If a smart phone is used, the agent can scan a static QR code from the customer to capture the customer’s information and initiate the transaction. + +Optionally the agent verifies the identity of the customer. + +##### Step 12 + +This is an optional step. The customer checks cash-in transaction information and related fees on their own handset and then makes the decision to accept or reject the transaction. + +##### Step 16 + +The agent checks fees and taxes and either accepts or rejects. + +##### Step 20 + +A notification is sent to the customer after the transaction is performed by Payee FSP. + +##### Step 28 + +Payer FSP sends notification to the agent to indicate the transaction result. + +#### Relevant Error Conditions + +[Table 5](#table-5) describes relevant errors and recommended follow-up actions for this use case. + +##### Table 5 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +|2 | Timeout | **Lookup Party Information** request timed out | Retry | +|4 | Payee cannot be found | Account Lookup System fails to locate Payee | Cancel the transaction | +|6 |Currency is not supported | The transaction currency is not supported. | Initiate a new transaction with supported currency by Payee FSP | +|9 | Timeout | **Calculate Quote** request timed out | Retry with the same ID | +|15 | Wrong quote | Payee FSP cannot provide quote due to internal business rule validation failure or system error.

    For example, invalid account status of Payee, wrong fee configuration or database error | Cancel the transaction +|17 | Timeout | **Perform Transfer** request timed out | Query transfer status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +|19 |Transaction failed | Transaction failed at Payee FSP.
    Possible reasons:
  • Low balance of Payee
  • Limit breached
  • Quote is expired
  • Payer or Payee blacklisted
  • Invalid account status of Payee
  • Payee FSP internal system error

  • | Cancel the transaction | +|22 |Funds reservation timeout | Funds reservation at Payer FSP timed out and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to the scheme rules + +**Table 5 – Agent-Initiated Cash-In: Relevant Error Conditions** + +
    + +### Agent-Initiated Cash-Out + +#### Use Case Description + +This section describes the business process and business rules for the use case in which a customer requests an agent of a different FSP to cash-out (withdraw funds) from their account. This is a 2-step transaction, the agent initiates cash-out transaction request and the customer authorizes the transaction on their handset. Once transaction is completed, the agent gives cash to the customer. + +Agent-Initiated Cash-Out is a face-to-face transaction in which the customer and the agent are in the same location. + +#### Reference to Generic Pattern + +_Payee-Initiated Transaction_ + +#### Actors and Roles + +The actors and roles for Agent-Initiated Cash-Out are described in [Table 6](#table-6). + +##### Table 6 + +| Role | Map to Generic
    Transaction Pattern
    | Description | +| --- | --- | --- | +|Customer | Payer | Payer is a customer (individual or organization) who wants to withdraw cash using an agent.

    Customer is a registered party in Payer FSP. | +|Agent | Payee | Payee is an agent registered with the Payee FSP. A pre-funded wallet for the agent is maintained at Payee FSP.

    Agent is a registered party in Payee FSP. | + +**Table 6 – Agent-Initiated Cash-Out: Actors and Roles** + +#### Addition to Generic Transaction Pattern + +##### Step 1 + +The customer requests that an agent cash-out (withdraw funds) from their account. + +If a smart phone is used, the agent can scan a static QR code containing the customer’s information to capture that information and initiate the transaction. + +Optionally, the agent may verify the identity of the customer to satisfy regulatory requirements. + +##### Step 17 + +The Payer FSP shows fees and taxes to the customer. The customer indicates whether they want to proceed or not. + +##### Step 25 + +A transaction notification is sent to the agent after the transaction is performed by Payee FSP. + +##### Step 33 + +After receiving transaction notification, the agent gives the cash-out amount to the customer. + +##### Relevant Error Conditions + +[Table 7](#table-7) describes relevant errors and recommended follow-up actions for this use case. + +##### Table 7 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +| 2 | Timeout | **Lookup Party Information** request timed out | Retry | +| 3 | Payer cannot be found | Account Lookup System fails to locate the Payer | Cancel the transaction | +| 7 | Currency is not supported | The transaction currency is not supported. | Initiate a new transaction supported by Payee FSP | +| 22 | Timeout | **Perform Transfer** request timed out | Query transfer status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 24 | Transaction failed | Transaction failed at the Payee FSP.
    Possible reasons:
  • Limit Breached
  • Payer or Payee blacklisted
  • Quote is expired
  • Invalid account status of Payee
  • Payee FSP internal system error

  • | Cancel the transaction | +| 27 | Reservation is expired | Funds reservation is expired and the transaction fails at Payer FSP but succeeds at Payee FSP. | Reconcile according to scheme rules | + +**Table 7 – Agent-Initiated Cash-Out: Relevant Error Conditions** + +### Agent-Initiated Cash-Out Authorized on POS + +#### Use Case Description + +This section describes the business process and business rules for the use case in which a customer requests that an agent of a different FSP cash-out (withdraw funds) from their account. In this use case, the agent initiates the transaction through a POS, and the customer inputs a OTP on POS to authorize the transaction. Alternatively, the agent can use POS to scan a QR code generated by the mobile app of the customer to initiate the transaction. + +- Approval using OTP – A Payer can approve a transaction by first creating an OTP in their FSP. The OTP is then entered in a Payee device (usually a POS device). The OTP in the transaction request is automatically matched by the Payer FSP to either approve or reject the transaction. The OTP does not need to be encrypted as it should only be valid once during a short time period. + +- Approval using QR code – A Payer can approve a transaction by requesting a Payer FSP to generate a QR code that encodes an OTP and customer’s identifier. + +- Approval using NFC – A Payer can approve a transaction by swiping a _Near Field Communication_ (NFC) phone on a POS. The interoperability for NFC POS of one FSP to read data from NFC tag or NFC phone of another FSP should be considered if NFC technology is adopted. + +Agent-Initiated Cash-Out Authorized on POS is typically a face-to-face transaction in which the customer and the agent are in the same location. + +#### Reference to Generic Pattern + +_Payee-Initiated Transaction using OTP_ + +#### Actors and Roles + +The actors and roles for Agent-Initiated Cash-Out Authorized on POS are described in [Table 8](#table-8). + +##### Table 8 + +| Role | Map to Generic Transaction Pattern | Description | +| --- | --- | --- | +| Customer | Payer | Payer is a customer (individual or organization) who wants to withdraw cash using an agent.

    The customer is a registered party with Payer FSP.| +| Agent | Payee | Payee is an agent registered with the Payee FSP. A pre-funded wallet for the agent is maintained at Payee FSP.

    The agent is registered party with Payee FSP. | + +**Table 8 – Agent-Initiated Cash-Out Authorized on POS: Actors and Roles** + +#### Addition to Generic Transaction Pattern + +##### Step 1 + +For OTP: + +- The customer requests Payer FSP to generate an OTP. + +For QR code: + +- The customer enters cash-out amount and requests Payer FSP to generate a QR code. + +- The QR code generation should be approved by customer transaction PIN. + +##### Step 4 + +The customer requests the agent to cash-out some amount from their account. + +For OTP: + +- The agent inputs the customer’s ID and cash-out amount to initiate the transaction + +For mobile app: + +- The agent inputs cash-out amount and then scan QR code of customer via scanner POS + +For NFC: + +- The agent inputs cash-out amount and the customer taps phone on NFC POS. + +- The agent verifies identity of the customer to satisfy regulation requirements. + +##### Step 21 + +There is a risk that someone other than the owner of phone may attempt to use the phone to make a transaction at an agent store. Thus, the transaction should be approved via PIN to allow an OTP to be generated automatically. + +##### Step 25 + +The customer checks fees and taxes. If the customer agrees: + +- For OTP: The customer enters OTP on the agent phone or device. + +- For QR code/NFC: The customer confirms the payment on POS. + +If the customer disagrees: + +- For OTP: The customer doesn’t enter OTP on the agent phone or device. + +- For QR code/NFC: The customer rejects the payment on POS. + +##### Step 36 + +A notification is sent to the agent after the transaction is performed by the Payee FSP. After receiving transaction notification, the agent gives the cash-out amount to the customer. + +##### Step 44 + +The Payer FSP sends a notification of the transaction result to the customer. + +##### Relevant Error Conditions + +[Table 9](#table-9) describes relevant errors and recommended follow-up actions for this use case. + +##### Table 9 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +| 5 | Timeout | **Lookup Party Information** request timedout| Retry| +| 6 | Payer cannot be found | Account Lookup System fails to locate the Payer | Cancel the transaction | +| 8 | Transaction request timeout | **Perform Transaction Request** to Payer FSP timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 28 | OTP is expired | OTP is expired | Push another authentication request to Payee FSP
    or
    Cancel the transaction in the Payer FSP | +| 28 | Invalid OTP | OTP is unrecognized | Push another authentication request to Payee FSP
    or
    Cancel the transaction in the Payer FSP | +| 35 | Transaction failed | Transaction failed at the Payee FSP.
    Possible reasons:
  • Limit Breached
  • Payer or Payee blacklisted
  • Quote is expired
  • Invalid account status of Payee
  • Payee FSP internal system error

  • | Cancel the transaction | +| 38 | Reservation is expired | Funds reservation is expired and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to scheme rules | + +**Table 9 – Agent-Initiated Cash-Out Authorized on POS: Relevant Error Conditions** + +### Customer-Initiated Cash-Out + +#### Use Case Description + +This section describes the business process and business rules for a use case in which a registered customer initiates a transaction to withdraw cash using an agent who is in a different FSP. This is two-step business process: a customer initiates cash-out transaction on their handset and then receives transaction information including fees, which can either be rejected or accepted. + +Customer-Initiated Cash-Out usually is a face-to-face transaction in which the customer and the agent are in the same location. + +#### Reference to Generic Pattern + +_Payer-Initiated Transaction_ + +#### Actors and Roles + +The actors and roles for Customer-Initiated Cash-Out are described in [Table 10](#table-10). + +##### Table 10 + +| Role | Map to Generic Transaction Pattern | Description | +| --- | --- | --- | +| Customer | Payer | Payer is a customer (individual or organization) who wants to cash-out (withdraw funds) using an agent.

    Customer is a registered party with Payer FSP. | +| Agent | Payee | Payee is an agent registered with the Payee FSP. A pre-funded wallet for the agent is maintained at Payee FSP.

    Agent is registered party with Payee FSP. | + +**Table 10 – Customer-Initiated Cash-Out: Actors and Roles** + +#### Addition to Generic Transaction Pattern + +##### Step 1 + +The customer requests that the agent cash-out some amount from their account. + +For USSD: + +- The customer inputs cash-out amount and merchant ID to initiate the transaction. + +For mobile app: + +- If a smart phone is used, the customer can scan the static QR code of the agent to capture the agent’s information and initiate transaction. + +Optionally, the agent can verify the identity of the customer to satisfy regulatory requirements. + +##### Step 12 + +This is an optional step. Payee FSP shows fees, taxes or both to the agent. If the agent does not accept the fees or commission, they can reject the transaction. + +##### Step 16 + +Payer FSP shows fees and taxes to the customer. If the customer doesn’t want to proceed, they reject the transaction. + +##### Step 20 + +A notification is sent to the agent once the transaction is performed by Payee FSP. + +##### Step 29 + +After the customer receives transaction notification, the agent gives cash-out amount to the customer. + +#### Relevant Error Conditions + +[Table 11](#table-11) describes relevant errors and recommended follow-up actions for this use case. + +##### Table 11 + +|Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +|2 | Timeout | **Lookup Party Information** request timed out | Retry | +| 4 | Agent cannot be found | Account Lookup System fails to locate agent | Cancel the transaction | +| 6 | Currency is not supported | The transaction currency is not supported. | Initiate a new transaction with supported currency by Payee FSP | +| 9 |Timeout | **Calculate Quote** request timed out | Retry with the same ID | +| 11 | Wrong quote | Payee FSP cannot provide quote due to internal business rule validation failure or system error.

    For example, invalid account status of Payee, wrong fee configuration or database error | Cancel the transaction | +| 17 | Timeout | **Perform Transfer** request timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 19 | Transaction failed | Transaction failed at Payee FSP.
    Possible reasons:
  • Limit breached
  • Payer or Payee blacklisted
  • Quote is expired
  • Invalid account status of Payee
  • Payee FSP internal system error

  • | Cancel the transaction | +| 22 | Reservation is expired | Funds reservation is expired and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to scheme rules | + +**Table 11 – Customer-Initiated Cash-Out: Relevant Error Conditions** + +### Customer-Initiated Merchant Payment + +#### Use Case Description + +This section describes the business process and business rules for a use case in which a registered customer initiates a merchant payment transaction to pay a merchant who is in another FSP. + +This could be a face to face transaction; for example, when a customer buys goods or services at the merchant store. Another case is online payment, in which an online shopping system generates a QR code and displays on the web page, and the customer then scans the QR code on the web page and authorizes and completes the payment transaction on their handset. + +**Assumption:** Encoding/Decoding QR code is handled in each FSP and is out of scope of API. The data and its format encoded in the QR code should be defined in the scheme rules to enable QR codes to be interoperable. + +#### Reference to General Pattern + +_Payer-Initiated Transaction_ + +#### Actors and Roles + +The actors and roles for Customer-Initiated Merchant Payment are described in [Table 12](#table-12). + +##### Table 12 + +| Role | Map to Generic Transaction Pattern | Description +| --- | --- | --- | +| Customer | Payer | An individual End User of one FSP who buys goods or service from a merchant of another FSP. | +| Merchant | Payee | The business that sells goods or provide service and then receives payment from the customer. | + +**Table 12 – Customer-Initiated Merchant Payment: Actors and Roles** + +#### Addition to Generic Transaction Pattern + +##### Step 1 + +For feature phone: + +- The customer can initiate a payment transaction by inputting relevant payment information on the USSD menu, such as amount and merchant ID. + +For smart phone: + +- The customer initiates merchant payment transaction by scanning the merchant QR code. After resolving the merchant QR code, there are two scenarios: + + a) The customer inputs transaction amount in their handset to continue the transaction if the transaction amount is not encoded in the QR code. This is the case for face-to-face payment at retailer merchant store. + + b) Transaction amount has already been encoded in the QR code, and then Payer FSP has enough information to continue the transaction. This case then follows the process of the online payment case identified in [4.6.1](#461-use-case-description). + +##### Step 2 + +The merchant FSP ID could be determined by the scheme rules without depending on an Account Lookup System. Otherwise, **Lookup Party Information** request is an option to find out in which FSP the merchant is located. + +In most cases, the merchant FSP ID is captured during initiating the transaction. For example, the customer selects the merchant FSP from USSD menu, or it is already encoded in the merchant QR code. + +##### Step 9 – Step 15 + +In most cases, the customer is free of charge for the purchase transaction. **Calculate Quote** request is still necessary, because all transaction details will be sent to Payee FSP and the condition of the transfer will be generated by Payee FSP for later use (in **Perform Transfer**). + +##### Step 20 + +A notification is sent to the merchant once the transaction is performed by the Payee FSP. + +##### Step 29 + +Customer receives transaction notification and customer receives goods. + +#### Relevant Error Conditions + +[Table 13](#table-13) describes relevant errors and recommended follow-up actions for this use case. + +##### Table 13 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +| 2 | Timeout | **Lookup Party Information** request timed out | Retry | +| 4 | Merchant is unreachable | Account Lookup System fails to locate merchant | Cancel the transaction | +| 6 | Currency is not supported | The transaction currency is not supported. | Initiate a new transaction with supported currency by Payee FSP | +| 9 | Timeout | **Calculate Quote** request timed out | Retry with the same ID | +| 11 | Wrong quote | Payee FSP cannot provide quote due to internal business rule validation failure or system error.

    For example, invalid account status of Payee, wrong fee configuration or database error | Cancel the transaction | +| 17 | Timeout | **Perform Transfer** request timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period +| 19 | Transaction failed | Transaction failed at Payee FSP.
    Possible reasons:
  • Limit breached
  • Payer or Payee blacklisted
  • Quote is expired
  • Invalid account status
  • Payee FSP internal system error

  • | Cancel the transaction | +| 22 | Reservation is expired | Funds reservation is expired and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to scheme rules | + +**Table 13 – Customer-Initiated Merchant Payment: Relevant Error Conditions** + +### Merchant-Initiated Merchant Payment + +#### Use Case Description + +This use case describes a merchant payment transaction, initiated by a merchant and then authorized by the customer on their handset. + +The business process involves two parties, a merchant and a customer. The merchant initiates a _request to pay_ transaction to the customer. The customer can review the transaction details and approve or reject the transaction on their mobile device. + +Thus, it is a two-step business process in which the merchant initiates a payment transaction and the customer authorizes the transaction from their account. + +#### Reference to Generic Pattern + +_Payee-Initiated Transaction_ + +#### Actors and roles + +The actors and roles for Merchant-Initiated Merchant Payment are described in [Table 14](#table-14). + +##### Table 14 + +| Role | Map to Generic Transaction Pattern | Description | +| --- | --- | --- | +| Customer | Payer | An individual End User of one FSP who buys goods or service from a merchant of another FSP. | +| Merchant | Payee | The business who sells goods or provides services and then receives payment from the customer. | + +**Table 14 – Merchant-Initiated Merchant Payment: Actors and Roles** + +#### Addition to General Pattern + +This section describes how the use case connects to the general pattern. The description is focused on the End User as the interactions between the participating systems are described in the general pattern. + +##### Step 1 + +For feature phone: + +- The merchants can input the customers’ ID in their USSD/STK menu when initiating payment transactions. + +For smart phone: + +- To capture the customer’s ID, the merchant may use a scan device or mobile app to scan QR code generated by the customer’s mobile app. + +##### Step 10-16 + +In a merchant payment transaction, the customer is usually free-of-charge. + +##### Step 13 + +This is an optional step. Payee FSP shows the transaction details including fees to the merchant; and the merchant can accept or reject the transaction. + +##### Step 25 + +A notification is sent to the merchant after the transaction is performed by the Payee FSP. + +##### Step 33 + +Payer FSP sends a notification to the customer to indicate the transaction result. + +#### Relevant Error Conditions + +[Table 15](#table-15) below describes relevant errors and recommended follow-up actions for this use case. + +##### Table 15 + +| Step | Error Condition | Error Description | Follow Up Action | +| -- | -- | -- | -- | +| 2 | Account Lookup Timeout | **Lookup Party Information** request timed out | Retry | +| 3 | Customer cannot be found | Account Lookup System fails to locate the customer | Cancel the transaction | +| 5 | Transaction request timeout | **Perform Transaction Request** to Payer FSP timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 10 | Quote request failed | **Calculate Quote** request timed out or failed at Switch or Payee FSP | Cancel the transaction | +| 24 | Quote expired | Quote expired | Cancel the transaction | +| 27 | Reservation timeout | Funds reservation timed out at Payer FSP and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to scheme rules | + +**Table 15 – Merchant-Initiated Merchant Payment: Relevant Error Conditions** + +
    + +### Merchant-Initiated Merchant Payment Authorized on POS + +#### Use Case Description + +This use case describes a merchant payment initiated by a merchant using a device such as POS, and how to authorize a transaction with an OTP or a QR code. + +The merchant initiates a merchant payment transaction using a POS device. This device has the capability to capture the customer’s authorization on POS instead of the customer’s mobile device. The authorization information captured in POS should be sent to Payer FSP to perform the authorization. + +The business process involves two parties, Merchant and Customer. The merchant initiates a request to pay for the customer, and the customer reviews the payment request on POS and authorizes the payment by OTP or QR code on the POS itself. The customer authentication information is sent from Payee FSP to Payer FSP for authentication by Payer FSP. If authentication is successful then transaction will be posted on Payer FSP and Payee FSP. + +#### Reference to Generic Pattern + +_Payee-Initiated Transaction using OTP_ + +#### Actors and roles + +The actors and roles for Merchant-Initiated Merchant Payment Authorized on POS are described in [Table 16](#table-16) below: + +##### Table 16 + +| Role | Map to Generic Transaction | Pattern Description | +| --- | --- | --- | +| Customer | Payer | An individual End User of one FSP who buys goods or service from a merchant of another FSP. | +| Merchant | Payee | The business who sells goods or provide service and then receive payment from the customer. | + +**Table 16 – Merchant-Initiated Merchant Payment Authorized on POS: Actors and Roles** + +#### Addition to General Pattern + +This section describes how the use case connects to the general pattern. The description is focused on the end-user, because the interactions between the participating systems are described in the general pattern. + +##### Step 1-3 + +The customer can pre-authorize the transaction by generating a dynamic payment QR code on a mobile app if they have a smart phone. + +The customer can request an OTP on the USSD menu if they have a feature phone. + +##### Step 4 + +For mobile app: + +- The merchant uses a scan device such as a POS to capture the QR code and initiate the payment. + +- Both customer ID and OTP are encoded in the QR code. + +For feature phone: + +- The merchant inputs customer’s ID and amount to initiate the transaction. + +##### Step 20 + +Steps 1-3 are optional and will be used only when OTP is generated by Payer to authenticate the purchase at the merchant +device. However, it would be very rare for a customer to generate the OTP manually; instead Payer FSP would generate an OTP for the customer as described in Step 20. + +##### Step 21 + +There is a risk that someone other than the owner of phone may attempt to use the phone to make a transaction at agent store. Thus, the transaction should be approved via PIN to allow OTP to be generated automatically. + +##### Step 25 + +The customer need only confirm the transaction on POS if initiating transaction with a QR code in step 4, because OTP is encoded in the QR code and parsed in Step 4. + +##### Step 36 + +A notification is sent to the merchant once the transaction is performed by the Payee FSP. After receiving the transaction notification, the merchant gives goods to the customer. + +##### Step 44 +The Payer FSP sends a notification of the transaction result to the customer. + +#### Relevant Error Conditions + +[Table 17](#table-17) below describes relevant errors and recommended follow-up actions for this use case. + +##### Table 17 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +| 5 | Timeout | **Lookup Party Information** request timed out | Retry | +| 6 | Customer cannot be found | Account Lookup System fails to locate the customer | Cancel the transaction | +| 8 | Transaction request timeout | **Perform Transaction Request** to Payer FSP timed out | Query status and retry | +| 19 | Quote request failed | Quote failed at Switch or Payee FSP | Cancel the transaction | +| 33 | Transfer request timeout | **Perform Transfer** request to Payee FSP timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 35 | Transaction failed | Transaction failed at the Payee FSP.
    Possible reasons:
  • Limit Breached
  • Payer or Payee blacklisted
  • Quote is expired
  • Invalid account status of Payee
  • Payee FSP internal system error

  • | Cancel the transaction | +| 38 | Reservation is expired | Funds reservation timed out and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to the scheme rules | + +**Table 17 – Merchant-Initiated Merchant Payment Authorized on POS: Relevant Error Conditions** + +
    + +### ATM-Initiated Cash-Out + +#### Use Case Description + +This section describes the business flows and rules of an _ATM-Initiated Cash-Out_ use case. + +This use case involves two parties: ATM and Customer. ATM initiates a Cash-Out request from the customer account and the customer confirms the request by providing authentication (OTP) on ATM. The customer pre-generates an OTP for cash-out and uses this OTP on ATM device to initiate ATM Cash-out. The Payer FSP validates the OTP received in _ATM-Initiated Cash-Out_ request for the validity of OTP as well as for authentication. If the customer authentication via OTP is successful; then the customer’s account will be debited at Payer FSP and ATM account maintained at Payee FSP will be credited. As a result, the customer receives cash from ATM. + +#### Reference to Generic Pattern + +_Payee-Initiated Transaction using OTP_ + +#### Actors and roles + +The actors and roles for ATM Initiated Cash Out are described in [Table 18](#table-18). + +##### Table 18 + +| Role | Map to Generic Transaction | Pattern Description | +| --- | --- | --- | +| Customer | Payer | Payer is a customer who wants to withdraw cash from ATM device belonging to another FSP. | +| ATM Provider | Payee | Payee is an ATM provider who provides cash withdrawal service on ATM device to a customer belonging to another FSP. ATM would be connected to a bank network which is connected to Payee FSP. There would be a pre-funded account in Payee FSP corresponding to an ATM or ATMs, or to a Bank Switch. | + +**Table 18 – ATM-Initiated Cash-Out: Actors and Roles** + +#### Addition to General Pattern + +This section describes how the use case connects to the general pattern. The description is focused on the end-user as the interactions between the participating systems are described in the general pattern. + +##### Step 1-3 + +Steps 1 to 3 are optional; however, it is recommended that customer generate an OTP before initiating the transaction request from ATM. + +Alternatively, a customer generates a QR code for cash-out via mobile app other than OTP. + +##### Step 4 + +For mobile app: + +- ATM can scan previously-generated cash-out QR code. + +For feature phone: + +- The customer initiates withdrawal transaction by inputting their account ID and amount. + +##### Step 20 + +In _ATM-Initiated Cash-Out_, it is very rare that an OTP is automatically generated by a Payer FSP, because this will delay the transaction due to SMS delivery, and the ATM transaction will time out. Therefore, it is recommended that customer generate an OTP for ATM Cash-out as mentioned in Steps 1-3. + +##### Step 21 + +There is a risk that someone other than the owner of phone holding the handset may make a transaction at an ATM device. In this case, the transaction should be approved via PIN so that the OTP can be generated automatically. + +##### Step 25 + +If an OTP is used, the customer enters the OTP that was generated in Steps 1-3 or Step 21. + +If a QR code is used to cash-out and it is captured by an ATM when initiating the transaction in Step 4, then the customer must confirm or reject the transaction on the ATM only; inputting security credentials such as OTP or password is not necessary. + +#### Relevant Error Conditions + +[Table 19](#table-19) below describes relevant errors and recommended follow-up actions for this use case. + +##### Table 19 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +| 5 | Timeout | **Lookup Party Information** request timed out | Retry | +| 6 | Customer cannot be found | Account Lookup System fails to locate the customer | Cancel the transaction | +| 8 | Transaction request timeout | **Perform Transaction Request** timed out at Switch or Payee FSP | Query and retry | +| 14 | Quote request timeout | **Calculate Quote** request timed out | Retry | +| 15 | Quote request failed | **Calculate Quote** request fails at Switch or Payee FSP | Cancel the transaction | +| 33 | Transfer request timeout | Perform Transfer request timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 35 | Transaction request is failed | Transaction failed at the Payee FSP.
    Possible reasons:
  • Limit Breached
  • Payer or Payee blacklisted
  • Quote is expired
  • Invalid account status of merchant
  • Payee FSP internal system error

  • | Cancel the transaction and try another new transaction | +| 38 | Reservation is timeout | Funds reservation is timeout and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to the scheme rules | + +**Table 19 – ATM-Initiated Cash-Out: Relevant Error Conditions** + +
    + +### Bulk Payments + +#### Use Case Description + +This section describes a _Bulk Payments_ use case. The use case is written from the end-user perspective to give additional information to the _Generic Transaction Patterns_ document. + +Bulk Payments are used when an organization or business is paying out funds; for example, aid or salary to multiple Payees. The organization or business can group transactions together to make it easier to upload and validate individual transactions in bulk before the bulk transaction is executed. It is also possible for the organization to follow up the result of the individual transactions in the bulk transaction after the bulk transaction is executed. + +#### Reference to Generic Pattern + +_Bulk Transactions_ + +#### Actors and roles + +The actors and roles for Bulk Payments are described in [Table 20](#table-20) below: + +##### Table 20 + +| Role | Map to Generic Transaction | Pattern Description | +| --- | --- | --- | +| Payer | Payer | The Payer is a corporate, government or aid organization that is transferring money from its own account to multiple Payees. The reason can for instance be payout of monthly salary or aid disbursement.

    The Payer is a registered user with an account in the Payer FSP. | +| Payee | Payee | The Payee is, for example, an employee at a corporate or receiver of aid that is receiving a payout from the Payer.

    The Payee is a registered user with an account in one of the connected FSPs. | + +**Table 20 – Bulk Payments: Actors and Roles** + +#### Addition to General Pattern + +This section describes how the use case connects to the general pattern. The description is focused on the end-user as the interactions between the participating systems are described in the general pattern. + +##### Step 1 + +The Payer creates a bulk transaction according to the format of the Payer FSP. Each row in the bulk transaction includes information about a transfer between a Payer account and a Payee account. The information includes: + +- A unique transaction ID for the bulk so that the Payer can follow up the status of individual transactions in the bulk. + +- Identifier of the Payee + +- Amount and currency to be transferred + +The Payer will upload the bulk transaction using the interface provided by the Payer FSP. + +##### Step 12 + +The Payer is notified by the Payer FSP that the bulk is ready for review. + +The Payer will get a bulk transaction report and validate that the specified Payees have accounts and can receive funds. + +The Payer can also validate any fees that will be charged for executing the bulk transaction. Fees will be calculated per transaction in the bulk transaction. + +Before the bulk transaction is executed, the Payer must ensure that there are enough funds in the Payer account for the value of the complete bulk transaction to be completed. Depending on scheme rules the Payer FSP needs to ensure that there are enough funds prefunded to the Payee FSP to be able to complete the transactions to the Payee. + +If the Payer is satisfied after reviewing the bulk transaction, then the Payer will initiate the execution of the bulk transaction. + +If the Payer does not want to execute the bulk transaction, then the bulk transaction can be canceled. Cancellation will be +handled internally in the Payer FSP. No information regarding cancelation will be sent to the Payee FSP. + +How execution and cancelation is handled depends on the implementation in the Payer FSP. + +##### Step 21 + +The Payer can review the result of the bulk transaction execution when the Payer FSP has processed all the transactions in the uploaded bulk transaction. + +The Payer will be able to get details about the execution for each individual transaction. + +Any reprocessing that might be needed to be executed (for example, failed transactions) will be treated as a new bulk transaction in the API. + +#### Relevant Error Conditions + +Bulk Transactions have two main types of logical errors: Errors connected to the header and errors related to the transactions in the bulk transaction. + +An error related to the header will fail the complete bulk transaction. For example, if the Payer of the bulk transaction is blocked, then no transaction shall be executed. + +Errors related to an individual transaction within the bulk transaction will get a failed status and be assigned an error code. The amount of the transaction that failed will be rolled back. Other transactions in the bulk transaction will not be affected if one individual transaction fails. + +[Table 21](#table-21) below contains a description of general error cases to give an overview of the bulk transaction use case and how different error cases are handled. Detailed error codes for the operations are not included, nor are codes for communication errors and format validations errors. + +##### Table 21 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +| 5 | Payee not found | Account lookup fails to look up Payee at any FSP. | Payee will be excluded from any bulk transactions request and marked as failed in the bulk transaction response to the Payer | +| 8 | Payee not found | Payee FSP cannot find the Payee account | Payee FSP will mark the individual transaction in the bulk transaction as failed. | +| 15 | Not enough funds on Payer FSP account | The Payer FSP account in the | Switch has not been prefunded to cover for the complete bulk transaction. Switch would fail the complete bulk transaction as the funds for the bulk transaction cannot be reserved. | +| 16 | Not enough funds on Payer FSP account | The Payer FSP account in the Payee FSP has not been prefunded to cover for the complete bulk transaction. | Payee FSP is not able to reserve the amount for the bulk transaction.

    Payee FSP can decide to execute as many transactions as possible or to fail the complete bulk transaction. | +| 16 | Payee transfer not allowed | The Payee FSP cannot complete the transfer of funds to the Payee. This could, for example, be blocked due to an account limit. | The individual transaction will be rolled back and reported in Payer response as failed. | +| 16 | Bulk quote expired | The quote for the bulk transaction has expired | The Payee FSP will fail the complete bulk transaction requests. | + +**Table 21 – Bulk Payments: Relevant Error Conditions** + +
    + +### Refund + +This section describes how to refund a completed interoperability transaction. + +There are several refund scenarios for merchant payment transaction: + +1. The customer has entered an amount incorrectly and paid more than the invoice. + +2. The merchant is not able to deliver the goods as specified by the invoice already paid by the customer, so the merchant wants to refund money to the customer. + +3. An online merchant selling tickets (train, air or bus) provides a refund to a customer when the customer cancels the ticket. + +4. The customer has returned the goods to the merchant and the merchant wants to refund the customer. + +Additional business scenarios may require transaction reversals. For example: + +1. The customer has sent money to incorrect recipient. + +2. The customer accidently created the same transaction twice. + +It is recommended to use refund transaction to fulfill the business purpose. + +The business process will remain as reversal, but the technical implementation would require Payee FSP CCE to initiate a refund transaction. Payer FSP CCE coordinates with Payee CCE manually. If there is a Switch, then Switch administrator may help to facilitate the conversation between Payer FSP and Payee FSP. + +Note the following: + +- Refund can only be initiated by Payee of the original transaction. Alternatively, CCE of Payee FSP in the original transaction can also initiate refund from Payee account. + +- An original transaction can be refunded multiple times. + +#### Reference to Generic Pattern + +_Payer-Initiated Transaction_ + +#### Actors and roles + +The actors and roles for Bulk Payment are described in [Table 22](#table-22). + +##### Table 22 + +| Role | Map to Generic Transaction | Pattern Description | +| --- | --- | --- | --- | +| Payee | Payee | The End User who has made a wrong payment and requests a refund. | +| Payer | Payer | The End User who has received the payment in the original transaction. | + +**Table 22 – Refund: Actors and Roles** + +#### Addition to General Pattern + +This section describes how the use case connects to the general pattern. The description is focused on the end-user, because the interactions between the participating systems are described in the general pattern. + +##### Step 1 + +Payer of the original transaction can contact Payee or CCE of Payer FSP to request refund. The actual refund amount is negotiated between Payer and Payee before the refund. + +##### Step 9-15 + +Typically, the refund transaction is free-of-charge. + +##### Step 17 + +The original transaction ID should be captured in the refund transaction. + +#### Relevant Error Conditions + +[Table 23](#table-23) below describes relevant errors and recommended follow-up actions for this use case. + +##### Table 23 + +| Step | Error Condition | Error Description | Follow on Action | +| --- | --- | --- | --- | +| 2 | Timeout | **Lookup Party Information** request timed out | Retry | +| 4 | Payee cannot be found | Account Lookup System fails to locate Customer | Cancel the transaction | +| 17 | Timeout | **Perform Transfer** request timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 19 | Transaction failed | Transaction failed at Payee FSP.
    Possible reasons:
  • Limit Breached
  • Quote is expired
  • Invalid account status of customer
  • Payee FSP internal system error

  • | Cancel the transaction | +| 22 | Funds reservation timeout | Funds reservation at Payer FSP timed out and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to the scheme rules | + +**Table 23 – Refund: Relevant Error Conditions** + +
    + +## List of Tables + +[Table 1](#table-1) – Use Case Summary + +[Table 2](#table-2) – P2P Actors and Roles + +[Table 3](#table-3) – P2P Relevant Error Conditions + +[Table 4](#table-4) – Agent-Initiated Cash-In: Actors and Roles + +[Table 5](#table-5) – Agent-Initiated Cash-In: Relevant Error Conditions + +[Table 6](#table-6) – Agent-Initiated Cash-Out: Actors and Roles + +[Table 7](#table-7) – Agent-Initiated Cash-Out: Relevant Error Conditions + +[Table 8](#table-8) – Agent-Initiated Cash-Out Authorized on POS: Actors and Roles + +[Table 9](#table-9) – Agent-Initiated Cash-Out Authorized on POS: Relevant Error Conditions + +[Table 10](#table-10) – Customer-Initiated Cash-Out: Actors and Roles + +[Table 11](#table-11) – Customer-Initiated Cash-Out: Relevant Error Conditions + +[Table 12](#table-12) – Customer-Initiated Merchant Payment: Actors and Roles + +[Table 13](#table-13) – Customer-Initiated Merchant Payment: Relevant Error Conditions + +[Table 14](#table-14) – Merchant-Initiated Merchant Payment: Actors and Roles + +[Table 15](#table-15) – Merchant-Initiated Merchant Payment: Relevant Error Conditions + +[Table 16](#table-16) – Merchant-Initiated Merchant Payment Authorized on POS: Actors and Roles + +[Table 17](#table-17) – Merchant-Initiated Merchant Payment Authorized on POS: Relevant Error Conditions + +[Table 18](#table-18) – ATM-Initiated Cash-Out: Actors and Roles + +[Table 19](#table-19) – ATM-Initiated Cash-Out: Relevant Error Conditions + +[Table 20](#table-20) – Bulk Payments: Actors and Roles + +[Table 21](#table-21) – Bulk Payments: Relevant Error Conditions + +[Table 22](#table-22) – Refund: Actors and Roles + +[Table 23](#table-23) – Refund: Relevant Error Conditions \ No newline at end of file diff --git a/docs/technical/api/fspiop/v1.0/README.md b/docs/technical/api/fspiop/v1.0/README.md new file mode 100644 index 000000000..96cef71e4 --- /dev/null +++ b/docs/technical/api/fspiop/v1.0/README.md @@ -0,0 +1,4 @@ +--- +showToc: false +--- +https://raw.githubusercontent.com/mojaloop/mojaloop-specification/master/fspiop-api/documents/v1.0-document-set/fspiop-rest-v1.0-OpenAPI-implementation.yaml \ No newline at end of file diff --git a/docs/technical/api/fspiop/v1.0/api-definition.md b/docs/technical/api/fspiop/v1.0/api-definition.md new file mode 100644 index 000000000..96cef71e4 --- /dev/null +++ b/docs/technical/api/fspiop/v1.0/api-definition.md @@ -0,0 +1,4 @@ +--- +showToc: false +--- +https://raw.githubusercontent.com/mojaloop/mojaloop-specification/master/fspiop-api/documents/v1.0-document-set/fspiop-rest-v1.0-OpenAPI-implementation.yaml \ No newline at end of file diff --git a/docs/technical/api/fspiop/v1.1/api-definition.md b/docs/technical/api/fspiop/v1.1/api-definition.md new file mode 100644 index 000000000..f5708abc5 --- /dev/null +++ b/docs/technical/api/fspiop/v1.1/api-definition.md @@ -0,0 +1,5495 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the +specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics with in angle brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature and API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| +|**1.1**|2020-05-19|1. This version contains a new option for a Payee FSP to request a commit notification from the Switch. The Switch should then send out the commit notification using the new request **PATCH /transfers/**_{ID}_. The option to use commit notification replaces the previous option of using the ”Optional Additional Clearing Check”. The section describing this has been replaced with the new section ”Commit Notification”. As the **transfers** resource has been updated with the new **PATCH** request, this resource has been updated to version 1.1. As part of adding the possibility to use a commit notification, the following changes has been made:
    a. PATCH has been added as an allowed HTTP Method in Section 3.2.2. b. The call flow for **PATCH** is described in Section 3.2.3.5.
    c. Table 6 in Section 6.1.1 has been updated to include **PATCH** as a possible HTTP Method.
    d. Section 6.7.1 contains the new version of the **transfers** resource.
    e. Section 6.7.2.6 contains the process for using commit notifications
    f. Section 6.7.3.3 describes the new **PATCH /transfers**/_{ID}_ request.

    2. In addition to the changes mentioned above regarding the commit notification, the following non-API affecting changes has been made:
    a. Updated Figure 6 as it contained a copy-paste error.
    b. Added Section 6.1.2 to describe a comprehensive view of the current version for each resource.
    c. Added a section for each resource to be able to see the resource version history.
    d. Minor editorial fixes.

    3. The descriptions for two of the HTTP Header fields in Table 1 have been updated to add more specificity and context
    a. The description for the **FSPIOP-Destination** header field has been updated to indicate that it should be left empty if the destination is not known to the original sender, but in all other cases should be added by the original sender of a request.
    b. The description for the **FSPIOP-URI** header field has been updated to be more specific.

    4. The examples used in this document have been updated to use the correct interpretation of the Complex type ExtensionList which is defined in Table 84. This doesn’t imply any change as such.
    a. Listing 5 has been updated in this regard.

    5. The data model is updated to add an optional ExtensionList element to the **PartyIdInfo** complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 103 has been updated. For consistency, the data model for the **POST /participants/**_{Type}/{ID}_ and **POST /participants/**_{Type}/{ID}/{SubId}_ calls in Table 10 has been updated to include the optional ExtensionList element as well.

    6. A new Section 6.5.2.2 is added to describe the process involved in the rejection of a quote.

    7. A note is added to Section 6.7.4.1 to clarify the usage of ABORTED state in **PUT /transfers/**_{ID}_ callbacks.| +|**1.1.1**|2021-09-22|This document version only adds information about optional HTTP headers regarding tracing support in [Table 2](#table-2), see _Distributed Tracing Support for OpenAPI Interoperability_ for more information. There are no changes in any resources as part of this version.| + +## Introduction + +This document introduces and describes the _Open API_ (Application Programming Interface) _for FSP_ (Financial Service Provider) _Interoperability_ (hereafter cited as "the API"). The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP. The API does not specify any front-end services between a Payer or Payee and its own FSP; all services defined in the API are between FSPs. FSPs are connected either (a) directly to each other or (b) by a _Switch_ placed between the FSPs to route financial transactions to the correct FSP. + +The transfer of funds from a Payer to a Payee should be performed in near real-time. As soon as a financial transaction has been agreed to by both parties, it is deemed irrevocable. This means that a completed transaction cannot be reversed in the API. To reverse a transaction, a new negated refund transaction should be created from the Payee of the original transaction. + +The API is designed to be sufficiently generic to support both a wide number of use cases and extensibility of those use cases. However, it should contain sufficient detail to enable implementation in an unambiguous fashion. + +Version 1.0 of the API is designed to be used within a country or region, international remittance that requires foreign exchange is not supported. This version also contains basic support for the [Interledger Protocol](#4-interledger-protocol), which will in future versions of the API be used for supporting foreign exchange and multi-hop financial transactions. + +This document: + +- Defines an asynchronous REST binding of the logical API introduced in _Generic Transaction Patterns_. +- Adds to and builds on the information provided in [Open API for FSP Interoperability Specification](#open-api-for-fsp-interoperability-specification). + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](../logical-data-model) + +- [Generic Transaction Patterns](../generic-transaction-patterns) + +- [Use Cases](../use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](../definitions) + +- [JSON Binding Rules](../json-binding-rules) + +- [Scheme Rules](../scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](../pki-best-practices) + +- [Signature](../v1.1/signature) + +- [Encryption](../v1.1/encryption) + +#### General Documents + +- [Glossary](../glossary) + +
    + +## API Definition + +This section introduces the technology used by the API, including: + +- [General Characteristics](#general-characteristics) +- [HTTP Details](#http-details) +- [API Versioning](#api-versioning) + +### General Characteristics + +This section describes the general characteristics of the API. + +#### Architectural Style + +The API is based on the REST (REpresentational State Transfer1) architectural style. There are, however, some differences between a typical REST implementation and this one. These differences include: + +- **Fully asynchronous API** -- To be able to handle numerous concurrent long-running processes and to have a single mechanism for handling requests, all API services are asynchronous. Examples of long-running processes are: + - Financial transactions done in bulk + - A financial transaction in which user interaction is needed + +- **Decentralized** -- Services are decentralized, there is no central authority which drives a transaction. + +- **Service-oriented** -- The resources provided by the API are relatively service-oriented compared to a typical implementation of a REST-based API. + +- **Not fully stateless** -- Some state information must be kept in both client and server during the process of performing a financial transaction. + +- **Client decides common ID** -- In a typical REST implementation, in which there is a clear distinction between client and server, it is the server that generates the ID of an object when the object is created on the server. In this API, a quote or a financial transaction resides both in the Payer and Payee FSP as the services are decentralized. Therefore, there is a need for a common ID of the object. The reason for having the client decide the common ID is two-fold: + - The common ID is used in the URI of the asynchronous callback to the client. The client therefore knows which URI to listen to for a callback regarding the request. + - The client can use the common ID in an HTTP **GET** request directly if it does not receive a callback from the server (see [HTTP Details](#http-details) section for more information). + + To keep the common IDs unique, each common ID is defined as a UUID (Universally Unique IDentifier2 (UUID). To further guarantee uniqueness, it is recommended that a server should separate each client FSP's IDs by mapping the FSP ID and the object ID together. If a server still receives a non-unique common ID during an HTTP **POST** request (see [HTTP Details](#http-details) section for more details). The request should be handled as detailed in [Idempotent Services in server](#idempotent-services-in-server) section. + +#### Application-Level Protocol + +HTTP, as defined in RFC 72303, is used as the application-level protocol in the API. All communication in production environments should be secured using HTTPS (HTTP over TLS4). For more details about the use of HTTP in the API, see [HTTP Details](#http-details). + +#### URI Syntax + +The syntax of URIs follows RFC 39865 to identify resources and services provided by the API. This section introduces and notes implementation subjects specific to each syntax part. + +A generic URI has the form shown in [Listing 1](#listing-1), where the part \[_user:password@_\]_host_\[_:port_\] is the `Authority` part described in [Authority](#authority) section. +_{resource}_. + +###### Listing 1 + +``` +scheme:[//[user:password@]host[:port]][/]path[?query][#fragment] +``` + +**Listing 1 -- Generic URI format** + +##### Scheme + +In accordance with the [Application Level Protocol](#aplication-level-protocol) section, the _scheme_ (that is, the set of rules, practices and standards necessary for the functioning of payment services) will always be either **http** or **https**. + +##### Authority + +The authority part consists of an optional authentication (`User Information`) part, a mandatory host part, followed by an optional port number. + +###### User Information + +User information should in general not be used by API deployments; the security measures detailed in *API Signature* and _API_ _Encryption_ should be used instead. + +###### Host + +The host is the server's address. It can be either an IP address or a hostname. The host will (usually) differ for each deployment. + +###### Port + +The port number is optional; by default, the HTTP port is **80** and HTTPS is **443**, but other ports could also be used. Which port to use might differ from deployment to deployment. + +##### Path + +The path points to an actual API resource or service. The resources in the API are: + +- **participants** +- **parties** +- **quotes** +- **transactionRequests** +- **authorizations** +- **transfers** +- **transactions** +- **bulkQuotes** +- **bulkTransfers** + +All resources found above are also organized further in a hierarchical form, separated by one or more forward slashes (**'/'**). Resources support different services depending on the HTTP method used. All supported API resources and services, tabulated with URI and HTTP method, appear in [Table 6](#table-6). + +##### Query + +The query is an optional part of a URI; it is currently only used and supported by a few services in the API. See the API resources in [API Services](#api-services) section for more details about which services support query strings. All other services should ignore the query string part of the URI, as query strings may be added in future minor versions of the API (see [HTTP Methods](#http-methods)). + +If more than one key-value pair is used in the query string, the pairs should be separated by an ampersand symbol (**'&'**). + +[Listing 2](#listing-2) shows a URI example from the API resource **/authorization**, in which four different key-value pairs are present in the query string, separated by an ampersand symbol. + +###### Listing 2 + +``` +/authorization/3d492671-b7af-4f3f-88de-76169b1bdf88?authenticationType=OTP&retriesLeft=2&amount=102¤cy=USD +``` + +**Listing 2 -- Example URI containing several key-value pairs in the query string** + +##### Fragment + +The fragment is an optional part of a URI. It is not supported for use by any service in the API and therefore should be ignored if received. + +#### URI Normalization and Comparison + +As specified in RFC 72306, the [scheme](#scheme)) and [host](#host)) part of the URI should be considered case-insensitive. All other parts of the URI should be processed in a case-sensitive manner. + +#### Character Set + +The character set should always be assumed to be UTF-8, defined in 36297; therefore, it does not need to be sent in any of the HTTP header fields (see [HTTP Header Fields](#http-header-fields)). No character set other than UTF-8 is supported by the API. + +#### Data Exchange Format + +The API uses JSON (JavaScript Object Notation), defined in RFC 71598, as its data exchange format. JSON is an open, lightweight, human-readable and platform-independent format, well-suited for interchanging data between systems. + +
    + +### HTTP Details + +This section contains detailed information regarding the use of the application-level protocol HTTP in the API. + +#### HTTP Header Fields + +HTTP Headers are generally described in RFC 72309. The following two sections describes the HTTP header fields that should be expected and implemented in the API. + +The API supports a maximum size of 65536 bytes (64 Kilobytes) in the HTTP header. + +#### HTTP Request Header Fields + +[Table 1](#table-1) contains the HTTP request header fields that must be supported by implementers of the API. An implementation should also expect other standard and non-standard HTTP request header fields not listed here. + +###### Table 1 + +|Field|Example Values|Cardinality|Description| +|---|---|---|---| +|**Accept**|**application/vnd.interoperability.resource+json**|0..1
    Mandatory in a request from a client. Not used in a callback from the server.
    The **Accept**10 header field indicates the version of the API the client would like the server to use. See [HTTP Accept Header](#http-accept-header) for more information on requesting a specific version of the API.| +|**Content-Length**|**3495**|0..1|The **Content-Length**11 header field indicates the anticipated size of the payload body. Only sent if there is a body.
    **Note**: The API supports a maximum size of 5242880 bytes (5 Megabytes).
    | +|**Content-Type**|**application/vnd.interoperability.resource+json;version=1.0**|1|The **Content-Type**12 header indicates the specific version of the API used to send the payload body. See [Acceptable Version Requested by Client](#acceptable-version-requested-by-client) for more information.| +|**Date**|**Tue, 15 Nov 1994 08:12:31 GMT**|1|The **Date**13 header field indicates the date when the request was sent.| +|**X- Forwarded- For**|**X-Forwarded-For: 192.168.0.4, 136.225.27.13**|1..0|The **X-Forwarded-For**14 header field is an unofficially accepted standard used to indicate the originating client IP address for informational purposes, as a request might pass multiple proxies, firewalls, and so on. Multiple **X-Forwarded-For** values as in the example shown here should be expected and supported by implementers of the API.
    **Note**: An alternative to **X-Forwarded-For** is defined in RFC 723915. However, as of 2018, RFC 7239 is less-used and supported than **X-Forwarded-For**.
    | +|**FSPIOP- Source**|**FSP321**|1|The **FSPIOP-Source** header field is a non- HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing (see [Call Flow Routing](#call-flow-routing-using-fspiop-destination-and-fspiop-source) section) and signature verification (see header field **FSPIOP-Signature**).| +|**FSPIOP- Destination**|**FSP123**|0..1|The **FSPIOP-Destination** header field is a non-HTTP standard field used by the API for HTTP header-based routing of requests and responses to the destination. The field must be set by the original sender of the request if the destination is known (valid for all services except GET /parties) so that any entities between the client and the server do not need to parse the payload for routing purposes (see [Call Flow Routing](#3236-call-flow-routing-using-fspiop-destination-and-fspiop-source) section for more information regarding routing). If the destination is not known (valid for service GET /parties), the field should be left empty.| +|**FSPIOP- Encryption**||0..1|The **FSPIOP-Encryption** header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request.
    For more information, see API Encryption.
    | +|**FSPIOP- Signature**||0..1|The **FSPIOP-Signature** header field is a non-HTTP standard field used by the API for applying an end-to-end request signature.
    For more information, see API Signature.
    | +|**FSPIOP-URI**|**/parties/msisdn/123456789**|0..1|The **FSPIOP-URI** header field is a non- HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information see _API Signature_.
    In the context of the Mojaloop FSPIOP API, the value for FSPIOP-URI starts with the **_service_** in the URI value. For example, if a URL is http://stg-simulator.moja.live/payerfsp/participants/MSISDN/123456789, then the FSPIOP-URI value is “/participants/MSISDN/123456789”.| +|**FSPIOP- HTTP- Method**|**GET**|0..1|The **FSPIOP-HTTP-Method** header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information see API Signature.| + +**Table 1 -- HTTP request header fields that must be supported** + +[Table 2](#table-2) contains the HTTP request header fields that are optional to support by implementers of the API. + +###### Table 2 + +|Field|Example Values|Cardinality|Description| +|---|---|---|---| +|**traceparent**|**00-91e502e28cd723686e9940bd3f378f85-b0f903d000944947-01**|0..1|The traceparent header represents the incoming request in a tracing system in a common format. See _Distributed Tracing Support for OpenAPI Interoperability_ for more information.| +|**tracestate**|**banknrone=b0f903d0009449475**|0..1|Provides optional vendor-specific trace information, and support for multiple distributed traces. See _Distributed Tracing Support for OpenAPI Interoperability_ for more information.| + +**Table 2 -- HTTP request header fields that are optional to support** + +##### HTTP Response Header Fields + +[Table 3](#table-3) contains the HTTP response header fields that must be supported by implementers of the API. An implementation should also expect other standard and non-standard HTTP response header fields that are not listed here. + +###### Table 3 + +|Field|Example Values|Cardinality|Description| +|---|---|---|---| +|**Content-Length**|**3495**|0..1|The **Content-Length**16 header field indicates the anticipated size of the payload body. Only sent if there is a body.| +|**Content-Type**|**application/vnd.interoperability.resource+json;version=1.0**|1|The **Content-Type**17 header field indicates the specific version of the API used to send the payload body. See [Section 3.3.4.2](#3342-acceptable-version-requested-by-client) for more information.| + +**Table 3 -- HTTP response header fields** + +#### HTTP Methods + +The following HTTP methods, as defined in RFC 723118, are supported by the API: + +- **GET** -- The HTTP **GET** method is used from a client to request information about a previously-created object on a server. As all services in the API are asynchronous, the response to the **GET** method will not contain the requested object. The requested object will instead come as part of a callback using the HTTP **PUT** method. + +- **PUT** -- The HTTP **PUT** method is used as a callback to a previously sent HTTP **GET**, HTTP **POST** or HTTP **DELETE** method, sent from a server to its client. The callback will contain either: + + - Object information concerning a previously created object (HTTP **POST**) or sent information request (HTTP **GET**). + - Acknowledgement that whether an object was deleted (HTTP **DELETE**). + - Error information in case the HTTP **POST** or HTTP **GET** request failed to be processed on the server. + +- **POST** -- The HTTP **POST** method is used from a client to request an object to be created on the server. As all services in the API are asynchronous, the response to the **POST** method will not contain the created object. The created object will instead come as part of a callback using the HTTP **PUT** method. + +- **DELETE** -- The HTTP **DELETE** method is used from a client to request an object to be deleted on the server. The HTTP **DELETE** method should only be supported in a common Account Lookup System (ALS) for deleting information regarding a previously added Party (an account holder in an FSP), no other object types can be deleted. As all services in the API are asynchronous, the response to the HTTP **DELETE** method will not contain the final acknowledgement that the object was deleted or not; the final acknowledgement will come as a callback using the HTTP **PUT** method. + +- **PATCH** -- The HTTP **PATCH** method is used from a client to send a notification regarding an update of an existing object. As all services in the API are asynchronous, the response to the **POST** method will not contain the created object. This HTTP method does not result in a callback, as the **PATCH** request is used as a notification. + +
    + +#### HTTP Sequence Flow + +All the sequences and related services use an asynchronous call flow. No service supports a synchronous call flow. + +##### HTTP POST Call Flow + +[Figure 1](#figure-1) shows the normal API call flow for a request to create an object in a Peer FSP using HTTP **POST**. The service **_/service_** in the flow should be renamed to any of the services in [Table 6](#table-6) that support the HTTP **POST** method. + +###### Figure 1 + +![](../../assets/diagrams/sequence/figure1.svg) + +**Figure 1 -- HTTP POST call flow** + +##### HTTP GET Call Flow + +[Figure 2](#figure-2) shows the normal API call flow for a request to get information about an object in a Peer FSP using HTTP **GET**. The service **/service/**_{ID}_ in the flow should be renamed to any of the services in [Table 6](#table-6) that supports the HTTP **GET** method. + +###### Figure 2 + +![](../../assets/diagrams/sequence/figure2.svg) + + +**Figure 2 -- HTTP GET call flow** + +##### HTTP DELETE Call Flow + +[Figure 3](#figure-3) contains the normal API call flow to delete FSP information about a Party in an ALS using HTTP **DELETE**. The service **/service/**_{ID}_ in the flow should be renamed to any of the services in [Table 6](#table-6) that supports the HTTP DELETE method. HTTP DELETE is only supported in a common ALS, which is why the figure shows the ALS entity as a server only. + +###### Figure 3 + +![](../../assets/diagrams/sequence/figure3.svg) + + +**Figure 3 -- HTTP DELETE call flow** + +**Note:** It is also possible that requests to the ALS be routed through a Switch, or that the ALS and the Switch are the same server. + +##### HTTP PUT Call Flow** + +The HTTP **PUT** is always used as a callback to either a **POST** service request, a **GET** service request, or a **DELETE** service request. + +The call flow of a **PUT** request and response can be seen in [Figure 1](#figure-1), [Figure 2](#figure-2), and [Figure 3](#figure-3). + +##### HTTP PATCH Call Flow + +[Figure 4](#figure-4) shows an example call flow for a HTTP **PATCH**, which is used for sending a notification. First, an object is created using a **POST** service request from the Switch. The object is created in the FSP in a non-finalized state. The FSP then requests to get a notification regarding the finalized state from the Switch by sending the non-finalized state in the **PUT** callback. The Switch handles the callback and sends the notification regarding the finalized state in a **PATCH** service request. The only resource that supports updated object notification using HTTP **PATCH** is /transfers. + +###### Figure 4 + +![](../../assets/diagrams/sequence/figure4.svg) + + +**Figure 4 -- HTTP PATCH call flow** + +**Note:** It is also possible that requests to the ALS be routed through a Switch, or that the ALS and the Switch are the same server. + +##### Call Flow Routing using FSPIOP-Destination and FSPIOP-Source + +The non-standard HTTP header fields **FSPIOP-Destination** and **FSPIOP-Source** are used for routing and message signature verification purposes (see _API Signature_ for more information regarding signature verification). [Figure 5](#figure-5) shows how the header fields are used for routing in an abstract **POST /service** call flow, where the destination (Peer) FSP is known. + +###### Figure 5 + +![](../../assets/diagrams/sequence/figure5.svg) + + +**Figure 5 -- Using the customized HTTP header fields FSPIOP-Destination and FSPIOP-Source** + +For some services when a Switch is used, the destination FSP might be unknown. An example of this scenario is when an FSP sends a **GET /parties** to the Switch without knowing which Peer FSP that owns the Party (see [Section 6.3.2](#632-service-details) describing the scenario). **FSPIOP-Destination** will in that case be empty (or set to the Switch's ID) from the FSP, but will subsequently be set by the Switch to the correct Peer FSP. See [Figure 6](#figure-6) for an example describing the usage of **FSPIOP-Destination** and **FSPIOP-Source**. + +###### Figure 6 + +![](../../assets/diagrams/sequence/figure6.svg) + + +**Figure 6 -- Example scenario where FSPIOP-Destination is unknown to FSP** + +
    + +#### HTTP Response Status Codes + +The API supports the HTTP response status codes19 in [Table 4](#table-4) below: + +###### Table 4 + +|Status Code|Reason|Description| +|---|---|---| +|**200**|`OK`|Standard response for a successful request. Used in the API by the client as a response on a callback to mark the completion of an asynchronous service.| +|**202**|`Accepted`|The request has been accepted for future processing at the server, but the server cannot guarantee that the outcome of the request will be successful. Used in the API to acknowledge that the server has received an asynchronous request.| +|**400**| `Bad Request`|The application cannot process the request; for example, due to malformed syntax or the payload exceeded size restrictions.| +|**401**|`Unauthorized`|The request requires authentication in order to be processed.| +|**403**|`Forbidden`|The request was denied and will be denied in the future.| +|**404**|`Not Found`|The resource specified in the URI was not found.| +|**405**|`Method Not Allowed`|An unsupported HTTP method for the request was used; see Table 6 for information on which HTTP methods are allowed in which services.| +|**406**|`Not acceptable`|The server is not capable of generating content according to the Accept headers sent in the request. Used in the API to indicate that the server does not support the version that the client is requesting.| +|**501**|`Not Implemented`|The server does not support the requested service. The client should not retry.| +|**503**|`Service Unavailable`|The server is currently unavailable to accept any new service requests. This should be a temporary state, and the client should retry within a reasonable time frame.| + + **Table 4 -- HTTP response status codes supported in the API** + +Any HTTP status codes 3*xx*20 returned by the server should not be retried and require manual investigation. + +An implementation of the API should also be capable of handling other errors not defined above as the request could potentially be routed through proxy servers. + +As all requests in the API are asynchronous, additional HTTP error codes for server errors (error codes starting with 5*xx*21 that are *not* defined in [Table 4](#table-4)) are not used by the API itself. Any error on the server during actual processing of a request will be sent as part of an error callback to the client (see [Section 9.2](#92-error-in-server-during-processing-of-request)). + +
    + +##### Error Information in HTTP Response + +In addition to the HTTP response code, all HTTP error responses (4*xx* and 5*xx* status codes) can optionally contain an **ErrorInformation** element, defined in the section on [ErrorInformation](#errorinformation). This element should be used to give more detailed information to the client if possible. + +
    + +##### Idempotent Services in Server + +All services that support HTTP **GET** must be _idempotent_; that is, the same request can be sent from a client any number of times without changing the object on the server. The server is allowed to change the state of the object; for example, a transaction state can be changed, but the FSP sending the **GET** request cannot change the state. + +All services that support HTTP **POST** must be idempotent in case the client is sending the same service ID again; that is, the server must not create a new service object if a client sends the same **POST** request again. The reason behind this is to simplify the handling of resends during error-handling in a client; however, this creates some extra requirements of the server that receives the request. An example in which the same **POST** request is sent several times can be seen [here](#client-missing-response-from-server---using-resend-of-request). + +##### Duplicate Analysis in Server on Receiving a HTTP POST Request + +When a server receives a request from a client, the server should check to determine if there is an already-existing service object with the same ID; for example, if a client has previously sent the request **POST /transfers** with the identical **transferId**. If the object already exists, the server must check to determine if the parameters of the already-created object match the parameters from the new request. + +- If the previously-created object matches the parameter from the new request, the request should be assumed to be a resend from the client. + + - If the server has not finished processing the old request and therefore has not yet sent the callback to the client, this new request can be ignored, because a callback is about to be sent to the client. + - If the server has finished processing the old request and a callback has already been sent, a new callback should be sent to the client, similar to if a HTTP **GET** request had been sent. + +- If the previously-created object does not match the parameters from the new request, an error callback should be sent to the client explaining that an object with the provided ID already exists with conflicting parameters. + +To simplify duplicate analysis, it is recommended to create and store a hash value of all incoming **POST** requests on the server, so that it is easy to compare the hash value against later incoming **POST** requests. + +
    + +### API Versioning + +The strategy of the development of the API is to maintain backwards compatibility between the API and its resources and services to the maximum extent possible; however, changes to the API should be expected by implementing parties. Versioning of the API is specific to the API resource (for example, **/participants**, **/quotes**, **/transfers**). + +There are two types of API resource versions: _Minor_ versions, which are backwards-compatible, and _major_ versions, which are backwards-incompatible. + +- Whenever a change in this document defining the characteristics of the API is updated that in some way affects an API service, the affected resource will be updated to a new major or minor version (depending on whether the changes are backwards-compatible or not). + +- Whenever a change is made to a specific service in the API, a new version of the corresponding resource will be released. + +The format of the resource version is _x_._y_ where _x_ is the major version and _y_ is the minor version. Both major and minor versions are sequentially numbered. When a new major version of a service is released, the minor version is reset to **0**. The initial version of each resource in the API is **1.0**. + +#### Changes not Affecting the API Resource Version + +Some changes will not affect the API resource version; for example, if the order of parameters within a request or callback were to be changed. + +#### Minor API Resource Version + +The following list describes the changes that are considered backwards compatible if the change affects any API service connected to a resource. API implementers should implement their client/server in such a way that the API services automatically support these changes without breaking any functionality. + +- Optional input parameters such as query strings added in a request +- Optional parameters added in a request or a callback +- Error codes added + +These types of changes affect the minor API service version. + +#### Major API Resource Versions + +The following list describes the changes that are considered backwards-incompatible if the change affects any API service connected to a resource. API implementers do _not_ need to implement their client/server in such a way that it automatically supports these changes. + +- Mandatory parameters removed or added to a request or callback +- Optional parameters changed to mandatory in a request or callback +- Parameters renamed +- Data types changed +- Business logic of API resource or connected services changed +- API resource/service URIs changed + +These types of changes affect the major API service version. Please note that the list is not comprehensive; there might be other changes as well that could affect the major API service version. + +#### Version Negotiation between Client and Server + +The API supports basic version negotiation by using HTTP content negotiation between the server and the client. A client should send the API resource version that it would like to use in the **Accept** header to the server (see [HTTP Accept Header](#http-accept-header)). If the server supports that version, it should use that version in the callback (see [Acceptable Version Requested by Client](#acceptable-version-requested-by-client)). If the server does not support the requested version, the server should reply with HTTP status 40622 including a list of supported versions (see [Non-Acceptable Version Requested by Client](#non-acceptable-version-requested-by-client)). + +#### HTTP Accept Header + +See below for an example of a simplified HTTP request which only includes an **Accept** header23. The **Accept** header should be used from a client requesting a service from a server specifying a major version of the API service. The example in [Listing 3](#listing-3) should be interpreted as "I would like to use major version 1 of the API resource, but if that version is not supported by the server then give me the latest supported version". + +###### Listing 3 + +``` +POST /service HTTP/1.1 +Accept: application/vnd.interoperability.{resource}+json;version=1, +application/vnd.interoperability.{resource}+json + +{ + ... +} +``` + +**Listing 3 -- HTTP Accept header example, requesting version 1 or the latest supported version** + +Regarding the example in [Listing 3](#listing-3): + +- The **_POST /service_** should be changed to any HTTP method and related service or resource that is supported by the API (see [Table 6](#table-6)). +- The **Accept** header field is used to indicate the API resource version the client would like to use. If several versions are supported by the client, more than one version can be requested separated by a comma (**,**) as in the example above. + - The application type is always **application/vnd.interoperability.**_{resource}_, where _{resource}_ is the actual resource (for example, **participants** or **quotes**). + - The only data exchange format currently supported is **json**. + - If a client can use any minor version of a major version, only the major version should be sent; for example, **version=1** or **version=2**. + - If a client would like to use a specific minor version, this should be indicated by using the specific _major.minor_ version; for example, **version=1.2** or **version=2.8**. The use of a specific _major.minor_ version in the request should generally be avoided, as minor versions should be backwards-compatible. + +#### Acceptable Version Requested by Client + +If the server supports the API resource version requested by the client in the Accept Headers, it should use that version in the subsequent callback. The used _major.minor_ version should always be indicated in the **Content-Type** header by the server, even if the client only requested a major version of the API. See the example in [Listing 4](#listing-4), which indicates that version 1.0 is used by the server: + +###### Listing 4 + +``` +Content-Type: application/vnd.interoperability.resource+json;version=1.0 +``` + +**Listing 4 -- Content-Type HTTP header field example** + +#### Non-Acceptable Version Requested by Client + +If the server does not support the version requested by the client in the **Accept** header, the server should reply with HTTP status 406, which indicates that the requested version is not supported. + +**Note:** There is also a possibility that the information might be sent as part of an error callback to a client instead of directly in the response; for example, when the request is routed through a Switch which does support the requested version, but the destination FSP does not support the requested version. + +Along with HTTP status 406, the supported versions should be listed as part of the error message in the extensions list, using the major version number as _key_ and minor version number as _value_. Please see error information in the example in [Listing 5](#listing-5), describing the server's supported versions. The example should be interpreted as "I do not support the resource version that you requested, but I do support versions 1.0, 2.1, and 4.2". + +###### Listing 5 + +```json +{ + "errorInformation": { + "errorCode": "3001", + "errorDescription": "The Client requested an unsupported version, see extension list for supported version(s).", + "extensionList": { + "extension": + [ + { "key": "1", "value": "0"}, + { "key": "2", "value": "1"}, + { "key": "4", "value": "2"} + ] + } + } +} +``` + +**Listing 5 -- Example error message when server does not support the requested version** + + +
    + +## Interledger Protocol + +The current version of the API includes basic support for the Interledger Protocol (ILP), by defining a concrete implementation of the Interledger Payment Request protocol24 in API Resource [/quotes](#api-resource-quotes), and API Resource, [**/transfers**](#api-resource-transfers). + +### More Information + +This document contains ILP information that is relevant to the API. For more information about the ILP protocol, see the Interledger project website25, the Interledger Whitepaper26, and the Interledger architecture specification27. + +### Introduction to Interledger + +ILP is a standard for internetworking payment networks. In the same way that the Internet Protocol (IP) establishes a set of basic standards for the transmission and addressing of data packets between different data networks, ILP establishes a set of basic standards for the addressing of financial transactions and transfer of value between accounts on different payment networks. + +ILP is not a scheme. It is a set of standards that, if implemented by multiple payment schemes, will allow those schemes to be interoperable. Therefore, implementing ILP involves adapting an existing scheme to conform to those standards. Conformance means ensuring that transfers between accounts within the scheme are done in two phases (_reserve_ and _commit_) and defining a mapping between the accounts in the scheme and the global ILP Addressing scheme. This can be done by modifying the scheme itself, or by the entities that provide ILP-conformant access to the scheme using scheme adaptors. + +The basic prerequisites for an ILP payment are the Payee ILP address (see [ILP addressing](#ilp-addressing)) and the condition (see [Conditional Transfers](#conditional-transfers)). In the current version of the API, both these prerequisites should be returned by the Payee FSP during quoting API Resource [**/quotes**](#api-resource-quotes)) of the financial transaction. + +### ILP Addressing + +A key component of the ILP standard is the ILP addressing28 scheme. It is a hierarchical scheme that defines one or more addresses for every account on a ledger. + +[Table 5](#table-5) shows some examples of ILP addresses that could be used in different scenarios, for different accounts. Note that while the structure of addresses is standardized, the content is not, except for the first segment (up to the first period (**.**)). + +###### Table 5 + +|ILP Address|Description| +|---|---| +|**g.tz.fsp1.msisdn.1234567890**|A mobile money account at **FSP1** for the user with **MSISDN 1234567890**.| +|**g.pk.fsp2.ac03396c-4dba-4743**|A mobile money account at **FSP2** identified by an opaque account id.| +|**g.us.bank1.bob**|A bank account at **Bank1** for the user **bob**.| + +**Table 5 -- ILP address examples** + +The primary purpose of an ILP addresses is to identify an account in order to route a financial transaction to that account. + +**Note:** An ILP address should not be used for identifying a counterparty in the Interoperability API. See section on [Refund](#refund) regarding how to address a Party in the API. + +It is useful to think of ILP addresses as analogous to IP addresses. They are seldom, if ever, be seen by end users but are used by the systems involved in a financial transaction to identify an account and route the ILP payment. The design of the addressing scheme means that a single account will often have many ILP addresses. The system on which the account is maintained may track these or, if they are all derived from a common prefix, may track a subset only. + +### Conditional Transfers + +ILP depends on the concept of _conditional transfers_, in which all ledgers involved in a financial transaction from the Payer to the Payee can first reserve funds out of a Payer account and then later commit them to the Payee account. The transfer from the Payer to the Payee account is conditional on the presentation of a fulfilment that satisfies the condition attached to the original transfer request. + +To support conditional transfers for ILP, a ledger must support a transfer API that attaches a condition and an expiry to the transfer. The ledger must prepare the transfer by reserving the funds from the Payer account, and then wait for one of the following events to occur: + +- The fulfilment of the condition is submitted to the ledger and the funds are committed to the Payee account. + +- The expiry timeout is reached, or the financial transaction is rejected by the Payee or Payee FSP. The transfer is then aborted and the funds that were reserved from the Payer account are returned. + +When the fulfilment of a transfer is submitted to a ledger, the ledger must ensure that the fulfilment is valid for the condition that was attached to the original transfer request. If it is valid, the transfer is committed, otherwise it is rejected, and the transfer remains in a pending state until a valid fulfilment is submitted or the transfer expires. + +ILP supports a variety of conditions for performing a conditional payment, but implementers of the API should use the SHA-256 hash of a 32-byte pre-image. The condition attached to the transfer is the SHA-256 hash and the fulfilment of that condition is the pre-image. Therefore, if the condition attached to a transfer is a SHA-256 hash, then when a fulfilment is submitted for that transaction, the ledger will validate it by calculating the SHA-256 hash of the fulfilment and ensuring that the hash is equal to the condition. + +See [Interledger Payment Request](#interledger-payment-request) for concrete information on how to generate the fulfilment and the condition. + +### ILP Packet + +The ILP Packet is the mechanism used to package end-to-end data that can be passed in a hop-by-hop service. It is included as a field in hop-by-hop service calls and should not be modified by any intermediaries. The integrity of the ILP Packet is tightly bound to the integrity of the funds transfer, as the commit trigger (the fulfilment) is generated using a hash of the ILP Packet. + +The packet has a strictly defined binary format, because it may be passed through systems that are designed for high performance and volume. These intermediary systems must read the ILP Address and the amount from the packet headers, but do not need to interpret the **data** field in the ILP Packet (see [Listing 6](#listing-6)). Since the intermediary systems should not need to interpret the **data** field, the format of the field is not strictly defined in the ILP Packet definition. It is simply defined as a variable length octet string. [Interledger Payment Request](#interledger-payment-request) contains concrete information on how the ILP Packet is populated in the API. + +The ILP Packet is the common thread that connects all the individual ledger transfers that make up an end-to-end ILP payment. The packet is parsed by the Payee of the first transfer and used to determine where to make the next transfer, and for how much. It is attached to that transfer and parsed by the Payee of the next transfer, who again determines where to make the next transfer, and for how much. This process is repeated until the Payee of the transfer is the Payee in the end-to-end financial transaction, who fulfils the condition, and the transfers are committed in sequence starting with the last and ending with the first. + +The ILP Packet format is defined in ASN.129 (Abstract Syntax Notation One), shown in [Listing 6](#listing-6). The packet is encoded using the canonical Octet Encoding Rules. + +###### Listing 6 + +``` +InterledgerProtocolPaymentMessage ::= SEQUENCE { + -- Amount which must be received at the destination amount UInt64, + -- Destination ILP Address account Address, + -- Information for recipient (transport layer information) data OCTET STRING (SIZE (0..32767)), + -- Enable ASN.1 Extensibility + extensions SEQUENCE { + ... + } +} +``` + +**Listing 6 -- The ILP Packet format in ASN.1 format** + +**Note:** The only mandatory data elements in the ILP Packet are the amount to be transferred to the account of the Payee and the ILP Address of the Payee. + +
    + +## Common API Functionality + +This section describes the common functionality used by the API, including: + +- [Quoting](#quoting) +- [Party Addressing](#party-addressing) +- [Mapping of Use Cases to Transaction Types](#mapping-of-use-cases-to-transaction-types) + +### Quoting + +Quoting is the process that determines any fees and any commission required to perform a financial transaction between two FSPs. It is always initiated by the Payer FSP to the Payee FSP, which means that the quote flows in the same way as a financial transaction. + +Two different modes for quoting between FSPs are supported in the API: _Non-disclosing of fees_ and _Disclosing of fees_. + +- _Non-Disclosing of fees_ should be used when either the Payer FSP does not want to show the Payee FSP its fee structure, or when the Payer FSP would like to have more control of the fees paid by the Payer after quoting has been performed (the latter is only applicable for _Receive amount_; see next bullet list). + +- _Disclosing of fees_ can be used for use cases in which the Payee FSP wants to subsidize the transaction in some use cases; for example, Cash-In at another FSP's agent. + +The _Non-Disclosing of fees_ mode should be the standard supported way of quoting in most schemes. _Disclosing of fees_ might be used in some schemes; for example, a scheme in which a dynamic fee structure is used and an FSP wants the ability to subsidize the Cash-In use case based on the dynamic cost. + +In addition, the Payer can decide if the amount should be _Receive amount_ or _Send amount_. + +- _Send amount_ should be interpreted as the actual amount that should be deducted from the Payer's account, including any fees. + +- _Receive amount_ should be interpreted as the amount that should be added to the Payee's account, regardless of any interoperable transaction fees. The amount excludes possible internal Payee fees added by the Payee FSP. + +The Payee FSP can choose if the actual receive amount for the Payee should be sent or not in the callback to the Payer FSP. The actual Payee receive amount should include any Payee FSP internal fees on the Payee. + +All taxes are assumed to be FSP-internal, which means that taxes are not sent as part of the API. See [Tax Information](#tax-information) for more information regarding taxes. + +**Note:** Dynamic fees implemented using a Switch, or any other intermediary, are not supported in this version of the API. + + +#### Non-Disclosing of Fees + +The fees and commission payments related to an interoperable transaction when fees are not disclosed are shown in [Figure 7](#figure-7). The fees and commission that are directly part of the API are identified by green text. The FSP internal fees, commission, and bonus payments are identified by red text. These are not part of the transaction between a Payer FSP and a Payee FSP, but the amount that the Payee will receive after any FSP internal fees can be sent for information by the Payee FSP. + +For send amount (see [Non-Disclosing Send Amount](#non-disclosing-send-amount) for more information), internal Payer FSP fees on the Payer will affect the amount that is sent from the Payer FSP. For example, if the Payer FSP has a fee of 1 USD for a 100 USD interoperable financial transaction, 99 USD is sent from the Payer FSP. For receive amount (see [Non-Disclosing Receive Amount](#non-disclosing-receive-amount) for more information), internal Payer FSP fees on the Payer will not affect the amount that is sent from the Payer FSP. Internal Payer FSP bonus or commission on the Payer should be hidden regardless of send or receive amount. + +###### Figure 7 + +![Figure 7](../../assets/diagrams/images/figure7.svg) + +**Figure 7 -- Fees and commission related to interoperability when fees are not disclosed** + +See [Fee Types](#fee-types) for more information on the fee types sent in the Interoperability API. + +#### Non-Disclosing Receive Amount + +[Figure 8](#figure-8) shows an example of non-disclosing receive amount, in which the Payer would like the Payee to receive exactly 100 USD. For non-disclosing receive amount, the Payer FSP need not set the internal rating of the transaction until after the quote has been received because the Payee FSP knows what amount it will receive. + +In this example, the Payee FSP decides to give commission to the Payer FSP since funds are flowing to the Payee FSP, which will later be spent in some way; this results in a future fee income for the Payee FSP. The Payer FSP can then decide how much in fees should be taken from the Payer for cost-plus pricing. In this example, the Payer FSP would like to have 1 USD from the Payer, which means that the Payer FSP will earn 2 USD in total, as the Payer FSP will also receive 1 USD in FSP commission from the Payee FSP. + +###### Figure 8 + +![](../../assets/diagrams/sequence/figure8.svg) + + +**Figure 8 -- Example of non-disclosing receive amount** + +###### Figure 9 + +![Figure 9](../../assets/diagrams/images/figure9.svg) + +**Figure 9 -- Simplified view of money movement for non-disclosing receive amount example** + +To calculate the element **transferAmount** in the Payee FSP for a non-disclosing receive amount quote, the equation in [Listing 9](#listing-9) should be used, where _Transfer Amount_ is **transferAmount** in [Table 24](#table-24), _Quote_ _Amount_ is **amount** in [Table 23](#table-23), _Payee_ _FSP fee_ is **payeeFspFee** in [Table 24](#table-24), and Payee FSP commission is payeeFspCommission in [Table 24](#table-24). + +###### Listing 7 + +``` +Transfer amount = Quote Amount + Payee FSP Fee -- Payee FSP Commission +``` + +**Listing 7 -- Relation between transfer amount and quote amount for non-disclosing receive amount** + +#### Non-Disclosing Send Amount + +[Figure 10](#figure-10) shows an example of non-disclosing send amount, where the Payer would like to send 100 USD from the Payer's account. For non-disclosing send amount, the Payer FSP must rate (determine the internal transaction fees, commission, or both) the transaction before the quote is sent to the Payee FSP so that the Payee FSP knows how much in funds it will receive in the transaction. The actual amount withdrawn from the Payer's account is not disclosed, nor are the fees. + +In the example, the Payer FSP and the Payee FSP would like to have 1 USD each in fees so that the amount that will be received by the Payee is 98 USD. The actual amount that will be received by the Payee is in this example (not mandatory) returned in the callback to the Payer FSP, in the element **payeeReceiveAmount**. + +###### Figure 10 + +![](../../assets/diagrams/sequence/figure10.svg) + + +**Figure 10 -- Example of non-disclosing send amount** + +###### Figure 11 + +[Figure 11](#figure-11) shows a simplified view of the movement of money for the non-disclosing send amount example. + +![Figure 11](../../assets/diagrams/images/figure11.svg) + +**Figure 11 -- Simplified view of money movement for non-disclosing send amount example** + +To calculate the element **transferAmount** in the Payee FSP for a non-disclosing send amount quote, the equation in [Listing 8](#listing-8) should be used, where _Transfer Amount_ is **transferAmount** in [Table 24](#table-24), _Quote_ _Amount_ is **amount** in [Table 24](#table-24), and Payee FSP commission is **payeeFspCommission** in [Table 24](#table-24). + +###### Listing 8 + +``` +Transfer amount = Quote Amount -- Payee FSP Commission +``` + +**Listing 8 -- Relation between transfer amount and quote amount for non-disclosing send amount** + +The reason for a Payee FSP fee to be absent in the equation is that the Payer would like to send a certain amount from their account. The Payee will receive less funds instead of a fee being added on top of the amount. + +#### Disclosing of Fees + +The fees and commission payments related to an interoperable transaction when fees are disclosed can be seen in [Figure 11](#figure-11). The fees and commission that are directly related to the API are marked with green text. Internal Payee fees, bonus, and commission are marked with red text, these will have an implication on the amount that is sent by the Payer and received by the Payee. They are not part of the interoperable transaction between a Payer FSP and a Payee FSP, but the actual amount to be received by the Payee after internal Payee FSP fees have been deducted can be sent for information by the Payee FSP. + +When disclosing of fees are used, the FSP commission that the Payee FSP sends should subsidize the transaction cost for the Payer. This means that any FSP commission sent from the Payee FSP will effectively pay either a part or all of the fees that the Payer FSP has added to the transaction. If the FSP commission amount from the Payee FSP is higher than the actual transaction fees for the Payer, the excess amount should be handled as a fee paid by Payee FSP to Payer FSP. An example of excess FSP commission can be found [here](#excess-fsp-commission-example). + +###### Figure 12 + +![Figure 12](../../assets/diagrams/images/figure12.svg) + +**Figure 12 -- Fees and commission related to interoperability when fees +are disclosed** + +See [Fee Types](#fee-types) for more information on the fee types sent in the Interoperability API. + +#### Disclosing Receive Amount + +[Figure 13](#figure-13) shows an example of disclosing receive amount where the Payer would like the Payee to receive exactly 100 USD. For disclosing receive amount, the Payer FSP must internally rate the transaction before the quote request is sent to the Payee FSP, because the fees are disclosed. In this example, the Payer FSP would like to have 1 USD in fees from the Payer. The Payee FSP decides to give 1 USD in commission to subsidize the transaction, so that the transaction is free for the Payer. + +###### Figure 13 + +![](../../assets/diagrams/sequence/figure13.svg) + + +**Figure 13 -- Example of disclosing receive amount** + +[Figure 14](#figure-14) shows a simplified view of the movement of money for the disclosing receive amount example. + +###### Figure 14 + +![Figure 14](../../assets/diagrams/images/figure14.svg) + +**Figure 14 -- Simplified view of money movement for disclosing receive amount example** + +To calculate the element **transferAmount** in the Payee FSP for a disclosing receive amount quote, the equation in [Listing 9](#listing-9) should be used, where _Transfer Amount_ is **transferAmount** in [Table 24](#table-24), _Quote_ _Amount_ is **amount** in [Table 24](#table-24), _Payee_ _FSP fee_ is **payeeFspFee** in [Table 24](#table-24), and Payee FSP commission is **payeeFspCommission** in [Table 24](#table-24). + +###### Listing 9 + +``` +Transfer amount = Quote Amount + Payee FSP Fee -- Payee FSP Commission +``` + +**Listing 9 -- Relation between transfer amount and quote amount for disclosing receive amount** + +#### Disclosing Send Amount + +[Figure 15](#figure-15) shows an example of disclosing send amount, where the Payer would like to send 100 USD from the Payer's account to the Payee. For disclosing send amount, the Payer FSP must rate the transaction before the quote request is sent to the Payee FSP, because the fees are disclosed. In this example, the Payer FSP and the Payee FSP would like to have 1 USD each in fees from the Payer. + +###### Figure 15 + +![](../../assets/diagrams/sequence/figure15.svg) + + +**Figure 15 -- Example of disclosing send amount** + +###### Figure 16 + +[Figure 16](#figure-16) shows a simplified view of the movement of money for the disclosing send amount example. +![Figure 16](../../assets/diagrams/images/figure16.svg) + +**Figure 16 -- Simplified view of money movement for disclosing send amount example** + +To calculate the element **transferAmount** in the Payee FSP for a disclosing send amount quote, the equation in [Listing 10](#listing-10) should be used, where _Transfer Amount_ is **transferAmount** in [Table 24](#table-24), _Quote_ _Amount_ is **amount** in [Table 24](#table-24), _Payer_ _Fee_ is **fees** in [Table 24](#table-24), and Payee FSP commission is **payeeFspCommission** in [Table 24](#table-24). + +###### Listing 10 + +``` +If (Payer Fee <= Payee FSP Commission) + Transfer amount = Quote Amount +Else + Transfer amount = Quote Amount -- (Payer Fee - Payee FSP Commission) +``` + +**Listing 10 -- Relation between transfer amount and quote amount for disclosing send amount** + +The reason for a Payee FSP fee to be absent in the equation, is that the Payer would like to send a certain amount from their account. The Payee will receive less funds instead of a fee being added on top of the amount. + +#### Excess FSP Commission Example + +[Figure 17](#figure-17) shows an example of excess FSP commission using disclosing send amount, where the Payer would like to send 100 USD from the Payer's account to the Payee. For disclosing send amount, the Payer FSP must rate the transaction before the quote request is sent to the Payee FSP, because the fees are disclosed. In this excess commission example, the Payer FSP would like to have 1 USD in fees from the Payer, and the Payee FSP gives 3 USD in FSP commission. Out of the 3 USD in FSP commission, 1 USD should cover the Payer fees, and 2 USD is for the Payer FSP to keep. + +###### Figure 17 + +![](../../assets/diagrams/sequence/figure17.svg) + + +**Figure 17 -- Example of disclosing send amount** + +###### Figure 18 + +[Figure 18](#figure-18) shows a simplified view of the movement of money for the excess commission using disclosing send amount example. + +![Figure 18](../../assets/diagrams/images/figure18.svg) + +**Figure 18 -- Simplified view of money movement for excess commission using disclosing send amount example** + +#### Fee Types + +As can be seen in [Figure 7](#figure-7) and [Figure 12](#figure-12), there are two different fee and commission types in the Quote object between the + +FSPs: + +1. **Payee FSP fee** -- A transaction fee that the Payee FSP would like to have for the handling of the transaction. + +2. **Payee FSP commission** -- A commission that the Payee FSP would like to give to the Payer FSP (non-disclosing of fees) or subsidize the transaction by paying some or all fees from the Payer FSP (disclosing of fees). In case of excess FSP commission, the excess commission should be handled as the Payee FSP pays a fee to the Payer FSP, see [here](#excess-fsp-commission-example) for an example. + +
    + +#### Quote Equations + +This section contains useful equations for quoting that have not already been mentioned. + +#### Payee Receive Amount Relation to Transfer Amount + +The amount that the Payee should receive, excluding any internal Payee FSP fees, bonus, or commission, can be calculated by the Payer FSP using the equation in [Listing 11](#listing-11), where _Transfer Amount_ is **transferAmount** in [Table 24](#table-24), _Payee_ _FSP fee_ is **payeeFspFee** in [Table 24](#table-24), and Payee FSP commission is payeeFspCommission in [Table 24](#table-24). + +###### Listing 11 + +``` +Payee Receive Amount = Transfer Amount - Payee FSP Fee + Payee FSP Commission +``` + +**Listing 11 -- Relation between transfer amount and Payee receive amount** + +The Payee receive amount including any internal Payee FSP fees can optionally be sent by the Payee FSP to the Payer FSP in the Quote callback, see element **payeeReceiveAmount** in [Table 24](#table-24). +
    + +#### Tax Information + +Tax information is not sent in the API, as all taxes are assumed to be FSP-internal. The following sections contain details pertaining to common tax types related to the API. + +##### Tax on Agent Commission + +Tax on Agent Commission is tax for an _Agent_ as a result of the Agent receiving commission as a kind of income. Either the Agent or its FSP has a relation with the tax authority, depending on how the FSP deployment is set up. As all Agent commissions are FSP-internal, no information is sent through the Interoperability API regarding Tax on Agent Commission. + +##### Tax on FSP Internal Fee + +FSPs could be taxed on FSP internal fees that they receive from the transactions; for example, Payer fees to Payer FSP or Payee fees to Payee FSP. This tax should be handled internally within the FSP and collected by the FSPs because they receive a fee. + +##### Tax on Amount (Consumption tax) + +Examples of tax on amount are VAT (Value Added Tax) and Sales Tax. These types of taxes are typically paid by a Consumer to the Merchant as part of the price of goods, services, or both. It is the Merchant who has a relationship with the tax authority, and forwards the collected taxes to the tax authority. If any VAT or Sales Tax is applicable, a Merchant should include these taxes in the requested amount from the Consumer. The received amount in the Payee FSP should then be taxed accordingly. + +##### Tax on FSP Fee + +In the API, there is a possibility for a Payee FSP to add a fee that the Payer or Payer FSP should pay to the Payee FSP. The Payee FSP should handle the tax internally as normal when receiving a fee (if local taxes apply). This means that the Payee FSP should consider the tax on the fee while rating the financial transaction as part of the quote. The tax is not sent as part of the API. + +##### Tax on FSP Commission + +In the API, there is a possibility for a Payee FSP to add a commission to either subsidize the transaction (if disclosing of fees) or incentivize the Payer FSP (if non-disclosing of fees). + +###### Non-Disclosing of Fees + +For non-disclosing of fees, all FSP commission from the Payee FSP should be understood as the Payer FSP receiving a fee from the Payee FSP. The tax on the received fee should be handled internally within the Payer FSP, similar to the way it is handled in [Tax on FSP Internal Fee](#tax-on-fsp-internal-fee). + +###### Disclosing of Fees + +If the Payee FSP commission amount is less than or equal to the amount of transaction fees originating from the Payer FSP, then the Payee FSP commission should always be understood as being used for covering fees that the Payer would otherwise need to pay. + +If the Payee FSP commission amount is higher than the fees from the Payer FSP, the excess FSP commission should be handled similarly as [Non-Disclosing of Fees](#non-disclosing-of-fees). + +
    + +#### Examples for each Use Case + +This section contains one or more examples for each use case. + +#### P2P Transfer + +A P2P Transfer is typically a receive amount, where the Payer FSP is not disclosing any fees to the Payee FSP. See [Figure 19](#figure-19) for an example. In this example, the Payer would like the Payee to receive 100 USD. The Payee FSP decides to give FSP commission to the Payer FSP, because the Payee FSP will receive funds into the system. The Payer FSP would also like to have 1 USD in fee from the Payer, so the total fee that the Payer FSP will earn is 2 USD. 99 USD is transferred from the Payer FSP to the Payee FSP after deducting the FSP commission amount of 1 USD. + +###### Figure 19 + +![](../../assets/diagrams/sequence/figure19.svg) + + +**Figure 19 -- P2P Transfer example with receive amount** + +###### Simplified View of Money Movement + +###### Figure 20 + +See [Figure 20](#figure-20) for a highly simplified view of the movement of money for the P2P Transfer example. + +![Figure 20](../../assets/diagrams/images/figure20.svg) + +**Figure 20 -- Simplified view of the movement of money for the P2P Transfer example** + +#####Agent-Initiated Cash-In (Send amount) + +[Figure 21](#figure-21) shows an example of an Agent-Initiated Cash-In where send amount is used. The fees are disclosed because the Payee (the customer) would like to know the fees in advance of accepting the Cash-In. In the example, the Payee would like to Cash-In a 100 USD bill using an Agent (the Payer) in the Payer FSP system. The Payer FSP would like to have 2 USD in fees to cover the agent commission. The Payee FSP decides to subsidize the transaction by 2 USD by giving 2 USD in FSP commission to cover the Payer FSP fees. 98 USD is transferred from the Payer FSP to the Payee FSP after deducting the FSP commission amount of 2 USD. + +###### Figure 21 + +![](../../assets/diagrams/sequence/figure21.svg) + + +**Figure 21 -- Agent-Initiated Cash-In example with send amount** + +###### Simplified View of Money Movement + +See [Figure 22](#figure-22) for a highly simplified view of the movement of money for the Agent-initiated Cash-In example with send amount. + +###### Figure 22 + +![Figure 22](../../assets/diagrams/images/figure22.svg) + +**Figure 22 -- Simplified view of the movement of money for the Agent-initiated Cash-In with send amount example** + +##### Agent-Initiated Cash-In (Receive amount) + +[Figure 23](#figure-23) shows an example of Agent-Initiated Cash-In where receive amount is used. The fees are disclosed as the Payee (the Consumer) would like to know the fees in advance of accepting the Cash-In. In the example, the Payee would like to Cash-In so that they receive 100 USD using an Agent (the Payer) in the Payer FSP system. The Payer FSP would like to have 2 USD in fees to cover the agent commission; the Payee FSP decides to subsidize the transaction by 1 USD by giving 1 USD in FSP commission to cover 50% of the Payer FSP fees. 99 USD is transferred from the Payer FSP to the Payee FSP after deducting the FSP commission amount of 1 USD. + +###### Figure 23 + +![](../../assets/diagrams/sequence/figure23.svg) + + +**Figure 23 -- Agent-initiated Cash-In example with receive amount** + +##### Simplified View of Money Movement + +###### Figure 24 + +See [Figure 24](#figure-24) for a highly simplified view of the movement of money for the Agent-initiated Cash-In example with receive amount. + +![Figure 24](../../assets/diagrams/images/figure24.svg) + +**Figure 24 -- Simplified view of the movement of money for the Agent-initiated Cash-In with receive amount example** + +##### Customer-Initiated Merchant Payment + +A Customer-Initiated Merchant Payment is typically a receive amount, where the Payer FSP is not disclosing any fees to the Payee FSP. See [Figure 25](#figure-25) for an example. In the example, the Payer would like to buy goods or services worth 100 USD from a Merchant (the Payee) in the Payee FSP system. The Payee FSP would not like to charge any fees from the Payer, but 1 USD in an internal hidden fee from the Merchant. The Payer FSP wants 1 USD in fees from the Payer. 100 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 25 + +![](../../assets/diagrams/sequence/figure25.svg) + + +**Figure 25 -- Customer-Initiated Merchant Payment example** + +###### Simplified View of Money Movement + +See [Figure 26](#figure-26) for a highly simplified view of the movement of money for the Customer-Initiated Merchant Payment example. + +###### Figure 26 + +![Figure 26](../../assets/diagrams/images/figure26.svg) + +**Figure 26 -- Simplified view of the movement of money for the Customer-Initiated Merchant Payment example** + +##### Customer-Initiated Cash-Out (Receive amount) + +A Customer-Initiated Cash-Out is typically a receive amount, where the Payer FSP is not disclosing any fees to the Payee FSP. See [Figure 27](#figure-27) for an example. In the example, the Payer would like to Cash-Out so that they will receive 100 USD in cash. The Payee FSP would like to have 2 USD in fees to cover the agent commission and the Payer FSP would like to have 1 USD in fee. 102 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 27 + +![](../../assets/diagrams/sequence/figure27.svg) + + +**Figure 27 -- Customer-Initiated Cash-Out example (receive amount)** + +###### Simplified View of Money Movement + +See [Figure 28](#figure-28) for a highly simplified view of the movement of money for the Customer-Initiated Cash-Out with receive amount example. + +###### Figure 28 + +![Figure 28](../../assets/diagrams/images/figure28.svg) + +**Figure 28 -- Simplified view of the movement of money for the Customer-Initiated Cash-Out with receive amount example** + +##### Customer-Initiated Cash-Out (Send amount) + +A Customer-Initiated Cash-Out is typically a receive amount, this +example is shown in [Customer-Initiated Cash-Out](#customer-initiated-cash-out). This section shows an example where send amount is used instead; see [Figure 29](#figure-29) for an example. In the example, the Payer would like to Cash-Out 100 USD from their account. The Payee FSP would like to have 2 USD in fees to cover the agent commission and the Payer FSP would like to have 1 USD in fee. 99 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 29 + +![](../../assets/diagrams/sequence/figure29.svg) + + +**Figure 29 -- Customer-Initiated Cash-Out example (send amount)** + +###### Simplified View of Money Movement + +See [Figure 30](#figure-30) for a highly simplified view of the movement of money for the Customer-Initiated Cash-Out with send amount example. + +###### Figure 30 + +![Figure 30](../../assets/diagrams/images/figure30.svg) + +**Figure 30 -- Simplified view of the movement of money for the Customer-Initiated Cash-Out with send amount example** + +#### Agent-Initiated Cash-Out + +An Agent-Initiated Cash-Out is typically a receive amount, in which the Payer FSP does not disclose any fees to the Payee FSP. See [Figure 31](#Figure-31) for an example. In the example, the Payer would like to Cash-Out so that they will receive 100 USD in cash. The Payee FSP would like to have 2 USD in fees to cover the agent commission and the Payer FSP would like to have 1 USD in fee. 102 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 31 + +![](../../assets/diagrams/sequence/figure31.svg) + + +**Figure 31 -- Agent-Initiated Cash-Out example** + +######1 Simplified View of Money Movement + +See [Figure 32](#figure-32) for a highly simplified view of the movement of money for the Agent-Initiated Cash-Out example. + +###### Figure 32 + +![Figure 32](../../assets/diagrams/images/figure32.svg) + +**Figure 32 -- Simplified view of the movement of money for the Agent-Initiated Cash-Out example** + +##### Merchant-Initiated Merchant Payment + +A Merchant-Initiated Merchant Payment is typically a receive amount, where the Payer FSP is not disclosing any fees to the Payee FSP. See [Figure 33](#figure-33) for an example. In the example, the Payer would like to buy goods or services worth 100 USD from a Merchant (the Payee) in the Payee FSP system. The Payee FSP does not want any fees and the Payer FSP would like to have 1 USD in fee. 100 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 33 + +![](../../assets/diagrams/sequence/figure33.svg) + + +**Figure 33 -- Merchant-Initiated Merchant Payment example** + +###### Simplified View of Money Movement + +See [Figure 34](#figure-34) for a highly simplified view of the movement of money for the Merchant-Initiated Merchant Payment example. + +###### Figure 34 + +![Figure 34](../../assets/diagrams/images/figure34.svg) + +**Figure 34 -- Simplified view of the movement of money for the Merchant-Initiated Merchant Payment example** + +##### ATM-Initiated Cash-Out + +An ATM-Initiated Cash-Out is typically a receive amount, in which the Payer FSP is not disclosing any fees to the Payee FSP. See [Figure 35](#figure-35) for an example. In the example, the Payer would like to Cash-Out so that they will receive 100 USD in cash. The Payee FSP would like to have 1 USD in fees to cover any ATM fees and the Payer FSP would like to have 1 USD in fees. 101 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 35 + +![](../../assets/diagrams/sequence/figure35.svg) + + +**Figure 35 -- ATM-Initiated Cash-Out example** + +###### Simplified View of Money Movement + +See [Figure 36](#figure-36) for a highly simplified view of the movement of money for the ATM-Initiated Cash-Out example. + +###### Figure 36 + +![Figure 36](../../assets/diagrams/images/figure36.svg) + +**Figure 36 -- Simplified view of the movement of money for the ATM-Initiated Cash-Out example** + +##### Merchant-Initiated Merchant Payment authorized on POS + +A Merchant-Initiated Merchant Payment authorized on a POS device is typically a receive amount, in which the Payer FSP does not disclose any fees to the Payee FSP. See [Figure 37](#figure-37) for an example. In the example, the Payer would like to buy goods or services worth 100 USD from a Merchant (the Payee) in the Payee FSP system. The Payee FSP decides to give 1 USD in FSP commission, and the Payer FSP decides to use the FSP commission as the transaction fee. 100 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 37 + +![](../../assets/diagrams/sequence/figure37.svg) + + +**Figure 37 -- Merchant-Initiated Merchant Payment authorized on POS example** + +###### Simplified View of Money Movement + +See [Figure 38](#figure-38) for a highly simplified view of the movement of money for the Merchant-Initiated Merchant Payment authorized on POS example. + +###### Figure 38 + +![Figure 38](../../assets/diagrams/images/figure38.svg) + +**Figure 38 -- Simplified view of the movement of money for the +Merchant-Initiated Merchant Payment authorized on POS example** + +##### Refund + +[Figure 39](#figure-39) shows an example of a Refund transaction of the entire amount of the [Agent-Initiated Cash-In (Receive amount)](#agent-initiated-cash-in-receive-amount) example. + +###### Figure 39 + +![](../../assets/diagrams/sequence/figure39.svg) + + +**Figure 39 -- Refund example** + +#### 5.1.6.11.1 Simplified View of Money Movement + +See [Figure 40](#figure-40) for a highly simplified view of the movement of money for the Refund example. + +###### Figure 40 + +![Figure 40](../../assets/diagrams/images/figure40.svg) + +**Figure 40 -- Simplified view of the movement of money for the Refund example** + +
    + +### Party Addressing + +Both Parties in a financial transaction, (that is, the `Payer` and the `Payee`) are addressed in the API by a _Party ID Type_ (element [**PartyIdType**](#partyidtype-element)), a _Party ID_ ([**PartyIdentifier**](#partyidentifier-element)), and an optional _Party Sub ID or Type_ ([PartySubIdOrType](#partysubidortype-element)). Some Sub-Types are pre-defined in the API for personal identifiers ([PersonalIdentifierType](#personalidentifiertype-enum)); for example, for passport number or driver's license number. + +The following are basic examples of how the elements _Party ID Type_ and _Party ID_ can be used: +- To use mobile phone number **+123456789** as the counterparty in a financial transaction, set *Party ID Type* to **MSISDN** and _Party ID_ to **+123456789**. + - Example service to get FSP information: + + **GET /participants/MSISDN/+123456789** + +- To use the email **john\@doe.com** as the counterparty in a financial transaction, set _Party ID Type_ to **EMAIL**, and _Party_ _ID_ to **john\@doe.com**. + + - Example service to get FSP information: + + **GET /participants/EMAIL/john\@doe.com** + +- To use the IBAN account number **SE45 5000 0000 0583 9825 7466** as counterparty in a financial transaction, set _Party_ _ID Type_ to **IBAN**, and _Party ID_ to **SE4550000000058398257466** (should be entered without any whitespace). + + - Example service to get FSP information: + + **GET /participants/IBAN/SE4550000000058398257466** + +The following are more advanced examples of how the elements _Party ID +Type_, _Party ID_, and _Party Sub ID or Type_ can be used: + +- To use the person who has passport number **12345678** as counterparty in a financial transaction, set _Party ID Type_ to **PERSONAL\_ID**, _Party ID_ to **12345678**, and _Party Sub ID or Type_ to **PASSPORT**. + + - Example service to get FSP information: + + **GET /participants/PERSONAL\_ID/123456789/PASSPORT** + +- To use **employeeId1** working in the company **Shoe-company** as counterparty in a financial transaction, set _Party ID_ _Type_ to **BUSINESS**, _Party ID_ to **Shoe-company**, and _Party Sub ID or Type_ to **employeeId1**. + + - Example service to get FSP information: + + **GET /participants/BUSINESS/Shoe-company/employeeId1** + +**5.2.1 Restricted Characters in Party ID and Party Sub ID or Type** + +Because the _Party ID_ and the _Party Sub ID or Type_ are used as part of the URI (see [URI Syntax](#uri-syntax)), some restrictions exist on the ID: + +- Forward slash (**/**) is not allowed in the ID, as it is used by the [Path](#path), to indicate a separation of the Path. + +- Question mark (**?**) is not allowed in the ID, as it is used to indicate the [Query](#query)) part of the URI. + +
    + +### Mapping of Use Cases to Transaction Types + +This section contains information about how to map the currently supported non-bulk use cases in the API to the complex type [**TransactionType**](#transactiontype)), using the elements [TransactionScenario](#transactionscenario)), and [TransactionInitiator](#transactioninitiator)). + +For more information regarding these use cases, see _API Use Cases_. + +#### P2P Transfer + +To perform a P2P Transfer, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **TRANSFER** +- [**TransactionInitiator**](#transactioninitiator) to **PAYER** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **CONSUMER**. + +#### Agent-Initiated Cash In + +To perform an Agent-Initiated Cash In, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **DEPOSIT** +- [**TransactionInitiator**](#transactioninitiator) to **PAYER** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **AGENT**. + +#### Agent-Initiated Cash Out + +To perform an Agent-Initiated Cash Out, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **WITHDRAWAL** +- [**TransactionInitiator**](#transactioninitiator) to **PAYEE** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **AGENT** + +#### Agent-Initiated Cash Out Authorized on POS + +To perform an Agent-Initiated Cash Out on POS, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **WITHDRAWAL** +- [**TransactionInitiator**](#transactioninitiator) to **PAYEE** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **AGENT** + + +#### Customer-Initiated Cash Out + +To perform a Customer-Initiated Cash Out, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **WITHDRAWAL** +- [**TransactionInitiator**](#transactioninitiator) to **PAYER** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **CONSUMER** + +#### Customer-Initiated Merchant Payment + +To perform a Customer-Initiated Merchant Payment, set elements as +follows: + +- [**TransactionScenario**](#transactionscenario) to **PAYMENT** +- [**TransactionInitiator**](#transactioninitiator) to **PAYER** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **CONSUMER**. + +#### Merchant-Initiated Merchant Payment + +To perform a Merchant-Initiated Merchant Payment, set elements as +follows: + +- [**TransactionScenario**](#transactionscenario) to **PAYMENT** +- [**TransactionInitiator**](#transactioninitiator) to **PAYEE** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **BUSINESS** + +#### Merchant-Initiated Merchant Payment Authorized on POS + +To perform a Merchant-Initiated Merchant Payment, set elements as +follows: + +- [**TransactionScenario**](#transactionscenario) to **PAYMENT** +- [**TransactionInitiator**](#transactioninitiator) to **PAYEE** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **DEVICE** + +#### ATM-Initiated Cash Out + +To perform an ATM-Initiated Cash Out, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **WITHDRAWAL** +- [**TransactionInitiator**](#transactioninitiator) to **PAYEE** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **DEVICE** + +#### Refund + +To perform a Refund, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **REFUND** +- [**TransactionInitiator**](#transactioninitiator) to **PAYER** +- [**TransactionInitiatorType**](#transactioninitiatortype) depends on the initiator of the Refund. + +Additionally, the [Refund](#refund) complex type must be populated with the transaction ID of the original transaction that is to be refunded. + +
    + +## API Services + +This section introduces and details all services that the API supports for each resource and HTTP method. Each API resource and service is also mapped to a logical API resource and service described in [Generic Transaction Patterns](../generic-transaction-patterns). + + +### High Level API Services + +On a high level, the API can be used to perform the following actions: + +- **Lookup Participant Information** -- Find out in which FSP the counterparty in a financial transaction is located. + + - Use the services provided by the API resource **/participants**. + +- **Lookup Party Information** -- Get information about the counterparty in a financial transaction. + + - Use the services provided by the API resource **/parties**. + +- **Perform Transaction Request** -- Request that a Payer transfer electronic funds to the Payee, at the request of the Payee. The Payer can approve or reject the request from the Payee. An approval of the request will initiate the actual financial transaction. + + - Use the services provided by the API resource **/transactionRequests**. + +- **Calculate Quote** -- Calculate all parts of a transaction that will influence the transaction amount; that is, fees and FSP commission. + + - Use the services provided by the API resource **/quotes** for a single transaction quote; that is, one Payer to one Payee. + - Use the services provided by the API resource **/bulkQuotes** for a bulk transaction quote; that is, one Payer to multiple Payees. + +- **Perform Authorization** -- Request the Payer to enter the applicable credentials when they have initiated the transaction from a POS, ATM, or similar device in the Payee FSP system. + + - Use the services provided by the API resource **/authorizations**. + +- **Perform Transfer** -- Perform the actual financial transaction by transferring the electronic funds from the Payer to the Payee, possibly through intermediary ledgers. + + - Use the services provided by the API resource **/transfers** for single transaction; that is, one Payer to one Payee. + - Use the services provided by the API resource **/bulkTransfers** for bulk transaction; that is, one Payer to multiple Payees. + +- **Retrieve Transaction Information** -- Get information related to the financial transaction; for example, a possible created token on successful financial transaction. + + - Use the services provided by the API resource **/transactions**. + + +#### Supported API services + +[Table 6](#table-6) includes high-level descriptions of the services that the API provides. For more detailed information, see the sections that follow. + +###### Table 6 + +|URI|HTTP method GET|HTTP method PUT|HTTP method POST|HTTP method DELETE|HTTP method PATCH| +|---|---|---|---|---|---| +|**/participants**|Not supported|Not supported|Request that an ALS create FSP information regarding the parties provided in the body or, if the information already exists, request that the ALS update it|Not supported|Not Supported| +|**/participants/**_{ID}_|Not supported|Callback to inform a Peer FSP about a previously-created list of parties.|Not supported|Not Supported|Not Supported| +|**/participants/**_{Type}_/_{ID}_ Alternative: **/participants/**_{Type}_/_{ID}_/_{SubId}_|Get FSP information regarding a Party from either a Peer FSP or an ALS.|Callback to inform a Peer FSP about the requested or created FSP information.|Request an ALS to create FSP information regarding a Party or, if the information already exists, request that the ALS update it|Request that an ALS delete FSP information regarding a Party.|Not Supported| +|**/parties/**_{Type}_/_{ID}_ Alternative: **/parties/**_{Type}_/_{ID}_/_{SubId}_|Get information regarding a Party from a Peer FSP.|Callback to inform a Peer FSP about the requested information about the Party.|Not supported|Not support|Not Supported| +|**/transactionRequests**|Not supported|Not supported|Request a Peer FSP to ask a Payer for approval to transfer funds to a Payee. The Payer can either reject or approve the request.|Not supported|Not Supported| +|**/transactionRequests/**_{ID}_|Get information about a previously-sent transaction request.|Callback to inform a Peer FSP about a previously-sent transaction request.|Not supported|Not supported|Not Supported| +|**/quotes**|Not supported|Not supported|Request that a Peer FSP create a new quote for performing a transaction.|Not supported|Not Supported| +|**/quotes/**_{ID}_|Get information about a previously-requested quote.|Callback to inform a Peer FSP about a previously- requested quote.|Not supported|Not supported|Not Supported| +|**/authorizations/**_{ID}_|Get authorization for a transaction from the Payer whom is interacting with the Payee FSP system.|Callback to inform Payer FSP regarding authorization information.|Not supported|Not supported|Not Supported| +|**/transfers**|Not supported|Not supported|Request a Peer FSP to perform the transfer of funds related to a transaction.|Not supported|Not Supported| +|**/transfers/**_{ID}_|Get information about a previously-performed transfer.|Callback to inform a Peer FSP about a previously-performed transfer.|Not supported|Not supported|Commit notification to Payee FSP| +|**/transactions/**_{ID}_|Get information about a previously-performed transaction.|Callback to inform a Peer FSP about a previously-performed transaction.|Not supported|Not supported|Not Supported| +|**/bulkQuotes**|Not supported|Not supported|Request that a Peer FSP create a new quote for performing a bulk transaction.|Not supported|Not Supported| +|**/bulkQuotes/**_{ID}_|Get information about a previously-requested bulk transaction quote.|Callback to inform a Peer FSP about a previously-requested bulk transaction quote.|Not supported|Not supported|Not Supported| +|**/bulkTransfers**|Not supported|Not supported|Request that a Peer FSP create a bulk transfer.|Not supported|Not Supported| +|**/bulkTransfers/**_{ID}_|Get information about a previously-sent bulk transfer.|Callback to inform a Peer FSP about a previously-sent bulk transfer.|Not supported|Not supported|Not supported| + +**Table 6 – API-supported services** + +#### Current Resource Versions + +[Table 7](#table-7) contains the version for each resource that this document version describes. + +###### Table 7 + +|Resource|Current Version|Last Updated| +|---|---|---| +|/participants|1.1|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/parties|1.1|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/transactionRequests|1.1|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/quotes|1.1|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/authorizations|1.0|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/transfers|1.1|Added possible commit notification using PATCH /transfers/``. The process of using commit notifications is described in Section 6.7.2.6. The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/transactions|1.0|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/bulkQuotes|1.1|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/bulkTransfers|1.1|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| + +**Table 7 – Current resource versions** + +
    + +### API Resource /participants + +This section defines the logical API resource **Participants**, described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-participants). + +The services provided by the resource **/participants** are primarily used for determining in which FSP a counterparty in a financial transaction is located. Depending on the scheme, the services should be supported, at a minimum, by either the individual FSPs or a common service. + +If a common service (for example, an ALS) is supported in the scheme, the services provided by the resource **/participants** can also be used by the FSPs for adding and deleting information in that system. + +#### Resource Version History + +[Table 8](#table-8) contains a description of each different version of the **/participants** resource. + +###### Table 8 + +|Version|Date|Description| +|---|---|---| +|1.0|2018-03-13|Initial version| +|1.1|2020-05-19|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated. +For consistency, the data model for the **POST /participants/**_{Type}/{ID}_ and **POST /participants/**_{Type}/{ID}/{SubId}_ calls in Table 10 has been updated to include the optional ExtensionList element as well.| + +**Table 8 – Version history for resource /participants** + +#### Service Details + +Different models are used for account lookup, depending on whether an ALS exists. The following sections describe each model in turn. + +#### No Common Account Lookup System + +[Figure 41](#figure-41) shows how an account lookup can be performed if there is no common ALS in a scheme. The process is to ask the other FSPs (in sequence) if they "own" the Party with the provided identity and type pair until the Party can be found. + +If this model is used, all FSPs should support being both client and server of the different HTTP **GET** services under the **/participants** resource. The HTTP **POST** or HTTP **DELETE** services under the **/participants** resource should not be used, as the FSPs are directly used for retrieving the information (instead of a common ALS). + +###### Figure 41 + +![](../../assets/diagrams/sequence/figure41.svg) + + +**Figure 41 -- How to use the services provided by /participants if there is no common Account Lookup System** + +#### Common Account Lookup System + +[Figure 42](#figure-42) shows how an account lookup can be performed if there is a common ALS in a scheme. The process is to ask the common Account Lookup service which FSP owns the Party with the provided identity. The common service is depicted as "Account Lookup" in the flows; this service could either be implemented by the switch or as a separate service, depending on the setup in the market. + +The FSPs do not need to support the server side of the different HTTP **GET** services under the **/participants** resource; the server side of the service should be handled by the ALS. Instead, the FSPs (clients) should provide FSP information regarding its accounts and account holders (parties) to the ALS (server) using the HTTP **POST** (to create or update FSP information, see [POST /participants](#post-participants) and [POST /participants/_{Type}_/_{ID}_](#post-participants-type-id)) and HTTP **DELETE** (to delete existing FSP information, see [DELETE /participants/_{Type}_/_{ID}_](#delete-participantstypeid)) methods. + +###### Figure 42 + +![](../../assets/diagrams/sequence/figure42.svg) + + +**Figure 42 -- How to use the services provided by /participants if there is a common Account Lookup System** + +#### Requests + +This section describes the services that can be requested by a client on the resource **/participants**. + +##### GET /participants/_{Type}_/_{ID}_ + +Alternative URI: **GET /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_ + +Logical API service: [Lookup Participant Information](../generic-transaction-patterns#lookup-participant-information) + +The HTTP request **GET /participants/**_{Type}_**/**_{ID}_ (or **GET /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_) is used to find out in which FSP the requested Party, defined by _{Type}_, _{ID}_ and optionally _{SubId}_, is located (for example, **GET** **/participants/MSISDN/123456789**, or **GET /participants/BUSINESS/shoecompany/employee1**). See [Refund](#refund) for more information regarding addressing of a Party. + +This HTTP request should support a query string (see [URI Syntax](#uri-syntax) for more information regarding URI syntax) for filtering of currency. To use filtering of currency, the HTTP request **GET /participants/**_{Type}_**/**_{ID}_**?currency=**_XYZ_ should be used, where _XYZ_ is the requested currency. + +Callback and data model information for **GET /participants/**_{Type}_**/**_{ID}_ (alternative **GET /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_): + +- Callback - [**PUT /participants/**_{Type}_/_{ID}_](#put-participants-type-id) +- Error Callback - [**PUT /participants/**_{Type}_/_{ID}_**/error**](#put-participants-type-iderror) +- Data Model -- Empty body + +##### POST /participants + +Alternative URI: N/A + +Logical API service: [Create Bulk Participant Information](../generic-transaction-patterns#create-bulk-participant-information) + +The HTTP request **POST /participants** is used to create information on the server regarding the provided list of identities. This request should be used for bulk creation of FSP information for more than one Party. The optional currency parameter should indicate that each provided Party supports the currency. + +Callback and data model information for **POST /participants**: + +- Callback -- [**PUT /participants/**_{ID}_](#put-participants-type-id) +- Error Callback -- [**PUT /participants/**_{ID}_ **/error**](#put-participants-type-iderror) +- Data Model -- See [Table 9](#table-9) + +###### Table 9 + +|Name|Cardinality|Type|Description| +|---|---|---|---| +|**requestId**|1|CorrelationId|The ID of the request, decided by the client. Used for identification of the callback from the server.| +|**partyList**|1..10000|PartyIdInfo|List of PartyIdInfo elements that the client would like to update or create FSP information about.| +|**currency**|0..1|Currency|Indicate that the provided Currency is supported by each PartyIdInfo in the list.| + +**Table 9 - POST /participants data model** + +##### POST /participants/_{Type}_/_{ID}_ + +Alternative URI: **POST /participants/**_{Type}_/_{ID}_/_{SubId}_ + +Logical API service: [Create Participant Information](../generic-transaction-patterns#create-participant-information) + +The HTTP request **POST /participants/**_{Type}_**/**_{ID}_ (or **POST /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_) is used to create information on the server regarding the provided identity, defined by _{Type}_, _{ID}_, and optionally _{SubId}_ (for example, **POST** **/participants/MSISDN/123456789** or **POST /participants/BUSINESS/shoecompany/employee1**). See [Refund](#refund) for more information regarding addressing of a Party. + +Callback and data model information for **POST /participants**/_{Type}_**/**_{ID}_ (alternative **POST** **/participants/**_{Type}_**/**_{ID}_**/**_{SubId}_): + +- Callback -- [**PUT /participants/**_{Type}_**/**_{ID}_](#put-participants-type-id) +- Error Callback -- [**PUT /participants/**_{Type}_**/**_{ID}_**/error**](#put-participants-type-iderror) +- Data Model -- See [Table 10](#table-10) + +###### Table 10 + +|Name|Cardinality|Type|Description| +|---|---|---|---| +|**fspId**|1|FspId|FSP Identifier that the Party belongs to.| +|**currency**|0..1|Currency|Indicate that the provided Currency is supported by the Party.| +|**extensionList**| 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 10 -- POST /participants/_{Type}_/_{ID}_ (alternative POST /participants/_{Type}_/_{ID}_/_{SubId}_) data model** + +##### DELETE /participants/_{Type}_/_{ID}_ + +Alternative URI: **DELETE /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_ + +Logical API service: [Delete Participant Information](../generic-transaction-patterns#delete-participant-information) + +The HTTP request **DELETE /participants/**_{Type}_**/**_{ID}_ (or **DELETE /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_) is used to delete information on the server regarding the provided identity, defined by _{Type}_ and _{ID}_) (for example, **DELETE** **/participants/MSISDN/123456789**), and optionally _{SubId}_. See [Refund](#refund) for more information regarding addressing of a Party. + +This HTTP request should support a query string (see [URI Syntax](#uri-syntax) for more information regarding URI syntax) to delete FSP information regarding a specific currency only. To delete a specific currency only, the HTTP request **DELETE** **/participants/**_{Type}_**/**_{ID}_**?currency**_=XYZ_ should be used, where _XYZ_ is the requested currency. + +**Note:** The ALS should verify that it is the Party's current FSP that is deleting the FSP information. + +Callback and data model information for **DELETE /participants/**_{Type}_**/**_{ID}_ (alternative **GET** **/participants/**_{Type}_**/**_{ID}_**/**_{SubId}_): + +- Callback -- [**PUT /participants/**_{Type}_**/**_{ID}_](#put-participants-type-id) + +- Error Callback -- [**PUT /participants/**_{Type}_**/**_{ID}_**/error**](#put-participants-type-iderror) + +- Data Model -- Empty body + +
    + +#### Callbacks + +This section describes the callbacks used by the server for services provided by the resource **/participants**. + +##### PUT /participants/_{Type}_/_{ID}_ + +Alternative URI: **PUT /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_ + +Logical API service: [Return Participant Information](../generic-transaction-patterns#return-participant-information) + +The callback **PUT /participants/**_{Type}_**/**_{ID}_ (or **PUT /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_) is used to inform the client of a successful result of the lookup, creation, or deletion of the FSP information related to the Party. If the FSP information is deleted, the **fspId** element should be empty; otherwise the element should include the FSP information for the Party. + +See [Table 11](#table-11) for data model. + +###### Table 11 + +|Name|Cardinality|Type|Description| +|---|---|---|---| +|**fspId**|0..1|FspId|FSP Identifier that the Party belongs to.| + +**Table 11 -- PUT /participants/_{Type}_/_{ID}_ (alternative PUT /participants/_{Type}_/_{ID}_/_{SubId}_) data model** + +##### PUT /participants/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Bulk Participant Information](../generic-transaction-patterns#return-bulk-participant-information) + +The callback **PUT /participants/**_{ID}_ is used to inform the client of the result of the creation of the provided list of identities. + +See [Table 12](#table-12) for data model. + +###### Table 12 + +|Name|Cardinality|Type|Description| +|---|---|---|---| +|**partyList**|1..10000|PartyResults|List of PartyResult elements that were either created or failed to be created.| +|**currency**|0..1|Currency|Indicate that the provided Currency was set to be supported by each successfully added PartyIdInfo.| + +**Table 12 -- PUT /participants/_{ID}_ data model** + +####Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/participants**. + +##### PUT /participants/_{Type}_/_{ID}_/error + +Alternative URI: **PUT /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_**/error** + +Logical API service: [Return Participant Information Error](../generic-transaction-patterns#return-participant-information-error) + +If the server is unable to find, create or delete the associated FSP of the provided identity, or another processing error occurred, the error callback **PUT /participants/**_{Type}_**/**_{ID}_**/error** (or **PUT /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_**/error**) is used. See [Table 13](#table-13) for data model. + +###### Table 13 + +|Name|Cardinality|Type|Description| +|---|---|---|---| +|**errorInformation**|1|ErrorInformation|Error code, category description.| + +**Table 13 -- PUT /participants/_{Type}_/_{ID}_/error (alternative PUT /participants/_{Type}_/_{ID}_/_{SubId}_/error) data model** + +##### PUT /participants/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Return Bulk Participant Information Error](../generic-transaction-patterns#return-bulk-participant-information-error) + +If there is an error during FSP information creation on the server, the error callback **PUT /participants/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the **requestId** (see [Table 9](#table-9)) that was used for the creation of the participant information. See [Table 14](#table-14) for data model. + +###### Table 14 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **error Information** | 1 | ErrorInformation | Error code, category description. | + +**Table 14 -- PUT /participants/_{ID}_/error data model** + +#### States + +There are no states defined for the **/participants** resource; either the server has FSP information regarding the requested identity or it does not. + +
    + +### API Resource /parties + +This section defines the logical API resource **Parties,** described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-parties). + +The services provided by the resource **/parties** is used for finding out information regarding a Party in a Peer FSP. + +#### Resource Version History + +[Table 15](#table-15) contains a description of each different version of the **/parties** resource. + +###### Table 15 + +|Version|Date|Description| +|---|---|---| +|1.0|2018-03-13|Initial version| +|1.1|2020-05-19|The data model is updated to add an optional ExtensioinList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| + +**Table 15 – Version history for resource /parties** + +#### Service Details + +[Figure 43](#figure-43) contains an example process for the [**/parties**](../generic-transaction-patterns#api-resource-parties) resource. Alternative deployments could also exist; for example, a deployment in which the Switch and the ALS are in the same server, or one in which the User's FSP asks FSP 1 directly for information regarding the Party. + +###### Figure 43 + +![](../../assets/diagrams/sequence/figure43.svg) + + +**Figure 43 -- Example process for /parties resource** + +
    + +#### Requests + +This section describes the services that can be requested by a client in the API on the resource **/parties**. + +##### GET /parties/_{Type}_/_{ID}_ + +Alternative URI: **GET /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_ + +Logical API service: [Lookup Party Information](../generic-transaction-patterns#lookup-party-information) + +The HTTP request **GET /parties/**_{Type}_**/**_{ID}_ (or **GET /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_) is used to lookup information regarding the requested Party, defined by _{Type}_, _{ID}_ and optionally _{SubId}_ (for example, **GET /parties/MSISDN/123456789**, or **GET** **/parties/BUSINESS/shoecompany/employee1**). See [Refund](#refund) for more information regarding addressing of a Party. + +Callback and data model information for **GET /parties/**_{Type}_**/**_{ID}_ (alternative **GET /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_): + +- Callback - [**PUT /parties/**_{Type}_**/**_{ID}_](#put-partiestypeid) +- Error Callback - [**PUT /parties/**_{Type}_**/**_{ID}_**/error**](#put-partiestypeiderror) +- Data Model -- Empty body + +
    + +#### Callbacks + +This section describes the callbacks that are used by the server for services provided by the resource **/parties**. + +##### PUT /parties/_{Type}_/_{ID}_ + +Alternative URI: **PUT /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_ + +Logical API service: [Return Party Information](../generic-transaction-patterns#return-party-information) + +The callback **PUT /parties/**_{Type}_**/**_{ID}_ (or **PUT /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_) is used to inform the client of a successful result of the Party information lookup. See [Table 16](#table-16) for data model. + +###### Table 16 + +| **Name** | **Cardinal** | **Type** | **Description** | +| --- | --- | --- | --- | +| **party** | 1 | Party | Information regarding the requested Party. | + +**Table 16 -- PUT /parties/_{Type}_/_{ID}_ (alternative PUT /parties/_{Type}_/_{ID}_/_{SubId}_) data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/parties**. + +#### PUT /parties/_{Type}_/_{ID}_/error + +Alternative URI: **PUT /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_**/error** + +Logical API service: [Return Party Information Error](../generic-transaction-patterns#return-party-information-error) + +If the server is unable to find Party information of the provided identity, or another processing error occurred, the error callback **PUT /parties/**_{Type}_**/**_{ID}_**/error** (or **PUT /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_**/error**) is used. See [Table 17](#table-17) for data model. + +###### Table 17 + +| **Name** | **Cardinality** | **Type** | **Description** | +|---|---|---|---| +| **errorInformation** | 1 | ErrorInformation | Error code, category description. | + +**Table 17 -- PUT /parties/_{Type}_/_{ID}_/error (alternative PUT /parties/_{Type}_/_{ID}_/_{SubId}_/error) data model** + +#### States + +There are no states defined for the **/parties** resource; either an FSP has information regarding the requested identity or it does not. + +
    + +### API Resource /transactionRequests + +This section defines the logical API resource **Transaction Requests**, described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-transaction-requests). + +The primary service that the API resource **/transactionRequests** enables is for a Payee to request a Payer to transfer electronic funds to the Payee. The Payer can either approve or reject the request from the Payee. The decision by the Payer could be made programmatically if: + +- The Payee is trusted (that is, the Payer has pre-approved the Payee in the Payer FSP), or + +- An authorization value - that is, a _one-time password_ (_OTP_) is correctly validated using the API Resource **/authorizations**, see [Section 6.6](#66-api-resource-authorizations). + +Alternatively, the Payer could make the decision manually. + +#### Resource Version History + +[Table 18](#table-18) contains a description of each different version of the **/transactionRequests** resource. + +###### Table 18 + +|Version|Date|Description| +|---|---|---| +|1.0|2018-03-13|Initial version| +|1.1|2020-05-19|The data model is updated to add an optional ExtensioinList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| + +**Table 18 – Version history for resource /transactionRequests** + +#### Service Details + +[Figure 44](#figure-44) shows how the request transaction process works, using the **/transactionRequests** resource. The approval or rejection is not shown in the figure. A rejection is a callback **PUT /transactionRequests/**_{ID}_ with a **REJECTED** state, similar to the callback in the figure with the **RECEIVED** state, as described in [Section 6.4.2.1](#6421-payer-rejected-transaction-request). An approval by the Payer is not sent as a callback; instead a quote and transfer are sent containing a reference to the transaction request. + +###### Figure 44 + +![](../../assets/diagrams/sequence/figure44.svg) + +**Figure 44 -- How to use the /transactionRequests service** + +##### Payer Rejected Transaction Request + +[Figure 45](#figure-45) shows the process by which a transaction request is rejected. Possible reasons for rejection include: + +- The Payer rejected the request manually. +- An automatic limit was exceeded. +- The Payer entered an OTP incorrectly more than the allowed number of times. + +###### Figure 45 + +![](../../assets/diagrams/sequence/figure45.svg) + +**Figure 45 -- Example process in which a transaction request is rejected** + +#### Requests + +This section describes the services that a client can request on the resource **/transactionRequests**. + +##### GET /transactionRequests/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Retrieve Transaction Request Information](../generic-transaction-patterns#retrieve-transaction-request-information) + +The HTTP request **GET /transactionRequests/**_{ID}_ is used to get information regarding a previously-created or requested transaction request. The _{ID}_ in the URI should contain the **transactionRequestId** (see [Table 15](#table-15)) that was used for the creation of the transaction request. + +Callback and data model information for **GET /transactionRequests/**_{ID}_: + +- Callback - [**PUT /transactionRequests/**_{ID}_](#put-transactionrequestsid) +- Error Callback - [**PUT /transactionRequests/**_{ID}_**/error**](#put-transactionrequestsiderror) +- Data Model -- Empty body + +##### POST /transactionRequests + +Alternative URI: N/A + +Logical API service: [Perform Transaction Request](../generic-transaction-patterns#perform-transaction-request) + +The HTTP request **POST /transactionRequests** is used to request the creation of a transaction request for the provided financial transaction on the server. + +Callback and data model information for **POST /transactionRequests**: + +- Callback - [**PUT /transactionRequests/**_{ID}_](#put-transactionrequestsid) +- Error Callback - [**PUT /transactionRequests/**_{ID}_**/error**](#put-transactionrequestsiderror) +- Data Model -- See [Table 19](#table-19) + +###### Table 19 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **transactionRequestId** | 1 | CorrelationId | Common ID between the FSPs for the transaction request object, decided by the Payee FSP. The ID should be reused for resends of the same transaction request. A new ID should be generated for each new transaction request. | +| **payee** | 1 | Party | Information about the Payee in the proposed financial transaction. | +| **payer** | 1 | PartyInfo | Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction. | +| **amount** | 1 | Money | Requested amount to be transferred from the Payer to Payee. | +| **transactionType** | 1 | TransactionType | Type of transaction. | +| **note** | 0..1 | Note | Reason for the transaction request, intended to the Payer. | +| **geoCode** | 0..1 | GeoCode | Longitude and Latitude of the initiating Party. Can be used to detect fraud. | +| **authenticationType** | 0.11 | AuthenticationType | OTP or QR Code, otherwise empty. | +| **expiration** | 0..1 | DateTime | Can be set to get a quick failure in case the peer FSP takes too long to respond. Also, it may be beneficial for Consumer, Agent, Merchant to know that their request has a time limit. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 19 -- POST /transactionRequests data model** + +####Callbacks + +This section describes the callbacks that are used by the server under the resource **/transactionRequests**. + +##### PUT /transactionRequests/_{ID}_ + +Alternative URI: N/A + +Logical API service: **Return Transaction Request Information** + +The callback **PUT /transactionRequests/**_{ID}_ is used to inform the client of a requested or created transaction request. The _{ID}_ in the URI should contain the **transactionRequestId** (see [Table 19](#table-19)) that was used for the creation of the transaction request, or the _{ID}_ that was used in the [**GET /transactionRequests/**_{ID}_](#get-transactionrequestsid). See [Table 20](#table-20) for data model. + +###### Table 20 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **transactionId** | 0..1 | CorrelationId | Identifies a related transaction (if a transaction has been created). | +| **transactionRequestState** | 1 | TransactionRequestState | State of the transaction request. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 20 -- PUT /transactionRequests/_{ID}_ data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/transactionRequests**. + +##### PUT /transactionRequests/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Return Transaction Request Information Error](../generic-transaction-patterns#return-transaction-request-information-error) + +If the server is unable to find or create a transaction request, or another processing error occurs, the error callback **PUT** **/transactionRequests/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the **transactionRequestId** (see [Table 19](#table-19)) that was used for the creation of the transaction request, or the _{ID}_ that was used in the [**GET /transactionRequests/**_{ID}_](#get-transactionrequestsid). See [Table 21](#table-21) for data model. + +###### Table 21 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | ---| --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description. | + +**Table 21 -- PUT /transactionRequests/_{ID}_/error data model** + +#### 6.4.6 States + +The possible states of a transaction request can be seen in [Figure 46](#figure-46). + +**Note:** A server does not need to keep transaction request objects that have been rejected in their database. This means that a client should expect that an error callback could be received for a rejected transaction request. + +###### Figure 46 + +![Figure 46](../../assets/diagrams/images/figure46.svg) + +**Figure 46 -- Possible states of a transaction request** + +
    + +### API Resource /quotes + +This section defines the logical API resource **Quotes**, described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-quotes). + +The main service provided by the API resource **/quotes** is calculation of possible fees and FSP commission involved in performing an interoperable financial transaction. Both the Payer and Payee FSP should calculate their part of the quote to be able to get a total view of all the fees and FSP commission involved in the transaction. + +A quote is irrevocable; it cannot be changed after it has been created. However, it can expire (all quotes are valid only until they reach expiration). + +**Note:** A quote is not a guarantee that the financial transaction will succeed. The transaction can still fail later in the process. A quote only guarantees that the fees and FSP commission involved in performing the specified financial transaction are applicable until the quote expires. + +For more information see [Quoting](#quoting). + +#### Resource Version History + +[Table 22](#table-22) contains a description of each different version of the **/quotes** resource. + +###### Table 22 + +|Version|Date|Description| +|---|---|---| +|1.0|2018-03-13|Initial version| +|1.1|2020-05-19|The data model is updated to add an optional ExtensioinList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| + +**Table 22 – Version history for resource /quotes** + +#### Service Details + +[Figure 47](#figure-47) contains an example process for the API resource **/quotes**. The example shows a Payer Initiated Transaction, but it could also be initiated by the Payee, using the API Resource [**/transactionRequests**](#api-resource-transactionrequests). The lookup process is in that case performed by the Payee FSP instead. + +###### Figure 47 + +![](../../assets/diagrams/sequence/figure47.svg) + + +**Figure 47 -- Example process for resource /quotes** + +#### Quote Expiry Details + +The quote request from the Payer FSP can contain an expiry of the quote, if the Payer FSP would like to indicate when it is no longer useful for the Payee FSP to return a quote. For example, the transaction itself might otherwise time out, or if its quote might time out. + +The Payee FSP should set an expiry of the quote in the callback to indicate when the quote is no longer valid for use by the Payer FSP. + +#### Rejection of Quote + +The Payee FSP can reject a quote request from the Payer FSP by sending the error callback **PUT /quotes/**_{ID}_/**error** instead of the callback **PUT /quotes/**_{ID}_. +Depending on which generic transaction pattern (see Section 8 for more information) that is used, the Payer FSP can reject a quote using one of the following processes: + +- If the transaction is initiated by the Payer (see Section 8.1), the Payer FSP should not inform the Payee FSP regarding the rejection. The created quote at the Payee FSP should have an expiry time, at which time it is automatically deleted. +- If the transaction is initiated by the Payee (see Section 8.2 and 8.3), the Payer FSP should inform the Payee FSP regarding the rejection using the callback **PUT /transactionRequests/**_{ID}_ with a rejected state. The process is described in more detail in Section 6.4.2.1. + +#### Interledger Payment Request + +As part of supporting Interledger and the concrete implementation of the Interledger Payment Request (see [Interledgeer Protocol](#interledger-protocol)), the Payee FSP must: + +- Determine the ILP Address (see [ILP Addressing](#ILP-addressing) for more information) of the Payee and the amount that the Payee will receive. Note that since the **amount** element in the ILP Packet is defined as an UInt64, which is an Integer value, the amount should be multiplied with the currency's exponent (for example, USD's exponent is 2, which means the amount should be multiplied by 102, and JPY's exponent is 0, which means the amount should be multiplied by 100). Both the ILP Address and the amount should be populated in the ILP Packet (see [ILP Packet](#ilp-packet) for more information). + +- Populate the **data** element in the ILP Packet by the [Transaction](#transaction) data model. +- Generate the fulfilment and the condition (see [Conditional Transfers](#conditional-transfers) for more information). Populate the **condition** element in the [PUT /quotes/**_{ID}_](#put-quotes-id)). [Table 19](#table-19) shows data model with the generated condition. + +The fulfilment is a temporary secret that is generated for each financial transaction by the Payee FSP and used as the trigger to commit the transfers that make up an ILP payment. + +The Payee FSP uses a local secret to generate a SHA-256 HMAC of the ILP Packet. The same secret may be used for all financial transactions or the Payee FSP may store a different secret per Payee or based on another segmentation. + +The choice and cardinality of the local secret is an implementation decision that may be driven by scheme rules. The only requirement is that the Payee FSP can determine which secret that was used when the ILP Packet is received back later as part of an incoming transfer (see [API Resource Transfers](#api-resource-transfers)). + +The fulfilment and condition are generated in accordance with the algorithm defined in [Listing 12](#listing-12). Once the Payee FSP has derived the condition, the fulfilment can be discarded as it can be regenerated later. + +###### Listing 12 + +Generation of the fulfilment and condition + +**Inputs:** + +- Local secret (32-byte binary string) +- ILP Packet + +**Algorithm:** + +1. Let the fulfilment be the result of executing the HMAC SHA-256 algorithm on the ILP Packet using the local secret as the key. + +2. Let the condition be the result of executing the SHA-256 hash algorithm on the fulfilment. + +**Outputs:** + +- Fulfilment (32-byte binary string) +- Condition (32-byte binary string) + +**Listing 12 -- Algorithm to generate the fulfilment and the condition** + +#### Requests + +This section describes the services that can be requested by a client in the API on the resource **/quotes**. + +##### GET /quotes/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Retrieve Quote Information](../generic-transaction-patterns#retrieve-quote-information) + +The HTTP request **GET /quotes/**_{ID}_ is used to get information regarding a previously-created or requested quote. The _{ID}_ in the URI should contain the **quoteId** (see [Table 23](#table-23)) that was used for the creation of the quote. + +Callback and data model information for **GET /quotes/**_{ID}_: + +- Callback -- [**PUT /quotes/**_{ID}_](#put-quotes-id) +- Error Callback -- [**PUT /quotes/**_{ID}_**/_error_**](#put-quotes-iderror) +- Data Model -- Empty body + +##### POST /quotes + +Alternative URI: N/A + +Logical API service: [Calculate Quote Information](../generic-transaction-patterns#calculate-quote-information) + +The HTTP request **POST /quotes** is used to request the creation of a quote for the provided financial transaction on the server. + +Callback and data model information for **POST /quotes**: + +- Callback -- [**PUT /quotes/**_{ID}_](#put-quotes-id) +- Error Callback -- [**PUT /quotes/**_{ID}_**/error**](#put-quotes-iderror) +- Data Model -- See [Table 23](#table-23) + +###### Table 23 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **quoteId** | 1 | CorrelationId | Common ID between the FSPs for the quote object, decided by the Payer FSP. The ID should be reused for resends of the same quote for a transaction. A new ID should be generated for each new quote for a transaction. | +| **transactionId** | 1 | CorrelationId | Common ID (decided by the Payer FSP) between the FSPs for the future transaction object. The actual transaction will be created as part of a successful transfer process. The ID should be reused for resends of the same quote for a transaction. A new ID should be generated for each new quote for a transaction. | +| **transactionRequestId** | 0..1 | CorrelationId | Identifies an optional previously-sent transaction request. | +| **payee** | 1 | Party | Information about the Payee in the proposed financial transaction. | +| **payer** | 1 | Party | Information about the Payer in the proposed financial transaction. | +| **amountType** | 1 | AmountType |**SEND** for send amount, **RECEIVE** for receive amount. | +| **amount** | 1 | Money | Depending on **amountType**:
    If **SEND**: The amount the Payer would like to send; that is, the amount that should be withdrawn from the Payer account including any fees. The amount is updated by each participating entity in the transaction.
    If **RECEIVE**: The amount the Payee should receive; that is, the amount that should be sent to the receiver exclusive any fees. The amount is not updated by any of the participating entities.
    | +| **fees** | 0..1 | Money | Fees in the transaction.
  • The fees element should be empty if fees should be non-disclosed.
  • The fees element should be non-empty if fee should be disclosed.
  • | +| **transactionType** | 1 | TransactionType | Type of transaction for which the quote is requested. | +| **geoCode** | 0..1 | GeoCode | Longitude and Latitude of the initiating Party. Can be used to detect fraud. | +| **note** | 0..1 | Note | A memo that will be attached to the transaction. | +| **expiration** | 0..1 | DateTime | Expiration is optional. It can be set to get a quick failure in case the peer FSP takes too long to respond. Also, it may be beneficial for Consumer, Agent, and Merchant to know that their request has a time limit. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 23 -- POST /quotes data model** + +#### Callbacks + +This section describes the callbacks that are used by the server under the resource **/quotes**. + +#### PUT /quotes/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Quote Information](../generic-transaction-patterns#return-quote-information) + +The callback **PUT /quotes/**_{ID}_ is used to inform the client of a requested or created quote. The _{ID}_ in the URI should contain the **quoteId** (see [Table 23](#table-23)) that was used for the creation of the quote, or the _{ID}_ that was used in the [**GET /quotes/**_{ID}_](#get-quotesid). See [Table 24](#table-24) for data model. + +###### Table 24 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **transferAmount** | 1 | Money | The amount of Money that the Payer FSP should transfer to the Payee FSP. | +| **payeeReceiveAmount** | 0..1 | Money | The amount of Money that the Payee should receive in the end-to-end transaction. Optional as the Payee FSP might not want to disclose any optional Payee fees. | +| **payeeFspFee** | 0..1 | Money | Payee FSP’s part of the transaction fee. | +| **payeeFspCommission** | 0..1 | Money | Transaction commission from the Payee FSP. | +| **expiration** | 1 | DateTime | Date and time until when the quotation is valid and can be honored when used in the subsequent transaction. | +| **geoCode** | 0..1 | GeoCode | Longitude and Latitude of the Payee. Can be used to detect fraud. | +| **ilpPacket** | 1 | IlpPacket | The ILP Packet that must be attached to the transfer by the Payer. | +| **condition** | 1 | IlpCondition | The condition that must be attached to the transfer by the Payer. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment | + +**Table 24 -- PUT /quotes/_{ID}_ data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server +under the resource **/quotes**. + +##### PUT /quotes/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Return Quote Information Error](../generic-transaction-patterns#return-quote-information-error) + +If the server is unable to find or create a quote, or some other processing error occurs, the error callback **PUT** **/quotes/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the **quoteId** (see [Table 23](#table-23)) that was used for the creation of the quote, or the _{ID}_ that was used in the [**GET /quotes/**_{ID}_](#get-quotesid). See [Table 25](#table-25) for data model. + +###### Table 25 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description.| + +**Table 25 -- PUT /quotes/_{ID}_/error data model** + +#### States + +###### Figure 48 + +[Figure 48](#figure-48) contains the UML (Unified Modeling Language) state machine for the possible states of a quote object. + +**Note:** A server does not need to keep quote objects that have been either rejected or expired in their database. This means that a client should expect that an error callback could be received for an expired or rejected quote. + +![Figure 48](../../assets/diagrams/images/figure48.svg) + +**Figure 48 -- Possible states of a quote** + +
    + +### API Resource /authorizations + +This section defines the logical API resource **Authorizations**, described in [Generic Transaction Patterns](../gerneric-transaction-patterns#api-resource-authorizations). + +The API resource **/authorizations** is used to request the Payer to enter the applicable credentials in the Payee FSP system for approving the financial transaction, when the Payer has initiated the transaction from a POS, ATM, or similar, in the Payee FSP system and would like to authorize by an OTP. + +#### Resource Version History + +[Table 26](#table-26) contains a description of each different version of the **/authorizations** resource. + +###### Table 26 + +|Version|Date|Description| +|---|---|---| +|1.0|2018-03-13|Initial version| + +**Table 26 – Version history for resource /authorizations** + +#### Service Details + +[Figure 49](#figure-49) contains an example process for the API resource **/authorizations.** The Payee FSP first sends a [transaction request](#api-resource-transactionrequests)) that is authorized using OTP. The Payer FSP then performs the quoting process (see [API Resource Quotes](#api-resource-quotes)) before an authorization request is sent to the Payee FSP system for the Payer to approve by entering the OTP. If the OTP is correct, the transfer process should be initiated (see [API Resource Transfers](#api-resource-transfers)). + +###### Figure 49 + +![](../../assets/diagrams/sequence/figure49.svg) + + +**Figure 49 -- Example process for resource /authorizations** + +#### Resend Authorization Value + +If the notification containing the authorization value fails to reach the Payer, the Payer can choose to request a resend of the authorization value if the POS, ATM, or similar device supports such a request. See [Figure 50](#figure-50) for an example of a process where the Payer requests that the OTP be resent. + +###### Figure 50 + +![](../../assets/diagrams/sequence/figure50.svg) + + +**Figure 50 -- Payer requests resend of authorization value (OTP)** + +##### Retry Authorization Value + +The Payer FSP must decide the number of times a Payer can retry the authorization value in the POS, ATM, or similar device. This will be set in the **retriesLeft** query string (see [URI Syntax](#uri-syntax) for more information regarding URI syntax) of the [**GET** **/authorizations/**_{ID}_](#get-authorizationsid) service for more information. If the Payer FSP sends retriesLeft=1, this means that it is the Payer's last try of the authorization value. See [Figure 51](#figure-51) for an example process where the Payer enters the incorrect OTP, and the **retriesLeft** value is subsequently decreased. + +###### Figure 51 + +![](../../assets/diagrams/sequence/figure51.svg) + + +**Figure 51 -- Payer enters incorrect authorization value (OTP)** + +##### Failed OTP authorization + +If the user fails to enter the correct OTP within the number of allowed retries, the process described in [Payer Rejected Transaction Request](#payer-rejected-transaction-request) is performed. + +#### Requests + +This section describes the services that can be requested by a client in the API on the resource **/authorizations**. + +##### GET /authorizations/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Perform Authorization](../generic-transaction-patterns#perform-authorization) + +The HTTP request **GET /authorizations/**_{ID}_ is used to request the Payer to enter the applicable credentials in the Payee FSP system. The _{ID}_ in the URI should contain the **transactionRequestID** (see [Table 15](#table-15)), received from the [**POST** **/transactionRequests**](#post-transactionrequests)) service earlier in the process. + +This request requires a query string (see [URI Syntax](#uri-syntax) for more information regarding URI syntax) to be included in the URI, with the following key-value pairs: + +- **authenticationType=**_{Type}_, where _{Type}_ value is a valid authentication type from the enumeration [AuthenticationType](#authenticationtype). +- **retriesLeft=**_{NrOfRetries}_, where _{NrOfRetries}_ is the number of retries left before the financial transaction is rejected. _{NrOfRetries}_ must be expressed in the form of the data type [Integer](#integer)). **retriesLeft=1** means that this is the last retry before the financial transaction is rejected. +- **amount=**_{Amount}_, where _{Amount}_ is the transaction amount that will be withdrawn from the Payer's account. _{Amount}_ must be expressed in the form of the data type [Amount](#amount). +- **currency=**_{Currency}_, where _{Currency}_ is the transaction currency for the amount that will be withdrawn from the Payer's account. The _{Currency}_ value must be expressed in the form of the enumeration [CurrencyCode](#currencycode)). + +An example URI containing all the required key-value pairs in the query string is the following: + +**GET /authorization/3d492671-b7af-4f3f-88de-76169b1bdf88?authenticationType=OTP&retriesLeft=2&amount=102¤cy=USD** + +Callback and data model information for **GET /authorization/**_{ID}_: + +- Callback - [**PUT /authorizations/**_{ID}_](#6641-put-authorizationsid) +- Error Callback - [**PUT /authorizations/**_{ID}_**/error**](#6651-put-authorizationsiderror) +- Data Model -- Empty body + +#### 6.6.4 Callbacks + +This section describes the callbacks that are used by the server under the resource **/authorizations**. + +#### 6.6.4.1 PUT /authorizations/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Authorization Result](../generic-transaction-patterns#return-authorization-result) + +The callback **PUT /authorizations/** _{ID}_ is used to inform the client of the result of a previously-requested authorization. The _{ID}_ in the URI should contain the _{ID}_ that was used in the [**GET /authorizations/**_{ID}_](#get-authorizationsid). **See** [Table 27](#table-27) **for** data model. + +###### Table 27 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **authenticationInfo** | 0..1 | AuthenticationInfo | OTP or QR Code if entered, otherwise empty. | +| **responseType** | 1 | AuthorizationResponse | Enum containing response information; if the customer entered the authentication value, rejected the transaction, or requested a resend of the authentication value. | + +**Table 27 – PUT /authorizations/{ID} data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/authorizations**. + +#### PUT /authorizations/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Return Authorization Error](../generic-transaction-patterns#return-authorization-error) + +If the server is unable to find the transaction request, or another processing error occurs, the error callback **PUT** **/authorizations/**_{ID}_ **/error** is used. The _{ID}_ in the URI should contain the _{ID}_ that was used in the [**GET /authorizations/**_{ID}_](#get-authorizationsid). **See** [Table 28](#table-28) **for** data model. + +###### Table 28 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description | + +**Table 28 -- PUT /authorizations/_{ID}_/error data model** + +#### States + +There are no states defined for the **/authorizations** resource. + +
    + +### API Resource /transfers + +This section defines the logical API resource **Transfers**, described in [Generic Transaction Patterns](../generic-transation-patterns#api-resource-transfers). + +The services provided by the API resource **/transfers** are used for performing the hop-by-hop ILP transfer or transfers, and to perform the end-to-end financial transaction by sending the transaction details from the Payer FSP to the Payee FSP. The transaction details are sent as part of the transfer data model in the ILP Packet. + +The Interledger protocol assumes that the setup of a financial transaction is achieved using an end-to-end protocol, but that an ILP transfer is implemented on the back of hop-by-hop protocols between FSPs connected to a common ledger. In the current version of the API, the API Resource **/quotes** performs the setup of the financial transaction. Before a transfer can be performed, the quote must be performed to setup the financial transaction. See [API Resource Quotes](#api-resource-quotes) for more information. + +An ILP transfer is exchanged between two account holders on either side of a common ledger. It is usually expressed in the form of a request to execute a transfer on the common ledger and a notification to the recipient of the transfer that the transfer has been reserved in their favor, including a condition that must be fulfilled to commit the transfer. + +When the Payee FSP presents the fulfilment to the common ledger, the transfer is committed in the common ledger. At the same time, the Payer FSP is notified that the transfer has been committed along with the fulfilment. + +#### Resource Version History + +Table 29 contains a description of each different version of the **/transfers** resource. + +| Version | Date | Description| +| ---- | ---- | ---- | +| **1.0** | 2018-03-13 | Initial version | +| **1.1** | 2020-05-19 | The resource is updated to support commit notifications using HTTP Method **PATCH**. The new request **PATCH /transfers/{ID}** is described in Section 6.7.3.3. The process of using commit notifications is described in Section 6.7.2.6.

    The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: [https://github.com/mojaloop/mojaloop-specification/issues/30](https://github.com/mojaloop/mojaloop-specification/issues/30). Following this, the data model as specified in Table 93 has been updated.| + +**Table 29 –- Version history for resource /transfers** + +#### Service Details + +This section provides details regarding hop-by-hop transfers and end-to-end financial transactions. + +#### Process + +[Figure 52](#figure-52) shows how the transaction process works using the **POST /transfers** service. + +###### Figure 52 + +![](../../assets/diagrams/sequence/figure52.svg) + + +**Figure 52 -- How to use the POST /transfers service** + +#### Transaction Irrevocability + +The API is designed to support irrevocable financial transactions only; this means that a financial transaction cannot be changed, cancelled, or reversed after it has been created. This is to simplify and reduce costs for FSPs using the API. A large percentage of the operating costs of a typical financial system is due to reversals of transactions. + +As soon as a Payer FSP sends a financial transaction to a Payee FSP (that is, using **POST /transfers** including the end-to-end financial transaction), the transaction is irrevocable from the perspective of the Payer FSP. The transaction could still be rejected in the Payee FSP, but the Payer FSP can no longer reject or change the transaction. An exception to this would be if the transfer's expiry time is exceeded before the Payee FSP responds (see [Expired Quote](#expired-quote) and [Client Receiving Expired Transfer](#client-receiving-expired-transfer) for more information). As soon as the financial transaction has been accepted by the Payee FSP, the transaction is irrevocable for all parties. + +#### Expired Quote + +If a server receives a transaction that is using an expired quote, the server should reject the transfer or transaction. + +#### Timeout and Expiry + +The Payer FSP must always set a transfer expiry time to allow for use cases in which a swift completion or failure is needed. If the use case does not require a swift completion, a longer expiry time can be set. If the Payee FSP fails to respond before the expiry time, the transaction is cancelled in the Payer FSP. The Payer FSP should still expect a callback from the Payee FSP. + +Short expiry times are often required in retail scenarios, in which a customer may be standing in front of a merchant; both parties need to know if the transaction was successful before the goods or services are given to the customer. + +In [Figure 52](#figure-52), an expiry has been set to 30 seconds from the current time in the request from the Payer FSP, and to 20 seconds from the same time in the request from the Switch to the Payee FSP. This strategy of using shorter timeouts for each entity in the chain from Payer FSP to Payee FSP should always be used to allow for extra communication time. + +**Note:** It is possible that a successful callback might be received in the Payer FSP after the expiry time; for example, due to congestion in the network. The Payer FSP should allow for some extra time after the actual expiry time before cancelling the financial transaction in the system. If a successful callback is received after the financial transaction has been cancelled, the transaction should be marked for reconciliation and handled separately in a reconciliation process. + +#### Client Receiving Expired Transfer + +[Figure 53](#figure-53) shows an example of a possible error scenario connected to expiry and timeouts. For some reason, the callback from the Payee FSP takes longer time to send than the expiry time in the optional Switch. This leads to the Switch cancelling the reserved transfer, and an error callback for the transfer is sent to the Payer FSP. Now the Payer FSP and the Payee FSP have two different views of the result of the financial transaction; the transaction should be marked for reconciliation. + +###### Figure 53 + +![](../../assets/diagrams/sequence/figure53.svg) + + +**Figure 53 -- Client receiving an expired transfer** + +To limit these kinds of error scenarios, the clients (Payer FSP and optional Switch in [Figure 52](#figure-52)) participating in the ILP transfer should allow some extra time after actual expiry time during which the callback from the server can be received. The client(s) should also query the server after expiry, but before the end of the extra time, if any callback from the server has been lost due to communication failure. Reconciliation could still be necessary though, even with extra time allowed and querying the server for the transaction. + +#### Commit Notification + +As an alternative option to avoid the error scenario described in [Client Receiving Expired Transfer](#client-receiving-expired-transfer) for use cases where it is complicated to perform a refund, a Payee FSP can (if the scheme allows it) reserve the transfer and then wait for a subsequent commit notification from the Switch. To request a commit notification instead of committing directly is a business decision made by the Payee FSP (if the scheme allows it), based on the context of the transaction. For example, a Cash Out or a Merchant Payment transaction can be understood as a higher-risk transaction, because it is not possible to reverse a transaction if the customer is no longer present; a P2P Transfer can be understood as lower risk because it is easier to reverse by refunding the transaction to the customer. +To request a commit notification from the Switch, the Payee FSP must mark the transfer state (see Section 6.7.6) as reserved instead of committed in the **PUT /transfers/**_{ID}_ callback. Based on the transfer state, the Switch should then perform the following: + +- If the transfer is committed, the Switch should not send a commit notification as the Payee FSP has already accepted the risk that the transfer in some rare cases might fail. This is the default way of committing, shown in [Process](#process). +- If the transfer is reserved, the Switch must send a commit notification to the Payee FSP when the transfer is completed (committed or aborted). + +The commit notification is sent in the request **PATCH /transfers/**_{ID}_ from the Switch to the Payee FSP. If the Payee FSP does not get a commit notification from the Switch within a reasonable time, the Payee FSP should resend the **PUT /transfers/**_{ID}_ callback to the Switch. The Payee FSP needs to receive the commit notification from the Switch before committing the transfer, or accept the risk that the transfer in the Switch might have failed. The Payee FSP is not allowed to rollback the transfer without receiving an aborted state (see Section 6.7.6) from the Switch, as the Payee FSP has sent the fulfilment (which is the commit trigger) to the Switch. +[Figure 54](#figure-54) shows an example where a commit notification is requested by the Payee FSP. In this example the commit was successful in the Switch. + +###### Figure 54 + +![](../../assets/diagrams/sequence/figure54.svg) + + +**Figure 54 -- Commit notification where commit of transfer was successful in Switch** + +[Figure 55](#figure-55) shows an example in which the commit in the Switch failed due to some reason, for example the expiry time had expired in the Switch due to network issues. This is the same example as in [Figure 53](#figure-53), but where no reconciliation is needed as the Payee FSP receives a commit notification before performing the actual transfer to the Payee. + +###### Figure 55 + +![](../../assets/diagrams/sequence/figure55.svg) + + +**Figure 55 -- Commit notification where commit of transfer in Switch failed** + +#### Refunds + +Instead of supporting reversals, the API supports refunds. To refund a transaction using the API, a new transaction should be created by the Payee of the original transaction. The new transaction should revers the original transaction (either the full amount or a partial amount); for example, if customer X sent 100 USD to merchant Y in the original transaction, a new transaction where merchant Y sends 100 USD to customer X should be created. There is a specific transaction type to indicate a refund transaction; for example, if the quote of the transaction should be handled differently than any other type of transaction. The original transaction ID should be sent as part of the new transaction for informational and reconciliation purposes. + +#### Interledger Payment Request + +As part of supporting Interledger and the concrete implementation of the Interledger Payment Request (see [Interledger Protocol](#interledger-protocol)), the Payer FSP must attach the ILP Packet, the condition, and an expiry to the transfer. The condition and the ILP Packet are the same as those sent by the Payee FSP in the callback of the quote; see [Interledger Payment Request](#interledger-payment-request) section for more information. + +The end-to-end ILP payment is a chain of one or more conditional transfers that all depend on the same condition. The condition is provided by the Payer FSP when it initiates the transfer to the next ledger. + +The receiver of that transfer parses the ILP Packet to get the Payee ILP Address and routes the ILP payment by performing another transfer on the next ledger, attaching the same ILP Packet and condition and a new expiry that is less than the expiry of the incoming transfer. + +When the Payee FSP receives the final incoming transfer to the Payee account, it extracts the ILP Packet and performs the following steps: + +1. Validates that the Payee ILP Address in the ILP Packet corresponds to the Payee account that is the destination of the transfer. +2. Validates that the amount in the ILP Packet is the same as the amount of the transfer and directs the local ledger to perform a reservation of the final transfer to the Payee account (less any hidden receiver fees, see [Quoting](#quoting)). +3. If the reservation is successful, the Payee FSP generates the fulfilment using the same algorithm that was used when generating the condition sent in the callback of the quote (see [Interledger Payment Request](#interledger-payment-request)). +4. The fulfilment is submitted to the Payee FSP ledger to instruct the ledger to commit the reservation in favor of the Payee. The ledger will validate that the SHA-256 hash of the fulfilment matches the condition attached to the transfer. If it does, it commits the reservation of the transfer. If not, it rejects the transfer and the Payee FSP rejects the payment and cancels the previously-performed reservation. + +The fulfilment is then passed back to the Payer FSP through the same ledgers in the callback of the transfer. As funds are committed on each ledger after a successful validation of the fulfilment, the entity that initiated the transfer will be notified that the funds it reserved have been committed and the fulfilment will be shared as part of that notification message. + +The final transfer to be committed is the transfer on the Payer FSP's ledger where the reservation is committed from their account. At this point the Payer FSP notifies the Payer of the successful financial transaction. + +#### Requests + +This section describes the services that can be requested by a client in the API on the resource **/transfers**. + +##### GET /transfers/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Authorization Result](../generic-transaction-patterns#return-authorization-result) + +The HTTP request **GET /transfers/**_{ID}_ is used to get information regarding a previously-created or requested transfer. The _{ID}_ in the URI should contain the **transferId** (see [Table 23](#table-23)) that was used for the creation of the transfer. + +Callback and data model information for **GET /transfer/**_{ID}_: + +- Callback -- [**PUT /transfers/**_{ID}_](#put-transfersid) +- Error Callback -- [**PUT /transfers/**_{ID}_**/error**](#put-transfersiderror) +- Data Model -- Empty body + +##### POST /transfers + +Alternative URI: N/A + +Logical API service: [Perform Transfer](../generic-transaction-patterns#perform-transfer) + +The HTTP request **POST /transfers** is used to request the creation of a transfer for the next ledger, and a financial transaction for the Payee FSP. + +Callback and data model information for **POST /transfers**: + +- Callback -- [**PUT /transfers/**_{ID}_](#put-transfersid) +- Error Callback -- [**PUT /transfers/**_{ID}_**/error**](#put-transfersiderror) +- Data Model -- See [Table 30](#table-30) + +###### Table 30 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **transferId** | 1| CorrelationId | The common ID between the FSPs and the optional Switch for the transfer object, decided by the Payer FSP. The ID should be reused for resends of the same transfer. A new ID should be generated for each new transfer. | +| **payeeFsp** | 1 | FspId | Payee FSP in the proposed financial transaction. | +| **payerFsp** | 1 | FspId | Payer FSP in the proposed financial transaction. | +| **amount** | 1 | Money | The transfer amount to be sent. | +| **ilpPacket** | 1 | IlpPacket | The ILP Packet containing the amount delivered to the Payee and the ILP Address of the Payee and any other end-to-end data. | +| **condition** | 1 | IlpCondition | The condition that must be fulfilled to commit the transfer. | +| **expiration** | 1 | DateTime | Expiration can be set to get a quick failure expiration of the transfer. The transfer should be rolled back if no fulfilment is delivered before this time. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 30 – POST /transfers data model** + +##### PATCH /transfers/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Commit Notiifcation](../generic-transaction-patterns#commit-notification) + +The HTTP request **PATCH /transfers/**_{ID}_ is used by a Switch to update the state of an earlier reserved transfer, if the Payee FSP has requested a commit notification when the Switch has completed processing of the transfer. The _{ID}_ in the URI should contain the transferId (see Table 30) that was used for the creation of the transfer. Please note that this request does not generate a callback. See Table 31 for data model. + +###### Table 31 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **completedTimestamp** | 1| DateTime | Time and date when the transaction was completed | +| **transferState** | 1 | TransferState | State of the transfer | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 31 –- PATCH /transfers/_{ID}_ data model** + +#### Callbacks + +This section describes the callbacks that are used by the server under the resource **/transfers**. + +##### PUT /transfers/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Transfer Information](../generic-transaction-patterns#return-transfer-information) + +The callback **PUT /transfers/**_{ID}_ is used to inform the client of a requested or created transfer. The _{ID}_ in the URI should contain the **transferId** (see [Table 30](#table-30)) that was used for the creation of the transfer, or the _{ID}_ that was used in the [**GET** **/transfers/**_{ID}_](#6731-get-transfersid). **See** [Table 32](#table-32) **for** data model. + +**Note**: For **PUT /transfers/**_{ID}_ callbacks, the state ABORTED is not a valid enumeration option as **transferState** in Table 32. If a transfer is to be rejected, then the FSP making the callback should use an error callback, i.e., a callback on the /error endpoint. At the same time, it should be noted that a **transferState** value ‘ABORTED’ is valid for a callback to a **GET /transfers/**_{ID}_ call. + +###### Table 32 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **fulfilment** | 0..1 | IlpFulfilment | Fulfilment of the condition specified with the transaction. Mandatory if transfer has completed successfully. | +| **completedTimestamp** | 0..1 | DateTime | Time and date when the transaction was completed | +| **transferState** | 1 | TransferState | State of the transfer | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment | + +**Table 32 -- PUT /transfers/_{ID}_ data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/transfers**. + +##### PUT /transfers/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Return Transfer Information Error](../generic-transaction-patterns#return-transfer-information-error) + +If the server is unable to find or create a transfer, or another processing error occurs, the error callback **PUT** + +**/transfers/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the **transferId** (see [Table 30](#table-30)) that was used for the creation of the transfer, or the _{ID}_ that was used in the [**GET /transfers/**_{ID}_](#6731-get-transfersid). See [Table 33](#table-33) for data model. + +###### Table 33 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description. | + +**Table 33 -- PUT /transfers/_{ID}_/error data model** + +**6.7.6 States** + +###### Figure 56 + +The possible states of a transfer can be seen in [Figure 56](#figure-56). + +![Figure 56](../../assets/diagrams/images/figure56.svg) + +**Figure 56 -- Possible states of a transfer** + +
    + + +### API Resource /transactions + +This section defines the logical API resource **Transactions**, described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-transactions). + +The services provided by the API resource **/transactions** are used for getting information about the performed end-to-end financial transaction; for example, to get information about a possible token that was created as part of the transaction. + +The actual financial transaction is performed using the services provided by the API Resource [**/transfers**](#67-api-resource-transfers), which includes the end-to-end financial transaction between the Payer FSP and the Payee FSP. + +#### Resource Version History + +[Table 34](#table-34) contains a description of each different version of the **/transactions** resource. + +###### Table 34 + +|Version|Date|Description| +|---|---|---| +|1.0|2018-03-13|Initial version| + +**Table 34 – Version history for resource /transactions** + +#### Service Details + +[Figure 57](#figure-57) shows an example for the transaction process. The actual transaction will be performed as part of the transfer process. The service **GET /transactions/**_{TransactionID}_ can then be used to get more information about the financial transaction that was performed as part of the transfer process. + +###### Figure 57 + +![](../../assets/diagrams/sequence/figure57.svg) + + +**Figure 57 -- Example transaction process** + +#### Requests + +This section describes the services that can be requested by a client on the resource **/transactions**. + +##### GET /transactions/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Retrieve Transaction Information](../generic-transaction-patterns#retrieve-transaction-information) + +The HTTP request **GET /transactions/**_{ID}_ is used to get transaction information regarding a previously-created financial transaction. The _{ID}_ in the URI should contain the **transactionId** that was used for the creation of the quote (see [Table 23](#table-23)), as the transaction is created as part of another process (the transfer process, see [API Resource Transfers](#api-resource-transfers)). + +Callback and data model information for **GET /transactions/**_{ID}_: + +- Callback -- [**PUT /transactions/**_{ID}_](#put-transactionsid) +- Error Callback -- [**PUT /transactions/**_{ID}_**/error**](#put-transactionsiderror) +- Data Model -- Empty body + +#### Callbacks + +This section describes the callbacks that are used by the server under the resource **/transactions**. + +##### PUT /transactions/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Transaction Information](../generic-transaction-patterns#return-transaction-information) + +The callback **PUT /transactions/**_{ID}_ is used to inform the client of a requested transaction. The _{ID}_ in the URI should contain the _{ID}_ that was used in the [**GET /transactions/**_{ID}_](#get-transactionsid). See [Table 35](#table-35) for data model. + +###### Table 35 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **completedTimestamp** | 0..1 | DateTime | Time and date when the transaction was completed. | +| **transactionState** | 1 | TransactionState | State of the transaction. | +| **code** | 0..1 | Code | Optional redemption information provided to Payer after transaction has been completed. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 35 -- PUT /transactions/_{ID}_ data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/transactions**. + +##### PUT /transactions/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Return Transaction Information Error](../generic-transaction-patterns#retrieve-transaction-information-error) + +If the server is unable to find or create a transaction, or another processing error occurs, the error callback **PUT** **/transactions/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the _{ID}_ that was used in the [**GET /transactions/**_{ID}_](#get-transactionsid). See [Table 36](#table-36) for data model. + +###### Table 36 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description. | + +**Table 36 -- PUT /transactions/_{ID}_/error data model** + +#### States + +###### Figure 58 + +The possible states of a transaction can be seen in [Figure 58](#figure-58). + +**Note:** For reconciliation purposes, a server must keep transaction objects that have been rejected in its database for a scheme-agreed time period. This means that a client should expect a proper callback about a transaction (if it has been received by the server) when requesting information regarding the same. + +![Figure 58](../../assets/diagrams/images/figure58.svg) + +**Figure 58 -- Possible states of a transaction** + +
    + +### API Resource /bulkQuotes + +This section defines the logical API resource **Bulk Quotes**, described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-bulk-quotes). + +The services provided by the API resource **/bulkQuotes** service are used for requesting the creation of a bulk quote; that is, a quote for more than one financial transaction. For more information regarding a single quote for a transaction, see API Resource [/quotes](#api-resource-quotes). + +A created bulk quote object contains a quote for each individual transaction in the bulk in a Peer FSP. A bulk quote is irrevocable; it cannot be changed after it has been created However, it can expire (all bulk quotes are valid only until they reach expiration). + +**Note:** A bulk quote is not a guarantee that the financial transaction will succeed. The bulk transaction can still fail later in the process. A bulk quote only guarantees that the fees and FSP commission involved in performing the specified financial transaction are applicable until the bulk quote expires. + +#### Resource Version History + +Table 37 contains a description of each different version of the **/bulkQuotes** resource. + +| Version | Date | Description| +| ---- | ---- | ---- | +| **1.0** | 2018-03-13 | Initial version | +| **1.1** | 2020-05-19 | The data model is updated to add an optional ExtensioinList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| + +**Table 37 –- Version history for resource /bulkQuotes** + +#### Service Details + +[Figure 59](#figure-59) shows how the bulk quotes process works, using the **POST /bulkQuotes** service. When receiving the bulk of transactions from the Payer, the Payer FSP should: + +1. Lookup the FSP in which each Payee is; for example, using the API Resource [/participants](#api-resource-participants). + +2. Divide the bulk based on Payee FSP. The service **POST /bulkQuotes** is then used for each Payee FSP to get the bulk quotes from each Payee FSP. Each quote result will contain the ILP Packet and condition (see [ILP Packet](#ilp-packet) and [Conditional Transfers](#conditional-transfers)) needed to perform each transfer in the bulk transfer (see API Resource [/bulkTransfers](#api-resource-bulktransfers)), which will perform the actual financial transaction from the Payer to each Payee. + +###### Figure 59 + +![](../../assets/diagrams/sequence/figure59.svg) + + +**Figure 59 -- Example bulk quote process** + +#### Requests + +This section describes the services that can be requested by a client in the API on the resource **/bulkQuotes**. + +##### GET /bulkQuotes/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Retrieve Bulk Quote Information](../generic-transaction-patterns#retrieve-bulk-quote-information) + +The HTTP request **GET /bulkQuotes/**_{ID}_ is used to get information regarding a previously-created or requested bulk quote. + +The _{ID}_ in the URI should contain the **bulkQuoteId** (see [Table 38](#table-38)) that was used for the creation of the bulk quote. + +Callback and data model information for **GET /bulkQuotes/**_{ID}_: + +- Callback -- [PUT /bulkQuotes/**_{ID}_](#put-bulkquotesid) +- Error Callback -- [PUT /bulkQuotes/**_{ID}_**/error**](#put-bulkquotesiderror) +- Data Model -- Empty body + +##### POST /bulkQuotes + +Alternative URI: N/A + +Logical API service: **Calculate Bulk Quote** + +The HTTP request **POST /bulkQuotes** is used to request the creation of a bulk quote for the provided financial transactions on the server. + +Callback and data model information for **POST /bulkQuotes**: + +- Callback -- [**PUT /bulkQuotes/**_{ID}_](#6941-put-bulkquotesid) +- Error Callback -- [**PUT /bulkQuotes/**_{ID}_**/error**](#6951-put-bulkquotesiderror) +- Data Model -- See [Table 38](#table-38) + +###### Table 38 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **bulkQuoteId** | 1 | CorrelationId | Common ID between the FSPs for the bulk quote object, decided by the Payer FSP. The ID should be reused for resends of the same bulk quote. A new ID should be generated for each new bulk quote. | +| **payer** | 1 | Party | Information about the Payer in the proposed financial transaction. | +| **geoCode** | 0..1 | GeoCode | Longitude and Latitude of the initiating Party. Can be used to detect fraud. | +| **expiration** | 0..1 | DateTime | Expiration is optional to let the Payee FSP know when a quote no longer needs to be returned. | +| **individualQuotes** | 1..1000 | IndividualQuote | List of quotes elements. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 38 -- POST /bulkQuotes data model** + +#### Callbacks + +This section describes the callbacks that are used by the server under the resource **/bulkQuotes**. + +##### PUT /bulkQuotes/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Bulk Quote Information](../generic-transaction-patterns#return-bulk-quote-information) + +The callback **PUT /bulkQuotes/**_{ID}_ is used to inform the client of a requested or created bulk quote. The _{ID}_ in the URI should contain the **bulkQuoteId** (see [Table 38](#table-38)) that was used for the creation of the bulk quote, or the _{ID}_ that was used in the [**GET /bulkQuotes/**_{ID}_](#6931-get-bulkquotesid). See [Table 39](#table-39) for data model. + +###### Table 39 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **individualQuoteResults** | 0..1000 | IndividualQuoteResult | Fees for each individual transaction, if any of them are charged per transaction. | +| **expiration** | 1 | DateTime | Date and time until when the quotation is valid and can be honored when used in the subsequent transaction request. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 39 -- PUT /bulkQuotes/_{ID}_ data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/bulkQuotes**. + +##### PUT /bulkQuotes/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Retrieve Bulk Quote Information Error](../generic-transaction-patterns#retrieve-bulk-quote-information-error) + +If the server is unable to find or create a bulk quote, or another processing error occurs, the error callback **PUT** **/bulkQuotes/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the **bulkQuoteId** (see [Table 38](#table-38)) that was used for the creation of the bulk quote, or the _{ID}_ that was used in the [**GET /bulkQuotes/**_{ID}_](#6931-get-bulkquotesid). See [Table 40](#table-40) for data model. + +###### Table 40 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description. | + +**Table 40 -- PUT /bulkQuotes/_{ID}_/error data model** + +#### States + +###### Figure 60 + +The possible states of a bulk quote can be seen in [Figure 60](#figure-60). + +**Note:** A server does not need to keep bulk quote objects that have been either rejected or expired in their database. This means that a client should expect that an error callback could be received for a rejected or expired bulk quote. + +![Figure 60](../../assets/diagrams/images/figure60.svg) + +**Figure 60 -- Possible states of a bulk quote** + +
    + +### API Resource /bulkTransfers + +This section defines the logical API resource **Bulk Transfers**, described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-bulk-transfers). + +The services provided by the API resource **/bulkTransfers** are used for requesting the creation of a bulk transfer or for retrieving information about a previously-requested bulk transfer. For more information about a single transfer, see API Resource [/transfers](#api-resource-transfers). Before a bulk transfer can be requested, a bulk quote needs to be performed. See API Resource [/bulkQuotes](#api-resource-bulkquotes), for more information. + +A bulk transfer is irrevocable; it cannot be changed, cancelled, or reversed after it has been sent from the Payer FSP. + +#### Resource Version History + +Table 41 contains a description of each different version of the **/bulkTransfers** resource. + +| Version | Date | Description| +| ---- | ---- | ---- | +| **1.0** | 2018-03-13 | Initial version | +| **1.1** | 2020-05-19 | The data model is updated to add an optional ExtensioinList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| + +**Table 41 –- Version history for resource /bulkTransfers** + +#### Service Details + +[Figure 61](#figure-61) shows how the bulk transfer process works, using the **POST /bulkTransfers** service. When receiving the bulk transactions from the Payer, the Payer FSP should perform the following: + +1. Lookup the FSP in which each Payee is; for example, using the API Resource **/participants**, [Section 6.2](#62-api-resource-participants). +2. Perform the bulk quote process using the API Resource **/bulkQuotes**, [Section 6.9](#69-api-resource-bulkquotes). The bulk quote callback should contain the required ILP Packets and conditions needed to perform each transfer. +3. Perform bulk transfer process in [Figure 61](#figure-61) using **POST /bulkTransfers**. This performs each hop-to-hop transfer and the end-to-end financial transaction. For more information regarding hop-to-hop transfers vs end-to-end financial transactions, see [Section 6.7](#67-api-resource-transfers). + +###### Figure 61 + +![](../../assets/diagrams/sequence/figure61.svg) + + +**Figure 61 -- Example bulk transfer process** + +#### Requests + +This section describes the services that can a client can request on the resource **/bulkTransfers**. + +##### GET /bulkTransfers/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Retrieve Bulk Transfer Information](../generic-transaction-patterns#retrieve-bulk-transfer-information) + +The HTTP request **GET /bulkTransfers/**_{ID}_ is used to get information regarding a previously-created or requested bulk transfer. The _{ID}_ in the URI should contain the **bulkTransferId** (see [Table 42](#table-42)) that was used for the creation of the bulk transfer. + +Callback and data model information for **GET /bulkTransfers/**_{ID}_: + +- Callback -- [PUT /bulkTransfers/_{ID}_](#put-bulktransfersid) +- Error Callback -- [PUT /bulkTransfers/_{ID}_/error](#put-bulktransfersiderror) +- Data Model -- Empty body + +##### POST /bulkTransfers + +Alternative URI: N/A + +Logical API service: [Perform Bulk Transfer](../generic-transaction-patterns#perform-bulk-transfer) + +The HTTP request **POST /bulkTransfers** is used to request the creation of a bulk transfer on the server. + +- Callback - [PUT /bulkTransfers/_{ID}_](#put-bulktransfersid) +- Error Callback - [PUT /bulkTransfers/_{ID}_/error](#put-bulktransfersiderror) +- Data Model -- See [Table 42](#table-42) + +###### Table 42 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **bulkTransferId** | 1 | CorrelationId | Common ID between the FSPs and the optional Switch for the bulk transfer object, decided by the Payer FSP. The ID should be reused for resends of the same bulk transfer. A new ID should be generated for each new bulk transfer. | +| **bulkQuoteId** | 1 | CorrelationId | ID of the related bulk quote | +| **payeeFsp** | 1 | FspId | Payee FSP identifier. | +| **payerFsp** | 1 | FspId | Payer FSP identifier. | +| **individualTransfers** | 1..1000 | IndividualTransfer | List of IndividualTransfer elements. | +| **expiration** | 1 | DateTime | Expiration time of the transfers. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 42 -- POST /bulkTransfers data model** + +#### Callbacks + +This section describes the callbacks that are used by the server under the resource **/bulkTransfers**. + +##### PUT /bulkTransfers/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Retrieve Bulk Transfer Information](../generic-transaction-patterns#retrieve-bulk-transfer-information) + +The callback **PUT /bulkTransfers/**_{ID}_ is used to inform the client of a requested or created bulk transfer. The _{ID}_ in the URI should contain the **bulkTransferId** (see [Table 42](#table-42)) that was used for the creation of the bulk transfer ([POST /bulkTransfers](#post-bulktransfers)), or the _{ID}_ that was used in the [GET /bulkTransfers/_{ID}_](#get-bulktransfersid). See [Table 43](#table-43) for data model. + +###### Table 43 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **completedTimestamp** | 0..1 | DateTime | Time and date when the bulk transaction was completed. | +| **individualTransferResults** | 0..1000 | **Error! Reference source not found.** | List of **Error! Reference source not found.** elements. | +| **bulkTransferState** | 1 | BulkTransferState | The state of the bulk transfer. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 43 -- PUT /bulkTransfers/_{ID}_ data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/bulkTransfers**. + +##### PUT /bulkTransfers/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Retrieve Bulk Transfer Information Eerror](../generic-transaction-patterns#retrieve-bulk-transfer-information-error) + +If the server is unable to find or create a bulk transfer, or another processing error occurs, the error callback **PUT** **/bulkTransfers/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the **bulkTransferId** (see [Table 42](#table-42)) that was used for the creation of the bulk transfer ([POST /bulkTransfers](#post-bulktransfers)), or the _{ID}_ that was used in the [GET /bulkTransfers/_{ID}_](#get-bulktransfersid). See [Table 44](#table-44) for data model. + +###### Table 44 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description. | + +**Table 44 -- PUT /bulkTransfers/_{ID}_/error data model** + +#### States + +###### Figure 62 + +The possible states of a bulk transfer can be seen in [Figure 62](#figure-62). + +**Note:** A server must keep bulk transfer objects that have been rejected in their database during a market agreed time-period for reconciliation purposes. This means that a client should expect a proper callback about a bulk transfer (if it has been received by the server) when requesting information regarding the same. + +![Figure 62](../../assets/diagrams/images/figure62.svg) + +**Figure 62 -- Possible states of a bulk transfer** + +
    + +## API Supporting Data Models + +This section provides information about additional supporting data models used by the API. + +### Format Introduction + +This section introduces formats used for element data types used by the API. + +All element data types have both a minimum and maximum length. These lengths are indicated by one of the following: + +- A minimum and maximum length +- An exact length +- A regular expression limiting the element such that only a specific length or lengths can be used. + +#### Minimum and Maximum Length + +If a minimum and maximum length is used, this will be indicated after the data type in parentheses: First the minimum value (inclusive value), followed by two period characters (..), and then the maximum value (inclusive value). + +Examples: + +- `String(1..32)` – A String that is minimum one character and maximum 32 characters long. +- `Integer(3..10)` - An Integerr that is minimum 3 digits, but maximum 10 digits long. + +#### Exact Length + +If an exact length is used, this will be indicated after the data type in parentheses containing only one exact value. Other lengths are not allowed. + +Examples: + +- `String(3)` – A String that is exactly three characters long. +- `Integer(4)` – An Integer that is exactly four digits long. + +#### Regular Expressions + +Some element data types are restricted using regular expressions. The regular expressions in this document use the standard for syntax and character classes established by the programming language Perl[30](https://perldoc.perl.org/perlre.html#Regular-Expressions). + +### Element Data Type Formats + +This section defines element data types used by the API. + + + +#### String + +The API data type `String` is a normal JSON String[31](https://tools.ietf.org/html/rfc7159#section-7), limited by a minimum and maximum number of characters. + +##### Example Format I + +`String(1..32)` – A String that is minimum *1* character and maximum *32* characters long. + +An example of `String(1..32)` appears below: + +- _This String is 28 characters_ + +##### Example Format II + +`String(1..128)` – A String that is minimum *1* character and maximum *128* characters long. + +An example of `String(32..128)` appears below: + +- _This String is longer than 32 characters, but less than 128_ + +
    + +#### Enum + +The API data type `Enum` is a restricted list of allowed JSON [String](#string)) values; an enumeration of values. Other values than the ones defined in the list are not allowed. + +##### Example Format + +`Enum of String(1..32)` – A String that is minimum one character and maximum 32 characters long and restricted by the allowed list of values. The description of the element contains a link to the enumeration. + +
    + +#### UndefinedEnum + +The API data type **UndefinedEnum** is a JSON String consisting of 1 to 32 uppercase characters including an underscore character (**\_**). + +##### Regular Expression + +The regular expression for restricting the **UndefinedEnum** type appears in [Listing 13](#listing-13). + +###### Listing 13 + +``` +^[A-Z_]{1,32}$ +``` + +**Listing 13 -- Regular expression for data type UndefinedEnum** + +
    + +#### Name + +The API data type `Name` is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. + +##### Regular Expression + +The regular expression for restricting the `Name` type appears in [Listing 14](#listing-14) below. The restriction does not allow a string consisting of whitespace only, all Unicode32 characters are allowed, as well as the period (**.**), apostrophe (**'**), dash (**-**), comma (**,**) and space characters ( ). The maximum number of characters in the **Name** is 128. + +**Note:** In some programming languages, Unicode support needs to be specifically enabled. As an example, if Java is used the flag `UNICODE_CHARACTER_CLASS` needs to be enabled to allow Unicode characters. + +###### Listing 14 + +``` +^(?!\s*$)[\w .,'-]{1,128}$ +``` + +**Listing 14 -- Regular expression for data type Name** + +
    + +#### Integer + +The API data type `Integer` is a JSON String consisting of digits only. Negative numbers and leading zeroes are not allowed. The data type is always limited by a number of digits. + +##### 7.2.5.1 Regular Expression + +The regular expression for restricting an `Integer` appears in [Listing 15](#listing-15). + +###### Listing 15 + +``` +^[1-9]\d*$ +``` + +**Listing 15 -- Regular expression for data type Integer** + + +##### Example Format + +`Integer(1..6)` – An `Integer` that is at minimum one digit long, maximum six digits. + +An example of `Integer(1..6)` appears below: + +- _123456_ + +
    + +#### OtpValue + +The API data type `OtpValue` is a JSON String of three to 10 characters, consisting of digits only. Negative numbers are not allowed. One or more leading zeros are allowed. + +##### Regular Expression + +The regular expression for restricting the `OtpValue` type appears in [Listing 16](#listing-16). + +###### Listing 16 + +``` +^\d{3,10}$ +``` + +**Listing 16 -- Regular expression for data type OtpValue** + +
    + +#### BopCode + +The API data type `BopCode` is a JSON String of three characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. + +##### Regular Expression + +The regular expression for restricting the `BopCode` type appears in [Listing 17](#listing-17). + +###### Listing 17 + +``` +^[1-9]\d{2}$ +``` + +**Listing 17 -- Regular expression for data type BopCode** + +
    + +#### ErrorCode + +The API data type `ErrorCode` is a JSON String of four characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. + +##### Regular Expression + +The regular expression for restricting the `ErrorCode` type appears in [Listing 18](#listing-18). + +###### Listing 18 + +``` +^[1-9]\d{3}$ +``` + +**Listing 18 -- Regular expression for data type ErrorCode** + +
    + +#### TokenCode + +The API data type `TokenCode` is a JSON String between four and 32 characters. It can consist of either digits, uppercase characters from **A** to **Z**, lowercase characters from **a** to **z**, or a combination of the three. + +##### 7.2.9.1 Regular Expression + +The regular expression for restricting the `TokenCode` appears in [Listing 19](#listing-19). + +###### Listing 19 + +``` +^[0-9a-zA-Z]{4,32}$ +``` + +**Listing 19 -- Regular expression for data type TokenCode** + +
    + +#### MerchantClassificationCode + +The API data type `MerchantClassificationCode` is a JSON String consisting of one to four digits. + +##### 7.2.10.1 Regular Expression + +The regular expression for restricting the `MerchantClassificationCode` type appears in [Listing 20](#listing-20). + +###### Listing 20 + +``` +^[\d]{1,4}$ +``` + +**Listing 20 -- Regular expression for data type MerchantClassificationCode** + +
    + +#### Latitude + +The API data type `Latitude` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### 7.2.11.1 Regular Expression + +The regular expression for restricting the `Latitude` type appears in [Listing 21](#listing-21). + +###### Listing 21 + +``` +^(\+|-)?(?:90(?:(?:\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\.[0-9]{1,6})?))$ +``` + +**Listing 21 -- Regular expression for data type Latitude** + +
    + +#### Longitude + +The API data type `Longitude` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### 7.2.12.1 Regular Expression + +The regular expression for restricting the `Longitude` type appears in [Listing 22](#listing-22). + +###### Listing 22 + +``` +^(\+|-)?(?:180(?:(?:\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.[0-9]{1,6})?))$ +``` + +**Listing 22 -- Regular expression for data type Longitude** + +
    + +#### Amount + +The API data type `Amount` is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting the `Amount` type appears in [Listing 23](#listing-23). This pattern does not allow any trailing zeroes at all, but allows an amount without a minor currency unit. It also only allows four digits in the minor currency unit; a negative value is not allowed. Using more than 18 digits in the major currency unit is not allowed. + +###### Listing 23 + +``` +^([0]|([1-9][0-9]{0,17}))([.][0-9]{0,3}[1-9])?$ +``` + +**Listing 23 -- Regular expression for data type Amount** + +##### Example Values + +See [Table 45](#table-45) for validation results for some example **Amount** values using the [regular expression](#regular-expression-6). + +###### Table 45 + +| **Value** | **Validation result** | +| --- | --- | +| **5** | Accepted | +| **5.0** | Rejected | +| **5.** | Rejected | +| **5.00** | Rejected | +| **5.5** | Accepted | +| **5.50** | Rejected | +| **5.5555** | Accepted | +| **5.55555** | Rejected | +| **555555555555555555** | Accepted | +| **5555555555555555555** | Rejected | +| **-5.5** | Rejected | +| **0.5** | Accepted | +| **.5** | Rejected | +| **00.5** | Rejected | +| **0** | Accepted | + +**Table 45 -- Example results for different values for Amount type** + +
    + +#### DateTime + +The API data type `DateTime` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### 7.2.14.1 Regular Expression + +The regular expression for restricting the `DateTime` type appears in [Listing 24](#listing-24). The format is according to ISO 860133, expressed in a combined date, time and time zone format. A more readable version of the format is + +_yyyy_**-**_MM_**-**_dd_**T**_HH_**:**_mm_**:**_ss_**.**_SSS_[**-**_HH_**:**_MM_] + +###### Listing 24 + +``` +^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468\][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:(\.\d{3}))(?:Z|[+-][01]\d:[0-5]\d)$ +``` + +**Listing 24 -- Regular expression for data type DateTime** + +##### Examples + +Two examples of the `DateTime` type appear below: + +**2016-05-24T08:38:08.699-04:00** + +**2016-05-24T08:38:08.699Z** (where **Z** indicates Zulu time zone, which is the same as UTC). + +
    + +#### Date + +The API data type `Date` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting the **Date** type appears in [Listing 25](#listing-25). This format, as specified in ISO 8601, contains a date only. A more readable version of the format is _yyyy_**-**_MM_**-**_dd_. + +###### Listing 25 + +``` +^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$ +``` + +**Listing 25 -- Regular expression for data type Date** + +##### Examples + +Two examples of the `Date` type appear below: + +- _1982-05-23_ + +- _1987-08-05_ + +
    + +#### UUID + +The API data type `UUID` (Universally Unique Identifier) is a JSON String in canonical format, conforming to RFC 412234, that is restricted by a regular expression for interoperability reasons. A UUID is always 36 characters long, 32 hexadecimal symbols and four dashes ('**-**'). + +##### 7.2.16.1 Regular Expression + +The regular expression for restricting the `UUID` type appears in [Listing 26](#listing-26). + +###### Listing 26 + +``` +^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ +``` + +**Listing 26 -- Regular expression for data type UUID** + +##### Example + +An example of a `UUID` type appears below: + +- _a8323bc6-c228-4df2-ae82-e5a997baf898_ + +
    + +#### BinaryString + +The API data type `BinaryString` is a JSON String. The string is a base64url35 encoding of a string of raw bytes, where a padding (character '**=**') is added at the end of the data if needed to ensure that the string is a multiple of four characters. The length restriction indicates the allowed number of characters. + +##### Regular Expression + +The regular expression for restricting the `BinaryString` type appears in [Listing 27](#listing-27). + +###### Listing 27 + +``` +^[A-Za-z0-9-_]+[=]{0,2}$ +``` + +**Listing 27 -- Regular expression for data type BinaryString** + +##### Example Format + +`BinaryString(32)` –32 bytes of data base64url encoded. + +An example of a `BinaryString(32..256)` appears below. Note that a padding character, `'='` has been added to ensure that the string is a multiple of four characters. + +- _QmlsbCAmIE1lbGluZGEgR2F0ZXMgRm91bmRhdGlvbiE=_ + +
    + +#### BinaryString32 + +The API data type `BinaryString32` is a fixed size version of the API data type `BinaryString` defined [here](#binarystring), where the raw underlying data is always of 32 bytes. The data type **BinaryString32** should not use a padding character as the size of the underlying data is fixed. + +##### Regular Expression + +The regular expression for restricting the `BinaryString32` type appears in [Listing 28](#listing-28). + +###### Listing 28 + +``` +^[A-Za-z0-9-_]{43}$ +``` + +**Listing 28 -- Regular expression for data type BinaryString32** + +##### Example Format +`BinaryString(32)` – 32 bytes of data base64url encoded. + +An example of a `BinaryString32` appears below. Note that this is the same binary data as the example shown in the [Example Format](#example-format-4) of the `BinaryString` type, but due to the underlying data being fixed size, the padding character `'='` is excluded. + +``` +QmlsbCAmIE1lbGluZGEgR2F0ZXMgRm91bmRhdGlvbiE +``` + +
    + +### Element Definitions + +This section defines elements types used by the API. + +#### AmountType element + +[Table 46](#table-46) below contains the data model for the element `AmountType`. + +###### Table 46 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **AmountType** | 1 | [Enum](#enum) of [String(1..32)](#string) | This element contains the amount type. See [AmountType](#amounttype-enum) enumeration for more information on allowed values. | + +**Table 46 – Element AmountType** + +
    + +#### AuthenticationType element + +[Table 47](#table-47) below contains the data model for the element `AuthenticationType`. + +###### Table 47 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Authentication** | 1 | [Enum](#enum) of [String(1..32)](#string) | This element contains the authentication type. See [AuthenticationType](#authenticationtype-enum) enumeration for possible enumeration values. | + +**Table 47 – Element AuthenticationType** + +
    + +#### AuthenticationValue element + +[Table 48](#table-48) below contains the data model for the element `AuthenticationValue`. + +###### Table 48 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **AuthenticationValue** | 1 | Depends on [AuthenticationType](#authenticationtype-element).

    If `OTP`: type is [Integer(1..6)](#integer). For example:**123456**

    OtpValue
    If `QRCODE`: type is [String(1..64)](#string) | This element contains the authentication value. The format depends on the authentication type used in the [AuthenticationInfo](#authenticationinfo) complex type. | + +**Table 48 – Element AuthenticationValue** + +
    + +#### AuthorizationResponse element + +[Table 49](#table-49) below contains the data model for the element `AuthorizationResponse`. + +###### Table 49 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **AuthorizationResponse** | 1 | [Enum](#enum) of [String(1..32)](#string) | This element contains the authorization response. See [AuthorizationResponse](#authorizationresponse-enum) enumeration for possible enumeration values. | + +**Table 49 – Element AuthorizationResponse** + +
    + +#### BalanceOfPayments element + +[Table 50](#table-50) below contains the data model for the element `BalanceOfPayment`. + +###### Table 50 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **BalanceOfPayments** | 1 | [BopCode](#bopcode) | The possible values and meaning are defined in [https://www.imf.org/external/np/sta/bopcode/](https://www.imf.org/external/np/sta/bopcode/) | + +**Table 50 – Element BalanceOfPayments** + +
    + +#### BulkTransferState element + +[Table 51](#table-51) below contains the data model for the element `BulkTransferState`. + +###### Table 51 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **BulkTransferState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [BulkTransferState](#bulktransferstate-enum) enumeration for information on allowed values| + +**Table 51 – Element BulkTransferState** + +
    + +#### Code element + +[Table 52](#table-52) below contains the data model for the element `Code`. + +###### Table 52 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Code** | 1 | [TokenCode](#tokencode) | Any code/token returned by the Payee FSP. | + +**Table 52 – Element Code** + +
    + +#### CorrelationId element + +[Table 53](#table-53) below contains the data model for the element `CorrelationId`. + +###### Table 53 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **CorrelationId** | 1 |[UUID](#uuid) | Identifier that correlates all messages of the same sequence. | + + +**Table 53 – Element CorrelationId** + +
    + +#### Currency element + +[Table 54](#table-54) below contains the data model for the element `Currency`. + +###### Table 54 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Currency** | 1 | [Enum](#enum) of [String(3)](#string) | See [Currency](#currencycode-enum) enumeration for information on allowed values | + +**Table 54 – Element Currency** + +
    + +#### DateOfBirth element + +[Table 55](#table-55) below contains the data model for the element `DateOfBirth`. + +###### Table 55 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **DateOfBirth** | 1 | Examples

    Two examples of the [DateTime](#datetime) type appear below:

    2016-05-24T08:38:08.699-04:00

    2016-05-24T08:38:08.699Z (where Z indicates Zulu time zone, which is the same as UTC).

    Date

    | Date of Birth of the Party.| + +**Table 55 – Element DateOfBirth** + +
    + +#### ErrorCode element + +[Table 56](#table-56) below contains the data model for the element `ErrorCode`. + +###### Table 56 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ErrorCode** | 1 | [ErrorCode](#errorcode) | Four digit error code, see section on [Error Codes](#error-codes) for more information. | + +**Table 56 – Element ErrorCode** + +
    + +#### ErrorDescription element + +[Table 57](#table-57] below contains the data model for the element `ErrorDescription`. + +###### Table 57 + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ErrorDescription** | 1 | [String(1..128)](#string) | Error description string. | + +**Table 57 – Element ErrorDescription** + +
    + +#### ExtensionKey element + +[Table 58](#table-58) below contains the data model for the element `ExtensionKey`. + +###### Table 58 + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ExtensionKey** | 1 | [String(1..32)](#string) | The extension key. | + +**Table 58 – Element ExtensionKey** + +
    + +#### ExtensionValue element + +[Table 59](#table-59) below contains the data model for the element `ExtensionValue`. + +###### Table 59 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ExtensionValue** | 1 | [String(1..128)](#string) | The extension value. | + +**Table 59 – Element ExtensionValue** + +
    + +#### FirstName element +[Table 60](#table-60) below contains the data model for the element `FirstName`. + +###### Table 60 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **FirstName** | 1 | [Name](#name) | First name of the Party | + +**Table 60 – Element FirstName** + +
    + +#### FspId element + +[Table 61](#table-61) below contains the data model for the element `FspId`. + +###### Table 61 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **FspId** | 1 | [String(1..32)](#string)| The FSP identifier. | + +**Table 61 – Element FspId** + +
    + +#### IlpCondition element + +[Table 62](#table-62) below contains the data model for the element `IlpCondition`. + +###### Table 62 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **IlpCondition** | 1 | [BinaryString32](#binarystring32) | The condition that must be attached to the transfer by the Payer. | + +**Table 62 – Element IlpCondition** + +
    + +#### IlpFulfilment element + +[Table 63](#table-63) below contains the data model for the element `IlpFulfilment`. + +###### Table 63 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **IlpFulfilment** | 1 | [BinaryString32](#binarystring32) | The fulfilment that must be attached to the transfer by the Payee. | + +**Table 63 – Element IlpFulfilment** + +
    + +#### IlpPacket element + +[Table 64](#table-64) below cntains the data model for the element `IlpPacket`. + +###### Table 64 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **IlpPacket** | 1 | Example

    An example of a [UUID](#uuid) type appears below:

    a8323bc6-c228-4df2-ae82-e5a997baf898

    [BinaryString(1..32768)](#binarystring)

    | Information for recipient (transport layer information). | + +**Table 64 – Element IlpPacket** + +
    + +#### LastName element + +[Table 65](#table-65) below contains the data model for the element `LastName`. + +###### Table 65 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **LastName** | 1 | [Name](#name) | Last name of the Party (ISO 20022 definition). | + +**Table 65 – Element LastName** + +
    + +#### MerchantClassificationCode element + +[Table 66](#table-66) below contains the data model for the element `MerchantClassificationCode`. + +###### Table 66 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **MerchantClassificationCode** | 1 | [MerchantClassificationCode](#merchantclassificationcode) | A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, and so on. | + +**Table 66 – Element MerchantClassificationCode** + +
    + +#### MiddleName element + +[Table 67](#table-67) below contains the data model for the element `MiddleName`. + +###### Table 67 + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **MiddleName** | 1 | [Name](#name) | Middle name of the Party (ISO 20022 definition). | + +**Table 67 – Element MiddleName** + +
    + +#### Note element + +[Table 68](#table-68) below contains the data model for the element `Note`. + +###### Table 68 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Note** | 1 | [String(1..128)](#string) | Memo assigned to transaction. | + +**Table 68 – Element Note** + +
    + + +#### PartyIdentifier element + +[Table 69](#table-69) below contains the data model for the element `PartyIdentifier`. + +###### Table 69 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartyIdentifier** | 1 | [String(1..128)](#string) | Identifier of the Party.| + +**Table 69 – Element PartyIdentifier** + +
    + +#### PartyIdType element + +[Table 70](#table-70) below contains the data model for the element `PartyIdType`. + +###### Table 70 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartyIdType** | 1 | Enum of [String(1..32)](#string) | See [PartyIdType](#partyidtype-enum) enumeration for more information on allowed values. | + +**Table 70 – Element PartyIdType** + +
    + +#### PartyName element + +[Table 71](#table-71) below contains the data model for the element `PartyName`. + +###### Table 71 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartyName** | 1 | `Name` | Name of the Party. Could be a real name or a nickname. | + +**Table 71 – Element PartyName** + +
    + +#### PartySubIdOrType element + +[Table 72](#table-72) below contains the data model for the element `PartySubIdOrType`. + +###### Table 72 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartySubIdOrType** | 1 | [String(1..128)](#string) | Either a sub-identifier of a [PartyIdentifier](#partyidentifier-element), or a sub-type of the [PartyIdType](#partyidtype-element), normally a `PersonalIdentifierType`. | + +**Table 72 – Element PartySubIdOrType** + +
    + +#### RefundReason element + +[Table 73](#table-73) below contains the data model for the element `RefundReason`. + +###### Table 73 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **RefundReason** | 1 | [String(1..128)](#string) | Reason for the refund. | + +**Table 73 – Element RefundReason** + +
    + +#### TransactionInitiator element + +[Table 74](#table-74) below contains the data model for the element `TransactionInitiator`. + +###### Table 74 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionInitiator** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionInitiator](#transactioninitiator-enum) enumeration for more information on allowed values. | + +**Table 74 – Element TransactionInitiator** + +
    + +#### TransactionInitiatorType element + +[Table 75](#table-75) below contains the data model for the element `TransactionInitiatorType`. + +###### Table 75 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionInitiatorType** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionInitiatorType](#transactioninitiatortype-enum) enumeration for more information on allowed values. | + +**Table 75 – Element TransactionInitiatorType** + +
    + +#### TransactionRequestState element + +[Table 76](#table-76) below contains the data model for the element `TransactionRequestState`. + +###### Table 76 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionRequestState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionRequestState](#transactionrequeststate-enum) enumeration for more information on allowed values. | + + +**Table 76 – Element TransactionRequestState** + +
    + +#### TransactionScenario element + +[Table 77](#table-77) below contains the data model for the element `TransactionScenario`. + +###### Table 77 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionScenario** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionScenario](#transactionscenario-enum) enumeration for more information on allowed values. | + +**Table 77 – Element TransactionScenario** + +
    + +#### TransactionState element + +[Table 78](#table-78) below contains the data model for the element `TransactionState`. + +###### Table 78 + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionState](#transactionstate-enum) enumeration for more information on allowed values. | + +**Table 78 – Element TransactionState** + +
    + + +#### TransactionSubScenario element + +[Table 79](#table-79) below contains the data model for the element `TransactionSubScenario`. + +###### Table 79 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionSubScenario** | 1 | [UndefinedEnum](#undefinedenum) | Possible sub-scenario, defined locally within the scheme.| + +**Table 79 – Element TransactionSubScenario** + +
    + +#### TransferState element + +[Table 80](#table-80) below contains the data model for the element `TransferState`. + +###### Table 80 + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransferState](#transferstate-enum) enumeration for more information on allowed values. | + +**Table 80 – Element TransferState** + + +
    + + +### Complex Types + +This section describes complex types used by the API. + +#### AuthenticationInfo + +[Table 81](#table-81) contains the data model for the complex type `AuthenticationInfo`. + +###### Table 81 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **authentication** | 1 | `AuthenticationType` | Type of authentication. | +| **authenticationValue** | 1 | `AuthenticationValue` | Authentication value. | + +**Table 81 -- Complex type AuthenticationInfo** + +
    + +#### ErrorInformation + +[Table 82](#table-82) contains the data model for the complex type `ErrorInformation`. + +###### Table 82 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **errorCode** | 1 | `Errorcode` | Specific error number. | +| **errorDescription** | 1 | `ErrorDescription` | Error description string. | +| **extensionList** | 1 | `ExtensionList` | Optional list of extensions, specific to deployment. | + +**Table 82 -- Complex type ErrorInformation** + +
    + +#### Extension + +[Table 83](#table-83) contains the data model for the complex type `Extension`. + +###### Table 83 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **key** | 1 | `ExtensionKey` | Extension key. | +| **value** | 1 | `ExtensionValue` | Extension value. | + +**Table 83 -- Complex type Extension** + +
    + +#### ExtensionList + +[Table 84](#table-84) contains the data model for the complex type `ExtensionList`. + +###### Table 84 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **extension** | 1..16 | `Extension` | Number of Extension elements. | + +**Table 84 -- Complex type ExtensionList** + +
    + +#### IndividualQuote + +[Table 85](#table-85) contains the data model for the complex type `IndividualQuote`. + +###### Table 85 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **quoteId** | 1 | `CorrelationId` | Identifies quote message. | +| **transactionId** | 1 | `CorrelationId` | Identifies transaction message. | +| **payee** | 1 | `Party` | Information about the Payee in the proposed financial transaction. | +| **amountType** | 1 | `AmountType` | **SEND** for sendAmount, **RECEIVE** for receiveAmount. | +| **amount** | 1 | `Money` | Depending on **amountType**:
    If **SEND**: The amount the Payer would like to send; that is, the amount that should be withdrawn from the Payer account including any fees. The amount is updated by each participating entity in the transaction.
    If **RECEIVE**: The amount the Payee should receive; that is, the amount that should be sent to the receiver exclusive any fees. The amount is not updated by any of the participating entities. | +| **fees** | 0..1 | `Money` | Fees in the transaction.
    • The fees element should be empty if fees should be non-disclosed.
    • The fees element should be non-empty if fees should be disclosed.
    +| **transactionType** | 1 | `TransactionType` | Type of transaction that the quote is requested for. | +| **note** | 0..1 | Note | Memo that will be attached to the transaction.| +| **extensionList** | 0..1 | `ExtensionList` | Optional extension, specific to deployment. | + +**Table 85 -- Complex type IndividualQuote** + +
    + +#### IndividualQuoteResult + +[Table 86](#table-86) contains the data model for the complex type `IndividualQuoteResult`. + +###### Table 86 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **quoteId** | 1 | `CorrelationId` | Identifies the quote message. | +| **payee** | 0..1 | `Party` | Information about the Payee in the proposed financial transaction. | +| **transferAmount** | 0..1 | `Money` | The amount of Money that the Payer FSP should transfer to the Payee FSP. | +| **payeeReceiveAmount** | 0..1 | `Money` | Amount that the Payee should receive in the end-to-end transaction. Optional as the Payee FSP might not want to disclose any optional Payee fees. | +| **payeeFspFee** | 0..1 | `Money` | Payee FSP’s part of the transaction fee. | +| **payeeFspCommission** | 0..1 | `Money` | Transaction commission from the Payee FSP. | +| **ilpPacket** | 0..1 | `IlpPacket` | ILP Packet that must be attached to the transfer by the Payer. | +| **condition** | 0..1 | `IlpCondition` | Condition that must be attached to the transfer by the Payer. | +| **errorInformation** | 0..1 | `ErrorInformation` | Error code, category description.
    **Note: payee, transferAmount, payeeReceiveAmount, payeeFspFee, payeeFspCommission, ilpPacket,** and **condition** should not be set if **errorInformation** is set.
    +| **extensionList** | 0..1 | `ExtensionList` | Optional extension, specific to deployment | + +**Table 86 -- Complex type IndividualQuoteResult** + +
    + +#### IndividualTransfer + +[Table 87](#table-87) contains the data model for the complex type `IndividualTransfer`. + +###### Table 87 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **transferId** | 1 | `CorrelationId` | Identifies messages related to the same **/transfers** sequence. | +| **transferAmount** | 1 | `Money` | Transaction amount to be sent. | +| **ilpPacket** | 1 | `IlpPacket` | ILP Packet containing the amount delivered to the Payee and the ILP Address of the Payee and any other end-to-end data. | +| **condition** | 1 | `IlpCondition` | Condition that must be fulfilled to commit the transfer. | +| **extensionList** | 0..1 | `ExtensionList` | Optional extension, specific to deployment. | + +**Table 87 -- Complex type IndividualTransfer** + +
    + +#### IndividualTransferResult + +[Table 88](#table-88) contains the data model for the complex type `IndividualTransferResult`. + +###### Table 88 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **transferId** | 1 | `CorrelationId` | Identifies messages related to the same /transfers sequence. | +| **fulfilment** | 0..1 | `IlpFulfilment` | Fulfilment of the condition specified with the transaction.
    **Note:** Either **fulfilment** or **errorInformation** should be set, not both. | +| **errorInformation** | 0..1 | `ErrorInformation` | If transfer is REJECTED, error information may be provided.
    **Note:** Either **fulfilment** or **errorInformation** should be set, not both.| +| **extensionList** | 0..1 | `ExtensionList` | Optional extension, specific to deployment.| + +**Table 88 -- Complex type IndividualTransferResult** + +
    + +#### GeoCode + +[Table 89](#table-89) contains the data model for the complex type `GeoCode`. + +###### Table 89 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **latitude** | 1 | `Latitude` | Latitude of the Party. | +| **longitude** | 1 | `Longitude` | Longitude of the Party. | + +**Table 89 -- Complex type GeoCode** + +
    + +#### Money + +[Table 90](#table-90) contains the data model for the complex type `Money`. + +###### Table 90 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **currency** | 1 | `Currency` | Currency of the amount. | +| **amount** | 1 | `Amount` | Amount of money. | + +**Table 90 -- Complex type Money** + +
    + +#### Party + +[Table 91](#table-91) contains the data model for the complex type `Party`. + +###### Table 91 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **partyIdInfo** | 1 | `PartyIdInfo` | Party Id type, id, sub ID or type, and FSP Id. | +| **merchantClassificationCode** | 0..1 | `MerchantClassificationCode` | Used in the context of Payee Information, where the Payee happens to be a merchant accepting merchant payments. | +| **name** | 0..1 | `PartyName` | Display name of the Party, could be a real name or a nick name. | +| **personalInfo** | 0..1 | `PartyPersonalInfo` | Personal information used to verify identity of Party such as first, middle, last name and date of birth. | + +**Table 91 -- Complex type Party** + +
    + +#### PartyComplexName + +[Table 92](#table-92) contains the data model for the complex type `PartyComplexName`. + +###### Table 92 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **firstName** | 0..1 | `FirstName` | Party's first name. | +| **middleName** | 0..1 | `MiddleName` | Party's middle name. | +| **lastName** | 0..1 | `LastName` | Party's last name. | + +**Table 92 -- Complex type PartyComplexName** + +
    + +#### PartyIdInfo + +[Table 93](#table-93) contains the data model for the complex type `PartyIdInfo`. + +###### Table 93 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **partyIdType** | 1 | `PartyIdType` | Type of the identifier. | +| **partyIdentifier** | 1 | `PartyIdentifier` | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | `PartySubIdOrType` | A sub-identifier or sub-type for the Party. | +| **fspId** | 0..1 | `FspId` | FSP ID (if know) | +| **extensionList** | 0..1 | `ExtensionList` | Optional extension, specific to deployment. | + +**Table 93 -- Complex type PartyIdInfo** + +
    + +#### PartyPersonalInfo + +[Table 94](#table-94) contains the data model for the complex type `PartyPersonalInfo`. + +###### Table 94 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **complexName** | 0..1 | `PartyComplexName` | First, middle and last name for the Party. | +| **dateOfBirth** | 0..1 | `DateOfBirth` | Date of birth for the Party. | + +**Table 94 -- Complex type PartyPersonalInfo** + +
    + +#### PartyResult + +[Table 95](#table-95) contains the data model for the complex type `PartyResult`. + +###### Table 95 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **partyId** | 1 | `PartyIdInfo` | Party Id type, id, sub ID or type, and FSP Id. | +| **errorInformation** | 0..1 | `ErrorInformation` | If the Party failed to be added, error information should be provided. Otherwise, this parameter should be empty to indicate success. | + +**Table 95 -- Complex type PartyResult** + +
    + +#### Refund + +[Table 96](#table-96) contains the data model for the complex type `Refund`. + +###### Table 96 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **originalTransactionId** | 1 | `CorrelationId` | Reference to the original transaction ID that is requested to be refunded. | +| **refundReason** | 0..1 | `RefundReason` | Free text indicating the reason for the refund. | + +**Table 96 -- Complex type Refund** + +
    + +#### Transaction + +[Table 97](#table-97) contains the data model for the complex type Transaction. The Transaction type is used to carry end-to-end data between the Payer FSP and the Payee FSP in the ILP Packet, see [IlpPacket](#ilp-packet). Both the **transactionId** and the **quoteId** in the data model is decided by the Payer FSP in the [POST /quotes](#post-quotes), see [Table 23](#table-23). + +###### Table 97 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **transactionId** | 1 | `CorrelationId` | ID of the transaction, the ID is decided by the Payer FSP during the creation of the quote. | +| **quoteId** | 1 | `CorrelationId` | ID of the quote, the ID is decided by the Payer FSP during the creation of the quote. | +| **payee** | 1 | `Party` | Information about the Payee in the proposed financial transaction. | +| **payer** | 1 | `Party` | Information about the Payer in the proposed financial transaction. | +| **amount** | 1 | `Money` | Transaction amount to be sent. | +| **transactionType** | 1 | `TransactionType` | Type of the transaction. | +| **note** | 0..1 | `Note` | Memo associated to the transaction, intended to the Payee. | +| **extensionList** | 0..1 | `ExtensionList` | Optional extension, specific to deployment. | + +**Table 97 -- Complex type Transaction** + +
    + +#### TransactionType + +[Table 98](#table-98) contains the data model for the complex type `TransactionType`. + +###### Table 98 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **scenario** | 1 | `TransactionScenario` | Deposit, withdrawal, refund, ... | +| **subScenario** | 0..1 | `TransactionSubScenario` | Possible sub-scenario, defined locally within the scheme. | +| **initiator** | 1 | `TransactionInitiator` | Who is initiating the transaction: Payer or Payee | +| **initiatorType** | 1 | `TransactionInitiatorType` | Consumer, agent, business, ... | +| **refundInfo** | 0..1 | `Refund` | Extra information specific to a refund scenario. Should only be populated if scenario is REFUND. | +| **balanceOfPayments** | 0..1 | `BalanceOfPayments` | Balance of Payments code. | + +**Table 98 -- Complex type TransactionType** + +
    + +### Enumerations + +This section contains the enumerations that are used by the API. + +#### AmountType enum + +[Table 99](#table-99) contains the allowed values for the enumeration `AmountType`. + +###### Table 99 + +| **Name** | **Description** | +| --- | --- | +| **SEND** | Amount the Payer would like to send; that is, the amount that should be withdrawn from the Payer account including any fees. | +| **RECEIVE** | Amount the Payer would like the Payee to receive; that is, the amount that should be sent to the receiver exclusive fees. | + +**Table 99 -- Enumeration AmountType** + +
    + +#### AuthenticationType enum + +[Table 100](#table-100) contains the allowed values for the enumeration `AuthenticationType`. + +###### Table 100 + +| **Name** | **Description** | +| --- | --- | +| **OTP** | One-time password generated by the Payer FSP. | +| **QRCODE** | QR code used as One Time Password. | + +**Table 100 -- Enumeration AuthenticationType** + +
    + +#### AuthorizationResponse enum + +[Table 101](#table-101) contains the allowed values for the enumeration `AuthorizationResponse`. + +###### Table 101 + +| **Name** | **Description** | +| --- | --- | +| **ENTERED** | Consumer entered the authentication value. | +| **REJECTED** | Consumer rejected the transaction. | +| **RESEND** | Consumer requested to resend the authentication value. | + +**Table 101 -- Enumeration AuthorizationResponse** + +
    + +#### BulkTransferState enum + +[Table 102](#table-102) contains the allowed values for the enumeration `BulkTransferState`. + +###### Table 102 + +| **Name** | **Description** | +| --- | --- | +| **RECEIVED** | Payee FSP has received the bulk transfer from the Payer FSP. | +| **PENDING** | Payee FSP has validated the bulk transfer. | +| **ACCEPTED** | Payee FSP has accepted the bulk transfer for processing. | +| **PROCESSING** | Payee FSP has started to transfer fund to the Payees. | +| **COMPLETED** | Payee FSP has completed transfer of funds to the Payees. | +| **REJECTED** | Payee FSP has rejected processing the bulk transfer. | + +**Table 102 -- Enumeration BulkTransferState** + +
    + +#### CurrencyCode enum + +The currency codes defined in ISO 421736 as three-letter alphabetic codes are used as the standard naming representation for currencies. The currency codes from ISO 4217 are not shown in this document, implementers are instead encouraged to use the information provided by the ISO 4217 standard directly. + +
    + +#### PartyIdType enum + +[Table 103](#Table-103) contains the allowed values for the enumeration `PartyIdType`. + +###### Table 103 + +| **Name** | **Description** | +| --- | --- | +| **MSISDN** | An MSISDN (Mobile Station International Subscriber Directory Number; that is, a phone number) is used in reference to a Party. The MSISDN identifier should be in international format according to the ITU-T E.16437 standard. Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix. | +| **EMAIL** | An email is used in reference to a Party. The format of the email should be according to the informational RFC 369638. | +| **PERSONAL_ID** | A personal identifier is used in reference to a participant. Examples of personal identification are passport number, birth certificate number, and national registration number. The identifier number is added in the [PartyIdentifier](#partyidentifier-element) element. The personal identifier type is added in the [PartySubIdOrType](#partysubidortype-element) element. | +| **BUSINESS** | A specific Business (for example, an organization or a company) is used in reference to a participant. The BUSINESS identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the [PartySubIdOrType](#partysubidortype-element) element should be used. | +| **DEVICE** | A specific device (for example, POS or ATM) ID connected to a specific business or organization is used in reference to a Party. For referencing a specific device under a specific business or organization, use the [PartySubIdOrType](#partysubidortype-element) element. | +| **ACCOUNT_ID** | A bank account number or FSP account ID should be used in reference to a participant. The ACCOUNT_ID identifier can be in any format, as formats can greatly differ depending on country and FSP. +| **IBAN** | A bank account number or FSP account ID is used in reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without whitespace. | +| **ALIAS** | An alias is used in reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias is a username in the FSP system. The ALIAS identifier can be in any format. It is also possible to use the [PartySubIdOrType](#partysubidortype-element) element for identifying an account under an Alias defined by the [PartyIdentifier](#partyidentifier-element). | + +**Table 103 -- Enumeration PartyIdType** + +
    + +#### PersonalIdentifierType enum + +[Table 104](#table-104) contains the allowed values for the enumeration `PersonalIdentifierType`. + +###### Table 104 + +| **Name** | **Description** | +| --- | --- | +| **PASSPORT** | A passport number is used in reference to a Party. | +| **NATIONAL_REGISTRATION** | A national registration number is used in reference to a Party. | +| **DRIVING_LICENSE** | A driving license is used in reference to a Party. | +| **ALIEN_REGISTRATION** | An alien registration number is used in reference to a Party. | +| **NATIONAL_ID_CARD** | A national ID card number is used in reference to a Party. | +| **EMPLOYER_ID** | A tax identification number is used in reference to a Party. | +| **TAX_ID_NUMBER** | A tax identification number is used in reference to a Party. | +| **SENIOR_CITIZENS_CARD** | A senior citizens card number is used in reference to a Party. | +| **MARRIAGE_CERTIFICATE** | A marriage certificate number is used in reference to a Party. | +| **HEALTH_CARD** | A health card number is used in reference to a Party. | +| **VOTERS_ID** | A voter’s identification number is used in reference to a Party. | +| **UNITED_NATIONS** | An UN (United Nations) number is used in reference to a Party. | +| **OTHER_ID** | Any other type of identification type number is used in reference to a Party. | + +**Table 104 -- Enumeration PersonalIdentifierType** + +
    + +#### TransactionInitiator + +[Table 105](#table-105) describes valid values for the enumeration `TransactionInitiator`. + +###### Table 105 + +| **Name** | **Description** | +| --- | --- | +| **PAYER** | Sender of funds is initiating the transaction. The account to send from is either owned by the Payer or is connected to the Payer in some way. | +| **PAYEE** | Recipient of the funds is initiating the transaction by sending a transaction request. The Payer must approve the transaction, either automatically by a pre-generated OTP or by pre-approval of the Payee, or manually by approving on their own Device. | + +**Table 105 -- Enumeration TransactionInitiator** + +
    + +#### TransactionInitiatorType + +[Table 106](#table-106) contains the allowed values for the enumeration `TransactionInitiatorType`. + +###### Table 106 + +| **Name** | **Description** | +| --- | --- | +| **CONSUMER ** | Consumer is the initiator of the transaction. | +| **AGENT** | Agent is the initiator of the transaction. | +| **BUSINESS** | Business is the initiator of the transaction. | +| **DEVICE** | Device is the initiator of the transaction. | + +**Table 106 -- Enumeration TransactionInitiatorType** + +
    + +#### TransactionRequestState + +[Table 107](#table-107) contains the allowed values for the enumeration `TransactionRequestState`. + +###### Table 107 + +| **Name** | **Description** | +| --- | --- | +| **RECEIVED** | Payer FSP has received the transaction from the Payee FSP. | +| **PENDING** | Payer FSP has sent the transaction request to the Payer. | +| **ACCEPTED** | Payer has approved the transaction. | +| **REJECTED** | Payer has rejected the transaction. | + +**Table 107 -- Enumeration TransactionRequestState** + +
    + +#### TransactionScenario + +[Table 108](#table-108) contains the allowed values for the enumeration `TransactionScenario`. + +###### Table 108 + +| **Name** | **Description** | +| --- | --- | +| **DEPOSIT** | Used for performing a Cash-In (deposit) transaction. In a normal scenario, electronic funds are transferred from a Business account to a Consumer account, and physical cash is given from the Consumer to the Business User. | +| **WITHDRAWAL** | Used for performing a Cash-Out (withdrawal) transaction. In a normal scenario, electronic funds are transferred from a Consumer’s account to a Business account, and physical cash is given from the Business User to the Consumer. | +| **TRANSFER** | Used for performing a P2P (Peer to Peer, or Consumer to Consumer) transaction. | +| **PAYMENT** | Usually used for performing a transaction from a Consumer to a Merchant or Organization, but could also be for a B2B (Business to Business) payment. The transaction could be online for a purchase in an Internet store, in a physical store where both the Consumer and Business User are present, a bill payment, a donation, and so on. | +| **REFUND** | Used for performing a refund of transaction. | + +**Table 108 -- Enumeration TransactionScenario** + +
    + +#### TransactionState + +[Table 109](#table-109) contains the allowed values for the enumeration `TransactionState`. + +###### Table 109 + +| **Name** | **Description** | +| --- | --- | +| **RECEIVED** | Payee FSP has received the transaction from the Payer FSP. | +| **PENDING** | Payee FSP has validated the transaction. | +| **COMPLETED** | Payee FSP has successfully performed the transaction. | +| **REJECTED** | Payee FSP has failed to perform the transaction. | + +**Table 109 -- Enumeration TransactionState** + +
    + +#### TransferState + +[Table 110](#table-110) contains the allowed values for the enumeration `TransferState`. + +###### Table 110 + +| **Name** | **Description** | +| --- | --- | +| **RECEIVED** | Next ledger has received the transfer. | +| **RESERVED** | Next ledger has reserved the transfer. | +| **COMMITTED** | Next ledger has successfully performed the transfer. | +| **ABORTED** | Next ledger has aborted the transfer due a rejection or failure to perform the transfer. | + +**Table 110 -- Enumeration TransferState** + +
    + +### Error Codes + +###### Figure 63 + +Each error code in the API is a four-digit number, for example, **1234**, where the first number (**1** in the example) represents the high-level error category, the second number (**2** in the example) represents the low-level error category, and the last two numbers (**34** in the example) represents the specific error. [Figure 63](#figure-63) shows the structure of an error code. The following sections contain information about defined error codes for each high-level error category. + +![Figure 63](../../assets/diagrams/images/figure63.svg) + +**Figure 63 -- Error code structure** + +Each defined high- and low-level category combination contains a generic error (_x_**0**_xx_), which can be used if there is no specific error, or if the server would not like to return information which is considered private. + +All specific errors below _xx_**40**; that is, _xx_**00** to _xx_**39**, are reserved for future use by the API. All specific errors above and including _xx_**40** can be used for scheme-specific errors. If a client receives an unknown scheme-specific error, the unknown scheme-specific error should be interpreted as a generic error for the high- and low-level category combination instead (_xx_**00**). + +#### Communication Errors -- 1_xxx_ + +All possible communication or network errors that could arise that cannot be represented by an HTTP status code should use the high-level error code **1** (error codes **1**_xxx_). Because all services in the API are asynchronous, these error codes should generally be used by a Switch in the Callback to the client FSP if the Peer FSP cannot be reached, or when a callback is not received from the Peer FSP within an agreed timeout. + +Low level categories defined under Communication Errors: + +- **Generic Communication Error** -- **10**_xx_ + +See [Table 111](#table-111) for all communication errors defined in the API. + +###### Table 111 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **1000** | Communication error | Generic communication error. | X | X | X | X | X | X | X | X | X | +| **1001** | Destination communication error | Destination of the request failed to be reached. This usually indicates that a Peer FSP failed to respond from an intermediate entity. | X | X | X | X | X | X | X | X | X | + +**Table 111 -- Communication errors -- 1_xxx_** + +#### Server Errors -- 2_xxx_ + +All possible errors occurring on the server in which it failed to fulfil an apparently valid request from the client should use the high-level error code **2** (error codes **2**_xxx_). These error codes should indicate that the server is aware that it has encountered an error or is otherwise incapable of performing the requested service. + +Low-level categories defined under server errors: + +- **Generic server error** -- **20**_xx_ + +See [Table 112](#Table-112) for server errors defined in the API. + +###### Table 112 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **2000** | Generic server error | Generic server error to be used in order not to disclose information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **2001** | Internal server error | Generic unexpected exception. This usually indicates a bug or unhandled error case. | X | X | X | X | X | X | X | X | X | +| **2002** | Not implemented | Service requested is not supported by the server. | X | X | X | X | X | X | X | X | X | +| **2003** | Service currently unavailable | Service requested is currently unavailable on the server. This could be because maintenance is taking place, or because of a temporary failure. | X | X | X | X | X | X | X | X | X | +| **2004** | Server timed out | Timeout has occurred, meaning the next Party in the chain did not send a callback in time. This could be because a timeout is set too low or because something took longer than expected. | X | X | X | X | X | X | X | X | X | +| **2005** | Server busy | Server is rejecting requests due to overloading. Try again later. | X | X | X | X | X | X | X | X | X | + +**Table 112 -- Server errors -- 2_xxx_** + +#### Client Errors -- 3_xxx_ + +All possible errors occurring on the server in which the server reports that the client has sent one or more erroneous parameters should use the high-level error code **3** (error codes **3**_xxx_). These error codes should indicate that the server could not perform the service according to the request from the client. The server should provide an explanation why the service could not be performed. + +Low level categories defined under client Errors: + +- **Generic Client Error** -- **30**_xx_ + + - See [Table 113](#table-113) for generic client errors defined in the API. + +- **Validation Error** -- **31**_xx_ + + - See [Table 114](#table-114) the validation errors defined in the API. + +- **Identifier Error** -- **32**_xx_ + + - See [Table 115](#table-115) for identifier errors defined in the API. + +- **Expired Error** -- **33**_xx_ + + - See [Table 116](#table-116) for expired errors defined in the API. + +###### Table 113 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **3000** | Generic client error | Generic client error, used in order not to disclose information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **3001** | Unacceptable version requested | Client requested to use a protocol version which is not supported by the server. | X | X | X | X | X | X | X | X | X | +| **3002** | Unknown URI | Provided URI was unknown to the server. | X | X | X | X | X | X | X | X | X | +| **3003** | Add Party information error | Error occurred while adding or updating information regarding a Party. | X | X | X | X | X | X | X | X | X | + +**Table 113 -- Generic client errors -- 30_xx_** + +###### Table 114 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **3100** | Generic validation error | Generic validation error to be used in order not to disclose information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **3101** | Malformed syntax | Format of the parameter is not valid. For example, amount set to **5.ABC**. The error description field should specify which information element is erroneous. | X | X | X | X | X | X | X | X | X | +| **3102** | Missing mandatory element | Mandatory element in the data model was missing. | X | X | X | X | X | X | X | X | X | +| **3103** | Too many elements | Number of elements of an array exceeds the maximum number allowed. | X | X | X | X | X | X | X | X | X | +| **3104** | Too large payload | Size of the payload exceeds the maximum size. | X | X | X | X | X | X | X | X | X | +| **3105** | Invalid signature | Some parameters have changed in the message, making the signature invalid. This may indicate that the message may have been modified maliciously. | X | X | X | X | X | X | X | X | X | +| **3106** | Modified request | Request with the same ID has previously been processed in which the parameters are not the same. ||| X | X | X | X | X | X | X | +| **3107** | Missing mandatory extension parameter | Scheme-mandatory extension parameter was missing. ||| X | X | X | X | X | X | X | + +**Table 114 -- Validation errors -- 31_xx_** + +###### Table 115 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **3200** | Generic ID not found | Generic ID error provided by the client. | X | X | X | X | X | X | X | X | X | +| **3201** | Destination FSP Error | Destination FSP does not exist or cannot be found. | X | X | X | X | X | X | X | X | X | +| **3202** | Payer FSP ID not found |Provided Payer FSP ID not found. |||||| X ||| X | +| **3203** | Payee FSP ID not found |Provided Payee FSP ID not found. |||||| X ||| X | +| **3204** | Party not found |Party with the provided identifier, identifier type, and optional sub id or type was not found. | X | X | X | X |||||| +| **3205** | Quote ID not found |Provided Quote ID was not found on the server. |||| X || X |||| +| **3206** | Transaction request ID not found |Provided Transaction Request ID was not found on the server. ||| X ||| X |||| +| **3207** | Transaction ID not found |Provided Transaction ID was not found on the server. ||||||| X ||| +| **3208** | Transfer ID not found |Provided Transfer ID was not found on the server. |||||| X |||| +| **3209** | Bulk quote ID not found |Provided Bulk Quote ID was not found on the server. |||||||| X | X | +| **3210** | Bulk transfer ID not found |Provided Bulk Transfer ID was not found on the server. ||||||||| X | + +**Table 115 -- Identifier errors -- 32_xx_** + +###### Table 116 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **3300** | Generic expired error | Generic expired object error, to be used in order not to disclose information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **3301** | Transaction request expired | Client requested to use a transaction request that has already expired. |||| X |||||| +| **3302** | Quote expired | Client requested to use a quote that has already expired. ||||| X | X ||| X | +| **3303** | Transfer expired | Client requested to use a transfer that has already expired. | X | X | X | X | X | X | X | X | X | + +**Table 116 -- Expired errors -- 33_xx_** + +#### Payer Errors -- 4_xxx_ + +All errors occurring on the server for which the Payer or the Payer FSP is the cause of the error should use the high-level error code **4** (error codes **4**_xxx_). These error codes indicate that there was no error on the server or in the request from the client, but the request failed for a reason related to the Payer or the Payer FSP. The server should provide an explanation why the service could not be performed. + +Low level categories defined under Payer Errors: + +- **Generic Payer Error** -- **40**_xx_ + +- **Payer Rejection Error** -- **41**_xx_ + +- **Payer Limit Error** -- **42**_xx_ + +- **Payer Permission Error** -- **43**_xx_ + +- **Payer Blocked Error** -- **44**_xx_ + +See [Table 117](#table-117) for Payer errors defined in the API. + +###### Table 117 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **4000** | Generic Payer error | Generic error related to the Payer or Payer FSP. Used for protecting information that may be considered private. ||| X | X | X | X | X | X | X | +| **4001** | Payer FSP insufficient liquidity | Payer FSP has insufficient liquidity to perform the transfer. |||||| X |||| +| **4100** | Generic Payer rejection | Payer or Payer FSP rejected the request. ||| X | X | X | X | X | X | X | +| **4101** | Payer rejected transaction request | Payer rejected the transaction request from the Payee. ||| X ||||||| +| **4102** | Payer FSP unsupported transaction type |Payer FSP does not support or rejected the requested transaction type ||| X ||||||| +| **4103** | Payer unsupported currency | Payer does not have an account which supports the requested currency. ||| X ||||||| +| **4200** | Payer limit error | Generic limit error, for example, the Payer is making more payments per day or per month than they are allowed to, or is making a payment which is larger than the allowed maximum per transaction. ||| X | X || X || X | X | +| **4300** | Payer permission error | Generic permission error, the Payer or Payer FSP does not have the access rights to perform the service. ||| X | X | X | X | X | X | X | +| **4400** | Generic Payer blocked error | Generic Payer blocked error; the Payer is blocked or has failed regulatory screenings. ||| X | X | X | X | X | X | X | + +**Table 117 -- Payer errors -- 4_xxx_** + +#### Payee Errors -- 5_xxx_ + +All errors occurring on the server for which the Payee or the Payee FSP is the cause of an error use the high-level error code **5** (error codes **5**_xxx_). These error codes indicate that there was no error on the server or in the request from the client, but the request failed for a reason related to the Payee or the Payee FSP. The server should provide an explanation why the service could not be performed. + +Low level categories defined under Payee Errors: + +- **Generic Payee Error** -- **50**_xx_ + +- **Payee Rejection Error** -- **51**_xx_ + +- **Payee Limit Error** -- **52**_xx_ + +- **Payee Permission Error** -- **53**_xx_ + +- **Payee Blocked Error** -- **54**_xx_ + +See [Table 118](#table-118) for all Payee errors defined in the API. + +###### Table 118 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **5000** | Generic Payee error | Generic error due to the Payer or Payer FSP, to be used in order not to disclose information that may be considered private. ||| X | X | X | X | X | X | X | +| **5001** | Payee FSP insufficient liquidity | Payee FSP has insufficient liquidity to perform the transfer. |||||| X |||| +| **5100** | Generic Payee rejection | Payee or Payee FSP rejected the request. ||| X | X | X | X | X | X | X | +| **5101** | Payee rejected quote | Payee does not want to proceed with the financial transaction after receiving a quote. |||| X |||| X || +| **5102** | Payee FSP unsupported transaction type | Payee FSP does not support or has rejected the requested transaction type |||| X ||||| X | +| **5103** | Payee FSP rejected quote | Payee FSP does not want to proceed with the financial transaction after receiving a quote. |||| X |||| X || +| **5104** | Payee rejected transaction | Payee rejected the financial transaction. |||||| X ||| X | +| **5105** | Payee FSP rejected transaction | Payee FSP rejected the financial transaction. |||||| X ||| X | +| **5106** | Payee unsupported currency | Payee does not have an account that supports the requested currency. |||| X || X || X | X | +| **5200** | Payee limit error | Generic limit error, for example, the Payee is receiving more payments per day or per month than they are allowed to, or is receiving a payment that is larger than the allowed maximum per transaction. ||| X | X || X || X | X | +| **5300** |Payee permission error | Generic permission error, the Payee or Payee FSP does not have the access rights to perform the service. ||| X | X | X | X | X | X | X | +| **5400** | Generic Payee blocked error | Generic Payee Blocked error, the Payee is blocked or has failed regulatory screenings. ||| X | X | X | X | X | X | X | + +**Table 118 -- Payee errors -- 5_xxx_** + + +## Generic Transaction Patterns Binding + +This section provides information about how the logical transaction patterns from [Generic Transaction Patterns](../generic-transaction-patterns) are used in the asynchronous REST binding of the API. Much of the information is provided by way of sequence diagrams. For more information regarding the steps in these diagrams, see [Generic Transaction Patterns](../generic-transaction-patterns). + +### Payer Initiated Transaction + +The `Payer Initiated Transaction` pattern is introduced in [Generic Transaction Patterns](../generic-transaction-patterns#payer-initiated-transaction). On a high-level, the pattern should be used whenever a Payer would like to transfer funds to another Party whom is not located in the same FSP as the Payer. [Figure 64](#figure-64) shows the sequence diagram for a `Payer Initiated Transaction` using the asynchronous REST binding of the logical version. The process for each number in the sequence diagram is described in [Generic Transaction Patterns](../generic-transaction-patterns#payer-initiated-transaction). + +###### Figure 64 + +![](../../assets/diagrams/sequence/figure64.svg) + + +**Figure 64 -- Payer Initiated Transaction pattern using the asynchronous REST binding** + +### Payee Initiated Transaction + +The `Payee Initiated Transaction` pattern is introduced in [Generic Transaction Patterns](../generic-transaction-patterns#payer-initiated-transaction). On a high-level, the pattern should be used whenever a Payee would like to request that Payer transfer funds to a Payee. The Payer and the Payee are assumed to be in different FSPs, and the approval of the transaction is performed in the Payer FSP. If the transaction information and approval occur on a Payee device instead, use the related Payee Initiated Transaction using OTP](#payee-initiated-transaction-using-otp) instead. [Figure 65](#figure-65) shows the sequence diagram for a `Payee Initiated Transaction` using the asynchronous REST binding of the logical version. The process for each number in the sequence diagram is described in [Generic Transaction Patterns](../generic-transaction-patterns#payee-initiated-transaction). + +###### Figure 65 + +![](../../assets/diagrams/sequence/figure65.svg) + + +**Figure 65 -- Payee Initiated Transaction pattern using the asynchronous REST binding** + +### Payee Initiated Transaction using OTP + +The `Payee Initiated Transaction using OTP` pattern is introduced in [Generic Transaction Patterns](../generic-transaction-patterns#payee-initiated-transaction-using-otp). On a high-level, this pattern is like the [Payee Initiated Transaction](#payee-initiated-transaction); however, in this pattern the transaction information and approval for the Payer is shown and entered on a Payee device instead. As in other transaction patterns, the Payer and the Payee are assumed to be in different FSPs. [Figure 66](#figure-66) shows the sequence diagram for a `Payee Initiated Transaction using OTP` using the asynchronous REST binding of the logical version. The process for each number in the sequence diagram is described in [Generic Transaction Patterns](../generic-transaction-patterns#payee-initiated-transaction-using-otp). + +###### Figure 66 + +![](../../assets/diagrams/sequence/figure66.svg) + + +**Figure 66 -- Payee Initiated Transaction using OTP pattern using the asynchronous REST binding** + +### Bulk Transactions + +The `Bulk Transactions` pattern is introduced in [Generic Transaction Patterns](../generic-transaction-patterns#bulk-transactions). On a high-level, the pattern is used whenever a Payer would like to transfer funds to multiple Payees using one single transaction. The Payees can be in different FSPs. [Figure 67](#figure-67) shows the sequence diagram for a `Bulk Transactions` using the asynchronous REST binding of the logical version. The process for each number in the sequence diagram is described in [Generic Transaction Patterns](../generic-transaction-patterns#bulk-transactions). + +###### Figure 67 + +![](../../assets/diagrams/sequence/figure67.svg) + + +**Figure 67 -- Bulk Transactions pattern using the asynchronous REST binding** + +
    + +## API Error Handling + +This section describes how to handle missing responses or callbacks, as well as how to handle errors in a server during processing of a request. + +### Erroneous Request + +If a server receives an erroneous service request that can be handled immediately (for example, malformed syntax or resource not found), a valid HTTP client error code (starting with **4_xx_**39) should be returned to the client in the response. The HTTP error codes defined in the API appear in [Table 4](#table-4). The HTTP response may also contain an [**ErrorInformation**](#errorinformation) element for the purpose of describing the error in more detail (for more information, see [Error Information in HTTP Response](#error-information-in-http-response)). + +
    + +### Error in Server During Processing of Request + +[Figure 68](#figure-68) shows an example of how to handle an error on a server during processing. + +###### Figure 68 + +![](../../assets/diagrams/sequence/figure68.svg) + + +**Figure 68 -- Error on server during processing of request** + +#### Internal Processing Steps + +The following list describes the steps in the sequence (see [Figure 68](#figure-68)). + +1. The client would like the server to create a new service object and thus uses a **POST** request. + +2. The server receives the request. It immediately sends an **accepted** response to the client, and then tries to create the object based on the service request. A processing error occurs, and the request cannot be handled as requested. The server sends the callback **_PUT_ /**_{resource}_**/**_{ID}_**/error** including an error code ([Error Codes](#error-codes)) and error description to notify the client of the error. + +3. The client receives the error callback and immediately responds with **OK**. The client then handles the error. + +4. The server receives the **OK** response and the process is completed. + +
    + +### Client Handling on Error Callback + +The following sections explain how a client handles error callbacks from a server. + +#### API Resource /participants + +The typical error from the **/participants** service is that the requested Party could not be found. The client could either try another server, or notify the end user that the requested Party could not be found. + +#### API Resource /parties + +The typical error from the **/parties** service is that the requested Party could not be found. The client could either try another server, or notify the end user that information regarding the requested Party could not be found. + +#### API Resource /quotes + +The typical error from the **/quotes** service is that a quote could not be calculated for the requested transaction. The client should notify the end user that the requested transaction could not be performed. + +#### API Resource /transactionRequests + +The typical error from the **/transactionRequests** service is that the Payer rejected the transaction or that an automatic validation failed. The client should notify the Payee that the transaction request failed. + +#### API Resource /authorizations + +The typical error from the **/authorizations** service is that the transaction request could not be found. The client should notify the Payer that the transaction request has been cancelled. + +#### API Resource /transfers + +The typical error from the **/transfers** service is that either the hop-to-hop transfer process or the end-to-end financial transaction failed. For example, a limit breach was discovered, or the Payee could not be found. The client (the Payer FSP) should in any error case cancel the reservation for the financial transaction that was performed before requesting the transaction to be performed on the server (the Payee FSP). See [Figure 69](#figure-69) for an example including a financial Switch between the FSPs. + +###### Figure 69 + +![](../../assets/diagrams/sequence/figure69.svg) + + +**Figure 69 -- Handling of error callback from POST /transfers** + +##### Internal Processing Steps + +The following list provides a detailed description of all the steps in the sequence (see [Figure 69](#figure-69)). + +1. The transfer is reserved from the Payer's account to either a combined Switch account or a Payee FSP account, depending on setup. After the transfer has been successfully reserved, the request [POST /transfers](#post-transfers) is used on the Switch. The transfer is now irrevocable from the Payer FSP. The Payer FSP then waits for an **accepted** response from the Switch. + +2. The Switch receives the request [POST /transfers](#post-transfers) and immediately sends an **accepted** response to the Payer FSP. The Switch then performs all applicable internal transfer validations. If the validations are successful, a transfer is reserved from a Payer FSP account to a Payee FSP account. After the transfer has been successfully reserved, the request [POST /transfers](#post-transfers) is used on the Payee FSP. The transfer is now irrevocable from the Switch. The Switch then waits for an **accepted** response from the Payee FSP. + +3. The Payee FSP receives the [POST /transfers](#post-transfers) and immediately sends an **accepted** response to the Switch. The Payee FSP then performs all applicable internal transaction validations. The validation is assumed to fail at this point, for example, due to a limit breach. The error callback [PUT /transfers/_{ID}_/error](#put-transfers-id-error) is used on the Switch to inform the Payer FSP about the error. The Payee FSP then waits for an **OK** response from the Switch to complete the transfer process. + +4. The Switch receives the error callback [PUT /transfers/_{ID}_/error](#put-transfers-id-error) and immediately responds with an **OK** response. The Switch then cancels the earlier reserved transfer, as it has received an error callback. The Switch will then use the callback [PUT /transfers/_{ID}_/error](#put-transfers-id-error) to the Payer FSP, using the same parameters, and wait for an **OK** response to complete the transfer process. + +5. The Payer FSP receives the callback [PUT /transfers/_{ID}_/error](#put-transfers-id-error) and immediately responds with an **OK** response. The Payer FSP then cancels the earlier reserved transfer because it has received an error callback. + +#### API Resource /transactions + +The normal error case from the **/transactions** service is that the transaction could not be found in the Peer FSP. + +#### API Resource /bulkQuotes + +The typical error from the **/bulkQuotes** service is that a quote could not be calculated for the requested transaction. The client should notify the end user that the requested transaction could not be performed. + +#### API Resource /bulkTransfers + +The typical error case from the **/bulkTransfers** service is that the bulk transaction was not accepted; for example, due to a validation error. The client (the Payer FSP) should in any error case cancel the reservation for the financial transaction that was performed before requesting that the transaction be performed on the server (the Payee FSP). See [Figure 70](#figure-70) for an example including a financial Switch between the FSPs. + +###### Figure 70 + +![](../../assets/diagrams/sequence/figure70.svg) + + +**Figure 70 -- Handling of error callback from API Service /bulkTransfers** + +##### Internal Processing Steps + +The following list describes the steps in the sequence (see [Figure 70](#figure-70)). + +1. Each individual transfer in the bulk transfer is reserved from the Payer's account to either a combined Switch account or a Payee FSP account, depending on setup. After each transfer has been successfully reserved, the request [POST /bulkTransfers](#post-bulktransfers) is used on the Switch. The bulk transfer is now irrevocable from the Payer FSP. The Payer FSP then waits for an **accepted** response from the Switch. + +2. The Switch receives the request [POST /bulkTransfers](#post-bulktransfers) and immediately sends an **accepted** response to the Payer FSP. The Switch then performs all applicable internal transfer validations. If the validations are successful, each individual transfer is reserved from a Payer FSP account to a Payee FSP account. After the transfers have been successfully reserved, the request [POST /bulkTransfers](#post-bulktransfers) is used on the Payee FSP. The bulk transfer is now irrevocable from the Switch. The Switch then waits for an **accepted** response from the Payee FSP. + +3. The Payee FSP receives [POST /bulkTransfers](#post-bulktransfers) and immediately sends an **accepted** response to the Switch. The Payee FSP then performs all applicable internal bulk transfer validations. The validation is assumed to fail due to some reason; for example, a validation failure that prevents the entire bulk transfer from being performed. The error callback [PUT /bulkTransfers/_{ID}_/error](#put-bulktransfers-id-error) is used on the Switch to inform the Payer FSP about the error. The Payee FSP then waits for an **OK** response from the Switch to complete the bulk transfer process. + +4. The Switch receives the error callback [PUT /bulkTransfers/_{ID}_/error](#put-bulktransfers-id-error) and immediately responds with an **OK** response. The Switch then cancels all the previous reserved transfers, because it has received an error callback. The Switch then uses the callback [PUT /bulkTransfers/_{ID}_/error](#put-bulktransfers-id-error) to the Payer FSP, using the same parameters, and waits for an **OK** response to complete the bulk transfer process. + +5. The Payer FSP receives the callback [PUT /bulkTransfers/_{ID}_/error](#put-bulktransfers-id-error) and immediately responds with an **OK** response. The Payer FSP then cancels all the earlier reserved transfers, as it has received an error callback. + +
    + +### Client Missing Response from Server - Using Resend of Request + +[Figure 71](#figure-71) shows an example UML (Unified Modeling Language) sequence diagram in which a client (FSP or Switch) performs error handling when the client misses a response from a server (Switch or Peer FSP) pertaining to a service request, using resend of the same service request. + +###### Figure 71 + +![](../../assets/diagrams/sequence/figure71.svg) + + +**Figure 71 -- Error handling from client using resend of request** + +#### Internal Processing Steps + +The following list provides a detailed description of all the steps in the sequence (see [Figure 71](#figure-71)). + +1. The client would like the server to create a new service object. The HTTP request is lost somewhere on the way to the server. + +2. The client notes that no response has been received from the server within a specified timeout. The client resends the service request. + +3. The server receives the resent request. It immediately sends an **accepted** response to the client, and then creates the object in accordance with the service request. + +4. The **accepted** HTTP response from the server is lost on the way to the client, and the client notes that no response has been received from the server within a specified timeout. The client resends the service request. + +5. The server receives the resent request. It immediately sends an **accepted** response to the client, and then notes that the service request is the same as in [Step 3](#figure-70). As the service request is a resend, the server should not create a new object based on the service request. The server sends a callback to notify the client about the object created in [Step 3](#figure-70). + +6. The client receives the callback regarding the created object. The client sends an **OK** HTTP response to the server to complete the process. + +7. The server receives the **OK** HTTP response from the client, completing the process. + +
    + +### Server Missing Response from Client + +A server using the API is not responsible for making sure that a callback is properly delivered to a client. However, it is considered good practice to retry if the server does not receive an **OK** response from the client. + +#### Client Missing Callback - Using GET request + +[Figure 72](#figure-72) is a UML sequence diagram showing how a client (Switch or Peer FSP) would perform error handling in case of no callback from a client (FSP or Switch) within a reasonable time. + +###### Figure 72 + +![](../../assets/diagrams/sequence/figure72.svg) + + +**Figure 72 -- Error handling from client using GET request** + +#### Internal Processing Steps + +The following list provides a detailed description of all the steps in the sequence (see [Figure 71](#figure-71)). + +1. The client would like the server to create a new service object; a service request is sent. + +2. The server receives the service request. It immediately sends an **accepted** response to the client, and then creates the object based on the service request. The object creation is a long running process; for example, a bulk transfer consisting of numerous financial transactions. + +3. The server notes that no callback has been received from the client within a reasonable time. The client uses a **GET** service request with the ID that was provided in the original service request. + +4. The server receives the **GET** service request. The server sends an accepted HTTP response to the client to notify that the request will be handled. + +5. The client receives the **accepted** HTTP response and waits for the callback, which arrives sometime later; the client sends an **OK** HTTP response and the process is completed. + +6. The server sends the callback to the client containing the requested information, and an **OK** HTTP response is received from the client, which completes the process. + +
    + +## End-to-End Example + +This section contains an end-to-end example in which an account holder is provisioned, and then a P2P Transfer from a Payer located in one FSP to a Payee located in another FSP is performed. The example includes both HTTP requests and responses, HTTP headers, and data models in JSON, but without additional security features of using JWS (see [_Signature_](./signature.md)) and field level encryption using JWE (see [_Encryption_](./encryption.md)). + +### Example Setup + +This section explains the setup of the example. + +#### Nodes + +###### Figure 73 + +The nodes in the end-to-end example in this section are simplified by having only two FSPs, where one FSP is a bank (identifier **BankNrOne**) and the other FSP is a mobile money operator (identifier **MobileMoney**), and one Switch (identifier **Switch**). The Switch also acts as the Account Lookup System (ALS) in this simplified setup (see [Figure 73](#figure-73)). + +![Figure 73](../../assets/diagrams/images/figure73.svg) + +**Figure 73 -- Nodes in end-to-end example** + +#### Account Holders + +The account holders in the example are: + +- One account holder in the FSP **BankNrOne** named Mats Hagman. Mats Hagman has a bank account with IBAN number **SE4550000000058398257466**. The currency of the account is USD. + +- One account holder in the FSP **MobileMoney** named Henrik Karlsson. Henrik Karlsson has a mobile money account that is identified by his phone number **123456789**. The currency of the account is USD. + +#### Scenario + +The scenario in the example is that Mats Hagman in FSP **BankNrOne** wants to transfer 100 USD to Henrik Karlsson in the FSP **MobileMoney**. Before Henrik Karlsson can be found by FSP **BankNrOne**, Henrik's FSP **MobileMoney** should provide information to the Switch specifying in which FSP Henrik Karlsson can be found in. The end-to-end flow including all used services can be found in [Other Notes](#other-notes). + +#### Other Notes + +The JSON messages used in the examples are formatted with color coding, indentations, and line breaks for very long lines to simplify the read of the examples. + +Both FSPs are assumed to have a pre-funded Switch account in their respective FSPs. + +### End-to-End Flow + +[Figure 74](#figure-74) shows the end-to-end flow of the entire example, from provisioning of FSP information to the actual transaction. + +###### Figure 74 + +![](../../assets/diagrams/sequence/figure74.svg) + + +**Figure 74 -- End-to-end flow, from provision of account holder FSP information to a successful transaction** + +### Provision Account Holder + +Before the Payee Henrik Karlsson can be found by the Payer FSP **BankNrOne**, Henrik Karlsson should be provisioned to the ALS, which is also the Switch in this simplified example, by Henrik's FSP (**MobileMoney**). This is performed through either one of the services [**POST /participants**](#6232-post-participants) (bulk version) or [POST /participants/_{Type}_/_{ID}_](#post-participants-type-id) (single version). As the Payee in this example is only one (Henrik Karlsson), the single [POST /participants/_{Type}_/_{ID}_](#post-participants-type-id) version is used by FSP **MobileMoney**. The provision could happen anytime, for example when Henrik Karlsson signed up for the financial account, or when the FSP **MobileMoney** connected to the Switch for the first time. + +#### FSP MobileMoney Provisions Henrik Karlsson: Step 1 in End-to-End Flow + +[Listing 29](#listing-29) shows the HTTP request where the FSP **MobileMoney** provisions FSP information for account holder Henrik Karlsson, identified by **MSISDN** and **123456789** (see [Party Addressing](#party-addressing) for more information). The JSON element **fspId** is set to the FSP identifier (MobileMoney), and JSON element **currency** is set to the currency of the account (USD). + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, +and [POST /participants/_{Type}_/_{ID}_](#post-participants-type-id) for more information about the service ). **More** information regarding routing of requests using **FSPIOP-Destination** and **FSPIOP-Source** can be found in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). Information about API version negotiation can be found in [Version Negotiation between Client and Server](#version-negotiation-between-client-and-server). + +###### Listing 29 + +``` +POST /participants/MSISDN/123456789 HTTP/1.1 +Accept: application/vnd.interoperability.participants+json;version=1 +Content-Length: 50 +Content-Type: +application/vnd.interoperability.participants+json;version=1.0 +Date: Tue, 14 Nov 2017 08:12:31 GMT +FSPIOP-Source: MobileMoney +FSPIOP-Destination: Switch +{ + "fspId": "MobileMoney", + "currency": "USD" +} +``` + +**Listing 29 -- Provision FSP information for account holder Henrik Karlsson** + +[Listing 30](#listing-30) shows the synchronous HTTP response where the Switch immediately (after basic verification of for example required headers) acknowledges the HTTP request in [Listing 29](#listing-29). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 30 + +``` +HTTP/1.1 202 Accepted +Content-Type: +application/vnd.interoperability.participants+json;version=1.0 +``` + +**Listing 30 -- Synchronous response on provision request** + +
    + +#### Switch Handles Provision: Step 2 in End-to-End Flow + +When the Switch has received the HTTP request in [Listing 29](#listing-29) and sent the synchronous response in [Listing 30](#listing-30), the Switch should verify the body of the request in [Listing 29](#listing-29). An example verification is to check that the **fspId** element is the same as the **FSPIOP-Source** , as it should be the FSP of the account holder who provisions the information. A scheme could also have restrictions on which currencies are allowed, which means that the Switch should then check that the currency in the **currency** element is allowed. + +After the Switch has verified the request correctly, the information that the account holder identified by **MSISDN** and **123456789** is located in FSP **MobileMoney** should be stored in the Switch's database. + +
    + +#### Switch Sends Successful Callback: Step 3 in End-to-End Flow + +When the Switch has successfully stored the information that the account holder identified by **MSISDN** and **123456789** is located in FSP **MobileMoney**, the Switch must send a callback using the service [PUT /participants/_{Type}_/_{ID}_](#put-participants-type-id) to notify the FSP **MobileMoney** about the outcome of the request in [Listing 29](#listing-29). [Listing 31](#listing-31) shows the HTTP request for the callback. + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request. In the callback, the **Accept** header should not be used as this is a callback to an earlier requested service. The HTTP headers **FSPIOP-Destination** and **FSPIOP-Source** are now inverted compared to the HTTP request in [Listing 29](#listing-29), as detailed in the section on [PUT /participants/_{Type}_/_{ID}_](#put-participants-type-id). + +###### Listing 31 + +``` +PUT /participants/MSISDN/123456789 HTTP/1.1 +Content-Length: 50 +Content-Type: +Date: Tue, 14 Nov 2017 08:12:32 GMT +FSPIOP-Source: MobileMoney +FSPIOP-Destination: Switch +{ + "fspId": "MobileMoney", + "currency": "USD" +} +``` + +**Listing 31 -- Callback for the earlier requested provision service** + +[Listing 32](#listing-32) shows the synchronous HTTP response where the FSP **MobileMoney** immediately (after basic verification of for example required headers) acknowledges the completion of the process, after receiving the callback in [Listing 31](#listing-31). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 32 + +``` +HTTP/1.1 200 OK +Content-Type: +application/vnd.interoperability.participants+json;version=1.0 +``` + +**Listing 32 -- Synchronous response for the callback** + +
    + +### P2P Transfer + +As the intended Payee Henrik Karlsson is now known by the Switch (which is also the ALS) as detailed in [Provision Account Holder](#provision-account-holder), Mats Hagman can now initiate and approve the use case P2P Transfer from his bank to Henrik Karlsson. + +#### Initiate Use Case: Step 4 in End-to-End Flow + +Mats Hagman knows that Henrik Karlsson has phone number **123456789**, so he inputs that number on his device as recipient and 100 USD as amount. The actual communication between Mats' device and his bank **BankNrOne** is out of scope for this API. + +
    + +#### Request Party Information from Switch: Step 5 in End-to-End Flow + +In Step 5 in the end-to-end flow, **BankNrOne** receives the request from Mats Hagman that he would like the phone number 123456789 to receive 100 USD. **BankNrOne** performs an internal search to see if 123456789 exists within the bank, but fails to find the account internally. **BankNrOne** then uses the service [GET /parties/_{Type}_/_{ID}_](#get-parties-type-id) in the Switch to see if the Switch knows anything about the account. + +[Listing 33](#listing-33) shows the HTTP request where the FSP **BankNrOne** asks the Switch for Party information regarding the account identified by **MSISDN** and **123456789**. + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, and [GET /parties/_{Type}_/_{ID}_](#get-parties-type-id) for more information about the service. **More** information regarding routing of requests using **FSPIOP-Destination** and **FSPIOP-Source** can be found in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). In this request, the FSP **BankNrOne** does not know in which FSP the other account holder resides. Thus, the **FSPIOP-Destination** is not present. Information about API version negotiation can be found in [Version Negotiation between Client and Server](#version-negotiation-between-client-and-server). + +###### Listing 33 + +``` +GET /parties/MSISDN/123456789 HTTP/1.1 +Accept: application/vnd.interoperability.parties+json;version=1 +Content-Type: application/vnd.interoperability.parties+json;version=1.0 +Date: Tue, 15 Nov 2017 10:13:37 GMT +FSPIOP-Source: BankNrOne +``` + +**Listing 33 -- Get Party information for account identified by MSISDN and 123456789 from FSP BankNrOne** + +[Listing 34](#listing-34) shows the synchronous HTTP response where the Switch immediately (after basic verification of for example required headers) acknowledges the HTTP request in [Listing 33](#listing-33). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 34 + +``` +HTTP/1.1 202 Accepted +Content-Type: application/vnd.interoperability.parties+json;version=1.0 +``` + +**Listing 34 -- Synchronous response on the request for Party information** + +#### Request Party Information from FSP: Step 6 in End-to-End Flow + +When the Switch has received the HTTP request in [Listing 33](#listing-33) and sent the synchronous response in [Listing 34](#listing-34), the Switch can proceed with checking its database if it has information regarding in which FSP the account holder identified by **MSISDN** and **123456789** is located. As that information was provisioned as detailed in [Provisoin Account Holder](#provision-account-holder), the Switch knows that the account is in FSP **MobileMoney**. Therefore, the Switch sends the HTTP request in [Listing 35](#listing-35). + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, and [GET /parties/_{Type}_/_{ID}_](#get-parties-type-id) for more information about the service. **More** information regarding routing of requests using **FSPIOP-Destination** and **FSPIOP-Source** can be found in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source); in this request the Switch has added the header **FSPIOP-Destination** because the Switch knew to where the request should be routed. Information about API version negotiation can be found in [Version Negotiation between Client and Server](#version-negotiation-between-client-and-server). + + + +###### Listing 35 + +``` +GET /parties/MSISDN/123456789 HTTP/1.1 +Accept: application/vnd.interoperability.parties+json;version=1 +Content-Type: application/vnd.interoperability.parties+json;version=1.0 +Date: Tue, 15 Nov 2017 10:13:38 GMT +FSPIOP-Source: BankNrOne +FSPIOP-Destination: MobileMoney +``` + +**Listing 35 -- Get Party information for account identified by MSISDN and 123456789 from Switch** + +[Listing 36](#listing-36) shows the synchronous HTTP response where the FSP **MobileMoney** immediately (after basic verification of for example required headers) acknowledges the HTTP request in [Listing 35](#listing-35). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 36 + +``` +HTTP/1.1 202 Accepted +Content-Type: application/vnd.interoperability.parties+json;version=1.0 +``` + +**Listing 36 -- Synchronous response on request for Party information** + +
    + +#### Lookup Party Information in FSP MobileMoney: Step 7 in End-to-End Flow + +When the FSP **MobileMoney** has received the HTTP request in [Listing 35](#listing-35) and sent the synchronous response in [Listing 36](#listing-36), the FSP **MobileMoney** can proceed with checking its database for more information regarding the account identified by **MSISDN** and **123456789**. As the account exists and is owned by Henrik Karlsson, the FSP **MobileMoney** sends the callback in [Listing 37](#listing-37). The FSP **MobileMoney** does not want to share some details, for example birth date, with the other FSP (**BankNrOne**), so some optional elements are not sent. + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, +and [PUT /participants/_{Type}_/_{ID}_](#put-participants-type-id) for more information about the callback. **In** the callback, the **Accept** header should not be sent. The HTTP headers **FSPIOP-Destination** and **FSPIOP-Source** are now inverted compared to the HTTP request in [Listing 35](#listing-35), as detailed in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). + +###### Listing 37 + +```` +PUT /parties/MSISDN/123456789 HTTP/1.1 +Content-Type: application/vnd.interoperability.parties+json;version=1.0 +Content-Length: 347 +Date: Tue, 15 Nov 2017 10:13:39 GMT +FSPIOP-Source: MobileMoney +FSPIOP-Destination: BankNrOne +{ + "party": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "123456789", + "fspId": "MobileMoney" + }, + "personalInfo": { + "complexName": { + "firstName": "Henrik", + "lastName": "Karlsson" + } + } + } +} +```` + +**Listing 37 -- Callback to the request for Party information** + +[Listing 38](#listing-38) shows the synchronous HTTP response where the Switch immediately (after basic verification of for example required headers) acknowledges the completion of the process, after receiving the callback in [Listing 37](#listing-37). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 38 + +``` +HTTP/1.1 200 OK +Content-Type: application/vnd.interoperability.parties+json;version=1.0 +``` + +**Listing 38 -- Synchronous response for the Party information callback** + +
    + +#### Send Callback to FSP BankNrOne: Step 8 in End-to-End Flow + +When the Switch has received the callback in [Listing 37](#listing-37) and sent the synchronous response in [Listing 38](#listing-38), it should relay the exact same callback as in [Listing 37](#listing-37) to the FSP **BankNrOne**, and **BankNrOne** should then respond synchronously with the exact same response as in [Listing 38](#listing-38). + +The HTTP request and response are not repeated in this section, as they are the same as in the last section, but sent from the Switch to **BankNrOne** (HTTP request in [Listing 37](#listing-37)) and from **BankNrOne** to the Switch (HTTP response in [Listing 38](#listing-38)) instead. + +
    + +#### Send Quote Request from FSP BankNrOne: Step 9 in End-to-End Flow + +After receiving Party information in the callback [PUT /parties/_{Type}_/_{ID}_](#put-parties-type-id), the FSP **BankNrOne** now knows that the account identified by **MSISDN** and **123456789** exists and that it is in the FSP **MobileMoney**. It also knows the name of the account holder. Depending on implementation, the name of the intended Payee (Henrik Karlsson) could be shown to Mats Hagman already in this step before sending the quote. In this example, a quote request is sent before showing the name and any fees. + +The FSP **BankNrOne** sends the HTTP request in [Listing 39](#listing-39) to request the quote. **BankNrOne** does not want to disclose its fees (see [Quoting](#quoting) for more information about quoting), which means that it does not include the **fees** element in the request. The **amountType** element is set to RECEIVE as Mats wants Henrik to receive 100 USD. The **transactionType** is set according to [Mapping of Use Cases to Transaction Types](#mapping-of-use-cases-to-transaction-types). Information about Mats is sent in the **payer** element. **BankNrOne** has also generated two UUIDs for the quote ID (7c23e80c-d078-4077-8263-2c047876fcf6) and the transaction ID (85feac2f-39b2-491b-817e-4a03203d4f14). These IDs must be unique, as described in [Architectural Style](#architectural-style). + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, and [Section 6.5.3.2](#6532-post-quotes) for more information about the service [POST /quotes](#6532-post-quotes). **More** information regarding routing of requests using **FSPIOP-Destination** and **FSPIOP-Source** can be found in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). Information about API version negotiation can be found in [Version Negotiation between Client and Server](#version-negotiation-between-client-and-server). + +###### Listing 39 + +```` +POST /quotes HTTP/1.1 +Accept: application/vnd.interoperability.quotes+json;version=1 +Content-Type: application/vnd.interoperability.quotes+json;version=1.0 +Content-Length: 975 +Date: Tue, 15 Nov 2017 10:13:40 GMT +FSPIOP-Source: BankNrOne +FSPIOP-Destination: MobileMoney +{ + "quoteId": "7c23e80c-d078-4077-8263-2c047876fcf6", + "transactionId": "85feac2f-39b2-491b-817e-4a03203d4f14", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "123456789", + "fspId": "MobileMoney" + } + }, + "payer": { + "personalInfo": { + "complexName": { + "firstName": "Mats", + "lastName": "Hagman" + } + }, + "partyIdInfo": { + "partyIdType": "IBAN", + "partyIdentifier": "SE4550000000058398257466", + "fspId": "BankNrOne" + } + }, + "amountType": "RECEIVE", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "note": "From Mats", + "expiration": "2017-11-15T22:17:28.985-01:00" +} +```` + +**Listing 39 -- Request quote for transaction of 100 USD** + +[Listing 40](#listing-40) shows the synchronous HTTP response where the Switch immediately (after basic verification of for example required headers) acknowledges the HTTP request in [Listing 39](#listing-39). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 40 + +``` +HTTP/1.1 202 Accepted +Content-Type: application/vnd.interoperability.quotes+json;version=1.0 +``` + +**Listing 40 -- Synchronous response on quote request** + +#### Send Quote Request from Switch: Step 10 in End-to-End Flow** + +When the Switch has received the quote request in [Listing 39](#listing-39) and sent the synchronous response in [Listing 40](#listing-40), it should relay the same request as in [Listing 39](#listing-39) to the FSP **MobileMoney**, and **MobileMoney** should then respond synchronously with the same response as in [Listing 40](#listing-40). + +The HTTP request and response are not repeated in this section, as they are the same as in the last section, but sent from the Switch to **MobileMoney** (HTTP request in [Listing 39](#listing-39)) and from **MobileMoney** to the Switch (HTTP response in [Listing 40](#listing-40)) instead. + +
    + +#### Determine fees and FSP commission in FSP MobileMoney: Step 11 in End-to-End Flow + +When the FSP **MobileMoney** has received the HTTP request in [Listing 39](#listing-40) and sent the synchronous response in [Listing 40](#listing-40), the FSP **MobileMoney** should validate the request and then proceed to determine the applicable fees and/or FSP commission for performing the transaction in the quote request. + +In this example, the FSP **MobileMoney** decides to give 1 USD in FSP commission as the FSP **MobileMoney** will receive money, which should later generate more income for the FSP (future possible fees). Since the Payee Henrik Karlsson should receive 100 USD and the FSP commission is determined to 1 USD, the FSP **BankNrOne** only needs to transfer 99 USD to the FSP **MobileMoney** (see [Non Disclosing Receive Amount](#non-disclosing-receive-amount) for the equation). The 99 USD is entered in the transferAmount element in the callback, which is the amount that should later be transferred between the FSPs. + +To send the callback, the FSP **MobileMoney** then needs to create an ILP Packet (see [ILP Packet](#ilp-packet) for more information) that is base64url-encoded, as the **ilpPacket** element in the [PUT /quotes/_{ID}_](#put-quotes-id) callback is defined as a [BinaryString](#binarystring). How to populate the ILP Packet is explained in [Interledger Payment Request](#interledger-payment-request). Henrik's ILP address in the FSP **MobileMoney** has been set to **g.se.mobilemoney.msisdn.123456789** (see [ILP Addressing](#ilp-addressing) for more information about ILP addressing). As the transfer amount is 99 USD and the currency USD's exponent is 2, the amount to be populated in the ILP Packet is 9900 (99 \* 10\^2 = 9900). The remaining element in the ILP Packet is the **data** element. As described in [Interledger Payment Request](#interledger-payment-request), this element should contain the Transaction data model (see [Transaction](#transaction)). With the information from the quote request, the Transaction in this example becomes as shown in [Listing 41](#listing-41). Base64url-encoding the entire ILP Packet with the **amount**, **account**, and the **data** element then results in the **ilpPacket** element in the [PUT /quotes/_{ID}_](#put-quotes-id) callback. + +When the ILP Packet has been created, the fulfilment and the condition can be generated as defined in the algorithm in [Listing 12](#listing-12). Using a generated example secret shown in [Listing 42](#listing-42) (shown as base64url-encoded), the fulfilment becomes as in [Listing 43](#listing-43) (shown as base64url-encoded) after executing the HMAC SHA-256 algorithm on the ILP Packet using the generated secret as key. The FSP **MobileMoney** is assumed to save the fulfilment in the database, so that it does not have to be regenerated later. The condition is then the result of executing the SHA-256 hash algorithm on the fulfilment, which becomes as in [Listing 44](#listing-44) (shown as base64url-encoded). + +The complete callback to the quote request becomes as shown in [Listing 45](#listing-45). + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, and [PUT /quotes/_{ID}_](#put-quotes-id) for more information about the callback. **The** _{ID}_ in the URI should be taken from the quote ID in the quote request, which in the example is 7c23e80c-d078-4077-8263-2c047876fcf6. In the callback, the **Accept** header should not be sent. The HTTP headers **FSPIOP-Destination** and **FSPIOP-Source** are now inverted compared to the HTTP request in [Listing 39](#listing-39), as detailed in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). + +###### Listing 41 + +``` +{ + "transactionId": "85feac2f-39b2-491b-817e-4a03203d4f14", + "quoteId": "7c23e80c-d078-4077-8263-2c047876fcf6", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "123456789", + "fspId": "MobileMoney" + }, + "personalInfo": { + "complexName": { + "firstName": "Henrik", + "lastName": "Karlsson" + } + } + }, + "payer": { + "personalInfo": { + "complexName": { + "firstName": "Mats", + "lastName": "Hagman" + } + }, + "partyIdInfo": { + "partyIdType": "IBAN", + "partyIdentifier": "SE4550000000058398257466", + "fspId": "BankNrOne" + } + }, + "amount": { + "amount": "99", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "note": "From Mats" +} +``` + +**Listing 41 -- The Transaction JSON object** + +###### Listing 42 + +``` +JdtBrN2tskq9fuFr6Kg6kdy8RANoZv6BqR9nSk3rUbY +``` + +**Listing 42 -- Generated secret, encoded in base64url** + +###### Listing 43 + +``` +mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s +``` + +**Listing 43 -- Calculated fulfilment from the ILP Packet and secret, encoded in base64url** + +###### Listing 44 + +``` +fH9pAYDQbmoZLPbvv3CSW2RfjU4jvM4ApG\_fqGnR7Xs +``` + +**Listing 44 -- Calculated condition from the fulfilment, encoded in base64url** + +###### Listing 45 + +``` +PUT /quotes/7c23e80c-d078-4077-8263-2c047876fcf6 HTTP/1.1 +Content-Type: application/vnd.interoperability.quotes+json;version=1.0 +Content-Length: 1802 +Date: Tue, 15 Nov 2017 10:13:41 GMT +FSPIOP-Source: MobileMoney +FSPIOP-Destination: BankNrOne +{ + "transferAmount": { + "amount": "99", + "currency": "USD" + }, + "payeeReceiveAmount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2017-11-15T14:17:09.663+01:00", + "ilpPacket": "AQAAAAAAACasIWcuc2UubW9iaWxlbW9uZXkubXNpc2RuLjEyMzQ1Njc4OY- +IEIXsNCiAgICAidHJhbnNhY3Rpb25JZCI6ICI4NWZlY- +WMyZi0zOWIyLTQ5MWItODE3ZS00YTAzMjAzZDRmMTQiLA0KICAgICJxdW90ZUlkIjogIjdjMjNlOD- +BjLWQwNzgtNDA3Ny04MjYzLTJjMDQ3ODc2ZmNmNiIsDQogICAgInBheWVlIjogew0KICAgICAgI- +CAicGFydHlJZEluZm8iOiB7DQogICAgICAgICAgICAicGFydHlJZFR5cGUiOiAiTVNJU0ROIiwNCiAgI- +CAgICAgICAgICJwYXJ0eUlkZW50aWZpZXIiOiAiMTIzNDU2Nzg5IiwNCiAgICAgICAgI- +CAgICJmc3BJZCI6ICJNb2JpbGVNb25leSINCiAgICAgICAgfSwNCiAgICAgI- +CAgInBlcnNvbmFsSW5mbyI6IHsNCiAgICAgICAgICAgICJjb21wbGV4TmFtZSI6IHsNCiAgICAgICAgI- +CAgICAgICAiZmlyc3ROYW1lIjogIkhlbnJpayIsDQogICAgICAgICAgICAgICAgImxhc3ROYW1lIjogIk- +thcmxzc29uIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfSwNCiAgICAicGF5ZXIi- +OiB7DQogICAgICAgICJwZXJzb25hbEluZm8iOiB7DQogICAgICAgICAgICAiY29tcGxleE5hbWUi- +OiB7DQogICAgICAgICAgICAgICAgImZpcnN0TmFtZSI6ICJNYXRzIiwNCiAgICAgICAgICAgICAgI- +CAibGFzdE5hbWUiOiAiSGFnbWFuIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9LA0KICAgICAgI- +CAicGFydHlJZEluZm8iOiB7DQogICAgICAgICAgICAicGFydHlJZFR5cGUiOiAiSUJBTiIsDQogICAgI- +CAgICAgICAicGFydHlJZGVudGlmaWVyI- +jogIlNFNDU1MDAwMDAwMDA1ODM5ODI1NzQ2NiIsDQogICAgICAgICAgICAiZnNwSWQiOiAiQmFua05yT25 +lIg0KICAgICAgICB9DQogICAgfSwNCiAgICAiYW1vdW50Ijogew0KICAgICAgICAiYW1vdW50IjogIjEw- +MCIsDQogICAgICAgICJjdXJyZW5jeSI6ICJVU0QiDQogICAgfSwNCiAgICAidHJhbnNhY3Rpb25UeXBlI- +jogew0KICAgICAgICAic2NlbmFyaW8iOiAiVFJBTlNGRVIiLA0KICAgICAgICAiaW5pdGlhdG9yI- +jogIlBBWUVSIiwNCiAgICAgICAgImluaXRpYXRvclR5cGUiOiAiQ09OU1VNRVIiDQogICAgfSwNCiAgI- +CAibm90ZSI6ICJGcm9tIE1hdHMiDQp9DQo\u003d\u003d", + "condition": "fH9pAYDQbmoZLPbvv3CSW2RfjU4jvM4ApG_fqGnR7Xs" +} +``` + +**Listing 45 -- Quote callback** + +**Note:** The element **ilpPacket** in [Listing 45](#listing-45) should be on a single line in a real implementation; it is shown with line breaks in this example in order to show the entire value. + +[Listing 46](#listing-46) shows the synchronous HTTP response where the Switch immediately (after basic verification of for example required headers) acknowledges the completion of the process, after receiving the callback in [Listing 45](#listing-45). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 46 + +``` +HTTP/1.1 200 OK +Content-Type: application/vnd.interoperability.quotes+json;version=1.0 +``` + +**Listing 46 -- Synchronous response on the quote callback** + +#### Send Callback to FSP BankNrOne: Step 12 in End-to-End Flow + +When the Switch has received the quote callback in [Listing 45](#listing-45) and sent the synchronous response in [Listing 46](#listing-46), it should relay the exact same callback as in [Listing 45](#listing-45) to the FSP **BankNrOne**, and **BankNrOne** should then respond synchronously with the exact same response as in [Listing 46](#listing-46). + +The HTTP request and response are not repeated in this section, as they are the same as in the last section, but sent from the Switch to **BankNrOne** (HTTP request in [Listing 45](#listing-45)) and from **BankNrOne** to the Switch (HTTP response in [Listing 46](#listing-46)) instead. + +
    + +#### Determine fees in FSP BankNrOne: Step 13 in End-to-End Flow + +When the FSP **BankNrOne** has received the quote callback in [Listing 45](#listing-45) and sent the synchronous response in [Listing 46](#listing-46), the FSP **BankNrOne** can proceed with determining the fees for the Payer Mats Hagman. In this example, the fee for the Payer is set to 0 USD, but the FSP commission from the FSP **MobileMoney** is kept as an income for the FSP **BankNrOne**. This means that for the Payee Henrik Karlsson to receive 100 USD, the Payer Mats Hagman must transfer 100 USD from his account. 99 USD will then be transferred between the FSPs **BankNrOne** and **MobileMoney**. + +The FSP **BankNrOne** then notifies Mats Hagman that the transaction to transfer 100 USD to Henrik Karlsson will cost 0 USD in fees. How Mats Hagman is notified is out of scope of this API. + +
    + +#### Payer Accepts Transaction: Step 14 in End-to-End Flow + +In this example, Mats Hagman accepts to perform the transaction. How the acceptance is sent is outside the scope of this API. + +#### Send Transfer Request from FSP BankNrOne: Step 15 in End-to-End Flow + +When Mats Hagman has accepted the transaction, FSP **BankNrOne** reserves the internal transfers needed to perform the transaction. This means that 100 USD will be reserved from Mats Hagman's account, where 1 USD will end up as income for the FSP and 99 USD will be transferred to the prefunded Switch account. After the reservations are successfully performed, the FSP **BankNrOne** sends a [POST /transfers](#post-transfers) to the Switch as in [Listing 47](#listing-47). The same ilpPacket and condition elements are sent as was received in the quote callback and the **amount** is the same as the received **transferAmount**, see [Listing 45](#listing-45). + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, and [Post Transfers](#post-transfers) for more information about the service [POST /transfers](#post-transfers).**More** information regarding routing of requests using **FSPIOP-Destination** and **FSPIOP-Source** can be found in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). Information about API version negotiation can be found in [Version Negotiation between Client and Server](#version-negotiation-between-client-and-server). + +###### Listing 47 + +``` +POST /transfers HTTP/1.1 +Accept: application/vnd.interoperability.transfers+json;version=1 +Content-Type: application/vnd.interoperability.transfers+json;version=1.0 +Content-Length: 1820 +Date: Tue, 15 Nov 2017 10:14:01 +FSPIOP-Source: BankNrOne +FSPIOP-Destination: MobileMoney +{ + "transferId":"11436b17-c690-4a30-8505-42a2c4eafb9d", + "payerFsp":"BankNrOne", + "payeeFsp": "MobileMoney", + "amount": { + "amount": "99", + "currency": "USD" + }, + "expiration": "2017-11-15T11:17:01.663+01:00", + "ilpPacket": "AQAAAAAAACasIWcuc2UubW9iaWxlbW9uZXkubXNpc2RuLjEyMzQ1Njc4OY- +IEIXsNCiAgICAidHJhbnNhY3Rpb25JZCI6ICI4NWZlY- +WMyZi0zOWIyLTQ5MWItODE3ZS00YTAzMjAzZDRmMTQiLA0KICAgICJxdW90ZUlkIjogIjdjMjNlOD- +BjLWQwNzgtNDA3Ny04MjYzLTJjMDQ3ODc2ZmNmNiIsDQogICAgInBheWVlIjogew0KICAgICAgI- +CAicGFydHlJZEluZm8iOiB7DQogICAgICAgICAgICAicGFydHlJZFR5cGUiOiAiTVNJU0ROIiwNCiAgI- +CAgICAgICAgICJwYXJ0eUlkZW50aWZpZXIiOiAiMTIzNDU2Nzg5IiwNCiAgICAgICAgI- +CAgICJmc3BJZCI6ICJNb2JpbGVNb25leSINCiAgICAgICAgfSwNCiAgICAgI- +CAgInBlcnNvbmFsSW5mbyI6IHsNCiAgICAgICAgICAgICJjb21wbGV4TmFtZSI6IHsNCiAgICAgICAgI- +CAgICAgICAiZmlyc3ROYW1lIjogIkhlbnJpayIsDQogICAgICAgICAgICAgICAgImxhc3ROYW1lIjogIk- +thcmxzc29uIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfSwNCiAgICAicGF5ZXIi- +OiB7DQogICAgICAgICJwZXJzb25hbEluZm8iOiB7DQogICAgICAgICAgICAiY29tcGxleE5hbWUi- +OiB7DQogICAgICAgICAgICAgICAgImZpcnN0TmFtZSI6ICJNYXRzIiwNCiAgICAgICAgICAgICAgI- +CAibGFzdE5hbWUiOiAiSGFnbWFuIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9LA0KICAgICAgI- +CAicGFydHlJZEluZm8iOiB7DQogICAgICAgICAgICAicGFydHlJZFR5cGUiOiAiSUJBTiIsDQogICAgI- CAgICAgICAicGFydHlJZGVudGlmaWVyI- +jogIlNFNDU1MDAwMDAwMDA1ODM5ODI1NzQ2NiIsDQogICAgICAgICAgICAiZnNwSWQiOiAiQmFua05yT25 lIg0KICAgICAgICB9DQogICAgfSwNCiAgICAiYW1vdW50Ijogew0KICAgICAgICAiYW1vdW50IjogIjEw- +MCIsDQogICAgICAgICJjdXJyZW5jeSI6ICJVU0QiDQogICAgfSwNCiAgICAidHJhbnNhY3Rpb25UeXBlI- +jogew0KICAgICAgICAic2NlbmFyaW8iOiAiVFJBTlNGRVIiLA0KICAgICAgICAiaW5pdGlhdG9yI- +jogIlBBWUVSIiwNCiAgICAgICAgImluaXRpYXRvclR5cGUiOiAiQ09OU1VNRVIiDQogICAgfSwNCiAgI- +CAibm90ZSI6ICJGcm9tIE1hdHMiDQp9DQo\u003d\u003d", +"condition": "fH9pAYDQbmoZLPbvv3CSW2RfjU4jvM4ApG_fqGnR7Xs" +} +``` + +**Listing 47 -- Request to transfer from FSP BankNrOne to FSP MobileMoney** + +**Note:** The element **ilpPacket** in [Listing 47](#listing-47) should be on a single line in a real implementation, it is shown with line breaks in this example for being able to show the entire value. + +[Listing 48](#listing-48) shows the synchronous HTTP response where the Switch immediately (after basic verification of for example required headers) acknowledges the HTTP request in [Listing 47](#listing-47). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 48 + +``` +HTTP/1.1 202 Accepted +Content-Type: application/vnd.interoperability.transfers+json;version=1.0 +``` + +**Listing 48 -- Synchronous response on transfer request** + +
    + +#### Send Transfer Request from Switch: Step 16 in End-to-End Flow + +When the Switch has received the transfer request in [Listing 47](#listing-47) and sent the synchronous response in [Listing 48](#listing-48), it should reserve the transfer from **BankNrOne**'s account in the Switch to **MobileMoney**'s account in the Switch. After the reservation is successful, the Switch relays nearly the same request as in [Listing 47](#listing-47) to the FSP **MobileMoney**; expect that the **expiration** element should be decreased as mentioned in [Timeout and Expiry](#timeout-and-expiry). [Listing 49](#listing-49) shows the HTTP request with the **expiration** decreased by 30 seconds compared to [Listing 47](#listing-47). The FSP **MobileMoney** should then respond synchronously with the same response as in [Listing 48](#listing-48). + +###### Listing 49 + +``` +POST /transfers HTTP/1.1 +Accept: application/vnd.interoperability.transfers+json;version=1 +Content-Type: application/vnd.interoperability.transfers+json;version=1.0 +Content-Length: 1820 +Date: Tue, 15 Nov 2017 10:14:01 GMT +FSPIOP-Source: BankNrOne +FSPIOP-Destination: MobileMoney +{ + "transferId":"11436b17-c690-4a30-8505-42a2c4eafb9d", + "payerFsp":"BankNrOne", + "payeeFsp": "MobileMoney", + "amount": { + "amount": "99", + "currency": "USD" + }, + "expiration": "2017-11-15T11:16:31.663+01:00", + "ilpPacket": "AQAAAAAAACasIWcuc2UubW9iaWxlbW9uZXkubXNpc2RuLjEyMzQ1Njc4OY- +IEIXsNCiAgICAidHJhbnNhY3Rpb25JZCI6ICI4NWZlY- +WMyZi0zOWIyLTQ5MWItODE3ZS00YTAzMjAzZDRmMTQiLA0KICAgICJxdW90ZUlkIjogIjdjMjNlOD- +BjLWQwNzgtNDA3Ny04MjYzLTJjMDQ3ODc2ZmNmNiIsDQogICAgInBheWVlIjogew0KICAgICAgI- +CAicGFydHlJZEluZm8iOiB7DQogICAgICAgICAgICAicGFydHlJZFR5cGUiOiAiTVNJU0ROIiwNCiAgI- +CAgICAgICAgICJwYXJ0eUlkZW50aWZpZXIiOiAiMTIzNDU2Nzg5IiwNCiAgICAgICAgI- +CAgICJmc3BJZCI6ICJNb2JpbGVNb25leSINCiAgICAgICAgfSwNCiAgICAgI- +CAgInBlcnNvbmFsSW5mbyI6IHsNCiAgICAgICAgICAgICJjb21wbGV4TmFtZSI6IHsNCiAgICAgICAgI- +CAgICAgICAiZmlyc3ROYW1lIjogIkhlbnJpayIsDQogICAgICAgICAgICAgICAgImxhc3ROYW1lIjogIk- +thcmxzc29uIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfSwNCiAgICAicGF5ZXIi- +OiB7DQogICAgICAgICJwZXJzb25hbEluZm8iOiB7DQogICAgICAgICAgICAiY29tcGxleE5hbWUi- +OiB7DQogICAgICAgICAgICAgICAgImZpcnN0TmFtZSI6ICJNYXRzIiwNCiAgICAgICAgICAgICAgI- +CAibGFzdE5hbWUiOiAiSGFnbWFuIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9LA0KICAgICAgI- +CAicGFydHlJZEluZm8iOiB7DQogICAgICAgICAgICAicGFydHlJZFR5cGUiOiAiSUJBTiIsDQogICAgI- +CAgICAgICAicGFydHlJZGVudGlmaWVyI- +jogIlNFNDU1MDAwMDAwMDA1ODM5ODI1NzQ2NiIsDQogICAgICAgICAgICAiZnNwSWQiOiAiQmFua05yT25 +lIg0KICAgICAgICB9DQogICAgfSwNCiAgICAiYW1vdW50Ijogew0KICAgICAgICAiYW1vdW50IjogIjEw- +MCIsDQogICAgICAgICJjdXJyZW5jeSI6ICJVU0QiDQogICAgfSwNCiAgICAidHJhbnNhY3Rpb25UeXBlI- +jogew0KICAgICAgICAic2NlbmFyaW8iOiAiVFJBTlNGRVIiLA0KICAgICAgICAiaW5pdGlhdG9yI- +jogIlBBWUVSIiwNCiAgICAgICAgImluaXRpYXRvclR5cGUiOiAiQ09OU1VNRVIiDQogICAgfSwNCiAgI- +CAibm90ZSI6ICJGcm9tIE1hdHMiDQp9DQo\u003d\u003d", +"condition": "fH9pAYDQbmoZLPbvv3CSW2RfjU4jvM4ApG_fqGnR7Xs" +} +``` + +**Listing 49 -- Request to transfer from FSP BankNrOne to FSP MobileMoney with decreased expiration** + +**Note:** The element **ilpPacket** in [Listing 49](#listing-49) should be on a single line in a real implementation; it is shown with line breaks in this example in order to show the entire value. + +
    + +#### Perform Transfer in FSP MobileMoney: Step 17 in End-to-End Flow + +When the FSP **MobileMoney** has received the transfer request in [Listing 47](#listing-47), it should perform the transfer as detailed in the earlier quote request, this means that 100 USD should be transferred to Henrik Karlsson's account, where 99 USD is from the prefunded Switch account and 1 USD is from an FSP commission account. + +As proof of performing the transaction, the FSP **MobileMoney** then retrieves the stored fulfilment [(Listing 43](#listing-43)) from the database (stored in [Determine Fees and FSP commission in FSP MobileMoney](#determine-fees-and-fsp-commission-in-fsp-mobilemoney-step-11-in-end-to-end-flow)) and enters that in the **fulfilment** element in the callback [PUT /transfers/_{ID}_](#put-transfersid). The **transferState** is set to COMMITTED and the **completedTimestamp** is set to when the transaction was completed; see [Listing 50](#listing-50) for the complete HTTP request. + +At the same time, a notification is sent to the Payee Henrik Karlsson to +say that he has received 100 USD from Mats Hagman. + +How the notification is sent is out of scope for this API. + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, and [PUT /transfers/_{ID}_](#put-transfersid) for more information about the callback. **The** _{ID}_ in the URI should be taken from the transfer ID in the transfer request, which in the example is 11436b17-c690-4a30-8505-42a2c4eafb9d. In the callback, the **Accept** header should not be sent. The HTTP headers **FSPIOP-Destination** and **FSPIOP-Source** are now inverted compared to the HTTP request in [Listing 47](#listing-47), as detailed in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). + +###### Listing 50 + +``` +PUT /transfers/11436b17-c690-4a30-8505-42a2c4eafb9d HTTP/1.1 +Content-Type: application/vnd.interoperability.transfers+json;version=1.0 +Content-Length: 166 +Date: Tue, 15 Nov 2017 10:14:02 GMT +FSPIOP-Source: MobileMoney +FSPIOP-Destination: BankNrOne +{ + "fulfilment": "mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s", + "completedTimestamp": "2017-11-16T04:15:35.513+01:00", + "transferState": "COMMITTED" +} +``` + +**Listing 50 -- Callback for the transfer request** + +[Listing 51](#listing-51) shows the synchronous HTTP response in which the Switch immediately (after basic verification of for example required headers) acknowledges the completion of the process, after receiving the callback in [Listing 50](#listing-50). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 51 + +``` +HTTP/1.1 200 OK +Content-Type: application/vnd.interoperability.transfers+json;version=1.0 +``` + +**Listing 51 -- Synchronous response on the transfers callback** + +
    + +#### Payee Receives Transaction Notification: Step 18 in End-to-End Flow + +The Payee Henrik Karlsson receives the transaction notification, and is thereby informed of the successful transaction. + +
    + +#### Perform Transfer in Switch: Step 19 in End-to-End Flow + +When the Switch has received the transfer callback in [Listing 50](#listing-50) and sent the synchronous response in [Listing 51](#listing-51), it should validate the fulfilment, perform the earlier reserved transfer and relay the exact same callback as in [Listing 50](#listing-50) to the FSP **BankNrOne**, and **BankNrOne** should then respond synchronously with the same response as in [Listing 51](#listing-51). + +The validation of the fulfilment is done by calculating the SHA-256 hash of the fulfilment and ensuring that the hash is equal to the condition from the transfer request. + +The HTTP request and response are not repeated in this section, as they are the same as in the last section, but sent from the Switch to **BankNrOne** (HTTP request in [Listing 50](#listing-51)) and from **BankNrOne** to the Switch (HTTP response in [Listing 51](#listing-51)) instead. + +
    + +#### Perform Transfer in FSP BankNrOne: Step 20 in End-to-End Flow + +When the FSP **BankNrOne** has received the transfer callback in [Listing 50](#listing-50) and sent the synchronous response in [Listing 51](#listing-51), the FSP **BankNrOne** should validate the fulfilment (see [Section 10.4.16](#10416-perform-transfer-in-switch----step-19-in-end-to-end-flow)) and then perform the earlier reserved transfer. + +After the reserved transfer has been performed, the Payer Mats Hagman should be notified of the successful transaction. How the notification is sent is outside the scope of this API. + +#### Payer Receives Transaction Notification: Step 21 in End-to-End Flow + +The Payer Mats Hagman receives the transaction notification and is thereby informed of the successful transaction. + + + + + +1 [http://www.ics.uci.edu/\~fielding/pubs/dissertation/rest\_arch\_style.htm](http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) -- Representational State Transfer (REST) + +2 [https://tools.ietf.org/html/rfc4122](https://tools.ietf.org/html/rfc4122) -- A Universally Unique IDentifier (UUID) URN Namespace + +3 [https://tools.ietf.org/html/rfc7230](https://tools.ietf.org/html/rfc7230) -- Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing + +4 [https://tools.ietf.org/html/rfc5246](https://tools.ietf.org/html/rfc5246) -- The Transport Layer Security (TLS) Protocol - Version 1.2 + +5 [https://tools.ietf.org/html/rfc3986](https://tools.ietf.org/html/rfc3986) -- Uniform Resource Identifier (URI): Generic Syntax + +6 [https://tools.ietf.org/html/rfc7230\#section-2.7.3](https://tools.ietf.org/html/rfc7230#section-2.7.3) -- Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing - http and https URI Normalization and Comparison + +7 [https://tools.ietf.org/html/rfc3629](https://tools.ietf.org/html/rfc3629) -- UTF-8, a transformation format of ISO 10646 + +8 [https://tools.ietf.org/html/rfc7159](https://tools.ietf.org/html/rfc7159) -- The JavaScript Object Notation (JSON) Data Interchange Format + +9 [https://tools.ietf.org/html/rfc7230\#section-3.2](https://tools.ietf.org/html/rfc7230#section-3.2) -- Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing - Header Fields + +10 [https://tools.ietf.org/html/rfc7231\#section-5.3.2](https://tools.ietf.org/html/rfc7231#section-5.3.2) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Accept + +11 [https://tools.ietf.org/html/rfc7230\#section-3.3.2](https://tools.ietf.org/html/rfc7230#section-3.3.2) -- Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing -- Content-Length + +12 [https://tools.ietf.org/html/rfc7231\#section-3.1.1.5](https://tools.ietf.org/html/rfc7231#section-3.1.1.5) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content -- Content-Type + +13 [https://tools.ietf.org/html/rfc7231\#section-7.1.1.2](https://tools.ietf.org/html/rfc7231#section-7.1.1.2) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content -- Date + +14 [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) -- X-Forwarded-For + +15 [https://tools.ietf.org/html/rfc7239](https://tools.ietf.org/html/rfc7239) -- Forwarded HTTP Extension + +16 [https://tools.ietf.org/html/rfc7230\#section-3.3.2](https://tools.ietf.org/html/rfc7230#section-3.3.2) -- Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing -- Content-Length + +17 [https://tools.ietf.org/html/rfc7231\#section-3.1.1.5](https://tools.ietf.org/html/rfc7231#section-3.1.1.5) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content -- Content-Type + +18 [https://tools.ietf.org/html/rfc7231\#section-4](https://tools.ietf.org/html/rfc7231#section-4) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Request Methods + +19 [https://tools.ietf.org/html/rfc7231\#section-6](https://tools.ietf.org/html/rfc7231#section-6) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Response Status Codes + +20 [https://tools.ietf.org/html/rfc7231\#section-6.4](https://tools.ietf.org/html/rfc7231#section-6.4) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Redirection 3xx + +21 [https://tools.ietf.org/html/rfc7231\#section-6.6](https://tools.ietf.org/html/rfc7231#section-6.6) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Server Error 5xx + +22 [https://tools.ietf.org/html/rfc7231\#section-6.5.6](https://tools.ietf.org/html/rfc7231#section-6.5.6) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - 406 Not Acceptable + +23 [https://tools.ietf.org/html/rfc7231\#section-5.3.2](https://tools.ietf.org/html/rfc7231#section-5.3.2) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Accept + +24 [https://interledger.org/rfcs/0011-interledger-payment-request/](https://interledger.org/rfcs/0011-interledger-payment-request/) -- Interledger Payment Request (IPR) + +25 [https://interledger.org/](https://interledger.org/) -- Interledger + +26 [https://interledger.org/interledger.pdf](https://interledger.org/interledger.pdf) -- A Protocol for Interledger Payments + +27 [https://interledger.org/rfcs/0001-interledger-architecture/](https://interledger.org/rfcs/0001-interledger-architecture/) -- Interledger Architecture + +28 [https://interledger.org/rfcs/0015-ilp-addresses/](https://interledger.org/rfcs/0015-ilp-addresses/) -- ILP Addresses + +29 [https://www.itu.int/rec/dologin\_pub.asp?lang=e&id=T-REC-X.696-201508-I!!PDF-E&type=items](https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-X.696-201508-I!!PDF-E&type=items) -- Information technology -- ASN.1 encoding rules: Specification of Octet Encoding Rules (OER) + +30 [https://perldoc.perl.org/perlre.html\#Regular-Expressions](https://perldoc.perl.org/perlre.html#Regular-Expressions) -- perlre - Perl regular expressions + +31 [https://tools.ietf.org/html/rfc7159\#section-7](https://tools.ietf.org/html/rfc7159#section-7) -- The JavaScript Object Notation (JSON) Data Interchange Format - Strings + +32 [http://www.unicode.org/](http://www.unicode.org/) -- The Unicode Consortium + +33 [https://www.iso.org/iso-8601-date-and-time-format.html](https://www.iso.org/iso-8601-date-and-time-format.html) -- Date and time format - ISO 8601 + +34 [https://tools.ietf.org/html/rfc4122](https://tools.ietf.org/html/rfc4122) -- A Universally Unique IDentifier (UUID) URN Namespace + +35 [https://tools.ietf.org/html/rfc4648\#section-5](https://tools.ietf.org/html/rfc4648#section-5) -- The Base16, Base32, and Base64 Data Encodings - Base 64 Encoding with URL and Filename Safe Alphabet + +36 [https://www.iso.org/iso-4217-currency-codes.html](https://www.iso.org/iso-4217-currency-codes.html) -- Currency codes - ISO 4217 + +37 [https://www.itu.int/rec/T-REC-E.164/en](https://www.itu.int/rec/T-REC-E.164/en) -- E.164 : The international public telecommunication numbering plan + +38 [https://tools.ietf.org/html/rfc3696](https://tools.ietf.org/html/rfc3696) -- Application Techniques for Checking and Transformation of Names + +39 [https://tools.ietf.org/html/rfc7231\#section-6.5](https://tools.ietf.org/html/rfc7231#section-6.5) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Client Error 4xx \ No newline at end of file diff --git a/docs/technical/api/fspiop/v1.1/encryption.md b/docs/technical/api/fspiop/v1.1/encryption.md new file mode 100644 index 000000000..714e27fde --- /dev/null +++ b/docs/technical/api/fspiop/v1.1/encryption.md @@ -0,0 +1,638 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- +# Encryption + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information + +| **Type of Information** | **Convention** | **Example** | +| :--- | :--- | :--- | +| **Elements of the API, such as resources** | Boldface | **/authorization** | +| **Variables** | Italics within curly brackets | _{ID}_ | +| **Glossary terms** | Italics on first occurrence; defined in _Glossary_ | The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP. | +| **Library documents** | Italics | User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead. | + +### Document Version Information + +| **Version** | **Date** | **Change Description** | +| :--- | :--- | :--- | +|**1.1**|2020-05-19|This version contains these changes: 1. ExstensionList elements in Section 4 have been updated based on the issue [Interpretation of the Data Model for the ExtensionList element](https://github.com/mojaloop/mojaloop-specification/issues/51), to fix the data model of the extensionList Object.| +| **1.0** | 2018-03-13 | Initial version | + +
    + +## Introduction + +This document details security methods to be implemented for Open API (Application Programming Interface) for FSP (Financial Service Provider) Interoperability (hereafter cited as "the API") to ensure confidentiality of API messages between an API client and the API +server. + +In information security, _confidentiality_ means that information is not made available or disclosed to unauthorized individuals, entities, or processes (excerpt from ISO27000[The ISO 27000 Directory](http://www.27000.org)). For the API, confidentiality means that some sensitive fields in the payload of an API message cannot be accessed or identified in an unauthorized or undetected manner by the intermediaries involved in the API communication. That is, if some fields of an API message are encrypted by the API client, then only the expected API recipient can decrypt those fields. + +JSON Web Encryption (JWE, defined in RFC 7516[JSON Web Encryption (JWE)](https://tools.ietf.org/html/rfc7516)) must be applied to the API to provide end to end message confidentiality. When an API client sends an HTTP request (such as an API request or callback message) to a counterparty, the API client can determine whether there are sensitive fields in the API message to be protected according to the regulation or local schema. If there is a field to be protected, then the API client uses JWE to encrypt the value of that field. Subsequently, the cipher text of that field will be transmitted to the counterparty. + +To support encryption for multiple fields of an API message, JWE is extended in this document to adapt to the requirements of the API. + +
    + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](./logical-data-model) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](../json-binding-rules) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](./v1.1/signature) + +- [Encryption](#) + +#### General Documents + +- [Glossary](./glossary) + +
    + +## API Encryption Definition + +This section introduces the technology used by API encryption, including: + +- Data exchange format for the encrypted fields of an API message. + +- Mechanism for encrypting and decrypting fields. + +### Encryption Data Model + +The API uses the customized HTTP header parameter **FSPIOP-Encryption** to represent the encrypted fields of an API message; its value is a JSON object serialization. The data model of this parameter is described in [Table 1](#table-1), [Table 2](#table-2) and [Table 3](#table-3). + +**Note**: If **FSPIOP-Encryption** is present in an API message, then it must also be protected by the API signature. That means **FSPIOP-Encryption** must be included in the JWS Protected Header of the signature. + +###### Table 1 + +| **Name** | **Cardinality** | **Type** | **Description** | +| :--- | :---: | :--- | :--- | +| **encryptedFields** | 1 | EncryptedFields | Information about the encrypted fields of an API message | +**Table 1 -- Data model of HTTP Header Field FSPIOP-Encryption** + +###### Table 2 + +| **Name** | **Cardinality** | **Type** | **Description** | +| :--- | :---: | :--- | :--- | +| **encryptedField** | 1..* | EncryptedField | Information about the encrypted field of an API message | +**Table 2 -- Data model of complex type EncryptedFields** + +###### Table 3 + +| **Name** | **Cardinality** | **Type** | **Description** | +| :--- | :---: | :--- | :--- | +|**fieldName** | 1 | String(1..512) | This element identifies the field to be encrypted in the payload of an API message.
    Because the API payload is a JSON Object serialization string, the field name must be able to identify the exact element path in the JSON Object. A single period ('**.**') character is used to separate the elements in an element path. For example, **payer.personalInfo.dateOfBirth** is a valid value for this element for the API request **POST /quotes**.
    | +| **encryptedKey** | 1 | String(1..512) | Encrypted Content Encryption Key (CEK) value. Its value is encoded by BASE64URL(JWE Encrypted Key).
    If there are multiple fields of the API message to be encrypted, we recommend that the same JWE Encrypted Key be used to simplify the implementation; however, this is a decision to be made by each FSP internally based on their implementation.
    | +|**protectedHeader** | 1 | String(1..1024) | This element identifies the Header Parameters that are applied to JWE to encrypt the specified field. Its value is encoded by BASE64URL(UTF8(JWE Protected Header)).
    For example, if the JWE Protected Header applied to the encryption is ```{"alg":"RSA-OAEP- 256","enc":"A256GCM"}```, then the value is ```eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ```.
    | +| **initializationVector** | 1 | String(1..128) | Initialization Vector value used when encrypting the plaintext. Its value is encoded by BASE64URL(JWE Initialization Vector). | +| **authenticationTag** | 1 | String(1..128) | Authentication Tag value resulting from authenticated encryption of the plaintext with Additional Authenticated Data. Its value is encoded by BASE64URL(JWE Authentication Tag) | +**Table 3 -- Data model of complex type EncryptedField** + +### Encrypt Fields of API Message + +This section describes the encryption process for message fields. The order of the steps is not significant in cases where there are no dependencies between the inputs and outputs of the steps. + +1. Determine the algorithm used to determine the CEK value (this is the algorithm recorded in the **alg** (algorithm) Header Parameter of the resulting JWE). Because the CEK should be encrypted with the public key of the API recipient, in the API the available algorithms to protect the CEK can only be **RSA-OAEP-256**. +2. If there are multiple fields to be encrypted in the API message, then perform Steps 3-15 for each field. +3. Generate a random CEK. The FSP can generate the value using either its own application or using the JWE implementation employed. +4. Encrypt the CEK with the algorithm determined by the JWE header parameter **alg**. +5. Compute the encoded key value BASE64URL(JWE Encrypted Key). +6. Generate a random JWE Initialization Vector of the correct size for the content encryption algorithm (if required for the algorithm); otherwise, let the JWE Initialization Vector be the empty octet sequence. +7. Compute the encoded Initialization Vector value BASE64URL(JWE Initialization Vector). +8. If a **zip** parameter was included, compress the plaintext using the specified compression algorithm and let *M* be the octet sequence representing the compressed plain text; otherwise, let _M_ be the octet sequence representing the plain text. +9. Create the JSON object or objects containing the desired set of header parameters, which together comprise the JWE Protected Header. Besides the parameter **alg**, the parameter **enc** must be included in the JWE Protected Header. The available values for the parameter **enc** in the API can only be: **A128GC**_M_, **A192GC**_M_, **A256GC**_M_. **A256GC**_M_ is recommended. +10. Compute the Encoded Protected Header value BASE64URL(UTF8(JWE Protected Header)). +11. Let the Additional Authenticated Data encryption parameter be ASCII(Encoded Protected Header). +12. Encrypt *M* using the CEK, the JWE Initialization Vector, and the Additional Authenticated Data value using the specified content encryption algorithm to create the JWE Cipher text value and the JWE Authentication Tag (which is the Authentication Tag output from the encryption operation). +13. Compute the encoded cipher text value BASE64URL(JWE Cipher Text). +14. Compute the encoded Authentication Tag value BASE64URL(JWE Authentication Tag). +15. Compute the **encryptedField** element (see Table 3) for the HTTP header parameter **FSPIOP-Encryption**. +16. Compute the value for the HTTP Header parameter **FSPIOP-Encryption** as described in [FSPIOP API](/fspiop) documentation. The value for this **FSPIOP-Encryption** is JSON Object Serialization string. + +**Note**: If JWE is used to encrypt some fields of the payload, then the API client should: + +1. Encrypt the desired fields. + +2. Replace those fields' value with the encoded cipher text in the payload. + +3. Sign the payload. + +### Decrypt Fields of API Message + +If the HTTP Header parameter **FSPIOP-Encryption** (which is also protected by the API signature) is present, then the API message recipient should decrypt the encrypted fields of the API message after the API signature is validated successfully. The message decryption process is the reverse of the encryption process. The order of the steps is not significant in cases where there are no dependencies between the inputs and outputs of the steps. If there are multiple fields being encrypted, then all fields must be decrypted successfully; otherwise it indicates the API message is invalid. + +1. Parse the HTTP Header parameter **FSPIOP-Encryption** to get encrypted fields' information, including field name, JWE Protected Header, JWE Encrypted Key, JWE Initialization Vector, and JWE Authentication Tag for each field. If there are multiple fields being encrypted, then perform Steps 2-9 for each encrypted field. +2. Get the cipher text of the encrypted field by parsing the payload with the specified field path. The value of the specified field is already encoded with BASE64URL. +3. Verify that the octet sequence resulting from decoding the encoded JWE Protected Header is a UTF-8-encoded representation of a valid JSON object conforming to JSON Data Interchange Format (defined in RFC 7159[The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc7159)); let the JWE Protected Header be this JSON object. +4. Verify that the parameters in the JWE Protected Header understand and can process all fields that are required to support the JWE specification; for example, the algorithm being used. +5. Determine that the algorithm specified by the **alg** (algorithm) Header Parameter matches the algorithm of the public / private key of the API recipient. +6. Decrypt the JWE Encrypted Key with the private key of the API recipient to get the JWE CEK. +7. Let the Additional Authenticated Data encryption parameter be ASCII(Encoded Protected Header). +8. Decrypt the JWE Cipher Text using the CEK, the JWE Initialization Vector, the Additional Authenticated Data value, and the JWE Authentication Tag (which is the Authentication Tag input to the calculation) using the specified content encryption algorithm, returning the decrypted plaintext and validating the JWE Authentication Tag in the manner specified for the algorithm. If the JWE Authentication Tag is incorrect, then reject the input without any decryption. +9. If a **zip** parameter was included, then the API recipient should decompress the decrypted plaintext using the specified compression algorithm. + +## API Encryption/Decryption Examples + +This section uses a typical quote process to explain how the API encryption and decryption are implemented using JWE. As the algorithm of public / private key of the API recipient can only be RSA, the RSA key used for this example is represented in JSON Web Key (JWK, defined in RFC 7517[JSON Web Key(JWK)](https://tools.ietf.org/html/rfc7517)) format below (with line breaks and indentation within values for display purposes only): + +```json +{ + "kty": "RSA", + "n": "oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E- + BVvxkeDNjbC4he8rUWcJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9Le + wND8MW2Krf3Spsk_ZkoFnilakGygTwpZ3uesH- + PFABNIUYpOiN15dsQRkgr0vEhxN92i2asbOenSZeyaxziK72UwxrrKoExv6kc5tw + XTq4h-QChLOln0_mtUZwfsRaMStPs6mS6XrgxnxbWhojf663tuEQueGC- + FCMfra36C9knDFGzKsNa7LZK2djYgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm- + L5StowjzGy-_bq6Gw", + "e": "AQAB", + "d": "kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4- + WY5NWV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD93D + t62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghkqDp0Vqj3 + kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vlt3UVe4WO3JkJOz + lpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K- + VFs3VSndVTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ", + "p": "1r52Xk46c-LsfB5P442p7atdPUrxQSy4mti_tZI3Mgf2EuFVbUoDBvaRQ- + SWxkbk- + moEzL7JXroSBjSrK3YIQgYdMgyAEPTPjXv_hI2_1eTSPVZfzL0lffNn03IXqWF5M + DFuoUYE0hzb2vhrlN_rKrbfDIwUbTrjjgieRbwC6Cl0", + "q": + "wLb35x7hmQWZsWJmB_vle87ihgZ19S8lBEROLIsZG4ayZVe9Hi9gDVCOBmUDdaD + YVTSNx_8Fyw1YYa9XGrGnDew00J28cRUoeBB_jKI1oma0Orv1T9aXIWxKwd4gvxF + ImOWr3QRL9KEBRzk2RatUBnmDZJTIAfwTs0g68UZHvtc", + "dp": "ZK- + YwE7diUh0qR1tR7w8WHtolDx3MZ_OTowiFvgfeQ3SiresXjm9gZ5KLhMXvo-uz- + KUJWDxS5pFQ_M0evdo1dKiRTjVw_x4NyqyXPM5nULPkcpU827rnpZzAJKpdhWAgq + rXGKAECQH0Xt4taznjnd_zVpAmZZq60WPMBMfKcuE", + "dq": + "Dq0gfgJ1DdFGXiLvQEZnuKEN0UUmsJBxkjydc3j4ZYdBiMRAy86x0vHCjywcMlY + Yg4yoC4YZa9hNVcsjqA3FeiL19rk8g6Qn29Tt0cj8qqyFpz9vNDBUfCAiJVeESOj + JDZPYHdHY8v1b-o-Z2X5tvLx-TCekf7oxyeKDUqKWjis", + "qi": "VIMpMYbPf47dT1w_zDUXfPimsSegnMOA1zTaX7aGk_8urY6R8- + ZW1FxU7AlWAyLWybqq6t16VFd7hQd0y6flUK4SlOydB61gwanOsXGOAOv82cHq0E + 3eL4HrtZkUuKvnPrMnsUUFlfUdybVzxyjz9JF_XyaY14ardLSjf4L_FNY" +} +``` + +### Encryption Example + +The following message text is an example of POST /quotes without encryption sent by Payer FSP to a Payee FSP. + +```json +POST /quotes HTTP/1.1 +FSPIOP-Destination:5678 +Accept:application/vnd.interoperability.quotes+json;version=1.0 +Content-Length:975 +Date:Tue, 23 May 2017 21:12:31 GMT +FSPIOP-Source:1234 +Content-Type:application/vnd.interoperability.quotes+json;version=1.0 +``` + +```json +{ + "payee": { + "partyIdInfo": { "partyIdType": "MSISDN", "partyIdentifier": "15295558888", + "fspId": "5678" } }, + "amountType": "RECEIVE", + "transactionType": { "scenario": "TRANSFER", "initiator": "PAYER", + "subScenario": "P2P Transfer across MM systems", "initiatorType": "CONSUMER" }, + "note": "this is a sample for POST /quotes", + "amount": { "amount": "150","currency": "USD" }, + "fees": { "amount": "1.5", "currency": "USD" }, + "extensionList": { + "extension": [ + { "value": "value1", "key": "key1"}, + { "value": "value2", "key": "key2"}, + { "value": "value3", "key": "key3" } + ] + }, + "geoCode": { "latitude": "57.323889", "longitude": "125.520001" + }, + "expiration": "2017-05-24T08:40:00.000-04:00", + "payer": { + "personalInfo": { + "complexName": { "firstName": "Bill", "middleName": "Ben", "LastName": "Lee" + }, "dateOfBirth": "1986-02-14" }, + "partyIdInfo": { "partyIdType": "MSISDN", + "partySubIdOrType": "RegisteredCustomer", "partyIdentifier": "16135551212", + "fspId": "1234" + }, "name": "Bill Lee" + }, "quoteId": "59e331fa-345f-4554-aac8-fcd8833f7d50", + "transactionId": "36629a51-393a-4e3c-b347-c2cb57e1e1fc" +} +``` + +In this case, the Payer FSP would like to encrypt two fields of the API message: **payer** and **payee.partyIdInfo.partyIdentifier**. + +#### Encrypt the Required Fields + +Because there are two fields to be encrypted, the Payer FSP needs to encrypt the two fields one-by-one. + +##### Encrypt "payer" + +The Payer FSP performs the following steps to encrypt the field **payer** in the **POST /quotes** API message. + +1. Determine the algorithm used to determine the CEK value. In this case, assuming it is **RSA-OAEP-256**. +2. Generate a 256-bit random CEK. In this case, its value is (using JSON Array notation): + +``` +191 100 167 60 2 248 21 136 172 39 145 120 102 7 73 31 166 66 114 199 219 157 104 162 7 253 10 105 33 136 57 167 +``` + +3. Encrypt the CEK with the Payee FSP's public key shown in JSON Web +Key format in [API Encryption/Decryption Examples](#api-encryptiondecryption-examples). In this case, the encrypted value is (using JSON Array notation): + +``` +22 210 45 47 153 95 183 79 84 26 194 42 27 152 50 195 163 18 235 121 140 120 224 129 180 120 21 0 46 196 21 114 251 148 127 75 198 42 87 250 186 98 15 136 249 131 224 73 111 108 159 140 107 156 80 30 133 77 86 26 28 13 66 83 248 229 132 77 203 113 229 24 208 155 81 172 9 164 25 126 206 217 25 206 30 218 38 190 128 196 250 233 34 47 86 91 157 140 87 240 29 119 126 136 168 10 87 246 213 23 104 114 215 134 71 87 46 55 131 174 15 193 194 90 194 208 212 15 24 33 143 38 253 125 121 175 220 202 106 95 127 129 192 2 72 137 14 40 147 207 166 239 161 248 159 203 52 223 103 129 54 83 85 199 211 228 56 82 83 135 166 103 42 76 191 146 80 40 192 123 42 18 31 113 25 198 24 58 87 149 47 182 144 86 182 137 253 103 214 34 192 76 254 64 14 114 97 194 28 60 75 164 131 170 210 231 168 205 181 78 79 136 82 115 218 174 5 48 158 162 230 229 164 85 26 135 15 164 206 36 182 131 115 224 207 12 178 234 145 6 181 140 243 41 8 151 +``` + +4. Compute the encoded key value BASE64URL(JWE Encrypted Key). In this case, its value is: + +``` +FtItL5lft09UGsIqG5gyw6MS63mMeOCBtHgVAC7EFXL7lH9LxipX-rpiD4j5g-BJb2yfjGucUB6 FTVYaHA1CU_jlhE3LceUY0JtRrAmkGX7O2RnOHtomvoDE-ukiL1ZbnYxX8B13foioClf21Rdoct eGR1cuN4OuD8HCWsLQ1A8YIY8m_X15r9zKal9_gcACSIkOKJPPpu-h-J_LNN9ngTZTVcfT5DhSU 4emZypMv5JQKMB7KhIfcRnGGDpXlS-2kFa2if1n1iLATP5ADnJhwhw8S6SDqtLnqM21Tk-IUnPa rgUwnqLm5aRVGocPpM4ktoNz4M8MsuqRBrWM8ykIlw +``` + +5. Generate a random JWE Initialization Vector of the correct size for the content encryption algorithm. In this case, its value is (using JSON Array notation): + +``` +101 98 192 15 167 157 93 152 54 145 173 236 83 4 6 243 +``` + +6. Compute the encoded Initialization Vector value BASE64URL(JWE Initialization Vector). In this case, its value is: + +``` +ZWLAD6edXZg2ka3sUwQG8w +``` + +7. Get the plaintext of the field **payer** of the API message as the payload to be encrypted. In this case, its value is: + +```json +{ + "personalInfo": { + "dateOfBirth": "1986-02-14", "complexName": { + "middleName": "Ben", "lastName": "Lee", "firstName": "Bill" } }, + "name": "Bill Lee", + "partyIdInfo": { "fspId": "1234", "partyIdType": "MSISDN", + "partySubIdOrType": "RegisteredCustomer", "partyIdentifier": "16135551212" + } +} +``` + +8. Create the JSON object or objects containing the desired set of header parameters, which together comprise the JWE Protected Header. In this case, its value is: + +```json +{"alg":"RSA-OAEP-256","enc":"A256GCM"} +``` + +9. Compute the Encoded Protected Header value BASE64URL(UTF8(JWE Protected Header)). In this case, its value is: + +``` +eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0 +``` + +10. Let the Additional Authenticated Data encryption parameter be ASCII(Base64URL(JWE Protected Header)). +11. Encrypt the plain text using the CEK, the JWE Initialization Vector, and the Additional Authenticated Data value using the specified content encryption algorithm to create the JWE Cipher text value and the JWE Authentication Tag (which is the Authentication Tag output from the encryption operation). +12. Compute the encoded cipher text value BASE64URL(JWE Cipher Text). In this case its value is: + +``` +BfXbxoyXcWCzL3DwG7B2P5UswlP8MPXerIkKbRR3vDLuN7lfa33puj7VICFeqG1fAlxrXgs_Nvk ZkE4WlqGNlQ_nBS1xYknxjh7hkPVb-V-Z9ZEvLdcaHlGJrH5oEvR7RIB8TOHgVHP1brlrEptB4- 4ejXXv80cbknRJtDl_mmjaU_Na4irGrWhA3ZhXZM1aM7wtquJLIk-1ZNLadGnGPygl21sEITF8h fPzbk7Djs45nBc5izWcoskCCNvLDU6PqOEhWe3y6GdsDiqFPB1OeZRq06ZBEfKZzAAJ0u3KZqoO BAEVHVvt41D3ejVimTVQJs1dVL2HacvuJyVW6YugwFotZbg +``` + +13. Compute the encoded Authentication Tag value BASE64URL(JWE Authentication Tag). In this case its value is: + +``` +9GaZEDZD9wmzqVGCI-FDgQ +``` + +##### Encrypt payee.partyIdInfo.partyIdentifier + +1. Determine the algorithm used to determine the CEK value. In this case, assuming it is **RSA-OAEP-256**. +2. Generate a 256-bit random CEK. In this case, the same CEK defined in [Encryption Data Model](#encryption-data-model) is used., Its value is (using JSON Array notation): + +``` +191 100 167 60 2 248 21 136 172 39 145 120 102 7 73 31 166 66 114 199 219 157 104 162 7 253 10 105 33 136 57 167 +``` + +3. Encrypt the CEK with the Payee FSP's public key represented in JSON Web Key format in [API Encryption/Decryption Examples](#api-encryptiondecryption-examples). In this case, its value is (using JSON Array notation): + +``` +149 174 138 153 221 70 241 229 93 27 56 185 185 210 242 238 81 187 207 88 40 43 24 7 245 121 94 73 151 150 249 19 15 158 11 97 80 99 194 60 143 138 168 211 202 210 52 19 128 211 156 179 101 248 95 163 23 166 217 222 14 12 163 206 242 182 170 211 119 22 84 107 3 97 153 207 240 211 82 113 100 254 39 62 224 183 250 176 156 63 198 73 245 187 239 16 136 127 120 130 146 236 29 47 255 116 223 240 39 224 94 165 102 120 242 9 182 84 138 109 205 55 242 20 186 91 140 49 198 244 250 58 123 3 63 22 51 59 5 183 112 17 160 238 34 217 11 109 79 246 174 221 138 118 82 21 15 239 72 185 77 20 178 20 192 89 45 68 140 190 251 233 82 123 33 49 191 135 49 21 25 42 253 171 211 151 7 238 142 206 201 140 206 6 129 23 173 56 153 159 31 39 52 119 102 147 197 213 230 97 113 71 168 184 6 57 183 109 173 233 206 110 112 202 179 74 56 153 184 122 114 234 151 28 15 131 79 192 80 145 130 170 188 82 92 61 121 90 63 148 37 110 20 132 49 131 +``` + +**Note**: Although the same CEK is used for the two fields **payer** and **payee.partyIdInfo.partyIdentifier**, the encrypted CEK values may be different from each other because of the use of a random number when encrypting the CEK by JWE implementations (for example, jose4j, nimbus-jose-jwt, and so on). This depends on how the JWE is implemented in each FSP system. +4. Compute the encoded key value BASE64URL(JWE Encrypted Key). In this case, its value is: + +``` +la6Kmd1G8eVdGzi5udLy7lG7z1goKxgH9XleSZeW-RMPngthUGPCPI-KqNPK0jQTgNOcs2X4X6M XptneDgyjzvK2qtN3FlRrA2GZz_DTUnFk_ic-4Lf6sJw_xkn1u--niH94gpLsHS__dN_wJ-BepW Z48gm2VIptzTfyFLpbjDHG9Po6ewM_FjM7BbdwEaDuItkLbU_2rt2KdlIVD-9IuU0UshTAWS1Ej L776VJ7ITG_hzEVGSr9q9OXB-6OzsmMzgaBF604mZ8fJzR3ZpPF1eZhcUeouAY5t22t6c5ucMqz SjiZuHpy6pccD4NPwFCRgqq8Ulw9eVo_lCVuFIQxgw +``` + +5. Generate a random JWE Initialization Vector of the correct size for the content encryption algorithm. In this case, its value is (using JSON Array notation): + +``` +86 250 136 87 147 231 201 138 65 75 164 215 147 100 136 195 +``` + +6. Compute the encoded Initialization Vector value BASE64URL(JWE Initialization Vector). In this case, its value is: + +``` +VvqIV5PnyYpBS6TXk2SIww +``` + +7. Get the plain text of the field **payee.partyIdInfo.partyIdentifier** of the API message as the payload to be encrypted. In this case, its value is + +``` +15295558888 +``` + +8. Create the JSON object or objects containing the desired set of Header Parameters, which together comprise the JWE Protected Header. In this case, its value is: + +```json +{"alg":"RSA-OAEP-256","enc":"A256GCM"} +``` + +9. Compute the Encoded Protected Header value BASE64URL(UTF8(JWE Protected Header)). In this case, its value is: + +``` +eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0 +``` + +10. Let the Additional Authenticated Data encryption parameter be ASCII(Encoded Protected Header). +11. Encrypt the plain text using the CEK, the JWE Initialization Vector, and the Additional Authenticated Data value using the specified content encryption algorithm to create the JWE Cipher text value and the JWE Authentication Tag (which is the Authentication Tag output from the encryption operation). +12. Compute the encoded cipher text value BASE64URL(JWE Cipher Text). In this case its value is: + +``` +WBQN5nLDGK26EiM +``` + +13. Compute the encoded Authentication Tag value BASE64URL(JWE Authentication Tag). In this case its value is: + +``` +6jQVo7kmZq3jMNXfavxoXQ +``` + +#### Producing FSPIOP-Encryption + +Using the given data model of the header **FSPIOP-Encryption**, get the header's value as shown below (line break and indentation are only for display purpose): + +```json +{ + "encryptedFields": + [ + { + "initializationVector":"ZWLAD6edXZg2ka3sUwQG8w", + "fieldName":"payer", + "encryptedKey":"FtItL5lft09UGsIqG5gyw6MS63mMeOCBtHgVAC7EFXL7lH9LxipX-rpiD4j5g- + BJb2yfjGucUB6FTVYaHA1CU_jlhE3LceUY0JtRrAmkGX7O2RnOHtomvoDE- + ukiL1ZbnYxX8B13foioClf21RdocteGR1cuN4OuD8HCWsLQ1A8YIY8m_X15r9zKal9_gcAC- + SIkOKJPPpu-h-J_LNN9ngTZTVcfT5DhSU4emZypMv5JQKMB7KhIfcRnGGDpXlS- + 2kFa2if1n1iLATP5ADnJhwhw8S6SDqtLnqM21Tk-IUnPargUwnqLm5aRVGo- + cPpM4ktoNz4M8MsuqRBrWM8ykIlw", + "authenticationTag":"9GaZEDZD9wmzqVGCI-FDgQ", + "protectedHeader":"eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0" + }, + { + "initializationVector":"VvqIV5PnyYpBS6TXk2SIww", + "fieldName":"payee.partyIdInfo.partyIdentifier", + "encryptedKey":"la6Kmd1G8eVdGzi5udLy7lG7z1goKxgH9XleSZeW-RMPngthUGPCPI- + KqNPK0jQTgNOcs2X4X6MXptneDgyjzvK2qtN3FlRrA2GZz_DTUnFk_ic-4Lf6sJw_xkn1u-- + niH94gpLsHS__dN_wJ-BepWZ48gm2VIptzTfyFLpbjDHG9Po6ewM_FjM7BbdwEa- + DuItkLbU_2rt2KdlIVD-9IuU0UshTAWS1EjL776VJ7ITG_hzEVGSr9q9OXB- + 6OzsmMzgaBF604mZ8fJzR3ZpPF1eZhcUeouAY5t22t6c5ucMqzS- + jiZuHpy6pccD4NPwFCRgqq8Ulw9eVo_lCVuFIQxgw", + "authenticationTag":"6jQVo7kmZq3jMNXfavxoXQ", + "protectedHeader":"eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0" + } + ] +} +``` + +#### Re-produce API message with encryption + +Using the cipher text of the encrypted field to replace the plain text of the corresponding field of the API message (the string with, **light grey** background in the message text below), add parameter **FSPIOP-Encryption** (the string with **light grey** background in the message text below) into the HTTP header of the API message. + +**Note**: The **FSPIOP-Encryption** parameter should be included in the JWS Protected Header for the signature of the API message, and the HTTP body of the API message below should be the JWS Payload for the signature. The signature process is out-of- scope for this document. + +```json +POST /quotes HTTP/1.1 +Accept:application/vnd.interoperability.quotes+json;version=1.0 +Content-Type:application/vnd.interoperability.quotes+json;version=1.0 +Date:Tue, 23 May 2017 21:12:31 GMT +FSPIOP-Source:1234 +FSPIOP-Destination:5678 +Content-Length:1068 +FSPIOP-Encryption: {"encryptedFields":{ + "initializationVector":"ZWLAD6edXZg2ka3sUwQG8w", + "fieldName":"payer", + "encryptedKey":"FtItL5lft09UGsIqG5gyw6MS63mMeOCBtHgVAC7EFXL7lH9LxipX- +rpiD4j5g-BJb2yfjGucUB6FTVYaHA1CU_jlhE3LceUY0JtRrAmkGX7O2RnOHtomvoDE- +ukiL1ZbnYxX8B13foioClf21RdocteGR1cuN4OuD8HCWsLQ1A8YIY8m_X15r9zKal9_gcACSIkOKJPPpu- +h-J_LNN9ngTZTVcfT5DhSU4emZypMv5JQKMB7KhIfcRnGGDpXlS- +2kFa2if1n1iLATP5ADnJhwhw8S6SDqtLnqM21Tk- +IUnPargUwnqLm5aRVGocPpM4ktoNz4M8MsuqRBrWM8ykIlw", + "authenticationTag":"9GaZEDZD9wmzqVGCI-FDgQ", + "protectedHeader":"eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0" + }, { + "initializationVector":"VvqIV5PnyYpBS6TXk2SIww", + "fieldName":"payee.partyIdInfo.partyIdentifier", + "encryptedKey":"la6Kmd1G8eVdGzi5udLy7lG7z1goKxgH9XleSZeW-RMPngthUGPCPI- +KqNPK0jQTgNOcs2X4X6MXptneDgyjzvK2qtN3FlRrA2GZz_DTUnFk_ic-4Lf6sJw_xkn1u-- +niH94gpLsHS__dN_wJ- +BepWZ48gm2VIptzTfyFLpbjDHG9Po6ewM_FjM7BbdwEaDuItkLbU_2rt2KdlIVD- +9IuU0UshTAWS1EjL776VJ7ITG_hzEVGSr9q9OXB- +6OzsmMzgaBF604mZ8fJzR3ZpPF1eZhcUeouAY5t22t6c5ucMqzSjiZuHpy6pccD4NPwFCRgqq8Ulw9eVo_lCVuFIQxgw", + "authenticationTag":"6jQVo7kmZq3jMNXfavxoXQ", + "protectedHeader":"eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0" + } + ] +} +{"amount":{"amount":"150","currency":"USD"},"transactionType":{"scenario":"TRANSFER","initiator":"PAYER","subScenario":"P2P Transfer across MM systems","initiatorType":"CONSUMER"},"transactionId":"36629a51-393a-4e3c-b347-c2cb57e1e1fc","quoteId":"59e331fa-345f-4554-aac8-fcd8833f7d50","payer":"BfXbcoyXcWCzL3DwG7B2P5UswlP8MPXerIkKbRR3vDLuN7lfa33puj7VICFeqG1fAlxrXgs_NvkZkE4WlqGNlQ_nBS1xYknxjh7hkPVb-B-Z9ZEvLdcaHlGJrH5oEvR7RIB8TOHgVHP1brlrEptB4-4ejXXv80cbknRJtDl_mmjaU_Na4irGrWhA3ZhXZM1aM7wtquJLIk-1ZNLadGnGPygl21sEITF8hfPzbk7Djs45nBc5izWcoskCCNvLDU6PqOEhWe3y6GdsDiqFPB10eZRq06ZBEfKZzAAJ0u3KZqoOBAEVHVvt41D3ejVimTVQJs1dVL2HacvuJyVW6ugwFotZbg","expiration":"2017-05-24T08:40:00.000-04:00","payee":{"partyIdInfo":{"fspId":"5678","partyIdType":"MSISDN","partyIdentifier":"WBQN5nLDGK26EiM"}},"fees":{"amount":"1.5","currency":"USD"},"extensionList":{"extension":[{"value":"value1","key":"key1"},{"value":"value2","key":"key2"},{"value":"value3","key":"key3"}]},"note":"this is a sample for POST/quotes","geoCode":{"longitude":"125.520001","latitude":"57.323889"},"amountType":"RECEIVE"} +``` + +### Decryption Example + +In this example, the Payee FSP receives the POST /quotes API message from Payer FSP. The message is described in [Encryption Data Model](#encryption-data-model). If the Payee FSP detects that the HTTP header parameter **FSPIOP-Encryption** is present in the message, then the Payee FSP knows that some fields were encrypted by the Payer FSP. The Payee FSP then performs the following steps to decrypt the encrypted fields.] + +#### Parse FSPIOP-Encryption + +The Payee FSP verifies that the value of **FSPIOP-Encryption** is a UTF-8-encoded representation of a valid JSON object conforming to RFC 7159. The FSP then parses the HTTP Header parameter **FSPIOP-Encryption** to get encrypted fields information, including field name, JWE Protected Header, JWE Encrypted Key, JWE Initialization Vector, and JWE Authentication Tag for each field. + +#### Decrypt the Encrypted Fields + +In this case, the Payee FSP gets two fields **payer** and **payee.partyIdInfo.partyIdentifier** from the HTTP header **FSPIOP- Encryption**. Then the Payee FSP decrypts the two fields one-by-one. + +##### Decrypt payer + +The Payer FSP performs the following steps to decrypt the field **payer** in the **POST /quotes** API message. + +1. Get the encoded BASE64RUL(JWE Protected Header) from the parsed **FSPIOP-Encryption** for the field **payer**. In this case its value is: + +``` +eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0 +``` + +2. Decode the encoded JWE Protected Header. In this case its value is: + +```json +{"alg":"RSA-OAEP-256","enc":"A256GCM" +``` + +3. Check that the decoded value of JWE Protected Header is a UTF-8-encoded representation of a completely valid JSON object conforming to JSON Data Interchange Format (RFC 7159), and that the parameters in the JWE Protected Header can process all fields that are required to support the JWE specification. +4. Get the encoded BASE64URL(JWE Encrypted Key). In this case its value is: + +``` +FtItL5lft09UGsIqG5gyw6MS63mMeOCBtHgVAC7EFXL7lH9LxipX-rpiD4j5g-BJb2yfjGucUB6 FTVYaHA1CU_jlhE3LceUY0JtRrAmkGX7O2RnOHtomvoDE-ukiL1ZbnYxX8B13foioClf21Rdoct eGR1cuN4OuD8HCWsLQ1A8YIY8m_X15r9zKal9_gcACSIkOKJPPpu-h-J_LNN9ngTZTVcfT5DhSU 4emZypMv5JQKMB7KhIfcRnGGDpXlS-2kFa2if1n1iLATP5ADnJhwhw8S6SDqtLnqM21Tk-IUnPa rgUwnqLm5aRVGocPpM4ktoNz4M8MsuqRBrWM8ykIlw] +``` + +5. Decode the encoded JWE Encrypted Key. In this case its value is as follows (using JSON Array notation): + +``` +[22 210 45 47 153 95 183 79 84 26 194 42 27 152 50 195 163 18 235 121 140 120 224 129 180 120 21 0 46 196 21 114 251 148 127 75 198 42 87 250 186 98 15 136 249 131 224 73 111 108 159 140 107 156 80 30 133 77 86 26 28 13 66 83 248 229 132 77 203 113 229 24 208 155 81 172 9 164 25 126 206 217 25 206 30 218 38 190 128 196 250 233 34 47 86 91 157 140 87 240 29 119 126 136 168 10 87 246 213 23 104 114 215 134 71 87 46 55 131 174 15 193 194 90 194 208 212 15 24 33 143 38 253 125 121 175 220 202 106 95 127 129 192 2 72 137 14 40 147 207 166 239 161 248 159 203 52 223 103 129 54 83 85 199 211 228 56 82 83 135 166 103 42 76 191 146 80 40 192 123 42 18 31 113 25 198 24 58 87 149 47 182 144 86 182 137 253 103 214 34 192 76 254 64 14 114 97 194 28 60 75 164 131 170 210 231 168 205 181 78 79 136 82 115 218 174 5 48 158 162 230 229 164 85 26 135 15 164 206 36 182 131 115 224 207 12 178 234 145 6 181 140 243 41 8 151] +``` + +6. Decrypt the JWE Encrypted Key using the specified algorithm **RSA-OAEP-256** with the Payee FSP's private key to get the CEK. In this case the decrypted CEK is (using JSON Array notat ion): + +``` +[191 100 167 60 2 248 21 136 172 39 145 120 102 7 73 31 166 66 114 199 219 157 104 162 7 253 10 105 33 136 57 167] +``` + +7. Get the encoded BASE64URL(JWE Initialization Vector). Its value is: + +``` +ZWLAD6edXZg2ka3sUwQG8w +``` + +8. Decode the encoded JWE Initialization Vector. In this case, its value is (using JSON Array notation): + +``` +[101 98 192 15 167 157 93 152 54 145 173 236 83 4 6 243] +``` + +9. Get the value of the field **payer** from the API message as the encoded BASE64URL(JWE Cipher Text) to be decrypted. In this case, its value is + +``` +BfXbxoyXcWCzL3DwG7B2P5UswlP8MPXerIkKbRR3vDLuN7lfa33puj7VICFeqG1fAlxrXgs\_Nvk ZkE4WlqGNlQ\_nBS1xYknxjh7hkPVb-V-Z9ZEvLdcaHlGJrH5oEvR7RIB8TOHgVHP1brlrEptB4- 4ejXXv80cbknRJtDl\_mmjaU\_Na4irGrWhA3ZhXZM1aM7wtquJLIk-1ZNLadGnGPygl21sEITF8h fPzbk7Djs45nBc5izWcoskCCNvLDU6PqOEhWe3y6GdsDiqFPB1OeZRq06ZBEfKZzAAJ0u3KZqoO BAEVHVvt41D3ejVimTVQJs1dVL2HacvuJyVW6YugwFotZbg +``` + +10. Get the encoded Authentication Tag value BASE64URL(JWE Authentication Tag). In this case its value is: + +``` +9GaZEDZD9wmzqVGCI-FDgQ +``` + +11. Decrypt the cipher text using the CEK, the JWE Initialization Vector, and the Additional Authenticated Data value using the specified content encryption algorithm to decrypt the JWE Cipher text. In this case, the plain text is + +```json +{ + "personalInfo": { + "dateOfBirth": "1986-02-14", + "complexName": { "middleName": "Ben", "lastName": "Lee", + "firstName": "Bill" } }, + "name": "Bill Lee", + "partyIdInfo": { + "fspId": "1234", "partyIdType": "MSISDN", + "partySubIdOrType": "RegisteredCustomer", "partyIdentifier": + "16135551212" + } +} +``` + +12. Verify that the plaintext is a UTF-8-encoded representation of a completely valid JSON object conforming to RFC 7159, and the content matches the data mode definition for the **payer**. + +##### Decrypt payee.partyIdInfo.partyIdentifier + +The Payer FSP performs the following steps to decrypt the field **payee.partyIdInfo.partyIdentifier** in the **POST /quotes** API message. + +1. Get the encoded BASE64RUL(JWE Protected Header) from the parsed **FSPIOP-Encryption** for the field **payee.partyIdInfo.partyIdentifier**. In this case its value is: + +``` +eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0 +``` + +2. Decode the encoded JWE Protected Header. In this case its value is: + +```json +{"alg":"RSA-OAEP-256","enc":"A256GCM"} +``` + +3. Verify that the decoded value of JWE Protected Header is a UTF-8-encoded representation of a completely valid JSON object conforming to RFC 7159, and that the parameters in the JWE Protected Header understand and can process all fields that are required to support the JWE specification. +4. Get the encoded BASE64URL(JWE Encrypted Key). In this case its value is: + +``` +la6Kmd1G8eVdGzi5udLy7lG7z1goKxgH9XleSZeW-RMPngthUGPCPI-KqNPK0jQTgNOcs2X4X6M XptneDgyjzvK2qtN3FlRrA2GZz_DTUnFk_ic-4Lf6sJw_xkn1u--niH94gpLsHS__dN_wJ-BepW Z48gm2VIptzTfyFLpbjDHG9Po6ewM_FjM7BbdwEaDuItkLbU_2rt2KdlIVD-9IuU0UshTAWS1Ej L776VJ7ITG_hzEVGSr9q9OXB-6OzsmMzgaBF604mZ8fJzR3ZpPF1eZhcUeouAY5t22t6c5ucMqz SjiZuHpy6pccD4NPwFCRgqq8Ulw9eVo_lCVuFIQxgw +``` + +5. Decode the encoded JWE Encrypted Key. In this case its value is (using JSON Array notation): + +``` +[149 174 138 153 221 70 241 229 93 27 56 185 185 210 242 238 81 187 207 88 40 43 24 7 245 121 94 73 151 150 249 19 15 158 11 97 80 99 194 60 143 138 168 211 202 210 52 19 128 211 156 179 101 248 95 163 23 166 217 222 14 12 163 206 242 182 170 211 119 22 84 107 3 97 153 207 240 211 82 113 100 254 39 62 224 183 250 176 156 63 198 73 245 187 239 167 136 127 120 130 146 236 29 47 255 116 223 240 39 224 94 165 102 120 242 9 182 84 138 109 205 55 242 20 186 91 140 49 198 244 250 58 123 3 63 22 51 59 5 183 112 17 160 238 34 217 11 109 79 246 174 221 138 118 82 21 15 239 72 185 77 20 178 20 192 89 45 68 140 190 251 233 82 123 33 49 191 135 49 21 25 42 253 171 211 151 7 238 142 206 201 140 206 6 129 23 173 56 153 159 31 39 52 119 102 147 197 213 230 97 113 71 168 184 6 57 183 109 173 233 206 110 112 202 179 74 56 153 184 122 114 234 151 28 15 131 79 192 80 145 130 170 188 82 92 61 121 90 63 148 37 110 20 132 49 131] +``` + +6. Decrypt the JWE Encrypted Key using the specified algorithm **RSA-OAEP-256** with the Payee FSP's private key to get the CEK. In this case the decrypted CEK is (using JSON Array notation): + +``` +[191 100 167 60 2 248 21 136 172 39 145 120 102 7 73 31 166 66 114 199 219 157 104 162 7 253 10 105 33 136 57 167] +``` + +7. Get the encoded BASE64URL(JWE Initialization Vector). Its value is: + +``` +VvqIV5PnyYpBS6TXk2SIww +``` + +8. Decode the encoded JWE Initialization Vector. In this case, its value is (using JSON Array notation): + +``` +[86 250 136 87 147 231 201 138 65 75 164 215 147 100 136 195] +``` + +9. Get the value of the field **payee.partyIdInfo.partyIdentifier** from the API message as the encoded BASE64URL(JWE Cipher Text) to be decrypted. In this case, its value is: + +``` +WBQN5nLDGK26EiM +``` + +10. Get the encoded Authentication Tag value BASE64URL(JWE Authentication Tag). In this case its value is: + +``` +6jQVo7kmZq3jMNXfavxoXQ +``` + +11. Decrypt the cipher text using the CEK, the JWE Initialization Vector, and the Additional Authenticated Data value using the specified content encryption algorithm to decrypt the JWE Cipher text. In this case, the plain text is + +``` +15295558888 +``` + +12. Verify that the plain text is a valid **partyIdentifier** value. + +
    + +## Table of Tables +- [Table 1 -- Data model of HTTP Header Field FSPIOP-Encryption](#table-1) +- [Table 2 -- Data model of complex type EncryptedFields](#table-2) +- [Table 3 -- Data model of complex type EncryptedField](#table-3) \ No newline at end of file diff --git a/docs/technical/api/fspiop/v1.1/signature.md b/docs/technical/api/fspiop/v1.1/signature.md new file mode 100644 index 000000000..6512726b1 --- /dev/null +++ b/docs/technical/api/fspiop/v1.1/signature.md @@ -0,0 +1,426 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- +# Signature + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +This document uses the notational conventions for BASE64URL(OCTETS), UTF8(STRING), ASCII(STRING), and || defined in RFC 7515[1](https://tools.ietf.org/html/rfc7515#section-1.1). + +The following conventions are used in this document to identify the specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.1**|2020-05-19|This version contains the below changes: 1. Sections 3.1, 3.2 and 3.3 have been updated based on ”Solution Proposal 12 - Clarify usage of FSPIOP-Destination”. 2. ExtensionList elements in Section 4 have been updated based on the issue [Interpretation of the Data Model for the ExtensionList element](https://github.com/mojaloop/mojaloop-specification/issues/51), to fix the data model of the extensionList Object.| +|**1.0**|2018-03-13|Initial version| + +
    + +## Introduction + +This document details the security methods to be implemented for Open API for FSP Interoperability (hereafter cited as the API) to ensure _integrity_ and _non-repudiation_ between the API client and the API server. + +In information security, _data integrity_ means maintaining and assuring the accuracy and completeness of data over its entire life-cycle. For the API, data integrity means that an API message cannot be modified in an unauthorized or undetected manner by parties involved in the API communication. + +In legal terms, _non-repudiation_ means that a person intends to fulfill their obligations to a contract. It also means that one party in a transaction cannot deny having received the transaction, nor can the other party deny having sent the transaction. For the API, non-repudiation means that an API client cannot deny having sent an API message to a counterparty. JSON Web Signature (JWS), as defined in RFC 7515[2](https://tools.ietf.org/html/rfc7515), must be applied to the API to provide message integrity and non-repudiation for either component fields of an API payload or the full API payload. Whenever an API client sends an API message to a counterparty, the API client should sign the message using its private key. After the counterparty receives the API message, the counterparty must validate the signature with the API client’s public key. Only the HTTP request message of an API message need to be signed, any HTTP response message of the APIs SHALL NOT be signed. + +**Note:** The corresponding public key should either be shared in advance with the counterparty or retrieved by the counterparty (for example, the local scheme Certificate Authority). + +Because intermediary fees are not supported in the current version of the API, intermediaries involved in API message-transit may not modify the API message payload. Thus, the signature at full payload level is used to protect the integrity of the full payload of an API message from end-to-end. Regardless of how many intermediaries there are in transit, the original payload cannot be modified by the intermediaries. The final recipient of the API message must validate the signature generated by the original API client based on the message payload received. + +**Note:** Whether the signature needs to be validated by the intermediaries in transit is determined by the internal implementation of each intermediary or the local schema. + +**Note:** In a future version of the API, intermediary fees may be supported; at that time, signature-at-field-level may also be supported. However, both features are out-of-scope for the current version of the API. + +
    + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](./logical-data-model) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./definitions) + +- [JSON Binding Rules](./json-binding-rules) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](#) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](../glossary) + +
    + +## API Signature Definition + +This section introduces the technology used by the API signature, including the data exchange format for the signature of an API message and the mechanism used to generate and verify a signature. + + +### Signature Data Model + +The API uses a customized HTTP header parameter **FSPIOP-Signature** to represent the signature that is produced by the initiating API client for the API message. The data model for this parameter is described in [Table 1](#table-1). + +**Note:** Currently the API does not support intermediaries in an API message; only the message-initiator can sign a message. If this is required in the future, there will be new customized HTTP header parameter, but this is out-of-scope for the current version of the API. + +###### Table 1 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| protectedHeader | 1 | String(1..32768) |
    This element indicates the HTTP header parameters that are protected by the signature. Its value must be BASE64URL(UTF8(JWS Protected Header)).

    According to JWS specification, the **alg** header parameter must be present to identify the cryptographic algorithm used to secure the JWS.

    A customized parameter **FSPIOP-URI** that represents the URI path and query parameters of HTTP request message of the APIs must be present.

    A customized parameter **FSPIOP-HTTP-Method** that holds the HTTP method used in the HTTP message must be present.

    A customized parameter **FSPIOP-Source** that represents the system which sent the API request must be present.

    The customized HTTP header parameter **FSPIOP-Destination** is mandatory in protectedHeader if the destination FSP is known by the message-initiator. Otherwise this header must not be protected as it can be changed by intermediate systems. See API Definition for more information regarding which services that the header FSPIOP-Destination is optional for.
    | +| signature | 1 | String(1..512) | This element indicates the signature. Its value is part of JWS serialization; that is, BASE64URL(JWS Signature). | +**Table 1 – Data model of HTTP header field FSPIOP-Signature** + +### Generating a Signature + +To create the signature for an API message, the following steps are performed. The order of the steps is not significant in cases where there are no dependencies between the inputs and outputs of the steps. + +1. Create the content to be used as the JWS Payload. Because the signature is currently at full payload level, the full HTTP body of the API message is the JWS Payload. + +2. Compute the encoded payload value BASE64URL(JWS Payload). + +3. Create the JSON object or objects containing the desired JWS Protected Header. + + A. The **alg** JWS Protected Header parameter must be present. In the API, the available algorithms for the signature are **RS256, RS384, RS512**. A key of size 2048 bits or larger must be used with these algorithms. + + B. Other parameters registered in the IANA JSON _Web Signature and Encryption Header Parameters_[3](https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-header-parameters) are optional. + + C. The customized parameter **FSPIOP-URI** must be included in JWS Protected Header to protect the URI path and query parameters of the APIs. + + D. The customized parameter **FSPIOP-HTTP-Method** must be included in JWS Protected Header to protect the HTTP request operation method. + + E. The parameter **FSPIOP-Source** must be present, and its value comes from the corresponding HTTP header parameter **FSPIOP-Source**. + + F. The parameter **FSPIOP-Destination** must be present if the destination FSP is known by the message-initiator, and its value must then be the same as the HTTP header parameter **FSPIOP-Destination**. + + G. Other HTTP Header parameters of the APIs are recommended to be included in JWS Protected Header, but they are optional in this JWS Protected Header. + +4. Compute the encoded header value BASE64URL(UTF8(JWS Protected Header)). + +5. Compute the JWS Signature according to the JWS specification using the output of Step 2 and Step 4. + +6. Compute the encoded signature value BASE64URL(JWS Signature). + +7. Compute the value for the HTTP header parameter **FSPIOP-Signature** as described in the [Signature Data Model](#signature-data-model) section. The value for this **FSPIOP-Signature** is a JSON Object Serialization string. + +**Note:** If JSON Web Encryption (JWE) is used to encrypt some fields of the payload (for more information, see Encryption), then the API client should first encrypt the desired fields, then replace the plain text of those fields with the encoded cipher text in the payload, and then finally sign the payload. + +### Validating Signature + +When validating the signature of an API request, the following steps are performed. The order of the steps is not significant in cases where there are no dependencies between the inputs and outputs of the steps. If any of the listed steps fails, then the signature cannot be validated. + +1. Parse the HTTP header parameter **FSPIOP-Signature** to get the components **protectedHeader** and **signature**. + +2. Use BASE64URL to decode the encoded representation of the JWS Protected Header. Verify that the resulting octet sequence is a UTF-8-encoded representation of a completely valid JSON object conforming to JSON Data Interchange Format, defined in RFC 7159[4](https://tools.ietf.org/html/rfc7159). + +3. Verify the parameters in the JWS Protected Header. + + a) The parameter **alg** must be present and its value must be one of **RS256, RS384, RS512**. + + b) Other parameters registered in the IANA JSON _Web Signature and Encryption Header Parameters_ are optional. + + c) The parameter **FSPIOP-URI** must be present and Its value must be the same as the input URL value of the request. + + d) The parameter **FSPIOP-HTTP-Method** must be present and its value must be same as the operation method of the request. + + e) The parameter **FSPIOP-Source** must be present, and its value must be the same as the corresponding HTTP header parameter **FSPIOP-Source**. + + f) If the parameter **FSPIOP-Destination** is present in the JWS Protected Header, then its value must be same as the corresponding HTTP header parameter **FSPIOP-Destination**. + + g) If there are other HTTP header parameters present in JWS Protected Header, then their values must be validated with the corresponding HTTP header values. + +4. Compute the encoded payload value BASE64URL(JWS Payload). Because the current signature is at full payload level, the full HTTP body of the API message is the JWS Payload. + +5. Validate the JWS Signature against the JWS Signing Input ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload)) in the manner defined for the algorithm being used, which must be accurately represented by the value of the **alg** (algorithm) Header Parameter. + +6. Record whether the validation succeeded. + +
    + +## API Signature Examples + +This section uses a typical quote process to explain how the API signature is implemented using JWS. The FSPs in the API can verify that their internal implementation for API signature is correct using the following case. + +The case in this section uses RS256 as the signature algorithm. The RSA key used for the signature example is represented in JSON Web Key (JWK), defined in RFC 7517[5](https://tools.ietf.org/html/rfc7517), format below (with line breaks and indentation within values for display purposes only): + +```json +{ + "kty": "RSA", + "n": "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddxHmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMsD1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSHSXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ", + "e": "AQAB", + "d": "Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97IjlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYTCBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLhBOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ", + "p": "4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdiYrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPGBY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc", + "q": "uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxaewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc", + "dp": "BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3QCLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0", + "dq": "h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-kyNlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU", + "qi": "IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2oy26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLUW0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U" +} +``` + +### Generating a Sample Signature + +The following message text is an example of `POST /quotes` without a signature sent by Payer FSP to a counterparty (line breaks and indentation within values for display purposes only). + +```json +POST /quotes HTTP/1.1 +Accept:application/vnd.interoperability.quotes+json;version=1.0 +FSPIOP-Source:1234 +FSPIOP-Destination:5678 +Content-Length:975 +Date:Tue, 23 May 2017 21:12:31 GMT +Content-Type:application/vnd.interoperability.quotes+json;version=1.0 +{ + "amount": { "amount": "150", "currency": "USD" },"transactionType": { + "scenario": "TRANSFER", "initiator": "PAYER","subScenario": "P2P Transfer across MM systems","initiatorType": "CONSUMER" + }, + "transactionId": "36629a51-393a-4e3c-b347-c2cb57e1e1fc","quoteId": "59e331fa-345f-4554-aac8-fcd8833f7d50","expiration": "2017-05-24T08:40:00.000-04:00", + "payer": { + "personalInfo": { + "dateOfBirth": "1986-02-14", + "complexName": { "middleName": "Ben", + "LastName": "Lee", "firstName": "Bill" } }, + "name": "Bill Lee", + "partyIdInfo": { "fspId": "1234", "partyIdType": "MSISDN", + "partySubIdOrType": "RegisteredCustomer","partyIdentifier": "16135551212" } + }, + "payee": { + "partyIdInfo": { "fspId": "5678", + "partyIdType": "MSISDN", + "partyIdentifier": "15295558888" } + }, + "fees": { "amount": "1.5", "currency": "USD" }, + "extensionList": { + "extension": [ + { "value": "value1", "key": "key1" }, + { "value": "value2", "key": "key2" }, + { "value": "value3", "key": "key3" } + ] + }, + "note": "this is a sample for POST /quotes", + "geoCode": { + "longitude": "125.520001", "latitude": "57.323889" }, + "amountType": "RECEIVE" +} +``` + +#### Computing Signature Input + +According to JWS specification, the signature input is BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload). + +Assuming the HTTP header parameters **Date** and **FSPIOP-Destination** are protected by the signature, and the algorithm RS256 is used to sign the message, the JWS Protected Header in this case is as follows (line breaks and indentation within values for display purposes only): + +```json +{ + "alg":"RS256", + "FSPIOP-Destination":"5678", + "FSPIOP-URI":"/quotes", + "FSPIOP-HTTP-Method":"POST", + "Date":"Tue, 23 May 2017 21:12:31 GMT", + "FSPIOP-Source":"1234" +} +``` + +Encoding this JWS Protected Header as BASE64URL(UTF8(JWS Protected Header)) gives this value: + +``` +eyJhbGciOiJSUzI1NiIsIkZTUElPUC1EZXN0aW5hdGlvbiI6IjU2NzgiLCJGU1BJT1AtVVJJIjoiL3F1b3RlcyIsIkZTUElPUC1IVFRQLU1ldGhvZCI6IlBPU1QiLCJEYXRlIjoiVHVlLCAyMyBNYXkgMjAxNyAyMToxMjozMSBHTVQiLCJGU1BJT1AtU291cmNlIjoiMTIzNCJ9 +``` + +In this case, JWS Payload is the HTTP Body described in [Generating A Signature](#generating-a-signature) section. Encoding this JWS Payload as BASE64URL(JWS Payload) gives this value: + +``` +eyJwYXllZSI6eyJwYXJ0eUlkSW5mbyI6eyJwYXJ0eUlkVHlwZSI6Ik1TSVNETiIsInBhcnR5SWRlbnRpZmllciI6IjE1Mjk1NTU4ODg4IiwiZnNwSWQiOiI1Njc4In19LCJhbW91bnRUeXBlIjoiUkVDRUlWRSIsInRyYW5zYWN0aW9uVHlwZSI6eyJzY2VuYXJpbyI6IlRSQU5TRkVSIiwiaW5pdGlhdG9yIjoiUEFZRVIiLCJzdWJTY2VuYXJpbyI6IlAyUCBUcmFuc2ZlciBhY3Jvc3MgTU0gc3lzdGVtcyIsImluaXRpYXRvclR5cGUiOiJDT05TVU1FUiJ9LCJub3RlIjoidGhpcyBpcyBhIHNhbXBsZSBmb3IgUE9TVCAvcXVvdGVzIiwiYW1vdW50Ijp7ImFtb3VudCI6IjE1MCIsImN1cnJlbmN5IjoiVVNEIn0sImZlZXMiOnsiYW1vdW50IjoiMS41IiwiY3VycmVuY3kiOiJVU0QifSwiZXh0ZW5zaW9uTGlzdCI6W3sidmFsdWUiOiJ2YWx1ZTEiLCJrZXkiOiJrZXkxIn0seyJ2YWx1ZSI6InZhbHVlMiIsImtleSI6ImtleTIifSx7InZhbHVlIjoidmFsdWUzIiwia2V5Ijoia2V5MyJ9XSwiZ2VvQ29kZSI6eyJsYXRpdHVkZSI6IjU3LjMyMzg4OSIsImxvbmdpdHVkZSI6IjEyNS41MjAwMDEifSwiZXhwaXJhdGlvbiI6IjIwMTctMDUtMjRUMDg6NDA6MDAuMDAwLTA0OjAwIiwicGF5ZXIiOnsicGVyc29uYWxJbmZvIjp7ImNvbXBsZXhOYW1lIjp7ImZpcnN0TmFtZSI6IkJpbGwiLCJtaWRkbGVOYW1lIjoiQmVuIiwiTGFzdE5hbWUiOiJMZWUifSwiZGF0ZU9mQmlydGgiOiIxOTg2LTAyLTE0In0sInBhcnR5SWRJbmZvIjp7InBhcnR5SWRUeXBlIjoiTVNJU0ROIiwicGFydHlTdWJJZE9yVHlwZSI6IlJlZ2lzdGVyZWRDdXN0b21lciIsInBhcnR5SWRlbnRpZmllciI6IjE2MTM1NTUxMjEyIiwiZnNwSWQiOiIxMjM0In0sIm5hbWUiOiJCaWxsIExlZSJ9LCJxdW90ZUlkIjoiNTllMzMxZmEtMzQ1Zi00NTU0LWFhYzgtZmNkODgzM2Y3ZDUwIiwidHJhbnNhY3Rpb25JZCI6IjM2NjI5YTUxLTM5M2EtNGUzYy1iMzQ3LWMyY2I1N2UxZTFmYyJ9 +``` + +#### Producing Signature + +Use the given RSA Private Key, the JWS Protected Header and the JWS Payload to generate the signature, then encoding the signature as BASE64URL(JWS Signature) produces this value: + +``` +dz2ntyS0_rDyA0pLeWluG--tBcYYrlvG99ffkXcEB-dz2ntyS0_rDyA0pLeWluG--tBcYYrlvG99ffkXcEB-uve5Qzvzyn0ZUi82J7h17RsdfHPuTnbEGvCeU9Y4Bg0nIZHGL4icswaaO09T5hPPYKBTzVQeHkokLmL4dXpHdr1ggSEpu3WEU3nfgOFGGAdOq355i1iGuDbhqm_lSfVHaqdVCEhkJ2Y_r2glO2QpdZrcbvsBV39derj_PlfISBBGjdh0dIPxnFIVcZuPHiq9Ha2MslrBHfqwFfNeU_xhErBd2PywkDQJbKOlfqdkmFC9bS8Ofx0O6Mg7qdFGw-QkseJTfp0HMbH1d9e6H0cocY8xfuDNGaZpOJhxiYtiPLg +``` + +#### Re-produce API Request with Signature + +As described in the [Signature Data Model](#signature-data-model) section, the API signature is represented by a customized HTTP header parameter **FSPIOP-Signature**; thus the API request with the signature in this case is the following message text (line breaks and indentation within values for display purposes only). + +```json +POST /quotes HTTP/1.1 +FSPIOP-Destination:5678 +Accept:application/vnd.interoperability.quotes+json;version=1.0 +Content-Length:975 +Date:Tue, 23 May 2017 21:12:31 GMT +FSPIOP-Source:1234 +Content-Type:application/vnd.interoperability.quotes+json;version=1.0 +FSPIOP-Signature: {"signature": "dz2ntyS0_rDyA0pLeWluG--tBcYYrlvG99ffkXcEBuve5Qzvzyn0ZUi82J7h17RsdfHPuTnbEGvCeU9Y4Bg0nIZHGL4icswaaO09T5hPPYKBTzVQeHkokLmL4dXpHdr1ggSEpu3WEU3nfgOFGGAdOq355i1iGuDbhqm_lSfVHaqdVCEhkJ2Y_r2glO2QpdZrcbvsBV39derj_PlfISBBGjdh0dIPxnFIVcZuPHiq9Ha2MslrBHfqwFfNeU_xhErBd2PywkDQJbKOlfqdkmFC9bS8Ofx0O6Mg7qdFGwQkseJTfp0HMbH1d9e6H0cocY8xfuDNGaZpOJhxiYtiPLg", "protectedHeader": "eyJhbGciOiJSUzI1NiIsIkZTUElPUC1EZXN0aW5hdGlvbiI6IjU2NzgiLCJGU1BJT1AtVVJJIjoiL3F1b3RlcyIsIkZTUElPUC1IVFRQLU1ldGhvZCI6IlBPU1QiLCJEYXRlIjoiVHVlLCAyMyBNYXkgMjAxNyAyMToxMjozMSBHTVQiLCJGU1BJT1AtU291cmNlIjoiMTIzNCJ9" +} +{ + "amount": { "amount": "150", "currency": "USD" }, + "transactionType": { + "scenario": "TRANSFER", "initiator": "PAYER", + "subScenario": "P2P Transfer across MM systems", + "initiatorType": "CONSUMER" }, + "transactionId": "36629a51-393a-4e3c-b347-c2cb57e1e1fc", + "quoteId": "59e331fa-345f-4554-aac8-fcd8833f7d50", + "expiration": "2017-05-24T08:40:00.000-04:00", + "payer": { + "personalInfo": { "dateOfBirth": "1986-02-14", + "complexName": { "middleName": "Ben", + "LastName": "Lee", "firstName": "Bill" } }, + "name": "Bill Lee", + "partyIdInfo": { "fspId": "1234", "partyIdType": "MSISDN", + "partySubIdOrType": "RegisteredCustomer", + "partyIdentifier": "16135551212" } }, + "payee": { "partyIdInfo": { "fspId": "5678", + "partyIdType": "MSISDN", + "partyIdentifier": "15295558888" } }, + "fees": { "amount": "1.5", "currency": "USD" }, + "extensionList": { + "extension": [ + { "value": "value1", "key": "key1" }, + { "value": "value2", "key": "key2" }, + { "value": "value3", "key": "key3" } + ] + }, + "note": "this is a sample for POST /quotes", + "geoCode": { "longitude": "125.520001", "latitude": "57.323889" }, + "amountType": "RECEIVE" +} +``` + +### Validating the Signature + +After the Payee FSP receives the `POST /quotes` API message from Payer FSP, the Payee FSP must validate the signature signed by the Payer FSP. + +#### Parse FSPIOP-Signature + +1. Parse the HTTP header parameter **FSPIOP-Signature** to get the components **protectedHeader** and signature. In this case, the value of **protectedHeader** is: + +``` +eyJhbGciOiJSUzI1NiIsIkZTUElPUC1EZXN0aW5hdGlvbiI6IjU2NzgiLCJGU1BJT1AtVVJJIjo +iL3F1b3RlcyIsIkZTUElPUC1IVFRQLU1ldGhvZCI6IlBPU1QiLCJEYXRlIjoiVHVlLCAyMyBNYX +kgMjAxNyAyMToxMjozMSBHTVQiLCJGU1BJT1AtU291cmNlIjoiMTIzNCJ9 +``` + +2. Use BASE64URL to decode the encoded representation of the JWS Protected Header. Verify that the resulting octet sequence is a UTF-8-encoded representation of a completely valid JSON object conforming to JSON Data Interchange Format, defined in RFC7159. In this case, the decoded JSON object is: + +```json +{ + "alg":"RS256", + "FSPIOP-Destination":"5678", + "FSPIOP-URI":"/quotes", + "FSPIOP-HTTP-Method":"POST", + "Date":"Tue, 23 May 2017 21:12:31 GMT", + "FSPIOP-Source":"1234" +} +``` + +3. Verify that the **alg** parameter is valid for the API. That means it must be in the list of **RS256, RS384, RS512**. In this case, the value of **alg** is **RS256**, which is valid. + +4. Verify that the value of the parameter **FSPIOP-URI** is same as the input URL of this API message. + +5. Verify that the value of the parameter **FSPIOP-HTTP-Method** is same as the HTTP method of this API message. + +6. Verify that the value of the HTTP header parameter **FSPIOP-Source** is the same as the corresponding value listed in this JWS Protected Header. + +7. Verify that the values for the HTTP header parameter **FSPIOP-Destination** are the same as the corresponding values stated in this JWS Protected Header. + +8. Verify the other protected HTTP header parameters. In this case, the **Date** parameter is protected by JWS Protected Header. If the parameters **Date** in the HTTP header of this API message and **Date** in the JWS Protected Header are equal, then the validation is successful. Both **Date** parameters in the example should be the following value: + +``` +"Tue, 23 May 2017 21:12:31 GMT" +``` + +The validation is passed. + +#### Verify JWS Signature + +1. In this case, the JWS Payload is the full HTTP body of the API message, that is (line breaks and indentation within values for display purposes only): + +```json +{ + "amount": { "amount": "150", "currency": "USD" }, + "transactionType": { "scenario": "TRANSFER", "initiator": "PAYER", + "subScenario": "P2P Transfer across MM systems", + "initiatorType": "CONSUMER" + }, + "transactionId": "36629a51-393a-4e3c-b347-c2cb57e1e1fc", + "quoteId": "59e331fa-345f-4554-aac8-fcd8833f7d50", + "expiration": "2017-05-24T08:40:00.000-04:00", + "payer": { + "personalInfo": { "dateOfBirth": "1986-02-14", + "complexName": { "middleName": "Ben", + "LastName": "Lee", "firstName": "Bill" } }, + "name": "Bill Lee", + "partyIdInfo": { "fspId": "1234", + "partyIdType": "MSISDN", + "partySubIdOrType": "RegisteredCustomer", + "partyIdentifier": "16135551212" } }, + "payee": { + "partyIdInfo": { "fspId": "5678", + "partyIdType": "MSISDN", + "partyIdentifier": "15295558888" } }, + "fees": { "amount": "1.5", "currency": "USD" }, + "extensionList": { + "extension": [ + { "value": "value1", "key": "key1" }, + { "value": "value2", "key": "key2" }, + { "value": "value3", "key": "key3" } + ] + }, + "note": "this is a sample for POST /quotes", + "geoCode": { "longitude": "125.520001", "latitude": "57.323889" }, + "amountType": "RECEIVE" +} + ``` + +2. Compute the encoded payload value BASE64URL(JWS Payload). Get the encoded value as: + +``` +eyJwYXllZSI6eyJwYXJ0eUlkSW5mbyI6eyJwYXJ0eUlkVHlwZSI6Ik1TSVNETiIsInBhcnR5SWRlbnRpZmllciI6IjE1Mjk1NTU4ODg4IiwiZnNwSWQiOiI1Njc4In19LCJhbW91bnRUeXBlIjoiUkVDRUlWRSIsInRyYW5zYWN0aW9uVHlwZSI6eyJzY2VuYXJpbyI6IlRSQU5TRkVSIiwiaW5pdGlhdG9yIjoiUEFZRVIiLCJzdWJTY2VuYXJpbyI6IlAyUCBUcmFuc2ZlciBhY3Jvc3MgTU0gc3lzdGVtcyIsImluaXRpYXRvclR5cGUiOiJDT05TVU1FUiJ9LCJub3RlIjoidGhpcyBpcyBhIHNhbXBsZSBmb3IgUE9TVCAvcXVvdGVzIiwiYW1vdW50Ijp7ImFtb3VudCI6IjE1MCIsImN1cnJlbmN5IjoiVVNEIn0sImZlZXMiOnsiYW1vdW50IjoiMS41IiwiY3VycmVuY3kiOiJVU0QifSwiZXh0ZW5zaW9uTGlzdCI6W3sidmFsdWUiOiJ2YWx1ZTEiLCJrZXkiOiJrZXkxIn0seyJ2YWx1ZSI6InZhbHVlMiIsImtleSI6ImtleTIifSx7InZhbHVlIjoidmFsdWUzIiwia2V5Ijoia2V5MyJ9XSwiZ2VvQ29kZSI6eyJsYXRpdHVkZSI6IjU3LjMyMzg4OSIsImxvbmdpdHVkZSI6IjEyNS41MjAwMDEifSwiZXhwaXJhdGlvbiI6IjIwMTctMDUtMjRUMDg6NDA6MDAuMDAwLTA0OjAwIiwicGF5ZXIiOnsicGVyc29uYWxJbmZvIjp7ImNvbXBsZXhOYW1lIjp7ImZpcnN0TmFtZSI6IkJpbGwiLCJtaWRkbGVOYW1lIjoiQmVuIiwiTGFzdE5hbWUiOiJMZWUifSwiZGF0ZU9mQmlydGgiOiIxOTg2LTAyLTE0In0sInBhcnR5SWRJbmZvIjp7InBhcnR5SWRUeXBlIjoiTVNJU0ROIiwicGFydHlTdWJJZE9yVHlwZSI6IlJlZ2lzdGVyZWRDdXN0b21lciIsInBhcnR5SWRlbnRpZmllciI6IjE2MTM1NTUxMjEyIiwiZnNwSWQiOiIxMjM0In0sIm5hbWUiOiJCaWxsIExlZSJ9LCJxdW90ZUlkIjoiNTllMzMxZmEtMzQ1Zi00NTU0LWFhYzgtZmNkODgzM2Y3ZDUwIiwidHJhbnNhY3Rpb25JZCI6IjM2NjI5YTUxLTM5M2EtNGUzYy1iMzQ3LWMyY2I1N2UxZTFmYyJ9 +``` + +3. Validate the JWS Signature against the JWS Signing Input (that is, the JWS Protected Header, JWS Payload) with the specified algorithm **RS256** (specified in the JWS Protected Header), and the public key. Record whether the validation succeeded or not. + +
    + +## References + +1 [https://tools.ietf.org/html/rfc7515#section-1.1](https://tools.ietf.org/html/rfc7515#section-1.1) – JSON Web Signature (JWS) - Notational Conventions + +2 [https://tools.ietf.org/html/rfc7515](https://tools.ietf.org/html/rfc7515) - JSON Web Signature (JWS) + +3 [https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-header-parameters](https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-header-parameters) - JSON Web Signature and Encryption Header Parameters + +4 [https://tools.ietf.org/html/rfc7159](https://tools.ietf.org/html/rfc7159) - The JavaScript Object Notation (JSON) Data Interchange Format + +5 [https://tools.ietf.org/html/rfc7517](https://tools.ietf.org/html/rfc7517) - JSON Web Key (JWK) diff --git a/docs/technical/api/license.md b/docs/technical/api/license.md new file mode 100644 index 000000000..4bf2f2526 --- /dev/null +++ b/docs/technical/api/license.md @@ -0,0 +1,27 @@ +# LICENSE + +This API specification is made available by **Ericsson**, **Huawei**, **Mahindra-Comviva**, **Telepin**, and the **Bill & Melinda Gates Foundation** under a **Creative Commons Attribution-NoDerivatives 4.0 International** License. In order to help maintain the integrity of the text of this document that reflects the underlying charitable goals of this project, we are circulating under a CC-BY license that prohibits the creation of derivative works based on this document. We ask that you do not create or distribute derivatives of this documentation. + +The Bill & Melinda Gates Foundation believes that an economy that includes everyone, benefits everyone. In support of this goal, we asked leading mobile wallet technology providers Ericsson, Huawei, Mahindra-Comviva and Telepin to work together to create a set of APIs for interoperability within the digital financial services infrastructure. Together with consultants from **Interledger** and **Modusbox**, the group worked to produce the APIs documented below. + +The underlying charitable goal for the API is to spur innovation and access to digital products and services that serve the financially underserved with a focus on interoperability, and strengthening and accelerating the availability of solutions that reflect the design principles of **L1P** as documented on www.leveloneproject.org. The contributors commit to making the relevant background technology which is provided to the API project necessary to implement the API in furtherance of the charitable goals available on a royalty-free basis. + +[**Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0)**](https://creativecommons.org/licenses/by-nd/4.0/) + +#### You are free to: +Share — copy and redistribute the material in any medium or format for any purpose, even commercially. The licensor cannot revoke these freedoms as long as you follow the license terms. +_____________________ + +Under the following terms: + +Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. + +NoDerivatives — If you remix, transform, or build upon the material, you may not distribute the modified material. + +No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. +________________________________ + +#### Notices: + +You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. +No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. \ No newline at end of file diff --git a/docs/technical/api/settlement/README.md b/docs/technical/api/settlement/README.md new file mode 100644 index 000000000..4fe520c99 --- /dev/null +++ b/docs/technical/api/settlement/README.md @@ -0,0 +1,8 @@ +--- +showToc: false +--- +# Settlement API + + + + diff --git a/docs/technical/api/thirdparty/README.md b/docs/technical/api/thirdparty/README.md new file mode 100644 index 000000000..0a05cd1e1 --- /dev/null +++ b/docs/technical/api/thirdparty/README.md @@ -0,0 +1,41 @@ +# Third Party API + +The Third Party API is an API for non-fund-holding participants to interact over a centralized Mojaloop hub. +Specifically, this API allows Payment Initiation Service Providers (PISPs) to act as a proxy in initiating +payments, while allowing for the strong authentication of users. + +## Terms + +The following terms are commonly used across the Third Party API Documentation + +| **Term** | **Alternative and Related Terms** | **Definition** | **Source** | +| --- | --- | --- | --- | +| **Payment Initiation Service Provider** | PISP, 3rd Party Payment Initiator (3PPI) | Regulated entities like retail banks or third parties, that allow customers to make payments without accessing bank accounts or cards | [PSD2](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32015L2366&qid=1633311418487) | +| **FSP** | Provider, Financial Service Provider (FSP), Payment Service Provider, Digital Financial Services Provider (DFSP) | The entity that provides a digital financial service to an end user (either a consumer, a business, or a government.) In a closed-loop payment system, the Payment System Operator is also the provider. In an open-loop payment system, the providers are the banks or non-banks which participate in that system. | [ITU-T](https://www.itu.int/dms_pub/itu-t/opb/tut/T-TUT-ECOPO-2018-PDF-E.pdf) | +| **User** | End User | An end user that is shared between a PISP and DFSP. Mostly used in the context of a real human being, but this could also be a machine user, or a business for example | +| **Consent** | Account Link | A representation of an agreement between the DFSP, PISP and User | | +| **Auth-Service** | | A service run by the Mojaloop Hub that is responsible for verifying and storing Consents, and verifying transaction request signatures | | + +## API Definitions + +The Third Party API is defined across the following OpenAPI 3.0 files: + +- [Third Party API - PISP](https://github.com/mojaloop/mojaloop-specification/blob/master/thirdparty-api/thirdparty-pisp-v1.0.yaml) +- [Third Party API - DFSP](https://github.com/mojaloop/mojaloop-specification/blob/master/thirdparty-api/thirdparty-dfsp-v1.0.yaml) + +The implementation of these APIs will depend on the role of the participant. PISPs should implement the [Third Party API - PISP](https://github.com/mojaloop/mojaloop-specification/blob/master/thirdparty-api/thirdparty-pisp-v1.0.yaml) +interface in order to request and manage Account Linking operations, and initiate Third Party Transaction Requests. + +DFSPs who wish to support Account Linking operations, and be able to respond to and verify Third Party Transaction Requests should +implement the [Third Party API - DFSP](https://github.com/mojaloop/mojaloop-specification/blob/master/thirdparty-api/thirdparty-dfsp-v1.0.yaml). + +## Transaction Patterns + +The interactions and examples of how a DFSP and PISP will interact with the Third Party API can be found in the following Transaction Patterns Documents: + +1. [Linking](./transaction-patterns-linking.md) describes how an account link and credential can be established between a DFSP and a PISP +2. [Transfer](./transaction-patterns-transfer.md) describes how a PISP can initate a payment from a DFSP's account using the account link + +## Data Models + +The [Data Models Document](./data-models.md) describes in detail the Data Models used in the Third Party API diff --git a/docs/technical/api/thirdparty/_sync_docs.sh b/docs/technical/api/thirdparty/_sync_docs.sh new file mode 100644 index 000000000..fd92ad483 --- /dev/null +++ b/docs/technical/api/thirdparty/_sync_docs.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +## +# Synchronises the definition docs from their disparate locations into one place. +# +# The API Spec for the Third Party API is managed by the api-snippets project +## + +set -eu + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +GIT_URL="https://github.com/mojaloop/api-snippets.git" +BRANCH='master' +CLONE_DIR='/tmp/api-snippets' + +rm -rf ${CLONE_DIR} + +git clone -b ${BRANCH} ${GIT_URL} ${CLONE_DIR} + +# API definition, grab from mojaloop/pisp-project +cp ${CLONE_DIR}/thirdparty/openapi3/thirdparty-dfsp-api.yaml ${DIR}/thirdparty-dfsp-v1.0.yaml +cp ${CLONE_DIR}/thirdparty/openapi3/thirdparty-pisp-api.yaml ${DIR}/thirdparty-pisp-v1.0.yaml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/0-pre-linking.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/0-pre-linking.puml new file mode 100644 index 000000000..b07cf9129 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/0-pre-linking.puml @@ -0,0 +1,49 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Pre-linking + +box "Mobile device" + participant App +end box + +box "PISP" + participant PISP +end box + +box "Mojaloop" + participant Switch +end box + +autonumber 1 "PRE-#" +activate App +App -> PISP ++: What DFSPs are available to link with? + + +PISP -> Switch ++: ""GET /services/THIRD_PARTY_DFSP""\n""FSPIOP-Source: pispa""\n""FSPIOP-Destination: switch"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> PISP ++: ""PUT /services/THIRD_PARTY_DFSP""\n""FSPIOP-Source: switch""\n""FSPIOP-Destination: pispa""\n\ + ""{""\n\ + "" "serviceProviders": ["" \n\ + "" "dfspa", "dfspb""" \n\ + "" ]"" \n\ + ""}"" +PISP --> Switch: ""200 OK"" + +PISP --> App --: We have dfspa and dfspb\n + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/0-pre-linking.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/0-pre-linking.svg new file mode 100644 index 000000000..1b57f3a75 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/0-pre-linking.svg @@ -0,0 +1,72 @@ + + PISP Linking: Pre-linking + + + PISP Linking: Pre-linking + + Mobile device + + PISP + + Mojaloop + + + + + + + + + App + + PISP + + Switch + + + + + + + PRE-1 + What DFSPs are available to link with? + + + PRE-2 + GET /services/THIRD_PARTY_DFSP + FSPIOP-Source: pispa + FSPIOP-Destination: switch + + + PRE-3 + 202 Accepted + + + PRE-4 + PUT /services/THIRD_PARTY_DFSP + FSPIOP-Source: switch + FSPIOP-Destination: pispa +   + { +    + "serviceProviders": [ +   +    + "dfspa", "dfspb + " +    + ] +   +   + } + + + PRE-5 + 200 OK + + + PRE-6 + We have dfspa and dfspb +   + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/1-discovery.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/1-discovery.puml new file mode 100644 index 000000000..c719fb2af --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/1-discovery.puml @@ -0,0 +1,85 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + + +title PISP Linking: Discovery + +box "Mobile device" + participant App +end box + +box "PISP" + participant PISP +end box + +box "Mojaloop" + participant Switch +end box + +participant DFSP + +autonumber 1 "DISC-#" +activate PISP + +... + +note over App, DFSP + The user will be prompted in the PISP App for the unique ID they use with their DFSP, and the type of identifier they use. This could be a an account ALIAS, MSISDN, email address, etc. +end note + +... + +PISP -> Switch ++: ""GET /accounts/username1234""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""GET /accounts/username1234""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> Switch ++: ""PUT /accounts/username1234""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""[""\n\ + "" { accountNickname: "Chequing Account", id: "dfspa.username.1234", currency: "ZAR" },""\n\ + "" { accountNickname: "Everyday Spend", id: "dfspa.username.5678", currency: "USD" }""\n\ + ""]"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /accounts/username1234""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""[""\n\ + "" { accountNickname: "Chequing Account", id: "dfspa.username.1234", currency: "ZAR" },""\n\ + "" { accountNickname: "Everyday Spend", id: "dfspa.username.5678", currency: "USD" }""\n\ + ""]"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +... + +note over App, DFSP + The PISP can now present a list of possible accounts to the user for pairing. +end note + +... + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/1-discovery.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/1-discovery.svg new file mode 100644 index 000000000..1a1a475ec --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/1-discovery.svg @@ -0,0 +1,151 @@ + + PISP Linking: Discovery + + + PISP Linking: Discovery + + Mobile device + + PISP + + Mojaloop + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + App + + PISP + + Switch + + DFSP + + + + + + + + + + + + + + + The user will be prompted in the PISP App for the unique ID they use with their DFSP, and the type of identifier they use. This could be a an account ALIAS, MSISDN, email address, etc. + + + DISC-1 + GET /accounts/username1234 +    + FSIOP-Source: pispa +    + FSIOP-Destination: dfspa + + + DISC-2 + 202 Accepted + + + DISC-3 + GET /accounts/username1234 +    + FSIOP-Source: pispa +    + FSIOP-Destination: dfspa + + + DISC-4 + 202 Accepted + + + DISC-5 + PUT /accounts/username1234 +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + [ +    + { accountNickname: "Chequing Account", id: "dfspa.username.1234", currency: "ZAR" }, +    + { accountNickname: "Everyday Spend", id: "dfspa.username.5678", currency: "USD" } +    + ] + + + DISC-6 + 200 OK + + + DISC-7 + PUT /accounts/username1234 +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + [ +    + { accountNickname: "Chequing Account", id: "dfspa.username.1234", currency: "ZAR" }, +    + { accountNickname: "Everyday Spend", id: "dfspa.username.5678", currency: "USD" } +    + ] + + + DISC-8 + 200 OK + + + The PISP can now present a list of possible accounts to the user for pairing. + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.puml new file mode 100644 index 000000000..8d52071bc --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.puml @@ -0,0 +1,119 @@ +@startuml + + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Request consent (OTP) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant DFSP + +autonumber 1 "REQ-#" + +activate PISP + +... + +note over PISP, DFSP + The user initiated some sort of account linking by choosing the appropriate DFSP from a screen inside the PISP application. +end note + +... + +PISP -> Switch ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234", ""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Verify the consentRequest validity + + +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ +"" {""\n\ + "" authChannels: [ "OTP" ], ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" + +note over PISP, DFSP + Here, the DFSP sends an OTP directly to the user (e.g., via SMS). +end note + +deactivate DFSP + +Switch -> PISP: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ +""{""\n\ + "" authChannels: [ "OTP" ], ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch + +note over PISP, DFSP + At this point, the PISP knows that the OTP authChannel is in use and the PISP App should prompt the user to provide the OTP. +end note + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.svg new file mode 100644 index 000000000..aefe18062 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.svg @@ -0,0 +1,203 @@ + + PISP Linking: Request consent (OTP) + + + PISP Linking: Request consent (OTP) + + Mojaloop + + + + + + + + + + + + + + + + + + + + + + + + + + + + PISP + + Switch + + DFSP + + + + + + + + + + + + + + The user initiated some sort of account linking by choosing the appropriate DFSP from a screen inside the PISP application. + + + REQ-1 + POST /consentRequests +    + FSIOP-Source: pispa +    + FSIOP-Destination: dfspa + { +    + consentRequestId: "11111111-0000-0000-0000-000000000000", +    + userId: "username1234", +    + scopes: [ +    + { accountId: "dfsp.username.1234", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + { accountId: "dfsp.username.5678", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + ], +    + authChannels: [ "Web", "OTP" ], +    + callbackUri: "pisp-app://callback... + " +    + } + + + REQ-2 + 202 Accepted + + + REQ-3 + POST /consentRequests +    + FSIOP-Source: pispa +    + FSIOP-Destination: dfspa + { +    + consentRequestId: "11111111-0000-0000-0000-000000000000", +    + userId: "username1234", +    + scopes: [ +    + { accountId: "dfsp.username.1234", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + { accountId: "dfsp.username.5678", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + ], +    + authChannels: [ "Web", "OTP" ], +    + callbackUri: "pisp-app://callback... + " +    + } + + + REQ-4 + 202 Accepted + + + + + REQ-5 + Verify the consentRequest validity + + + REQ-6 + PUT /consentRequests/11111111-0000-0000-0000-000000000000 +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa + { +    + authChannels: [ "OTP" ], +    + scopes: [ +    + { accountId: "dfsp.username.1234", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + { accountId: "dfsp.username.5678", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + ], +    + callbackUri: "pisp-app://callback... + " +    + } + + + REQ-7 + 200 OK + + + Here, the DFSP sends an OTP directly to the user (e.g., via SMS). + + + REQ-8 + PUT /consentRequests/11111111-0000-0000-0000-000000000000 +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa + { +    + authChannels: [ "OTP" ], +    + scopes: [ +    + { accountId: "dfsp.username.1234", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + { accountId: "dfsp.username.5678", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + ], +    + callbackUri: "pisp-app://callback... + " +    + } + + + REQ-9 + 200 OK + + + At this point, the PISP knows that the OTP authChannel is in use and the PISP App should prompt the user to provide the OTP. + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/2-request-consent-web.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/2-request-consent-web.puml new file mode 100644 index 000000000..de404fc39 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/2-request-consent-web.puml @@ -0,0 +1,118 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + + +title PISP Linking: Request consent (Web) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant DFSP + +autonumber 1 "REQ-#" + +activate PISP + +... + +note over PISP, DFSP + The user initiated some sort of account linking by choosing the appropriate DFSP from a screen inside the PISP application. +end note + +... + +PISP -> Switch ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ + "" {""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234", ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234", ""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ + "" {""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234", ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" + +DFSP -> DFSP: Verify the consentRequest validity +DFSP -> DFSP: In this case, DFSP chooses to use the Web channel, \n and adds the PISP's callback uri to an allow-list +deactivate Switch + +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + "" {""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + "" authUri: "dfspa.com/authorize?consentRequestId=11111111-0000-0000-0000-000000000000" ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + "" {""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + "" authUri: "dfspa.com/authorize?consentRequestId=11111111-0000-0000-0000-000000000000" ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch + +note over PISP, DFSP + At this point, the PISP knows that the Web authChannel is in use and the PISP App should redirect the user to the provided ""authUri"". +end note + + + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/2-request-consent-web.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/2-request-consent-web.svg new file mode 100644 index 000000000..ab3853b5c --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/2-request-consent-web.svg @@ -0,0 +1,219 @@ + + PISP Linking: Request consent (Web) + + + PISP Linking: Request consent (Web) + + Mojaloop + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PISP + + Switch + + DFSP + + + + + + + + + + + + + + + The user initiated some sort of account linking by choosing the appropriate DFSP from a screen inside the PISP application. + + + REQ-1 + POST /consentRequests +    + FSIOP-Source: pispa +    + FSIOP-Destination: dfspa +    + { +    + consentRequestId: "11111111-0000-0000-0000-000000000000", +    + userId: "username1234", +    + scopes: [ +    + { accountId: "dfsp.username.1234", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + { accountId: "dfsp.username.5678", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + ], +    + authChannels: [ "Web", "OTP" ], +    + callbackUri: "pisp-app://callback... + " +    + } + + + REQ-2 + 202 Accepted + + + REQ-3 + POST /consentRequests +    + FSIOP-Source: pispa +    + FSIOP-Destination: dfspa +    + { +    + consentRequestId: "11111111-0000-0000-0000-000000000000", +    + userId: "username1234", +    + scopes: [ +    + { accountId: "dfsp.username.1234", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + { accountId: "dfsp.username.5678", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + ], +    + authChannels: [ "Web", "OTP" ], +    + callbackUri: "pisp-app://callback... + " +    + } + + + REQ-4 + 202 Accepted + + + + + REQ-5 + Verify the consentRequest validity + + + + + REQ-6 + In this case, DFSP chooses to use the Web channel, + and adds the PISP's callback uri to an allow-list + + + REQ-7 + PUT /consentRequests/11111111-0000-0000-0000-000000000000 +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + { +    + scopes: [ +    + { accountId: "dfsp.username.1234", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + { accountId: "dfsp.username.5678", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + ], +    + authChannels: [ "Web" ], +    + callbackUri: "pisp-app://callback... + " +    + authUri: "dfspa.com/authorize?consentRequestId=11111111-0000-0000-0000-000000000000" +    + } + + + REQ-8 + 200 OK + + + REQ-9 + PUT /consentRequests/11111111-0000-0000-0000-000000000000 +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + { +    + scopes: [ +    + { accountId: "dfsp.username.1234", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + { accountId: "dfsp.username.5678", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + ], +    + authChannels: [ "Web" ], +    + callbackUri: "pisp-app://callback... + " +    + authUri: "dfspa.com/authorize?consentRequestId=11111111-0000-0000-0000-000000000000" +    + } + + + REQ-10 + 200 OK + + + At this point, the PISP knows that the Web authChannel is in use and the PISP App should redirect the user to the provided + authUri + . + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-otp.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-otp.puml new file mode 100644 index 000000000..2fdb17e5d --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-otp.puml @@ -0,0 +1,62 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Authentication (OTP) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "AUTH-#" + +... + +note over PISP, DFSP + Here the user provides the OTP sent directly to them by the DFSP into the PISP App. It's then used as the secret to prove to the DFSP that the user trusts the PISP. +end note + +... + +PISP -> Switch ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Verify the OTP is correct. + +note over PISP, DFSP + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. +end note + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-otp.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-otp.svg new file mode 100644 index 000000000..17b7c6856 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-otp.svg @@ -0,0 +1,82 @@ + + PISP Linking: Authentication (OTP) + + + PISP Linking: Authentication (OTP) + + Mojaloop + + + + + + + + + + + + + + + + + + + PISP + + Switch + + DFSP + + + + + Here the user provides the OTP sent directly to them by the DFSP into the PISP App. It's then used as the secret to prove to the DFSP that the user trusts the PISP. + + + AUTH-1 + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 +      + FSIOP-Source: pispa +      + FSIOP-Destination: dfspa + { +      + authToken: "<OTP>" +      + } + + + AUTH-2 + 202 Accepted + + + AUTH-3 + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 +      + FSIOP-Source: pispa +      + FSIOP-Destination: dfspa + { +      + authToken: "<OTP>" +      + } + + + AUTH-4 + 202 Accepted + + + + + AUTH-5 + Verify the OTP is correct. + + + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. +   + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.puml new file mode 100644 index 000000000..9d05ec448 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.puml @@ -0,0 +1,45 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Authentication (Third-party FIDO registration) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "3P-FIDO-AUTH-#" + +... + +note over PISP, DFSP + Here the user goes through the web authentication process with their DFSP. + The end result is a redirect back to the PISP with a special URL parameter indicating to the PISP that it should wait to be notified about a credential. +end note + +... + +autonumber 1 "AUTH-#" + +note over PISP, DFSP + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. +end note + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.svg new file mode 100644 index 000000000..467116a14 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.svg @@ -0,0 +1,39 @@ + + PISP Linking: Authentication (Third-party FIDO registration) + + + PISP Linking: Authentication (Third-party FIDO registration) + + Mojaloop + + + + + + + + + + + + + + + + + PISP + + Switch + + DFSP + + + Here the user goes through the web authentication process with their DFSP. + The end result is a redirect back to the PISP with a special URL parameter indicating to the PISP that it should wait to be notified about a credential. + + + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. +   + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-web.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-web.puml new file mode 100644 index 000000000..f31a9ed55 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-web.puml @@ -0,0 +1,65 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Authentication (Web) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "WEB-AUTH-#" + +... + +note over PISP, DFSP + Here the user goes through the web authentication process with their DFSP. + The end result is a redirect back to the PISP with a special URL parameter with a secret provided by the DFSP. +end note + +... + +autonumber 1 "AUTH-#" + +PISP -> Switch ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Verify the auth token is correct. + +note over PISP, DFSP + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. +end note + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-web.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-web.svg new file mode 100644 index 000000000..f1752adad --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/3-authentication-web.svg @@ -0,0 +1,83 @@ + + PISP Linking: Authentication (Web) + + + PISP Linking: Authentication (Web) + + Mojaloop + + + + + + + + + + + + + + + + + + + PISP + + Switch + + DFSP + + + + + Here the user goes through the web authentication process with their DFSP. + The end result is a redirect back to the PISP with a special URL parameter with a secret provided by the DFSP. + + + AUTH-1 + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 +      + FSIOP-Source: pispa +      + FSIOP-Destination: dfspa + { +      + authToken: "<SECRET>" +      + } + + + AUTH-2 + 202 Accepted + + + AUTH-3 + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 +      + FSIOP-Source: pispa +      + FSIOP-Destination: dfspa + { +      + authToken: "<SECRET>" +      + } + + + AUTH-4 + 202 Accepted + + + + + AUTH-5 + Verify the auth token is correct. + + + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. +   + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/4-grant-consent.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/4-grant-consent.puml new file mode 100644 index 000000000..e0ede15d5 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/4-grant-consent.puml @@ -0,0 +1,64 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Grant consent + +participant "PISP" as PISP + +box "Mojaloop" + participant "Switch" as Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "GRANT-#" + +DFSP -> Switch ++: ""POST /consents""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSIOP-Destination: pispa""\n\ +"" {""\n\ + "" consentId: "22222222-0000-0000-0000-000000000000",""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + ""}"" +Switch --> DFSP: ""202 Accepted"" +deactivate DFSP + +Switch -> PISP ++: ""POST /consents""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSIOP-Destination: pispa""\n\ +"" {""\n\ + "" consentId: "22222222-0000-0000-0000-000000000000",""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + ""}"" + +PISP --> Switch: ""202 Accepted"" + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/4-grant-consent.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/4-grant-consent.svg new file mode 100644 index 000000000..1dce24129 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/4-grant-consent.svg @@ -0,0 +1,82 @@ + + PISP Linking: Grant consent + + + + Mojaloop + PISP Linking: Grant consent + + + + + + + PISP + + Switch + + DFSP + + + GRANT-1 + POST /consents + FSIOP-Source: dfspa + FSIOP-Destination: pispa + { +      + consentId: "22222222-0000-0000-0000-000000000000", +      + consentRequestId: "11111111-0000-0000-0000-000000000000", +      + status: "ISSUED", +      + scopes: [ +      + { accountId: "dfsp.username.1234", +      + actions: [ "ACCOUNTS_TRANSFER" ] }, +      + { accountId: "dfsp.username.5678", +      + actions: [ "ACCOUNTS_TRANSFER" ] }, +      + ], +      + } + + + GRANT-2 + 202 Accepted + + + GRANT-3 + POST /consents + FSIOP-Source: dfspa + FSIOP-Destination: pispa + { +      + consentId: "22222222-0000-0000-0000-000000000000", +      + consentRequestId: "11111111-0000-0000-0000-000000000000", +      + status: "ISSUED", +      + scopes: [ +      + { accountId: "dfsp.username.1234", +      + actions: [ "ACCOUNTS_TRANSFER" ] }, +      + { accountId: "dfsp.username.5678", +      + actions: [ "ACCOUNTS_TRANSFER" ] }, +      + ], +      + } + + + GRANT-4 + 202 Accepted + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/5a-credential-registration.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/5a-credential-registration.puml new file mode 100644 index 000000000..b7cd8fe0e --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/5a-credential-registration.puml @@ -0,0 +1,219 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Credential registration (verification) + +participant "PISP" as PISP + +box "Mojaloop" + participant "Thirdparty-API-Adapter" as Switch + participant "Account Lookup Service" as ALS + participant "Auth Service" as Auth +end box + +participant "DFSP" as DFSP + +autonumber 0 "CRED-#" + +... + +note over PISP, DFSP + The PISP uses the FIDO registration flow to generate a new keypair and sign the challenge, relying on the user performing an "unlock action" on their mobile device. + + The PISP uses the PublicKeyCredential as the fidoPayload for the credential, which can be understood by the Auth Service and DFSP + See https://webauthn.guide/#authentication for more information on this object +end note + +... + +PISP -> Switch ++: ""PUT /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: pispa""\n\ +"" FSPIOP-Destination: dfspa""\n\ +"" {""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [""\n\ + "" {""\n\ + "" accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ],""\n\ + "" },""\n\ + "" {""\n\ + "" accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ],""\n\ + "" }""\n\ + "" ],""\n\ + "" credential: { ""\n\ + "" credentialType: "FIDO",""\n\ + "" status: "PENDING",""\n\ + "" fidoPayload: { ""\n\ + "" id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", "" \n\ + "" response: { ""\n\ + "" "" authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==",\n\ + "" "" clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...",\n\ + "" "" signature: "MEUCIDcJRBu5aOLJVc..."\n\ + "" } ""\n\ + "" } ""\n\ + "" }""\n\ +"" }"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + + +Switch -> DFSP ++: ""PUT /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: pispa""\n\ +"" FSPIOP-Destination: dfspa""\n\ +"" {...}"" + +DFSP --> Switch: ""202 Accepted"" + + +rnote over DFSP + 1. DFSP checks the signed challenge against the derived challenge from the scopes + + If the DFSP opts to use the hub-hosted Auth-Service it then: + 1. Registers the consent with the Auth Service ""POST /consents"" + 2. If the DFSP recieves a `PUT /consents/{id}` and the callback contains + ""Consent.credential.status"" of ""VERIFIED"", for each scope in the + Consent, the DFSP creates a ""CredentialScope"" else, if it recieves + a `PUT /consents/{id}/error` callback, it knows that the Consent is + invalid, and can propagate the error back to the PISP + +end note + + +DFSP -> Switch: ""POST /consents"" \n\ +"" FSIOP-Source: dfspa""\n\ +"" FSPIOP-Destination: central-auth""\n\ +"" {""\n\ + "" consentId: "22222222-0000-0000-0000-000000000000"""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000"""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [""\n\ + "" {""\n\ + "" accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ],""\n\ + "" }""\n\ + "" },""\n\ + "" {""\n\ + "" accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ],""\n\ + "" }""\n\ + "" },""\n\ + "" ],""\n\ + "" credential: { ""\n\ + "" credentialType: "FIDO",""\n\ + "" status: "PENDING",""\n\ + "" fidoPayload: { ""\n\ + "" id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", "" \n\ + "" response: { ""\n\ + "" "" authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==",\n\ + "" "" clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...",\n\ + "" "" signature: "MEUCIDcJRBu5aOLJVc..."\n\ + "" } ""\n\ + "" } ""\n\ + "" }""\n\ +"" }"" + +Switch --> DFSP: "202 Accepted" + + +Switch -> Auth: ""POST /consents"" \n\ +"" FSIOP-Source: dfspa""\n\ +"" FSPIOP-Destination: central-auth""\n\ +"" {...}"" + +Auth --> Switch: "202 Accepted" + + +rnote over Auth + The Auth Service checks the signature against the challenge +end note + +rnote over Auth + The auth service is now the authoritative source for the Consent object. + + It must register the consentId with the ALS + - `Consent` - to allow for `GET /consent/{ID}` calls etc. Will point to the fspId of the Auth Service responsible for the Consent +end note + +Auth -> ALS: ""POST /participants/CONSENTS/22222222-0000-0000-0000-000000000000"" \n\ +"" FSIOP-Source: central-auth""\n\ +"" {""\n\ +"" fspId: "central-auth",""\n\ +"" }"" +ALS --> Auth: ""202 Accepted"" + +rnote over ALS #LightGray + ALS registers a new entry in the Consents oracle +end note + +ALS -> Auth: ""PUT /participants/CONSENTS/22222222-0000-0000-0000-000000000000"" \n\ +"" FSIOP-Source: account-lookup-service""\n\ +"" FSIOP-Destination: central-auth""\n\ +"" {""\n\ +"" fspId: "central-auth",""\n\ +"" }"" +Auth --> ALS: ""200 OK"" + +rnote over Auth #LightGray + The auth service now informs the DFSP that the credential is valid +end note + + +Auth -> Switch: ""PUT /consents/22222222-0000-0000-0000-000000000000"" \n\ +"" FSIOP-Source: central-auth""\n\ +"" FSPIOP-Destination: dfspa""\n\ +"" {""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000"""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [""\n\ + "" {""\n\ + "" accountId: "dfsp.username.1234",""\n\ + "" actions: [ "accounts.transfer", "accounts.getBalance" ],""\n\ + "" },""\n\ + "" {""\n\ + "" accountId: "dfsp.username.5678",""\n\ + "" actions: [ "accounts.transfer", "accounts.getBalance" ],""\n\ + "" },""\n\ + "" ],""\n\ + "" credential: { ""\n\ + "" credentialType: "FIDO",""\n\ + "" status: "VERIFIED",""\n\ + "" fidoPayload: { ""\n\ + "" id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", "" \n\ + "" response: { ""\n\ + "" "" authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==",\n\ + "" "" clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...",\n\ + "" "" signature: "MEUCIDcJRBu5aOLJVc..."\n\ + "" } ""\n\ + "" } ""\n\ + "" }""\n\ +"" }"" +Switch --> Auth: "200 OK" + +Switch -> DFSP: ""PUT /consents/22222222-0000-0000-0000-000000000000"" \n\ +"" FSIOP-Source: central-auth""\n\ +"" FSPIOP-Destination: dfspa""\n\ +"" {...}"" + +DFSP --> Switch: "200 OK" + +rnote over DFSP + DFSP is now satisfied that the Consent registered by the PISP is valid. +end note + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/5a-credential-registration.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/5a-credential-registration.svg new file mode 100644 index 000000000..77bdd635b --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/5a-credential-registration.svg @@ -0,0 +1,348 @@ + + PISP Linking: Credential registration (verification) + + + + Mojaloop + PISP Linking: Credential registration (verification) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PISP + + Thirdparty-API-Adapter + + Account Lookup Service + + Auth Service + + DFSP + + + The PISP uses the FIDO registration flow to generate a new keypair and sign the challenge, relying on the user performing an "unlock action" on their mobile device. +   + The PISP uses the PublicKeyCredential as the fidoPayload for the credential, which can be understood by the Auth Service and DFSP + See https://webauthn.guide/#authentication for more information on this object + + + CRED-0 + PUT /consents/22222222-0000-0000-0000-000000000000 + FSIOP-Source: pispa + FSPIOP-Destination: dfspa + { +      + consentRequestId: "11111111-0000-0000-0000-000000000000", +      + status: "ISSUED", +      + scopes: [ +      + { +      + accountId: "dfsp.username.1234", +      + actions: [ "ACCOUNTS_TRANSFER" ], +      + }, +      + { +      + accountId: "dfsp.username.5678", +      + actions: [ "ACCOUNTS_TRANSFER" ], +      + } +      + ], +      + credential: { +      + credentialType: "FIDO", +      + status: "PENDING", +      + fidoPayload: { +      + id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", +   +      + response: { +      +          + authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==", +      +          + clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...", +      +          + signature: "MEUCIDcJRBu5aOLJVc..." +      + } +      + } +      + } + } + + + CRED-1 + 202 Accepted + + + CRED-2 + PUT /consents/22222222-0000-0000-0000-000000000000 + FSIOP-Source: pispa + FSPIOP-Destination: dfspa + {...} + + + CRED-3 + 202 Accepted + + 1. DFSP checks the signed challenge against the derived challenge from the scopes +   + If the DFSP opts to use the hub-hosted Auth-Service it then: + 1. Registers the consent with the Auth Service + POST /consents + 2. If the DFSP recieves a `PUT /consents/{id}` and the callback contains +     + Consent.credential.status + of + VERIFIED + , for each scope in the + Consent, the DFSP creates a + CredentialScope + else, if it recieves + a `PUT /consents/{id}/error` callback, it knows that the Consent is + invalid, and can propagate the error back to the PISP +   + + + CRED-4 + POST /consents +   + FSIOP-Source: dfspa + FSPIOP-Destination: central-auth + { +      + consentId: "22222222-0000-0000-0000-000000000000 + " +      + consentRequestId: "11111111-0000-0000-0000-000000000000 + " +      + status: "ISSUED", +      + scopes: [ +      + { +      + accountId: "dfsp.username.1234", +      + actions: [ "ACCOUNTS_TRANSFER" ], +      + } +      + }, +      + { +      + accountId: "dfsp.username.5678", +      + actions: [ "ACCOUNTS_TRANSFER" ], +      + } +      + }, +      + ], +      + credential: { +      + credentialType: "FIDO", +      + status: "PENDING", +      + fidoPayload: { +      + id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", +   +      + response: { +      +          + authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==", +      +          + clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...", +      +          + signature: "MEUCIDcJRBu5aOLJVc..." +      + } +      + } +      + } + } + + + CRED-5 + "202 Accepted" + + + CRED-6 + POST /consents +   + FSIOP-Source: dfspa + FSPIOP-Destination: central-auth + {...} + + + CRED-7 + "202 Accepted" + + The Auth Service checks the signature against the challenge + + The auth service is now the authoritative source for the Consent object. +   + It must register the consentId with the ALS + - `Consent` - to allow for `GET /consent/{ID}` calls etc. Will point to the fspId of the Auth Service responsible for the Consent + + + CRED-8 + POST /participants/CONSENTS/22222222-0000-0000-0000-000000000000 +   + FSIOP-Source: central-auth + { + fspId: "central-auth", + } + + + CRED-9 + 202 Accepted + + ALS registers a new entry in the Consents oracle + + + CRED-10 + PUT /participants/CONSENTS/22222222-0000-0000-0000-000000000000 +   + FSIOP-Source: account-lookup-service + FSIOP-Destination: central-auth + { + fspId: "central-auth", + } + + + CRED-11 + 200 OK + + The auth service now informs the DFSP that the credential is valid + + + CRED-12 + PUT /consents/22222222-0000-0000-0000-000000000000 +   + FSIOP-Source: central-auth + FSPIOP-Destination: dfspa + { +      + consentRequestId: "11111111-0000-0000-0000-000000000000 + " +      + status: "ISSUED", +      + scopes: [ +      + { +      + accountId: "dfsp.username.1234", +      + actions: [ "accounts.transfer", "accounts.getBalance" ], +      + }, +      + { +      + accountId: "dfsp.username.5678", +      + actions: [ "accounts.transfer", "accounts.getBalance" ], +      + }, +      + ], +      + credential: { +      + credentialType: "FIDO", +      + status: "VERIFIED", +      + fidoPayload: { +      + id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", +   +      + response: { +      +          + authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==", +      +          + clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...", +      +          + signature: "MEUCIDcJRBu5aOLJVc..." +      + } +      + } +      + } + } + + + CRED-13 + "200 OK" + + + CRED-14 + PUT /consents/22222222-0000-0000-0000-000000000000 +   + FSIOP-Source: central-auth + FSPIOP-Destination: dfspa + {...} + + + CRED-15 + "200 OK" + + DFSP is now satisfied that the Consent registered by the PISP is valid. + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.puml new file mode 100644 index 000000000..791a929de --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.puml @@ -0,0 +1,97 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Credential registration (verification) + +participant "PISP" as PISP + +box "Mojaloop" + participant "Switch" as Switch + participant "Account Lookup Service" as ALS +end box + +participant "DFSP" as DFSP + +autonumber 16 "CRED-#" + +... + + +rnote over DFSP + DFSP is now satisfied that the Consent registered by the PISP is valid, + and now proceeds to register with the ALS: + - `THIRD_PARTY_LINK` (optional - for routing of funds to a Third Party Link) + ALS +end note + +loop for each scope in ""Consents.scopes"" + +DFSP -> ALS: ""POST /participants/THIRD_PARTY_LINK/dfsp.username.5678"" \n\ +"" FSIOP-Source: dfspa""\n\ +"" {""\n\ +"" fspId: "dfspa",""\n\ +"" }"" +ALS --> DFSP: ""202 Accepted"" + +rnote over ALS #LightGray + ALS registers a new entry in the THIRD_PARTY_LINK oracle +end note + +ALS -> DFSP: ""PUT /participants/THIRD_PARTY_LINK/dfsp.username.5678"" \n\ +"" FSIOP-Source: account-lookup-service""\n\ +"" FSIOP-Destination: dfspa""\n\ +"" {""\n\ +"" fspId: "dfspa",""\n\ +"" }"" +DFSP --> ALS: ""200 OK"" +end + + +rnote over DFSP + Now that the Credentials are verified and registered with the Auth Service, + the DFSP can update the PISP with the final status +end note + +DFSP -> Switch: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSPIOP-Destination: pispa""\n\ +"" Content-Type: application/merge-patch+json""\n\ +"" {""\n\ + "" credential: {""\n\ + "" **status: "VERIFIED", //this is new!**""\n\ + "" }""\n\ +"" }"" +DFSP --> Switch: ""200 OK"" + +Switch -> PISP ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSPIOP-Destination: pispa""\n\ +"" Content-Type: application/merge-patch+json""\n\ +"" {""\n\ + "" credential: {""\n\ + "" **status: "VERIFIED", //this is new!**""\n\ + "" }""\n\ +"" }"" +PISP --> Switch: ""200 OK"" + + +note over PISP, DFSP + Now we have a new identifier that the PISP can use to initiate transactions, a registered credential, and that credential is stored in the auth-service +end note + + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.svg new file mode 100644 index 000000000..07530567b --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.svg @@ -0,0 +1,116 @@ + + PISP Linking: Credential registration (verification) + + + + Mojaloop + PISP Linking: Credential registration (verification) + + + + + + + + + + + + + + + PISP + + Switch + + Account Lookup Service + + DFSP + + DFSP is now satisfied that the Consent registered by the PISP is valid, + and now proceeds to register with the ALS: + - `THIRD_PARTY_LINK` (optional - for routing of funds to a Third Party Link) + ALS + + + loop + [for each scope in + Consents.scopes + ] + + + CRED-16 + POST /participants/THIRD_PARTY_LINK/dfsp.username.5678 +   + FSIOP-Source: dfspa + { + fspId: "dfspa", + } + + + CRED-17 + 202 Accepted + + ALS registers a new entry in the THIRD_PARTY_LINK oracle + + + CRED-18 + PUT /participants/THIRD_PARTY_LINK/dfsp.username.5678 +   + FSIOP-Source: account-lookup-service + FSIOP-Destination: dfspa + { + fspId: "dfspa", + } + + + CRED-19 + 200 OK + + Now that the Credentials are verified and registered with the Auth Service, + the DFSP can update the PISP with the final status + + + CRED-20 + PATCH /consents/22222222-0000-0000-0000-000000000000 + FSIOP-Source: dfspa + FSPIOP-Destination: pispa + Content-Type: application/merge-patch+json + { +      + credential: { +      +      + status: "VERIFIED", //this is new! +      + } + } + + + CRED-21 + 200 OK + + + CRED-22 + PATCH /consents/22222222-0000-0000-0000-000000000000 + FSIOP-Source: dfspa + FSPIOP-Destination: pispa + Content-Type: application/merge-patch+json + { +      + credential: { +      +      + status: "VERIFIED", //this is new! +      + } + } + + + CRED-23 + 200 OK + + + Now we have a new identifier that the PISP can use to initiate transactions, a registered credential, and that credential is stored in the auth-service + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.puml new file mode 100644 index 000000000..4c2ff1b57 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.puml @@ -0,0 +1,72 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Unlinking + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "UNLINK-A-#" + +activate PISP + +... + +note over PISP, DFSP + In this scenario there is no Hub-hosted Auth Service. The DFSP is the authority on the ""Consent"" object. +end note + +... + +PISP -> Switch ++: ""DELETE /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: pispa""\n\ +"" FSIOP-Destination: dfspa"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""DELETE /consents/22222222-0000-0000-0000-000000000000"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Mark the ""Consent"" object as "REVOKED" + +DFSP -> Switch ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSIOP-Destination: pispa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSIOP-Destination: pispa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000""\n\ +""}"" +PISP --> Switch: ""200 OK"" + + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.svg new file mode 100644 index 000000000..63e31ab9c --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.svg @@ -0,0 +1,102 @@ + + PISP Linking: Unlinking + + + + Mojaloop + PISP Linking: Unlinking + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PISP + + Switch + + DFSP + + + In this scenario there is no Hub-hosted Auth Service. The DFSP is the authority on the + Consent + object. + + + UNLINK-A-1 + DELETE /consents/22222222-0000-0000-0000-000000000000 + FSIOP-Source: pispa + FSIOP-Destination: dfspa + + + UNLINK-A-2 + 202 Accepted + + + UNLINK-A-3 + DELETE /consents/22222222-0000-0000-0000-000000000000 + + + UNLINK-A-4 + 202 Accepted + + + + + UNLINK-A-5 + Mark the + Consent + object as "REVOKED" + + + UNLINK-A-6 + PATCH /consents/22222222-0000-0000-0000-000000000000 + FSIOP-Source: dfspa + FSIOP-Destination: pispa + { + status: "REVOKED", + revokedAt: "2020-06-15T13:00:00.000 + " + } + + + UNLINK-A-7 + 200 OK + + + UNLINK-A-8 + PATCH /consents/22222222-0000-0000-0000-000000000000 + FSIOP-Source: dfspa + FSIOP-Destination: pispa + { + status: "REVOKED", + revokedAt: "2020-06-15T13:00:00.000 + } + + + UNLINK-A-9 + 200 OK + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.puml new file mode 100644 index 000000000..914dc7704 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.puml @@ -0,0 +1,105 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Unlinking + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch + participant "Account Lookup Service" as ALS + participant "Auth Service" as Auth +end box + +participant "DFSP" as DFSP + +autonumber 1 "UNLINK-B-#" + +activate PISP + +... + +note over PISP, DFSP + In this scenario there is no Hub-hosted Auth Service. The DFSP is the authority on the ""Consent"" object. +end note + +... + +PISP -> Switch ++: ""DELETE /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: pispa""\n\ +"" FSIOP-Destination: dfspa"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> ALS: ""GET /participants/CONSENT/22222222-0000-0000-0000-000000000000"" +ALS --> Switch: ""200 OK""\n\ +"" { "fspId": "central-auth" }"" + +rnote over Switch #LightGray + Hub has determined that 'central-auth- is responsible for ""Consent"" 22222222-0000-0000-0000-000000000000 +end note + +Switch -> Auth ++: ""DELETE /consents/22222222-0000-0000-0000-000000000000"" +Auth --> Switch: ""202 Accepted"" +deactivate Switch + +Auth -> Auth: Mark the ""Consent"" object as "REVOKED" + +Auth -> Switch ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: central-auth""\n\ +"" FSIOP-Destination: pispa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +Switch --> Auth: ""200 OK"" +deactivate Auth + +Switch -> PISP ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: central-auth""\n\ +"" FSIOP-Destination: pispa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +PISP --> Switch: ""200 OK"" + + +rnote over Auth #LightGray + Auth Service must also inform the DFSP of the updated status +end note + +Auth -> Switch ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: central-auth""\n\ +"" FSIOP-Destination: dfspa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +Switch --> Auth: ""200 OK"" +deactivate Auth + +Switch -> DFSP ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: central-auth""\n\ +"" FSIOP-Destination: dfspa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +DFSP --> Switch: ""200 OK"" + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.svg new file mode 100644 index 000000000..aaa186304 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.svg @@ -0,0 +1,164 @@ + + PISP Linking: Unlinking + + + + Mojaloop + PISP Linking: Unlinking + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PISP + + Switch + + Account Lookup Service + + Auth Service + + DFSP + + + In this scenario there is no Hub-hosted Auth Service. The DFSP is the authority on the + Consent + object. + + + UNLINK-B-1 + DELETE /consents/22222222-0000-0000-0000-000000000000 + FSIOP-Source: pispa + FSIOP-Destination: dfspa + + + UNLINK-B-2 + 202 Accepted + + + UNLINK-B-3 + GET /participants/CONSENT/22222222-0000-0000-0000-000000000000 + + + UNLINK-B-4 + 200 OK + { "fspId": "central-auth" } + + Hub has determined that 'central-auth- is responsible for + Consent + 22222222-0000-0000-0000-000000000000 + + + UNLINK-B-5 + DELETE /consents/22222222-0000-0000-0000-000000000000 + + + UNLINK-B-6 + 202 Accepted + + + + + UNLINK-B-7 + Mark the + Consent + object as "REVOKED" + + + UNLINK-B-8 + PATCH /consents/22222222-0000-0000-0000-000000000000 + FSIOP-Source: central-auth + FSIOP-Destination: pispa + { + status: "REVOKED", + revokedAt: "2020-06-15T13:00:00.000 + " + } + + + UNLINK-B-9 + 200 OK + + + UNLINK-B-10 + PATCH /consents/22222222-0000-0000-0000-000000000000 + FSIOP-Source: central-auth + FSIOP-Destination: pispa + { + status: "REVOKED", + revokedAt: "2020-06-15T13:00:00.000 + " + } + + + UNLINK-B-11 + 200 OK + + Auth Service must also inform the DFSP of the updated status + + + UNLINK-B-12 + PATCH /consents/22222222-0000-0000-0000-000000000000 + FSIOP-Source: central-auth + FSIOP-Destination: dfspa + { + status: "REVOKED", + revokedAt: "2020-06-15T13:00:00.000 + " + } + + + UNLINK-B-13 + 200 OK + + + UNLINK-B-14 + PATCH /consents/22222222-0000-0000-0000-000000000000 + FSIOP-Source: central-auth + FSIOP-Destination: dfspa + { + status: "REVOKED", + revokedAt: "2020-06-15T13:00:00.000 + " + } + + + UNLINK-B-15 + 200 OK + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.puml new file mode 100644 index 000000000..bf5d76ca5 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.puml @@ -0,0 +1,79 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Discovery error case + +box "PISP" + participant PISP +end box + +box "Mojaloop" + participant Switch +end box + +participant DFSP + +autonumber 1 "DISC-#" +activate PISP + +PISP -> Switch ++: ""GET /accounts/username1234""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""GET /accounts/username1234""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Lookup a user for **username1234** +DFSP -> DFSP: No user found + +DFSP -> Switch ++: ""PUT /accounts/username1234/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6205", ""\n\ + "" errorDescription: "No accounts found" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /accounts/username1234/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6205", ""\n\ + "" errorDescription: "No accounts found" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +... + +note over Switch + The PISP can now show error message and user can try again with another username or different DFSP. +end note + +... + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.svg new file mode 100644 index 000000000..9081344f6 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.svg @@ -0,0 +1,130 @@ + + PISP Linking: Discovery error case + + + PISP Linking: Discovery error case + + PISP + + Mojaloop + + + + + + + + + + + + + + + + + + + + + + PISP + + Switch + + DFSP + + + + + + + + DISC-1 + GET /accounts/username1234 +    + FSIOP-Source: pispa +    + FSIOP-Destination: dfspa + + + DISC-2 + 202 Accepted + + + DISC-3 + GET /accounts/username1234 +    + FSIOP-Source: pispa +    + FSIOP-Destination: dfspa + + + DISC-4 + 202 Accepted + + + + + DISC-5 + Lookup a user for + username1234 + + + + + DISC-6 + No user found + + + DISC-7 + PUT /accounts/username1234/error +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + { +    + errorInformation : { +    + errorCode: "6205", +    + errorDescription: "No accounts found" +    + } +    + } + + + DISC-8 + 200 OK + + + DISC-9 + PUT /accounts/username1234/error +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + { +    + errorInformation : { +    + errorCode: "6205", +    + errorDescription: "No accounts found" +    + } +    + } + + + DISC-10 + 200 OK + + + The PISP can now show error message and user can try again with another username or different DFSP. + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.puml new file mode 100644 index 000000000..e3cbf4565 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.puml @@ -0,0 +1,162 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title **PISP Linking: consentRequest error cases** + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +== NO_SUPPORTED_SCOPE_ACTIONS == + +autonumber 1 "REQ-#" +PISP -> Switch ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234", ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.91011",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "WEB", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.91011",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "WEB", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +autonumber 1 "DFSP-#" +DFSP -> DFSP: The PISP requested permissions \nfor accountId dfsp.username.91011 which \n isn't owned by username1234 + +autonumber 5 "REQ-#" +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6101", ""\n\ + "" errorDescription: "Unsupported scopes were requested" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6101", ""\n\ + "" errorDescription: "Unsupported scopes were requested" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +== UNTRUSTED_CALLBACK_URI == + +autonumber 1 "REQ-#" +PISP -> Switch ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234", ""\n\ + "" scopes: [ ""\n\ + "" { **accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "WEB", "OTP" ],""\n\ + "" callbackUri: "http://phishing.com"""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "WEB", "OTP" ],""\n\ + "" callbackUri: "http://phishing.com"""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +autonumber 1 "DFSP-#" +DFSP -> DFSP: The callbackUri uses http scheme \ninstead of https. Reject the consentRequest + +autonumber 5 "REQ-#" +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6204", ""\n\ + "" errorDescription: "Bad callbackUri" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6204", ""\n\ + "" errorDescription: "Bad callbackUri" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.svg new file mode 100644 index 000000000..249fe4f27 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.svg @@ -0,0 +1,299 @@ + + **PISP Linking: consentRequest error cases** + + + PISP Linking: consentRequest error cases + + Mojaloop + + + + + + + + + + + + + PISP + + Switch + + DFSP + + + + + + + + + + + + + NO_SUPPORTED_SCOPE_ACTIONS + + + REQ-1 + POST /consentRequests +    + FSIOP-Source: pispa +    + FSIOP-Destination: dfspa + { +    + consentRequestId: "11111111-0000-0000-0000-000000000000", +    + userId: "username1234", +    + scopes: [ +    + { accountId: "dfsp.username.1234", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + { accountId: "dfsp.username.91011", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + ], +    + authChannels: [ "WEB", "OTP" ], +    + callbackUri: "pisp-app://callback... + " +    + } + + + REQ-2 + 202 Accepted + + + REQ-3 + POST /consentRequests +    + FSIOP-Source: pispa +    + FSIOP-Destination: dfspa + { +    + consentRequestId: "11111111-0000-0000-0000-000000000000", +    + userId: "username1234", +    + scopes: [ +    + { accountId: "dfsp.username.1234", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + { accountId: "dfsp.username.91011", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + ], +    + authChannels: [ "WEB", "OTP" ], +    + callbackUri: "pisp-app://callback... + " +    + } + + + REQ-4 + 202 Accepted + + + + + DFSP-1 + The PISP requested permissions + for accountId dfsp.username.91011 which + isn't owned by username1234 + + + REQ-5 + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + { +    + errorInformation : { +    + errorCode: "6101", +    + errorDescription: "Unsupported scopes were requested" +    + } +    + } + + + REQ-6 + 200 OK + + + REQ-7 + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + { +    + errorInformation : { +    + errorCode: "6101", +    + errorDescription: "Unsupported scopes were requested" +    + } +    + } + + + REQ-8 + 200 OK + + + + + UNTRUSTED_CALLBACK_URI + + + REQ-1 + POST /consentRequests +    + FSIOP-Source: pispa +    + FSIOP-Destination: dfspa + { +    + consentRequestId: "11111111-0000-0000-0000-000000000000", +    + userId: "username1234", +    + scopes: [ +    + { **accountId: "dfsp.username.1234", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + { accountId: "dfsp.username.5678", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + ], +    + authChannels: [ "WEB", "OTP" ], +    + callbackUri: "http://phishing.com + " +    + } + + + REQ-2 + 202 Accepted + + + REQ-3 + POST /consentRequests +    + FSIOP-Source: pispa +    + FSIOP-Destination: dfspa + { +    + consentRequestId: "11111111-0000-0000-0000-000000000000", +    + userId: "username1234", +    + scopes: [ +    + { accountId: "dfsp.username.1234", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + { accountId: "dfsp.username.5678", +    + actions: [ "ACCOUNTS_TRANSFER" ] }, +    + ], +    + authChannels: [ "WEB", "OTP" ], +    + callbackUri: "http://phishing.com + " +    + } + + + REQ-4 + 202 Accepted + + + + + DFSP-1 + The callbackUri uses http scheme + instead of https. Reject the consentRequest + + + REQ-5 + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + { +    + errorInformation : { +    + errorCode: "6204", +    + errorDescription: "Bad callbackUri" +    + } +    + } + + + REQ-6 + 200 OK + + + REQ-7 + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + { +    + errorInformation : { +    + errorCode: "6204", +    + errorDescription: "Bad callbackUri" +    + } +    + } + + + REQ-8 + 200 OK + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.puml new file mode 100644 index 000000000..c88560017 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.puml @@ -0,0 +1,87 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Authentication Invalid authToken + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "AUTH-#" + +== Failure case == + +... + +note over PISP, DFSP + The user enters an incorrect OTP for authentication. +end note + +... + +PISP -> Switch ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: The OTP is incorrect. + +note over PISP, DFSP + We respond with an error that the OTP is incorrect so the PISP can inform the user. +end note + +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6203", ""\n\ + "" errorDescription: "Invalid authentication token" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6203", ""\n\ + "" errorDescription: "Invalid authentication token" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.svg new file mode 100644 index 000000000..205c13319 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.svg @@ -0,0 +1,137 @@ + + PISP Linking: Authentication Invalid authToken + + + PISP Linking: Authentication Invalid authToken + + Mojaloop + + + + + + + + + + + + + + + + + + + + + PISP + + Switch + + DFSP + + + + + + + + + Failure case + + + The user enters an incorrect OTP for authentication. + + + AUTH-1 + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 +      + FSIOP-Source: pispa +      + FSIOP-Destination: dfspa + { +      + authToken: "<OTP>" +      + } + + + AUTH-2 + 202 Accepted + + + AUTH-3 + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 +      + FSIOP-Source: pispa +      + FSIOP-Destination: dfspa + { +      + authToken: "<OTP>" +      + } + + + AUTH-4 + 202 Accepted + + + + + AUTH-5 + The OTP is incorrect. + + + We respond with an error that the OTP is incorrect so the PISP can inform the user. + + + AUTH-6 + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + { +    + errorInformation : { +    + errorCode: "6203", +    + errorDescription: "Invalid authentication token" +    + } +    + } + + + AUTH-7 + 200 OK + + + AUTH-8 + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + { +    + errorInformation : { +    + errorCode: "6203", +    + errorDescription: "Invalid authentication token" +    + } +    + } + + + AUTH-9 + 200 OK + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.puml b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.puml new file mode 100644 index 000000000..c9e4f772d --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.puml @@ -0,0 +1,82 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + + +!pragma teoz true + +title PISP Linking: Grant consent scope retrieval error + +participant "PISP" as PISP + +box "Mojaloop" + participant "Thirdparty-API-Adapter" as Switch + participant "Account Lookup Service" as ALS + participant "Auth Service" as Auth +end box + +participant "DFSP" as DFSP + +autonumber 1 "GRANT-#" + +== Failure case == + +PISP -> Switch ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Verify the OTP is correct. + +DFSP -> DFSP: Unable to fetch stored scopes + +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "7207", ""\n\ + "" errorDescription: "FSP failed retrieve scopes for consent request" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "7207", ""\n\ + "" errorDescription: "FSP failed retrieve scopes for consent request" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.svg b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.svg new file mode 100644 index 000000000..b8ba689c8 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.svg @@ -0,0 +1,127 @@ + + PISP Linking: Grant consent scope retrieval error + + + + Mojaloop + PISP Linking: Grant consent scope retrieval error + + + + + + + + + + + PISP + + Thirdparty-API-Adapter + + Account Lookup Service + + Auth Service + + DFSP + + + + + Failure case + + + GRANT-1 + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 +      + FSIOP-Source: pispa +      + FSIOP-Destination: dfspa + { +      + authToken: "<OTP>" +      + } + + + GRANT-2 + 202 Accepted + + + GRANT-3 + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 +      + FSIOP-Source: pispa +      + FSIOP-Destination: dfspa + { +      + authToken: "<OTP>" +      + } + + + GRANT-4 + 202 Accepted + + + + + GRANT-5 + Verify the OTP is correct. + + + + + GRANT-6 + Unable to fetch stored scopes + + + GRANT-7 + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + { +    + errorInformation : { +    + errorCode: "7207", +    + errorDescription: "FSP failed retrieve scopes for consent request" +    + } +    + } + + + GRANT-8 + 200 OK + + + GRANT-9 + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error +    + FSIOP-Source: dfspa +    + FSIOP-Destination: pispa +    + { +    + errorInformation : { +    + errorCode: "7207", +    + errorDescription: "FSP failed retrieve scopes for consent request" +    + } +    + } + + + GRANT-10 + 200 OK + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-1-discovery.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-1-discovery.puml new file mode 100644 index 000000000..ed4cfbbfe --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-1-discovery.puml @@ -0,0 +1,72 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.1 Discovery + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box + + +== Discovery (Lookup) == +rnote right of D1 #LightGray +**""GET /parties/MSISDN/+4412345678""** +""FSPIOP-Source: pispa"" +end note +D1 -> S: ""GET /parties/MSISDN/+4412345678"" +S --> D1: ""202 Accepted"" + +... ALS lookup flow not shown here ... + +rnote over S #LightGray +**""GET /parties/MSISDN/+4412345678""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspb"" +end note +S -> D3: ""GET /parties/MSISDN/+4412345678"" +D3 --> S: ""202 Accepted"" + +rnote left of D3 #LightGray +**""PUT /parties/MSISDN/+4412345678""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: pispa"" +{ + partyIdType: "MSISDN", + partyIdentifier: "+4412345678", + party: { + partyIdInfo: { + partyIdType: "MSISDN", + partyIdentifier: "+4412345678", + fspId: 'dfspb", + }, + name: "Bhavesh S.", + } +} +end note +D3 -> S: ""PUT /parties/MSISDN/+4412345678"" +S --> D3: ""200 OK"" +S -> D1: ""PUT /parties/MSISDN/+4412345678"" +D1 --> S: ""200 OK"" + +... PISP confirms payee party with their user ... + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-1-discovery.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-1-discovery.svg new file mode 100644 index 000000000..9886a2797 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-1-discovery.svg @@ -0,0 +1,89 @@ + + Transfer: 1.1 Discovery + + + Transfer: 1.1 Discovery + + PISP + + Mojaloop + + DFSP B + + + + + + + + + + + + + + + + + PISP Server + + Switch + + DFSP B + (Payee) + + + + + Discovery (Lookup) + + GET /parties/MSISDN/+4412345678 + FSPIOP-Source: pispa + + + GET /parties/MSISDN/+4412345678 + + + 202 Accepted + ALS lookup flow not shown here + + GET /parties/MSISDN/+4412345678 + FSPIOP-Source: pispa + FSPIOP-Destination: dfspb + + + GET /parties/MSISDN/+4412345678 + + + 202 Accepted + + PUT /parties/MSISDN/+4412345678 + FSPIOP-Source: dfspb + FSPIOP-Destination: pispa + { + partyIdType: "MSISDN", + partyIdentifier: "+4412345678", + party: { + partyIdInfo: { + partyIdType: "MSISDN", + partyIdentifier: "+4412345678", + fspId: 'dfspb", + }, + name: "Bhavesh S.", + } + } + + + PUT /parties/MSISDN/+4412345678 + + + 200 OK + + + PUT /parties/MSISDN/+4412345678 + + + 200 OK + PISP confirms payee party with their user + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.puml new file mode 100644 index 000000000..1ca03bf19 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.puml @@ -0,0 +1,86 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.1 Agreement + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +== Agreement Phase == +rnote right of D1 #LightGray +**""POST /thirdpartyRequests/transactions""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T22:17:28.985-01:00" +} +end note +D1 -> S: ""POST /thirdpartyRequests/transactions"" +S --> D1: ""202 Accepted"" +S -> D2: ""POST /thirdpartyRequests/transactions"" +D2 --> S: ""202 Accepted"" +D2 -> D2: Lookup the consent for this ""payer"", verify that they exist, and consent \nis granted with a valid credential +D2 -> D2: Store a referece to the ""consentId"" with the ""transactionRequestId"" +D2 -> D2: Generate a unique transactionId for this transaction request:\n**""11111111-0000-0000-0000-000000000000""** + + +rnote left of D2 #LightGray +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionRequestState": "RECEIVED" +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.svg new file mode 100644 index 000000000..6a74a58bc --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.svg @@ -0,0 +1,114 @@ + + Transfer: 1.2.1 Agreement + + + Transfer: 1.2.1 Agreement + + PISP + + Mojaloop + + DFSP A + + + + + PISP Server + + Switch + + DFSP A + (Payer) + + + + + Agreement Phase + + POST /thirdpartyRequests/transactions + FSPIOP-Source: pispa + FSPIOP-Destination: dfspa + { + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T22:17:28.985-01:00" + } + + + POST /thirdpartyRequests/transactions + + + 202 Accepted + + + POST /thirdpartyRequests/transactions + + + 202 Accepted + + + + + Lookup the consent for this + payer + , verify that they exist, and consent + is granted with a valid credential + + + + + Store a referece to the + consentId + with the + transactionRequestId + + + + + Generate a unique transactionId for this transaction request: + 11111111-0000-0000-0000-000000000000 + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000 + FSPIOP-Source: dfspa + FSPIOP-Destination: pispa + { + "transactionRequestState": "RECEIVED" + } + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000 + + + 200 OK + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000 + + + 200 OK + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.puml new file mode 100644 index 000000000..f18da5725 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.puml @@ -0,0 +1,150 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.2 Authorization + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box + +rnote left of D2 #LightGray +**""POST /quotes""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "quoteId": "22222222-0000-0000-0000-000000000000", + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "personalInfo": { + "complexName": { + "firstName": "Ayesha", + "lastName": "Takia" + } + }, + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "123456789", + "fspId": "dfspa" + }, + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "note": "quote note" +} +end note +D2 -> S: ""POST /quotes"" +S --> D2: ""202 Accepted"" +S -> D3: ""POST /quotes"" +D3 --> S: ""202 Accepted"" + +rnote left of D2 #LightGray +**""PUT /quotes/22222222-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: dfspa"" +{ + "transferAmount": { + "amount": "100", + "currency": "USD" + }, + "payeeReceiveAmount": { + "amount": "99", + "currency": "USD" + }, + "payeeFspFee": { + "amount": "1", + "currency": "USD" + }, + "expiration": "2020-06-15T12:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +D3 -> S: ""PUT /quotes/22222222-0000-0000-0000-000000000000"" +S --> D3: ""200 OK"" +S -> D2: ""PUT /quotes/22222222-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +note left of D2 + DFSP A has the quote, they can now ask + the PISP for authorization +end note + +D2 -> D2: Generate a UUID for the authorization Request:\n""33333333-0000-0000-0000-000000000000"" +D2 -> D2: Derive the challenge based \non ""PUT /quotes/{ID}"" + +rnote left of D2 #LightGray +**""POST /thirdpartyRequests/authorizations""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "authorizationRequestId": "33333333-0000-0000-0000-000000000000", + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "challenge": """", + "transferAmount": {"amount": "100", "currency": "USD"}, + "payeeReceiveAmount": {"amount": "99", "currency": "USD"}, + "fees": {"amount": "1", "currency": "USD"}, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T12:00:00.000", +} +end note +D2 -> S: ""POST /thirdpartyRequests/authorizations"" +S --> D2: ""202 Accepted"" +S -> D1: ""POST /thirdpartyRequests/authorizations"" +D1 --> S: ""202 Accepted"" + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.svg new file mode 100644 index 000000000..cbaf79e38 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.svg @@ -0,0 +1,175 @@ + + Transfer: 1.2.2 Authorization + + + Transfer: 1.2.2 Authorization + + PISP + + Mojaloop + + DFSP A + + DFSP B + + + + + + PISP Server + + Switch + + DFSP A + (Payer) + + DFSP B + (Payee) + + POST /quotes + FSPIOP-Source: dfspa + FSPIOP-Destination: dfspb + { + "quoteId": "22222222-0000-0000-0000-000000000000", + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "personalInfo": { + "complexName": { + "firstName": "Ayesha", + "lastName": "Takia" + } + }, + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "123456789", + "fspId": "dfspa" + }, + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "note": "quote note" + } + + + POST /quotes + + + 202 Accepted + + + POST /quotes + + + 202 Accepted + + PUT /quotes/22222222-0000-0000-0000-000000000000 + FSPIOP-Source: dfspb + FSPIOP-Destination: dfspa + { + "transferAmount": { + "amount": "100", + "currency": "USD" + }, + "payeeReceiveAmount": { + "amount": "99", + "currency": "USD" + }, + "payeeFspFee": { + "amount": "1", + "currency": "USD" + }, + "expiration": "2020-06-15T12:00:00.000", + "ilpPacket": "...", + "condition": "...", + } + + + PUT /quotes/22222222-0000-0000-0000-000000000000 + + + 200 OK + + + PUT /quotes/22222222-0000-0000-0000-000000000000 + + + 200 OK + + + DFSP A has the quote, they can now ask + the PISP for authorization + + + + + Generate a UUID for the authorization Request: + 33333333-0000-0000-0000-000000000000 + + + + + Derive the challenge based + on + PUT /quotes/{ID} + + POST /thirdpartyRequests/authorizations + FSPIOP-Source: dfspa + FSPIOP-Destination: pispa + { + "authorizationRequestId": "33333333-0000-0000-0000-000000000000", + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "challenge": + <base64 encoded binary - the encoded challenge> + , + "transferAmount": {"amount": "100", "currency": "USD"}, + "payeeReceiveAmount": {"amount": "99", "currency": "USD"}, + "fees": {"amount": "1", "currency": "USD"}, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T12:00:00.000", + } + + + POST /thirdpartyRequests/authorizations + + + 202 Accepted + + + POST /thirdpartyRequests/authorizations + + + 202 Accepted + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.puml new file mode 100644 index 000000000..12f1293fc --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.puml @@ -0,0 +1,76 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.3 Rejected Authorization + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +== Agreement Phase == +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the quote with the user, + + + User rejects the terms of the transcationRequest +end note + +rnote right of D1 #LightGray +**""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "REJECTED" +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Look up the ""transactionRequestId"" for this ""authorizationId"" + +note over D2 + User has rejected the transaction request. +end note + +rnote over D2 #LightGray +**""PATCH /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionRequestState": "REJECTED", + "transactionId": "11111111-0000-0000-0000-000000000000", +} +end note +D2 -> S: ""PATCH /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" + +S -> D1: ""PATCH /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + +note over D1 + PISP can inform the user the transaction did not proceed +end note + + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.svg new file mode 100644 index 000000000..deaaa05cf --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.svg @@ -0,0 +1,93 @@ + + Transfer: 1.2.3 Rejected Authorization + + + Transfer: 1.2.3 Rejected Authorization + + PISP + + Mojaloop + + DFSP A + + + + + PISP Server + + Switch + + DFSP A + (Payer) + + + + + Agreement Phase + + + PISP looks up the + transactionRequestId + and + checks the quote with the user, +   +   + User rejects the terms of the transcationRequest + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + FSPIOP-Source: pispa + FSPIOP-Destination: dfspa + { + "responseType": "REJECTED" + } + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + 200 OK + + + PUT /thirdpartyRequests/authorizations + /33333333-0000-0000-0000-000000000000 + + + 200 OK + + + + + Look up the + transactionRequestId + for this + authorizationId + + + User has rejected the transaction request. + + PATCH /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + FSPIOP-Source: dfspa + FSPIOP-Destination: pispa + { + "transactionRequestState": "REJECTED", + "transactionId": "11111111-0000-0000-0000-000000000000", + } + + + PATCH /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000 + + + 200 OK + + + PATCH /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000 + + + 200 OK + + + PISP can inform the user the transaction did not proceed + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.puml new file mode 100644 index 000000000..d05d3f6c8 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.puml @@ -0,0 +1,74 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.3 Signed Authorization FIDO + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +== Agreement Phase == +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the terms with the user. + + If the user agrees to the terms, the PISP + uses the FIDO API on the user's device to sign the + the **""challenge""** string +end note + +rnote right of D1 #LightGray +**""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Look up the ""transactionRequestId"" for this ""authorizationId"" +D2 -> D2: Look up the ""consentId"" for this ""transactionRequestId"" + +note over D2 + DFSP has the signed challenge. + It now needs to ask the Auth-Service to verify + the signed challenge. +end note + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.svg new file mode 100644 index 000000000..4b6355121 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.svg @@ -0,0 +1,95 @@ + + Transfer: 1.2.3 Signed Authorization FIDO + + + Transfer: 1.2.3 Signed Authorization FIDO + + PISP + + Mojaloop + + DFSP A + + + + + PISP Server + + Switch + + DFSP A + (Payer) + + + + + Agreement Phase + + + PISP looks up the + transactionRequestId + and + checks the terms with the user. +   + If the user agrees to the terms, the PISP + uses the FIDO API on the user's device to sign the + the + challenge + string + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + FSPIOP-Source: pispa + FSPIOP-Destination: dfspa + { + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } + } + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + 200 OK + + + PUT /thirdpartyRequests/authorizations + /33333333-0000-0000-0000-000000000000 + + + 200 OK + + + + + Look up the + transactionRequestId + for this + authorizationId + + + + + Look up the + consentId + for this + transactionRequestId + + + DFSP has the signed challenge. + It now needs to ask the Auth-Service to verify + the signed challenge. + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.puml new file mode 100644 index 000000000..2e85d4142 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.puml @@ -0,0 +1,63 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.3 Signed Authorization + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +== Agreement Phase == +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the quote with the user. + + If the user agrees to the terms, the PISP uses + the Credential's privateKey to sign the challenge +end note + +rnote right of D1 #LightGray +**""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "GENERIC", + "genericSignedPayload": "utf-8 base64 encoded signature" + } +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Look up the ""transactionRequestId"" for this ""authorizationId"" +D2 -> D2: Look up the ""consentId"" for this ""transactionRequestId"" + +note over D2 + DFSP has the signed challenge. + It now needs to ask the Auth-Service to verify + the signed challenge. +end note + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.svg new file mode 100644 index 000000000..58ab50236 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.svg @@ -0,0 +1,82 @@ + + Transfer: 1.2.3 Signed Authorization + + + Transfer: 1.2.3 Signed Authorization + + PISP + + Mojaloop + + DFSP A + + + + + PISP Server + + Switch + + DFSP A + (Payer) + + + + + Agreement Phase + + + PISP looks up the + transactionRequestId + and + checks the quote with the user. +   + If the user agrees to the terms, the PISP uses + the Credential's privateKey to sign the challenge + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + FSPIOP-Source: pispa + FSPIOP-Destination: dfspa + { + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "GENERIC", + "genericSignedPayload": "utf-8 base64 encoded signature" + } + } + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + 200 OK + + + PUT /thirdpartyRequests/authorizations + /33333333-0000-0000-0000-000000000000 + + + 200 OK + + + + + Look up the + transactionRequestId + for this + authorizationId + + + + + Look up the + consentId + for this + transactionRequestId + + + DFSP has the signed challenge. + It now needs to ask the Auth-Service to verify + the signed challenge. + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.puml new file mode 100644 index 000000000..d96dbd5c7 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.puml @@ -0,0 +1,82 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.4 Verify Authorization + + +box "Mojaloop" + participant Switch as S + participant "Auth-Service" as AUTHS +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +D2 -> D2: Generate a new ""verificationRequestId"", and associate \n it with the ""thirdpartyTransactionRequestId"" + +rnote left of D2 #LightGray +**""POST /thirdpartyRequests/verifications""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: central-auth"" +{ + "verificationRequestId": "44444444-0000-0000-0000-000000000000", + "challenge": """", + "consentId": "123", + "signedPayloadType": "FIDO", + "fidoValue": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } +} +end note +D2 -> S: ""POST /thirdpartyRequests/verifications"" +S --> D2: ""202 Accepted"" +S -> AUTHS: ""POST /thirdpartyRequests/verifications"" +AUTHS --> S: ""202 Accepted"" + +AUTHS -> AUTHS: Lookup this consent based on consentId +AUTHS -> AUTHS: Ensure the accountAddress matches what is in Consent +AUTHS -> AUTHS: Check that the signed bytes match the \npublickey we have stored for the consent + +rnote right of AUTHS #LightGray +**""PUT /thirdpartyRequests/verifications/44444444-0000-0000-0000-000000000000""** +""FSPIOP-Source: central-auth"" +""FSPIOP-Destination: dfspa"" +{ + "authenticationResponse": "VERIFIED" +} +end note +AUTHS -> S: ""PUT /thirdpartyRequests/verifications""\n"" /44444444-0000-0000-0000-000000000000"" +S --> AUTHS: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/verifications""\n"" /44444444-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +note over D2 + DFSPA now knows that the user signed this transaction + and can go ahead and initiate the transfer +end note + + + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.svg new file mode 100644 index 000000000..ec93b340b --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.svg @@ -0,0 +1,106 @@ + + Transfer: 1.2.4 Verify Authorization + + + Transfer: 1.2.4 Verify Authorization + + Mojaloop + + DFSP A + + + + + Switch + + Auth-Service + + DFSP A + (Payer) + + + + + Generate a new + verificationRequestId + , and associate + it with the + thirdpartyTransactionRequestId + + POST /thirdpartyRequests/verifications + FSPIOP-Source: dfspa + FSPIOP-Destination: central-auth + { + "verificationRequestId": "44444444-0000-0000-0000-000000000000", + "challenge": + <base64 encoded binary - the encoded challenge> + , + "consentId": "123", + "signedPayloadType": "FIDO", + "fidoValue": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } + + + POST /thirdpartyRequests/verifications + + + 202 Accepted + + + POST /thirdpartyRequests/verifications + + + 202 Accepted + + + + + Lookup this consent based on consentId + + + + + Ensure the accountAddress matches what is in Consent + + + + + Check that the signed bytes match the + publickey we have stored for the consent + + PUT /thirdpartyRequests/verifications/44444444-0000-0000-0000-000000000000 + FSPIOP-Source: central-auth + FSPIOP-Destination: dfspa + { + "authenticationResponse": "VERIFIED" + } + + + PUT /thirdpartyRequests/verifications + /44444444-0000-0000-0000-000000000000 + + + 200 OK + + + PUT /thirdpartyRequests/verifications + /44444444-0000-0000-0000-000000000000 + + + 200 OK + + + DFSPA now knows that the user signed this transaction + and can go ahead and initiate the transfer + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-3-transfer.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-3-transfer.puml new file mode 100644 index 000000000..cfd38cc89 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-3-transfer.puml @@ -0,0 +1,178 @@ +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +hide footbox + +title Transfer: 1.3 Final transfer + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box +actor "<$actor>\nPayee" as CB + + + +== Transfer Phase == + +... DFSP A initiates a normal Mojaloop P2P Transfer ... + +D2 -> D2: Generate a new ""transferId"", and associate \n it with the ""transactionRequestId"" + +rnote over D2 #LightGray +**""POST /transfers""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +D2 -> S: ""POST /transfers"" +S --> D2: ""202 Accepted"" + +rnote over S #LightGray +**""POST /transfers""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +S -> D3: ""POST /transfers"" +D3 --> S: ""202 Accepted"" + +rnote left of D3 #LightGray +**""PUT /transfers/55555555-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: dfspa"" +{ + "fulfilment": "...", + "completedTimestamp": "2020-06-15T12:01:00.000", + "transferState": "COMMITTED" +} +end note +D3 -> S: ""PUT /transfers/55555555-0000-0000-0000-000000000000"" +S --> D3: ""200 OK"" +D3 -> CB: You have received funds! +S -> D2: ""PUT /transfers/55555555-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + + +D2 -> D2: Look up ""transactionRequestId"" from the ""transferId"" + +rnote over D2 #LightGray +**""PATCH /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionRequestState": "ACCEPTED", + "transactionState": "COMMITTED" +} +end note +D2 -> S: ""PATCH /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" + +S -> D1: ""PATCH /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + +note over D1 + PISP can now inform the user the + funds have been sent +end note + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/1-3-transfer.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-3-transfer.svg new file mode 100644 index 000000000..3c037e93b --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/1-3-transfer.svg @@ -0,0 +1,161 @@ + + Transfer: 1.3 Final transfer + + + Transfer: 1.3 Final transfer + + PISP + + Mojaloop + + DFSP A + + DFSP B + + + + + + + + + + + + + + + + + PISP Server + + Switch + + DFSP A + (Payer) + + DFSP B + (Payee) + + Payee + + + + + + + Transfer Phase + DFSP A initiates a normal Mojaloop P2P Transfer + + + + + Generate a new + transferId + , and associate + it with the + transactionRequestId + + POST /transfers + FSPIOP-Source: dfspa + FSPIOP-Destination: dfspb + { + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", + } + + + POST /transfers + + + 202 Accepted + + POST /transfers + FSPIOP-Source: dfspa + FSPIOP-Destination: dfspb + { + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", + } + + + POST /transfers + + + 202 Accepted + + PUT /transfers/55555555-0000-0000-0000-000000000000 + FSPIOP-Source: dfspb + FSPIOP-Destination: dfspa + { + "fulfilment": "...", + "completedTimestamp": "2020-06-15T12:01:00.000", + "transferState": "COMMITTED" + } + + + PUT /transfers/55555555-0000-0000-0000-000000000000 + + + 200 OK + + + You have received funds! + + + PUT /transfers/55555555-0000-0000-0000-000000000000 + + + 200 OK + + + + + Look up + transactionRequestId + from the + transferId + + PATCH /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + FSPIOP-Source: dfspa + FSPIOP-Destination: pispa + { + "transactionRequestState": "ACCEPTED", + "transactionState": "COMMITTED" + } + + + PATCH /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000 + + + 200 OK + + + PATCH /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000 + + + 200 OK + + + PISP can now inform the user the + funds have been sent + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.puml new file mode 100644 index 000000000..16b214c2e --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.puml @@ -0,0 +1,90 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.2.1 Bad Thirdparty Transaction Request + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +== Agreement Phase == +rnote right of D1 #LightGray +**""POST /thirdpartyRequests/transactions""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T22:17:28.985-01:00" +} +end note +D1 -> S: ""POST /thirdpartyRequests/transactions"" +S --> D1: ""202 Accepted"" +S -> D2: ""POST /thirdpartyRequests/transactions"" +D2 --> S: ""202 Accepted"" + +D2 -> D2: DFSP finds something wrong with this transaction request. + + +rnote left of D2 #LightGray +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6104", + "errorDescription": "Thirdparty request rejection", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.svg new file mode 100644 index 000000000..3c48a8ee7 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.svg @@ -0,0 +1,101 @@ + + Transfer: 3.2.1 Bad Thirdparty Transaction Request + + + Transfer: 3.2.1 Bad Thirdparty Transaction Request + + PISP + + Mojaloop + + DFSP A + + + + + PISP Server + + Switch + + DFSP A + (Payer) + + + + + Agreement Phase + + POST /thirdpartyRequests/transactions + FSPIOP-Source: pispa + FSPIOP-Destination: dfspa + { + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T22:17:28.985-01:00" + } + + + POST /thirdpartyRequests/transactions + + + 202 Accepted + + + POST /thirdpartyRequests/transactions + + + 202 Accepted + + + + + DFSP finds something wrong with this transaction request. + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + FSPIOP-Source: dfspa + FSPIOP-Destination: pispa + { + "errorInformation": { + "errorCode": "6104", + "errorDescription": "Thirdparty request rejection", + "extensionList": [] + } + } + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + + + 200 OK + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + + + 200 OK + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.puml new file mode 100644 index 000000000..4ee3e839b --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.puml @@ -0,0 +1,140 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.3.1 Bad Quote Request + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box + +... PISP has initiated Thirdparty Transaction Request with ""POST /thirdpartyRequests/transactions""... + +D2 -> D2: Generate a unique transactionId for this transaction request:\n**""11111111-0000-0000-0000-000000000000""** + + +rnote left of D2 #LightGray +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestState": "RECEIVED" +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + +rnote left of D2 #LightGray +**""POST /quotes""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "quoteId": "22222222-0000-0000-0000-000000000000", + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "personalInfo": { + "complexName": { + "firstName": "Ayesha", + "lastName": "Takia" + } + }, + "partyIdInfo": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "note": "quote note" +} +end note +D2 -> S: ""POST /quotes"" +S --> D2: ""202 Accepted"" +S -> D3: ""POST /quotes"" +D3 --> S: ""202 Accepted"" + +D3 -> D3: Quote fails for some reason. + +rnote left of D3 #LightGray +**""PUT /quotes/22222222-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: dfspa"" +{ + "errorInformation": { + "errorCode": "XXXX", + "errorDescription": "XXXX", + "extensionList": [] + } +} +end note +D3 -> S: ""PUT /quotes/22222222-0000-0000-0000-000000000000/error"" +S --> D3: ""200 OK"" +S -> D2: ""PUT /quotes/22222222-0000-0000-0000-000000000000/error"" +D2 --> S: ""200 OK"" + +note left of D2 + Quote failed, DFSP needs to inform PISP +end note + +rnote left of D2 #LightGray +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6003", + "errorDescription": "Downstream Failure", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.svg new file mode 100644 index 000000000..7c1471c24 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.svg @@ -0,0 +1,177 @@ + + Transfer: 3.3.1 Bad Quote Request + + + Transfer: 3.3.1 Bad Quote Request + + PISP + + Mojaloop + + DFSP A + + DFSP B + + + + + + + + + + + + + + PISP Server + + Switch + + DFSP A + (Payer) + + DFSP B + (Payee) + PISP has initiated Thirdparty Transaction Request with + POST /thirdpartyRequests/transactions + + + + + Generate a unique transactionId for this transaction request: + 11111111-0000-0000-0000-000000000000 + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000 + FSPIOP-Source: dfspa + FSPIOP-Destination: pispa + { + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestState": "RECEIVED" + } + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000 + + + 200 OK + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000 + + + 200 OK + + POST /quotes + FSPIOP-Source: dfspa + FSPIOP-Destination: dfspb + { + "quoteId": "22222222-0000-0000-0000-000000000000", + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "personalInfo": { + "complexName": { + "firstName": "Ayesha", + "lastName": "Takia" + } + }, + "partyIdInfo": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "note": "quote note" + } + + + POST /quotes + + + 202 Accepted + + + POST /quotes + + + 202 Accepted + + + + + Quote fails for some reason. + + PUT /quotes/22222222-0000-0000-0000-000000000000/error + FSPIOP-Source: dfspb + FSPIOP-Destination: dfspa + { + "errorInformation": { + "errorCode": "XXXX", + "errorDescription": "XXXX", + "extensionList": [] + } + } + + + PUT /quotes/22222222-0000-0000-0000-000000000000/error + + + 200 OK + + + PUT /quotes/22222222-0000-0000-0000-000000000000/error + + + 200 OK + + + Quote failed, DFSP needs to inform PISP + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + FSPIOP-Source: dfspa + FSPIOP-Destination: pispa + { + "errorInformation": { + "errorCode": "6003", + "errorDescription": "Downstream Failure", + "extensionList": [] + } + } + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + + + 200 OK + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + + + 200 OK + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.puml new file mode 100644 index 000000000..31d95a3f8 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.puml @@ -0,0 +1,122 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.3.2 Bad Transfer Request + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box + +... PISP has initiated Thirdparty Transaction Request with ""POST /thirdpartyRequests/transactions""... + +... DFSP A has received quote, and asked PISP to verify... + +... DFSP A has received ""PUT /thirdpartyRequests/verifications from Auth-Service""... + +... DFSP A initiates a normal Mojaloop P2P Transfer ... + +D2 -> D2: Generate a new ""transferId"", and associate \n it with the ""transactionRequestId"" + +rnote over D2 #LightGray +**""POST /transfers""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +D2 -> S: ""POST /transfers"" +S --> D2: ""202 Accepted"" + +rnote over S #LightGray +**""POST /transfers""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +S -> D3: ""POST /transfers"" +D3 --> S: ""202 Accepted"" + +rnote left of D3 #LightGray +**""PUT /transfers/55555555-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: dfspa"" +{ + "errorInformation": { + "errorCode": "XXXX", + "errorDescription": "XXXX", + "extensionList": [] + } +} +end note +D3 -> S: ""PUT /transfers/55555555-0000-0000-0000-000000000000/error"" +S --> D3: ""200 OK"" +S -> D2: ""PUT /transfers/55555555-0000-0000-0000-000000000000/error"" +D2 --> S: ""200 OK"" + +note left of D2 + Transfer failed, DFSP needs to inform PISP +end note + +rnote left of D2 #LightGray +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6003", + "errorDescription": "Downstream failure", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.svg new file mode 100644 index 000000000..3aa23dd2e --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.svg @@ -0,0 +1,172 @@ + + Transfer: 3.3.2 Bad Transfer Request + + + Transfer: 3.3.2 Bad Transfer Request + + PISP + + Mojaloop + + DFSP A + + DFSP B + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PISP Server + + Switch + + DFSP A + (Payer) + + DFSP B + (Payee) + PISP has initiated Thirdparty Transaction Request with + POST /thirdpartyRequests/transactions + DFSP A has received quote, and asked PISP to verify + DFSP A has received + PUT /thirdpartyRequests/verifications from Auth-Service + DFSP A initiates a normal Mojaloop P2P Transfer + + + + + Generate a new + transferId + , and associate + it with the + transactionRequestId + + POST /transfers + FSPIOP-Source: dfspa + FSPIOP-Destination: dfspb + { + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", + } + + + POST /transfers + + + 202 Accepted + + POST /transfers + FSPIOP-Source: dfspa + FSPIOP-Destination: dfspb + { + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", + } + + + POST /transfers + + + 202 Accepted + + PUT /transfers/55555555-0000-0000-0000-000000000000/error + FSPIOP-Source: dfspb + FSPIOP-Destination: dfspa + { + "errorInformation": { + "errorCode": "XXXX", + "errorDescription": "XXXX", + "extensionList": [] + } + } + + + PUT /transfers/55555555-0000-0000-0000-000000000000/error + + + 200 OK + + + PUT /transfers/55555555-0000-0000-0000-000000000000/error + + + 200 OK + + + Transfer failed, DFSP needs to inform PISP + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + FSPIOP-Source: dfspa + FSPIOP-Destination: pispa + { + "errorInformation": { + "errorCode": "6003", + "errorDescription": "Downstream failure", + "extensionList": [] + } + } + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + + + 200 OK + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + + + 200 OK + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.puml new file mode 100644 index 000000000..3d927a08e --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.puml @@ -0,0 +1,95 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.4.1 Bad Signed Challenge - Self Hosted Auth-Service + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + +... PISP has initiated Thirdparty Transaction Request with ""POST /thirdpartyRequests/transactions""... + +... DFSP A has received quote, and asked PISP to verify... + +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the quote with the user, + and uses the FIDO API to sign the + the **""challenge""** string +end note + +rnote right of D1 #LightGray +**""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Look up the ""transactionRequestId"" for this ""authorizationId"" +D2 -> D2: Look up the ""consentId"" for this ""transactionRequestId"" +D2 -> D2: Look up the ""publicKey"" for this ConsentId. Check the signing of the signed challenge + +note over D2 + Signed challenge is invalid. Transaction Request failed. +end note + + +rnote left of D2 #LightGray +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6201", + "errorDescription": "Invalid transaction signature", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.svg new file mode 100644 index 000000000..fd5f91fad --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.svg @@ -0,0 +1,134 @@ + + Transfer: 3.4.1 Bad Signed Challenge - Self Hosted Auth-Service + + + Transfer: 3.4.1 Bad Signed Challenge - Self Hosted Auth-Service + + PISP + + Mojaloop + + DFSP A + + + + + + + + + + + + + + + + + PISP Server + + Switch + + DFSP A + (Payer) + PISP has initiated Thirdparty Transaction Request with + POST /thirdpartyRequests/transactions + DFSP A has received quote, and asked PISP to verify + + + PISP looks up the + transactionRequestId + and + checks the quote with the user, + and uses the FIDO API to sign the + the + challenge + string + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + FSPIOP-Source: pispa + FSPIOP-Destination: dfspa + { + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } + } + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + 200 OK + + + PUT /thirdpartyRequests/authorizations + /33333333-0000-0000-0000-000000000000 + + + 200 OK + + + + + Look up the + transactionRequestId + for this + authorizationId + + + + + Look up the + consentId + for this + transactionRequestId + + + + + Look up the + publicKey + for this ConsentId. Check the signing of the signed challenge + + + Signed challenge is invalid. Transaction Request failed. + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + FSPIOP-Source: dfspa + FSPIOP-Destination: pispa + { + "errorInformation": { + "errorCode": "6201", + "errorDescription": "Invalid transaction signature", + "extensionList": [] + } + } + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + + + 200 OK + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + + + 200 OK + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.puml new file mode 100644 index 000000000..5749390a0 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.puml @@ -0,0 +1,149 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.4.2 Bad Signed Challenge - Hub Hosted Auth-Service + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S + participant "Auth-Service" as AUTHS +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +... PISP has initiated Thirdparty Transaction Request with ""POST /thirdpartyRequests/transactions""... + +... DFSP A has received quote, and asked PISP to verify... + +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the quote with the user, + and uses the FIDO API to sign the + the **""challenge""** string +end note + +rnote right of D1 #LightGray +**""PUT /thirdpartyRequests/authorizations""** +**"" /33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Lookup ""transactionRequestId"" for this ""authorizationId"" +D2 -> D2: Lookup ""consentId"" for this ""transactionRequestId"" + + +D2 -> D2: Generate a new ""verificationRequestId"", and associate \n it with the ""thirdpartyTransactionRequestId"" + +rnote left of D2 #LightGray +**""POST /thirdpartyRequests/verifications""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: central-auth"" +{ + "verificationRequestId": "44444444-0000-0000-0000-000000000000", + "challenge": """", + "consentId": "123", + "signedPayloadType": "FIDO", + "fidoValue": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } +} +end note +D2 -> S: ""POST /thirdpartyRequests/verifications"" +S --> D2: ""202 Accepted"" +S -> AUTHS: ""POST /thirdpartyRequests/verifications"" +AUTHS --> S: ""202 Accepted"" + +AUTHS -> AUTHS: Lookup this consent based on consentId +AUTHS -> AUTHS: Ensure the accountAddress matches what is in Consent +AUTHS -> AUTHS: Check that the signed bytes match the \npublickey we have stored for the consent + +rnote right of AUTHS #LightGray +**""PUT /thirdpartyRequests/verifications""** +**"" /44444444-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: central-auth"" +""FSPIOP-Destination: dfspa"" +{ + "errorInformation": { + "errorCode": "6201", + "errorDescription": "Invalid transaction signature", + "extensionList": [] + } +} +end note +AUTHS -> S: ""PUT /thirdpartyRequests/verifications""\n"" /44444444-0000-0000-0000-000000000000/error"" +S --> AUTHS: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/verifications""\n"" /44444444-0000-0000-0000-000000000000/error"" +D2 --> S: ""200 OK"" + +note over D2 + Signed challenge is invalid. Transaction Request failed. +end note + + +rnote left of D2 #LightGray +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6201", + "errorDescription": "Invalid transaction signature", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.svg new file mode 100644 index 000000000..9789b4778 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.svg @@ -0,0 +1,222 @@ + + Transfer: 3.4.2 Bad Signed Challenge - Hub Hosted Auth-Service + + + Transfer: 3.4.2 Bad Signed Challenge - Hub Hosted Auth-Service + + PISP + + Mojaloop + + DFSP A + + + + + + + + + + + + + + + + + + + + + + PISP Server + + Switch + + Auth-Service + + DFSP A + (Payer) + PISP has initiated Thirdparty Transaction Request with + POST /thirdpartyRequests/transactions + DFSP A has received quote, and asked PISP to verify + + + PISP looks up the + transactionRequestId + and + checks the quote with the user, + and uses the FIDO API to sign the + the + challenge + string + + PUT /thirdpartyRequests/authorizations + /33333333-0000-0000-0000-000000000000 + FSPIOP-Source: pispa + FSPIOP-Destination: dfspa + { + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } + } + + + PUT /thirdpartyRequests/authorizations + /33333333-0000-0000-0000-000000000000 + + + 200 OK + + + PUT /thirdpartyRequests/authorizations + /33333333-0000-0000-0000-000000000000 + + + 200 OK + + + + + Lookup + transactionRequestId + for this + authorizationId + + + + + Lookup + consentId + for this + transactionRequestId + + + + + Generate a new + verificationRequestId + , and associate + it with the + thirdpartyTransactionRequestId + + POST /thirdpartyRequests/verifications + FSPIOP-Source: dfspa + FSPIOP-Destination: central-auth + { + "verificationRequestId": "44444444-0000-0000-0000-000000000000", + "challenge": + <base64 encoded binary - the encoded challenge> + , + "consentId": "123", + "signedPayloadType": "FIDO", + "fidoValue": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } + + + POST /thirdpartyRequests/verifications + + + 202 Accepted + + + POST /thirdpartyRequests/verifications + + + 202 Accepted + + + + + Lookup this consent based on consentId + + + + + Ensure the accountAddress matches what is in Consent + + + + + Check that the signed bytes match the + publickey we have stored for the consent + + PUT /thirdpartyRequests/verifications + /44444444-0000-0000-0000-000000000000/error + FSPIOP-Source: central-auth + FSPIOP-Destination: dfspa + { + "errorInformation": { + "errorCode": "6201", + "errorDescription": "Invalid transaction signature", + "extensionList": [] + } + } + + + PUT /thirdpartyRequests/verifications + /44444444-0000-0000-0000-000000000000/error + + + 200 OK + + + PUT /thirdpartyRequests/verifications + /44444444-0000-0000-0000-000000000000/error + + + 200 OK + + + Signed challenge is invalid. Transaction Request failed. + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + FSPIOP-Source: dfspa + FSPIOP-Destination: pispa + { + "errorInformation": { + "errorCode": "6201", + "errorDescription": "Invalid transaction signature", + "extensionList": [] + } + } + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + + + 200 OK + + + PUT /thirdpartyRequests/transactions + /00000000-0000-0000-0000-000000000000/error + + + 200 OK + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.puml new file mode 100644 index 000000000..3c083936d --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.puml @@ -0,0 +1,77 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.Thirdparty Transaction Request Times Out + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +rnote right of D1 #LightGray +**""POST /thirdpartyRequests/transactions""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T22:17:28.985-01:00" +} +end note +D1 -> S: ""POST /thirdpartyRequests/transactions"" +S --> D1: ""202 Accepted"" +S -> D2: ""POST /thirdpartyRequests/transactions"" +D2 --> S: ""202 Accepted"" + + +... DFSP doesn't respond for some reason... + + +D1 -> D1: Thirdparty Transaction Request expiration reached + +note over D1 + PISP informs their user that the transaction failed. + +end note + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.svg new file mode 100644 index 000000000..3767c779d --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.svg @@ -0,0 +1,81 @@ + + Transfer: 3.Thirdparty Transaction Request Times Out + + + Transfer: 3.Thirdparty Transaction Request Times Out + + PISP + + Mojaloop + + DFSP A + + + + + + + + + + + PISP Server + + Switch + + DFSP A + (Payer) + + POST /thirdpartyRequests/transactions + FSPIOP-Source: pispa + FSPIOP-Destination: dfspa + { + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T22:17:28.985-01:00" + } + + + POST /thirdpartyRequests/transactions + + + 202 Accepted + + + POST /thirdpartyRequests/transactions + + + 202 Accepted + DFSP doesn't respond for some reason + + + + + Thirdparty Transaction Request expiration reached + + + PISP informs their user that the transaction failed. +   + + diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/get_transaction_request.puml b/docs/technical/api/thirdparty/assets/diagrams/transfer/get_transaction_request.puml new file mode 100644 index 000000000..63224d6a9 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/get_transaction_request.puml @@ -0,0 +1,67 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISPGetTransactionRequest + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + +autonumber 1 "GTR-#" + +note over S + Assuming a previously created thirdparty transaction request with id: ""00000000-0000-0000-0000-000000000000"" + +end note + + + +rnote right of D1 #LightGray +**""GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +end note + +D1 -> S: ""GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" +S --> D1: ""202 Accepted"" + +S -> D2: ""GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" +D2 --> S: ""202 Accepted"" + +D2 -> D2: DFSP looks up already created \nthirdparty transaction request +D2 -> D2: DFSP ensures that the FSPIOP-Source (pisp)\nis the same as the original sender of \n""POST /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" + +rnote left of D2 #LightGray +**""PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionRequestState": "ACCEPTED", +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" + +S -> D1: ""PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/docs/technical/api/thirdparty/assets/diagrams/transfer/get_transaction_request.svg b/docs/technical/api/thirdparty/assets/diagrams/transfer/get_transaction_request.svg new file mode 100644 index 000000000..3ba41a634 --- /dev/null +++ b/docs/technical/api/thirdparty/assets/diagrams/transfer/get_transaction_request.svg @@ -0,0 +1,86 @@ + + PISPGetTransactionRequest + + + PISPGetTransactionRequest + + PISP + + Mojaloop + + DFSP A + + + + + PISP Server + + Switch + + DFSP A + (Payer) + + + Assuming a previously created thirdparty transaction request with id: + 00000000-0000-0000-0000-000000000000 +   + + GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + FSPIOP-Source: pispa + FSPIOP-Destination: dfspa + + + GTR-1 + GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + GTR-2 + 202 Accepted + + + GTR-3 + GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + GTR-4 + 202 Accepted + + + + + GTR-5 + DFSP looks up already created + thirdparty transaction request + + + + + GTR-6 + DFSP ensures that the FSPIOP-Source (pisp) + is the same as the original sender of + POST /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + FSPIOP-Source: dfspa + FSPIOP-Destination: pispa + { + "transactionRequestState": "ACCEPTED", + } + + + GTR-7 + PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + GTR-8 + 200 OK + + + GTR-9 + PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + GTR-10 + 200 OK + + diff --git a/docs/technical/api/thirdparty/data-models.md b/docs/technical/api/thirdparty/data-models.md new file mode 100644 index 000000000..0fa1c4b4a --- /dev/null +++ b/docs/technical/api/thirdparty/data-models.md @@ -0,0 +1,991 @@ +# Data Models + +Third Party API + +### Table Of Contents + +1. [Preface](#Preface) + 1.1 [Conventions Used in This Document](#ConventionsUsedinThisDocument) + 1.2 [Document Version Information](#DocumentVersionInformation) + 1.3 [References](#References) +2. [Introduction](#Introduction) + 2.1 [Third Party API Specification](#ThirdPartyAPISpecification) +3. [Third Party API Elements](#ThirdPartyAPIElements) + 3.1 [Resources](#Resources) + 3.2 [Data Models](#DataModels) + 3.3 [Error Codes](#ErrorCodes) +# 1. Preface +This section contains information about how to use this document. + +## 1.1 Conventions Used in This Document + +The following conventions are used in this document to identify the +specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics with in angle brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature and API Encryption_ should be used instead.| + +## 1.2 Document Version Information + +| Version | Date | Change Description | +| --- | --- | --- | +| **1.0** | 2021-10-03 | Initial Version + +## 1.3 References + +The following references are used in this specification: + +| Reference | Description | Version | Link | +| --- | --- | --- | --- | +| Ref. 1 | Open API for FSP Interoperability | `1.1` | [API Definition v1.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md)| + + +# 2. Introduction + +This document specifies the data model used by the Mojaloop Third Party API ("the API"). + +## 2.1 Third Party API Specification + +The Mojaloop Third Party API Specification includes the following documents: + +- [Data Models](./data-models.md) +- [Transaction Patterns - Linking](./transaction-patterns-linking.md) +- [Transaction Patterns - Transfer](./transaction-patterns-transfer.md) +- [Third Party Open API Definition - DFSP](./thirdparty-dfsp-v1.0.yaml) +- [Third Party Open API Definition - PISP](./thirdparty-dfsp-v1.0.yaml) + + +# 3. Third Party API Elements + +This section describes the content of the API which will be used by PISPs and DFSPs. + +The content of the API falls into two sections: + +1. [Transaction Patterns - Linking](./transaction-patterns-linking.md) describes the process for linking customer accounts and providing a general permission mechanism for PISPs to perform operations on those accounts +2. [Transaction Patterns - Transfer](./transaction-patterns-transfer.md) describes the transfer of funds at the instigation of a PISP. + +The API is used by the following different types of participant, as follows: + 1. PISPs + 2. DFSPs who offer services to their customer which allow the customer to access their account via one or more PISPs + 3. Auth-Services + 4. The Mojaloop switch + +Each resource in the API definition is accompanied by a definition of the type(s) of participant allowed to access it. + +## 3.1 Resources + +The API contains the following resources: + +### 3.1.1 **/accounts** + +The **/accounts** resource is used to request information from a DFSP relating to the accounts +it holds for a given identifier. The identifier is a user-provided value which the user +uses to access their account with the DFSP, such as a phone number, email address, or +some other identifier previously provided by the DFSP. + +The DFSP returns a set of information about the accounts it is prepared to divulge to the PISP. +The PISP can then display the names of the accounts to the user, and allow the user to select +the accounts with which they wish to link via the PISP. + +The **/accounts** resource supports the endpoints described below. + +#### 3.1.1.1 Requests + +This section describes the services that a PISP can request on the /accounts resource. + +##### 3.1.1.1.1 **GET /accounts/**_{ID}_ + +Used by: PISP + +The HTTP request **GET /accounts/**_{ID}_ is used to lookup information about the requested +user's accounts, defined by an identifier *{ID}*, where *{ID}* is an identifier a user +uses to access their account with the DFSP, such as a phone number, email address, or +some other identifier previously provided by the DFSP. + +Callback and data model information for **GET /accounts/**_{ID}_: +- Callback - **PUT /accounts/**_{ID}_ +- Error Callback - **PUT /accounts/**_{ID}_**/error** +- Data Model – Empty body + +#### 3.1.1.2 Callbacks + +The responses for the **/accounts** resource are as follows + +##### 3.1.1.2.1 **PUT /accounts/**_{ID}_ + +Used by: DFSP + +The **PUT /accounts/**_{ID}_ response is used to inform the requester of the result of a request +for accounts information. The identifier ID given in the call are the +values given in the original request (see Section 3.1.1.1.1 above.) + +The data content of the message is given below. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| accountList | 1 | AccountList | Information about the accounts that the DFSP associates with the identifier sent by the PISP. | + +##### 3.1.1.2.2 **PUT /accounts/**_{ID}_**/error** + +Used by: DFSP + +The **PUT /accounts/**_{ID}_**/error** response is used to inform the requester that an account list +request has given rise to an error. The identifier ID given in the call are +the values given in the original request (see Section 3.1.1.1.1 above.) + +The data content of the message is given below. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + +### 3.1.2 **/consentRequests** + +The **/consentRequests** resource is used by a PISP to initiate the process of linking with a DFSP’s +account on behalf of a user. The PISP contacts the DFSP and sends a list of the permissions that +it wants to obtain and the accounts for which it wants permission. + +#### 3.1.2.1 Requests + +This section describes the services that can be requested by a client on the API resource +**/consentRequests**. +##### 3.1.2.1.1 **GET /consentRequests/**_{ID}_ + +Used by: PISP + +The HTTP request **GET /consentRequests/**_{ID}_ is used to get information about a previously +requested consent. The *{ID}* in the URI should contain the consentRequestId that was assigned to the +request by the PISP when the PISP originated the request. + +Callback and data model information for **GET /consentRequests/**_{ID}_: +- Callback – **PUT /consentRequests/**_{ID}_ +- Error Callback – **PUT /consentRequests/**_{ID}_**/error** +- Data Model – Empty body + +##### 3.1.2.1.2 **POST /consentRequests** + +Used by: PISP + +The HTTP request **POST /consentRequests** is used to request a DFSP to grant access to one or more +accounts owned by a customer of the DFSP for the PISP who sends the request. + +Callback and data model for **POST /consentRequests**: +- Callback: **PUT /consentRequests/**_{ID}_ +- Error callback: **PUT /consentRequests/**_{ID}_**/error** +- Data model – see below + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| consentRequestId | 1 | CorrelationId | Common ID between the PISP and the Payer DFSP for the consent request object. The ID should be reused for resends of the same consent request. A new ID should be generated for each new consent request. | +| userId | 1 | String(1..128) | The identifier used in the **GET /accounts/**_{ID}_. Used by the DFSP to correlate an account lookup to a `consentRequest` | +| scopes | 1..256 | Scope | One or more requests for access to a particular account. In each case, the address of the account and the types of access required are given. | +| authChannels | 1..256 | ConsentRequestChannelType | A collection of the types of authentication that the DFSP may use to verify that its customer has in fact requested access for the PISP to the accounts requested. | +| callbackUri | 1 | Uri | The callback URI that the user will be redirected to after completing verification via the WEB authorization channel. This field is mandatory as the PISP does not know ahead of time which AuthChannel the DSFP will use to authenticate their user. | + +#### 3.1.2.2 Callbacks + +This section describes the callbacks that are used by the server under the resource /consentRequests. + +##### 3.1.2.2.1 **PUT /consentRequests/**_{ID}_ + +Used by: DFSP + +A DFSP uses this callback to (1) inform the PISP that the consentRequest has been accepted, +and (2) communicate to the PISP which `authChannel` it should use to authenticate their user +with. + +When a PISP requests a series of permissions from a DFSP on behalf of a DFSP’s customer, not all +the permissions requested may be granted by the DFSP. Conversely, the out-of-band authorization +process may result in additional privileges being granted by the account holder to the PISP. The +**PUT /consentRequests/**_{ID}_ resource returns the current state of the permissions relating to a +particular authorization request. The data model for this call is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| scopes | 1..256 | Scope | One or more requests for access to a particular account. In each case, the address of the account and the types of access required are given. | +| authChannels | 1 | ConsentRequestChannelType | A list of one element, which the DFSP uses to inform the PISP of the selected authorization channel. | +| callbackUri | 0..1 | Uri |The callback URI that the user will be redirected to after completing verification via the WEB authorization channel | +| authUri | 0..1 | Uri | The URI that the PISP should call to complete the linking procedure if completion is required. | + + +##### 3.1.2.2.2 **PATCH /consentRequests/**_{ID}_ + +Used by: PISP + +After the user completes an out-of-band authorization with the DFSP, the PISP will receive +a token which they can use to prove to the DFSP that the user trusts this PISP. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| authToken | 1 | BinaryString |The token given to the PISP by the DFSP as part of the out-of-band authentication process | + +#### 3.1.2.3 Error callbacks + +This section describes the error callbacks that are used by the server under the resource +**/consentRequests**. + +##### 3.1.2.3.1 **PUT /consentRequests/**_{ID}_**/error** + +Used by: DFSP + +If the server is unable to complete the consent request, or if an out-of-band processing error or +another processing error occurs, the error callback **PUT /consentRequests/**_{ID}_**/error** is used. The +*{ID}* in the URI should contain the *{ID}* that was used in the **GET /consentRequests/**_{ID}_ +request or the **POST /consentRequests** request. The data model for this resource is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + + +### 3.1.3 **/consents** + +The **/consents** resource is used to negotiate a series of permissions between the PISP and the +DFSP which owns the account(s) on behalf of which the PISP wants to transact. + +A **/consents** call is originally sent to the PISP by the DFSP following the original consent +request process described in Section 3.1.2.1.2 above. At the close of this process, the DFSP +which owns the customer’s account(s) will have satisfied itself that its customer really has +requested that the PISP be allowed access to their accounts, and will have defined the accounts in +question and the type of access which is to be granted. +#### 3.1.3.1 Requests +The **/consents** resource will support the following requests. +##### 3.1.3.1.1 **GET /consents/**_{ID}_ + +Used by: DFSP + +The **GET /consents/**_{ID}_ resource allows a party to enquire after the status of a consent. The +*{ID}* used in the URI of the request should be the consent request ID which was used to identify +the consent when it was created. + +Callback and data model information for **GET /consents/**_{ID}_: +- Callback – **PUT /consents/**_{ID}_ +- Error Callback – **PUT /consents/**_{ID}_**/error** +- Data Model – Empty body +##### 3.1.3.1.2 **POST /consents** + +Used by: DFSP + +The **POST /consents** request is used to request the creation of a consent for interactions between +a PISP and the DFSP who owns the account which a PISP’s customer wants to allow the PISP access to. + +Callback and data model information for **POST /consents/**: + +- Callback – **PUT /consents/**_{ID}_ +- Error Callback – **PUT /consents/**_{ID}_**/error** +- Data Model – defined below + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| consentId | 1 | CorrelationId | Common ID between the PISP and the Payer DFSP for the consent object. The ID should be reused for resends of the same consent. A new ID should be generated for each new consent.| +| consentRequestId | 1 | CorrelationId | The ID given to the original consent request on which this consent is based. | +| scopes | 1..256 | Scope | A list Scope objects, which represent the accounts and attached permissions on which the DFSP is prepared to grant specified permissions to the PISP. | +| status | 1 | ConsentStatus | The status of the Consent. | +| credential | 0..1 | Credential | The credential which is being used to support the consents. | +| extensionList | 0..1 | ExtensionList |Optional extension, specific to deployment | +##### 3.1.3.1.3 **DELETE /consents/**_{ID}_ + +Used by PISP, DFSP + +The **DELETE /consents/**_{ID}_ request is used to request the revocation of a previously agreed consent. +For tracing and auditing purposes, the switch should be sure not to delete the consent physically; +instead, information relating to the consent should be marked as deleted and requests relating to the +consent should not be honoured. + +> Note: the ALS should verify that the participant who is requesting the deletion is either the +> initiator named in the consent or the account holding institution named in the consent. If any +> other party attempts to delete a consent, the request should be rejected, and an error raised. + +Callback and data model information for **DELETE /consents/**_{ID}_: +- Callback – **PATCH /consents/**_{ID}_ +- Error Callback – **PUT /consents/**_{ID}_**/error** + +#### 3.1.3.2 Callbacks +The **/consents** resource supports the following callbacks: +##### 3.1.3.2.1 **PATCH/consents/**_{ID}_ + +Used by: Auth-Service, DFSP + +**PATCH /consents/**_{ID}_ is used in 2 places: +1. To inform the PISP that the `consent.credential` is valid and the account linking process completed + successfully. +2. To inform the PISP or the DFSP that the Consent has been revoked. + +In the first case, a DFSP sends a **PATCH/consents/**_{ID}_ request to the PISP with a `credential.status` +of `VERIFIED`. + +In the second case, an Auth-Service or DFSP sends a **PATCH/consents/**_{ID}_ request with a `status` of +`REVOKED`, and the `revokedAt` field set. + +The syntax of this call complies with the JSON Merge Patch specification [RFC-7386](https://datatracker.ietf.org/doc/html/rfc7386) +rather than the JSON Patch specification [RFC-6902](https://datatracker.ietf.org/doc/html/rfc6902). +The **PATCH /consents/**_{ID}_ resource contains a set of proposed changes to the current state of the +permissions relating to a particular authorization grant. The data model +for this call is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| status | 0..1 | ConsentStatus | The status of the Consent. | +| revokedAt | 0..1 | DateTime | The DateTime the consent was revoked at. | +| credential | 0..1 | Credential | The credential which is being used to support the consents. | +| extensionList | 0..1 | ExtensionList | Optional extension, specific to deployment | + +##### 3.1.3.2.2 **PUT /consents/**_{ID}_ + +Used by: PISP + +The **PUT /consents/**_{ID}_ resource is used to return information relating to the consent object +whose `consentId` is given in the URI. And for registering a credential for the consent. The +data returned by the call is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| scopes | 1..256 | Scope | The scopes covered by the consent. | +| status | 0..1 | ConsentStatus | The status of the Consent. | +| credential | 1 | Credential | The credential which is being used to support the consents. | +| extensionList | 0..1 | ExtensionList | Optional extension, specific to deployment | +#### 3.1.3.3 Error callbacks +This section describes the error callbacks that are used by the server under the resource **/consents**. +##### 3.1.3.3.1 **PUT /consents/**_{ID}_**/error** + +Used by: PISP, DFSP, Auth-Service + +If the server is unable to complete the consent, or if an out-of-loop processing error or another +processing error occurs, the error callback **PUT /consents/**_{ID}_**/error** is used. The *{ID}* in the +URI should contain the *{ID}* that was used in the **GET /consents/**_{ID}_ request or the +**POST /consents** request. The data model for this resource is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + +### 3.1.4 **/parties** + +The **/parties** resource will be used by the PISP to identify a party to a transfer. This will be +used by the PISP to identify the payee DFSP when it requests a transfer. + +The PISP will be permitted to issue a **PUT /parties** response. Although it does not own any +transaction accounts, there are circumstances in which another party may want to pay a customer +via their PISP identification: for instance, where the customer is at a merchant’s premises and +tells the merchant that they would like to pay via their PISP app. In these circumstances, the PISP +will need to be able to confirm that it does act for the customer. +#### 3.1.4.1 Requests + +The **/parties** resource will support the following requests. +##### 3.1.4.1.1 **GET /parties** + +Used by: PISP + +The **GET /parties** resource will use the same form as the resource described in +[Section 6.3.3.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#6331-get-partiestypeid) of Ref. 1 above. +#### 3.1.4.2 Callbacks +The parties resource will support the following callbacks. +##### 3.1.4.2.1 **PUT /parties** + +Used by: DFSP + +The **PUT /parties** resource will use the same form as the resource described in +[Section 6.3.4.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#6341-put-partiestypeid) of Ref. 1 above. + +### 3.1.5 **/services** +The **/services** resource is a new resource which enables a participant to query for other +participants who offer a particular service. The requester will issue a `GET` request, specifying +the type of service for which information is required as part of the query string. The switch will +respond with a list of the current DFSPs in the scheme which are registered as providing that +service. +#### 3.1.5.1 Requests +The services resource will support the following requests. +#### 3.1.5.2 **GET /services/**_{ServiceType}_ + +Used by: DFSP, PISP + +The HTTP request **GET /services/**_{ServiceType}_ is used to find out the names of the participants in a +scheme which provide the type of service defined in the *{ServiceType}* parameter. The *{ServiceType}* parameter +should specify a value from the ServiceType enumeration. If it does not, the request will be +rejected with an error. + +Callback and data model information for **GET /services/**_{ServiceType}_: +- Callback - **PUT /services/**_{ServiceType}_ +- Error Callback - **PUT /services/**_{ServiceType}_**/error** +- Data Model – Empty body +#### 3.1.5.3 Callbacks +This section describes the callbacks that are used by the server for services provided by the +resource **/services**. +##### 3.1.5.3.1 **PUT /services/**_{ServiceType}_ + +Used by: Switch + +The callback **PUT /services/**_{ServiceType}_ is used to inform the client of a successful result of +the service information lookup. The information is returned in the following form: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| providers | 0...256 | FspId | A list of the Ids of the participants who provide the service requested. | + +##### 3.1.5.3.2 **PUT /services/**_{ServiceType}_**/error** + +Used by: Switch + +If the server encounters an error in fulfilling a request for a list of participants who +provide a service, the error callback **PUT /services/**_{ServiceType}_**/error** is used to inform the +client that an error has occurred. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + +### 3.1.6 **thirdpartyRequests/authorizations** + +The **/thirdpartyRequests/authorizations** resource is analogous to the **/authorizations** resource + described in [Section 6.6](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#66-api-resource-authorizations) of Ref. 1 above. The DFSP uses it to request the PISP to: + +1. Display the information defining the terms of a proposed transfer to its customer; +2. Obtain the customer’s confirmation that they want the transfer to proceed; +3. Return a signed version of the terms which the DFSP can use to verify the consent + +The **/thirdpartyRequests/authorizations** resource supports the endpoints described below. +#### 3.1.6.1 Requests + +This section describes the services that a client can request on the +**/thirdpartyRequests/authorizations** resource. +##### 3.1.6.1.1 **GET /thirdpartyRequests/authorizations/**_{ID}_ + +Used by: DFSP + +The HTTP request **GET /thirdpartyRequests/authorizations/**_{ID}_ is used to get information relating +to a previously issued authorization request. The *{ID}* in the request should match the +`authorizationRequestId` which was given when the authorization request was created. + +Callback and data model information for **GET /thirdpartyRequests/authorizations/**_{ID}_: +- Callback - **PUT /thirdpartyRequests/authorizations/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/authorizations/**_{ID}_**/error** +- Data Model – Empty body +##### 3.1.6.1.2 **POST /thirdpartyRequests/authorizations** + +Used by: DFSP + +The HTTP request **POST /thirdpartyRequests/authorizations** is used to request the validation by a + customer for the transfer described in the request. + +Callback and data model information for **POST /thirdpartyRequests/authorizations:** + +- Callback - **PUT /thirdpartyRequests/authorizations/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/authorizations/**_{ID}_**/error** +- Data Model – See Table below + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| authorizationRequestId | 1 | CorrelationId | Common ID between the PISP and the Payer DFSP for the authorization request object. The ID should be reused for resends of the same authorization request. A new ID should be generated for each new authorization request. | +| transactionRequestId | 1 | CorrelationId | The unique identifier of the transaction request for which authorization is being requested. | +| challenge | 1 | BinaryString | The challenge that the PISP’s client is to sign. | +| transferAmount | 1 | Money | The amount that will be debited from the sending customer’s account as a consequence of the transaction. | +| payeeReceiveAmount | 1 | Money | The amount that will be credited to the receiving customer’s account as a consequence of the transaction. | +| fees | 1 | Money | The amount of fees that the paying customer will be charged as part of the transaction. | +| payer | 1 | PartyIdInfo | Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction. | +| payee | 1 | Party | Information about the Payee in the proposed transaction | +| transactionType | 1 | TransactionType | The type of the transaction. | +| expiration | 1 | DateTime | The time by which the transfer must be completed, set by the payee DFSP. | +| extensionList | 0..1 | ExtensionList |Optional extension, specific to deployment. | + +#### 3.1.6.2 Callbacks +The following callbacks are supported for the **/thirdpartyRequests/authorizations** resource +##### 3.1.6.2.1 **PUT /thirdpartyRequests/authorizations/**_{ID}_ + +Used by: PISP + +After receiving the **POST /thirdpartyRequests/authorizations**, the PISP will present the details of the +transaction to their user, and request that the client sign the `challenge` field using the credential +they previously registered. + +The signed challenge will be sent back by the PISP in **PUT /thirdpartyRequests/authorizations/**_{ID}_: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| responseType | 1 | AuthorizationResponseType | `ACCEPTED` or `REJECTED` | +| signedPayload | 0..1 | SignedPayload | If the `responseType` is `ACCEPTED`, `signedPayload` is required. | + +#### 3.1.6.3 Error callbacks +This section describes the error callbacks that are used by the server under the resource +**/thirdpartyRequests/authorizations**. +##### 3.1.6.3.1 **PUT /thirdpartyRequests/authorizations/**_{ID}_**/error** + +Used by: DFSP + +The **PUT /thirdpartyRequests/authorizations/**_{ID}_**/error** resource will have the same content +as the **PUT /authorizations/**_{ID}_**/error** resource described in [Section 6.6.5.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#6651-put-authorizationsiderror) +of Ref. 1 above. +### 3.1.7 **/thirdpartyRequests/transactions** +The **/thirdpartyRequests/transactions` resource is analogous to the `/transactionRequests** +resource described in [Section 6.4](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#64-api-resource-transactionrequests) of Ref. 1 above. The PISP uses it to request the +owner of the PISP’s customer’s account to transfer a specified amount from the customer’s +account with the DFSP to a named Payee. + +The **/thirdpartyRequests/transactions** resource supports the endpoints described below. +#### 3.1.7.1 Requests + +This section describes the services that a client can request on the +**/thirdpartyRequests/transactions** resource. +##### 3.1.7.1.1 **GET /thirdpartyRequests/transactions/**_{ID}_ + +Used by: PISP + +The HTTP request **GET /thirdpartyRequests/transactions/**_{ID}_ is used to get information +relating to a previously issued transaction request. The *{ID}* in the request should +match the `transactionRequestId` which was given when the transaction request was created. + +Callback and data model information for **GET /thirdpartyRequests/transactions/**_{ID}_: +- Callback - **PUT /thirdpartyRequests/transactions/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** +- Data Model – Empty body +##### 3.1.7.1.2 **POST /thirdpartyRequests/transactions** + +Used by: PISP + +The HTTP request **POST /thirdpartyRequests/transactions** is used to request the creation +of a transaction request on the server for the transfer described in the request. + +Callback and data model information for **POST /thirdpartyRequests/transactions**: +- Callback - **PUT /thirdpartyRequests/transactions/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** +- Data Model – See Table below + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| transactionRequestId | 1 | CorrelationId |Common ID between the PISP and the Payer DFSP for the transaction request object. The ID should be reused for resends of the same transaction request. A new ID should be generated for each new transaction request. | +| payee | 1 | Party |Information about the Payee in the proposed financial transaction. | +| payer | 1 | PartyIdInfo |Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction. | +| amountType | 1 | AmountType | SEND for send amount, RECEIVE for receive amount. | +| amount | 1 | Money | Requested amount to be transferred from the Payer to Payee. | +| transactionType | 1 | TransactionType |Type of transaction | +| note | 0..1 | Note | Memo assigned to Transaction. | +| expiration | 0..1 | DateTime |Can be set to get a quick failure in case the peer FSP takes too long to respond. Also, it may be beneficial for Consumer, Agent, Merchant to know that their request has a time limit. | +| extensionList | 0..1 | ExtensionList |Optional extension, specific to deployment. | +#### 3.1.7.2 Callbacks +The following callbacks are supported for the **/thirdpartyRequests/transactions** resource +##### 3.1.7.2.1 **PUT /thirdpartyRequests/transactions/**_{ID}_ + +Used by: DFSP + +After a PISP requests the creation of a Third Party Transaction request (**POST /thirdpartyRequests/transactions**) +or the status of a previously created Third Party Transaction request +(**GET /thirdpartyRequests/transactions/**_{ID}_), the DFSP will send this callback. + +The data model for this endpoint is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| transactionRequestState | 1 | TransactionRequestState | State of the transaction request. | +| extensionList | 0..1 | ExtensionList | Optional extension, specific to deployment | + +##### 3.1.7.2.2 **PATCH /thirdpartyRequests/transactions/**_{ID}_ + +Used by: DFSP + +The issuing PISP will expect a response to their request for a transfer which describes +the finalised state of the requested transfer. This response will be given by a `PATCH` call on the +**/thirdpartyRequests/transactions/**_{ID}_ resource. The *{ID}* given in the query string should be +the `transactionRequestId` which was originally used by the PISP to identify the transaction +request (see [Section 3.1.8.1.2](#31812-post-thirdpartyrequestsverifications) above.) + +The data model for this endpoint is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| completedTimestamp | 0..1 | DateTime |Time and date when the transaction was completed, if it was completed. | +| transactionRequestState | 1 | TransactionRequestState | State of the transaction request | +| transactionState | 1 | TransactionState | State of the transaction created by the DFSP in response to this transaction request | +| extensionList | 0..1 | ExtensionList |Optional extension, specific to deployment | + +#### 3.1.7.3 Error callbacks +This section describes the error callbacks that are used by the server under the resource +**/thirdpartyRequests/transactions**. +##### 3.1.7.3.1 **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** + +Used by: DFSP + +The **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** resource will have the same content as +the **PUT /transactionRequests/**_{ID}_**/error** resource described in [Section 6.4.5.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#6451-put-transactionrequestsiderror) of Ref. 1 above. + +### 3.1.8 **/thirdpartyRequests/verifications** + +The **/thirdpartyRequests/verifications** resource is used by a Payer DFSP to verify that an authorization +response received from a PISP was signed using the correct private key, in cases where the authentication service +to be used is implemented by the switch and not internally by the DFSP. The DFSP sends the original +challenge and the signed response to the authentication service, together with the `consentId` to be used +for the verification. The authentication service compares the response with the result of signing the +challenge with the private key associated with the `consentId`, and, if the two match, it returns a +positive result. Otherwise, it returns an error. + +The **/thirdpartyRequests/verifications** resource supports the endpoints described below. +#### 3.1.8.1 Requests +This section describes the services that a client can request on the **/thirdpartyRequests/verifications** +resource. +##### 3.1.8.1.1 **GET /thirdpartyRequests/verifications/**_{ID}_ + +Used by: DFSP + +The HTTP request **/thirdpartyRequests/verifications/**_{ID}_ is used to get information regarding a previously +created or requested authorization. The *{ID}* in the URI should contain the verification request ID +(see [Section 3.1.8.1.2](#31812-post-thirdpartyrequestsverifications) below) that was used for the creation of the transfer.Callback and data model +information for **GET /thirdpartyRequests/verifications/**_{ID}_: + +- Callback – **PUT /thirdpartyRequests/verifications/**_{ID}_ +- Error Callback – **PUT /thirdpartyRequests/verifications/**_{ID}_**/error** +- Data Model – Empty body +##### 3.1.8.1.2 **POST /thirdpartyRequests/verifications** + +Used by: DFSP + +The **POST /thirdpartyRequests/verifications** resource is used to request confirmation from an authentication +service that a challenge has been signed using the correct private key. + +Callback and data model information for **POST /thirdpartyRequests/verifications**: +- Callback - **PUT /thirdpartyRequests/verifications/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/verifications /**_{ID}_**/error** +- Data Model – See Table below + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| verificationRequestId | 1 | CorrelationId |Common ID between the DFSP and authentication service for the verification request object. The ID should be reused for resends of the same authorization request. A new ID should be generated for each new authorization request. | +| challenge | 1 | BinaryString |The challenge originally sent to the PISP | +| consentId | 1 | CorrelationId |Common Id between the DFSP and the authentication service for the agreement against which the authentication service is to evaluate the signature | +| signedPayloadType | 1 | SignedPayloadType | The type of the SignedPayload, depending on the type of credential registered by the PISP | +| genericSignedPayload | 0..1 | BinaryString | Required if signedPayloadType is GENERIC. The signed challenge returned by the PISP. A BinaryString representing a signature of the challenge + private key of the credential. | +| fidoSignedPayload | 0..1 | FIDOPublicKeyCredentialAssertion | Required if signedPayloadType is FIDO. The signed challenge returned by the PISP in the form of a [`FIDOPublicKeyCredentialAssertion` Object](https://w3c.github.io/webauthn/#iface-pkcredential) | + +#### 3.1.8.2 Callbacks +This section describes the callbacks that are used by the server under the resource +**/thirdpartyRequests/verifications** +##### 3.1.8.2.1 **PUT /thirdpartyRequests/verifications/**_{ID}_ + +Used by: Auth Service + +The callback **PUT /thirdpartyRequests/verifications/**_{ID}_ is used to inform the client of the result +of an authorization check. The *{ID}* in the URI should contain the `authorizationRequestId` +(see [Section 3.1.8.1.2](#31812-post-thirdpartyrequestsverifications) above) which was used to request the check, or the *{ID}* that was +used in the **GET /thirdpartyRequests/verifications/**_{ID}_. The data model for this resource is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| authenticationResponse | 1 | AuthenticationResponse | The result of the authorization check. | +#### 3.1.8.3 Error callbacks +This section describes the error callbacks that are used by the server under the resource +**/thirdpartyRequests/verifications**. +##### 3.1.8.3.1 **PUT /thirdpartyRequests/verifications/**_{ID}_**/error** + +Used by: Auth Service + +If the server is unable to complete the authorization request, or another processing error occurs, the +error callback **PUT /thirdpartyRequests/verifications/**_{ID}_**/error** is used.The *{ID}* in the URI should +contain the `verificationRequestId` (see [Section 3.1.8.1.2](#31812-post-thirdpartyrequestsverifications) above) which was used to request the +check, or the *{ID}* that was used in the **GET /thirdpartyRequests/verifications/**_{ID}_. + +The data model for this resource is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + +## 3.2 Data Models + +The following additional data models will be required to support the Third Party API + +### 3.2.1 Element definitions +#### 3.2.1.1 Account + +The Account data model contains information relating to an account. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| address | 1 | AccountAddress | An address which can be used to identify the account | +| currency | 1 | Currency | The currency in which the account is denominated | +| accountNickname | 0..1 | Name | Display name of the account, as set by the account owning DFSP. This will normally be a type name, such as “Transaction Account” or “Savings Account” | +#### 3.2.1.2 AccountAddress + +The AccountAddress data type is a variable length string with a maximum size of 1023 characters and consists of: +- Alphanumeric characters, upper or lower case. (Addresses are case-sensitive so that they can contain data encoded in formats such as base64url.) +- Underscore (\_) +- Tilde (~) +- Hyphen (-) +- Period (.) Addresses MUST NOT end in a period (.) character + +An entity providing accounts to parties (i.e. a participant) can provide any value for an `AccountAddress` that is meaningful to that entity. +It does not need to provide an address that makes the account identifiable outside the entity’s domain. + +> ***IMPORTANT:* The policy for defining addresses and the life-cycle of these is at the discretion of the address space owner (the payer DFSP in this case).** +#### 3.2.1.3 AccountList +The AccountList data model is used to hold information about the accounts that a party controls. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| account | 1..256 | Account | Information relating to an account that a party controls. | + + +#### 3.2.1.5 AuthenticationResponse + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| AuthenticationResponse | 1 | Enum of String(1..32) | See [Section 3.2.2.1](#3221-AuthenticationResponse) below (AuthenticationResponse) for more information on allowed values.| +#### 3.2.1.6 BinaryString +The BinaryString type used in these definitions is as defined in [Section 7.2.17](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7217-binarystring) of Ref. 1 above. +#### 3.2.1.7 ConsentRequestChannelType +The ConsentRequestChannelType is used to hold an instance of the ConsentRequestChannelType enumeration. Its data model is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| ConsentRequestChannelType | 1 | Enum of String(1..32) | See [Section 3.2.2.4](#3223-consentrequestchanneltype) below ( ConsentRequestChannelType) for more information on allowed values. | + +#### 3.2.1.8 ConsentStatus +The ConsentStatus type stores the status of a consent request, as described in [Section 3.1.3.2.2](#31322-put-consentsid) above. Its data model is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| ConsentStatus | 1 | Enum of String(1..32) | See [Section 3.2.2.5](#3224-consentstatustype) below (ConsentStatusType) for more information on allowed values.| + +#### 3.2.1.9 CorrelationId +The CorrelationId type used in these definitions is as defined in [Section 7.3.8](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#738-correlationid) of Ref. 1 above. +##### 3.2.1.10 Credential +The Credential object is used to store information about a publicKey and signature that has been registered with a Consent. +This publicKey can be used to verify that transaction authorizations have been signed by the previously-registered privateKey, +which resides on a User's device. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| credentialType | 1 | CredentialType | The type of credential this is - `FIDO` or `GENERIC` | +| status | 1 | CredentialStatus | The current status of the credential. | +| genericPayload | 0..1 | GenericCredential | Required if credentialType is GENERIC. A description of the credential and information which allows the recipient of the credential to test its veracity. | +| fidoPayload | 0..1 | FIDOPublicKeyCredentialAttestation | Required if credentialType is FIDO. A description of the credential and information which allows the recipient of the credential to test its veracity. | + +##### 3.2.1.11 CredentialStatus +The CredentialStatus data type stores the state of a credential request. Its data model is as follows. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| CredentialStatus | 1 | Enum of String(1..32) |See [Section 3.2.2.6](#3225-CredentialStatus) below (CredentialStatus) for more information on allowed values. | + +##### 3.2.1.12 DateTime +The DateTime data type used in these definitions is as defined in [Section 7.2.14](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7214-datetime) of Ref. 1 above. +##### 3.2.1.13 ErrorInformation +The ErrorInformation data type used in these definitions is as defined in [Section 7.4.2](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#742-errorinformation) of Ref. 1 above + +Valid values for ErrorCode and ErrorDescription are defined in [Error Codes](#ErrorCodes) + +##### 3.2.1.14 ExtensionList +The ExtensionList data type used in these definitions is as defined in [Section 7.4.4](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#744-extensionlist) of Ref. 1 above. +##### 3.2.1.15 FspId +The FspId data type used in these definitions is as defined in [Section 7.3.16](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7316-fspid) of Ref. 1 above. + +##### 3.2.1.16 GenericCredential +The GenericCredential object stores the payload for a credential which is validated according to a comparison of the signature created from the challenge using a private key against the same challenge signed using a public key. Its content is as follows. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| publicKey | 1 | BinaryString | The public key to be used in checking the signature. | +| signature | 1 | BinaryString | The signature to be checked against the public key. | + +##### 3.2.1.17 Money +The Money type used in these definitions is a defined in [Section 7.4.10](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7410-money) of Ref. 1 above. +##### 3.2.1.18 Note +The Note data type used in these definitions is as defined in [Section 7.3.23](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7323-note) of Ref. 1 above. +##### 3.2.1.19 Party + +The Note data type used in these definitions is as defined in [Section 7.4.11](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7411-party) of Ref. 1 above. + +##### 3.2.1.20 PartyIdInfo +The PartyIdInfo data type used in these definitions is as defined in [Section 7.4.13](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7413-partyidinfo) of Ref. 1 above. + + +##### 3.2.1.21 Scope +The Scope element contains an identifier defining, in the terms of a DFSP, an account on which access types can be requested or granted. It also defines the access types which are requested or granted. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| address | 1 |AccountAddress | The address of the account to which the PISP wishes to be permitted access, or is being granted access | +| actions | 1..32 |ScopeAction | The action that the PISP wants permission to take in relation to the customer’s account, or that it has been granted in relation to the customer’s account| +##### 3.2.1.22 ScopeAction +The ScopeAction element contains an access type which a PISP can request from a DFSP, or which a DFSP can grant to a PISP. It must be a member of the appropriate enumeration. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| scopeAction | 1 | Enum of String(1..32)| See [Section 3.2.2.9](#3228-scopeenumeration) below (ScopeEnumeration) for more information on allowed values. | +##### 3.2.1.23 ServiceType +The ServiceType element contains a type of service where the requester wants a list of the participants in the scheme which provide that service. It must be a member of the appropriate enumeration. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| serviceType | 1 | Enum of String(1..32) | See [Section 3.2.2.10](#3229-servicetype) below (ServiceType) for more information on allowed values. | + +##### 3.2.1.24 TransactionType +The TransactionType type used in these definitions is as defined in [Section 7.4.18](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7418-transactiontype) of Ref. 1 above. +##### 3.2.1.25 TransactionState +The TransactionState type used in these definitions is as defined in [Section 7.3.33](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7333-transactionstate) of Ref. 1 above. +##### 3.2.1.26 Uri +The API data type Uri is a JSON string in a canonical format that is restricted by a regular expression for interoperability reasons. The regular expression for restricting the Uri type is as follows: +`^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? ` +##### 3.2.1.27 FIDOPublicKeyCredentialAttestation + +A data model representing a FIDO Attestation result. Derived from [`PublicKeyCredential` Interface](https://w3c.github.io/webauthn/#iface-pkcredential). + +The `PublicKeyCredential` interface represents the below fields with a Type of Javascript [ArrayBuffer](https://heycam.github.io/webidl/#idl-ArrayBuffer). +For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| id | 1 | String(59..118) | The identifier of a keypair created by an authenticator | +| rawId | 0..1 | String(59..118) | The identifier of a keypair created by an authenticator, base64 encoded | +| response | 1 | AuthenticatorAttestationResponse | The attestation response from the authenticator | + +##### 3.2.1.28 FIDOPublicKeyCredentialAssertion + +A data model representing a FIDO Assertion result. Derived from [`PublicKeyCredential` Interface](https://w3c.github.io/webauthn/#iface-pkcredential) in [WebAuthN](https://w3c.github.io/webauthn/). + +The `PublicKeyCredential` interface represents the below fields with a Type of Javascript [ArrayBuffer](https://heycam.github.io/webidl/#idl-ArrayBuffer). +For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| id | 1 | String(59..118) | The identifier of a keypair created by an authenticator | +| rawId | 0..1 | String(59..118) | The identifier of a keypair created by an authenticator, base64 encoded | +| response | 1 | AuthenticatorAssertionResponse | The assertion response from the authenticator | + +##### 3.2.1.29 AuthenticatorAttestationResponse + +A data model representing an [AttestationStatement](https://w3c.github.io/webauthn/#attestation-statement) from [WebAuthN](https://w3c.github.io/webauthn/). + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| clientDataJSON | 1 | String(121...512) | JSON string with client data | +| attestationObject | 1 | String(306...2048) | Object encoded in Concise Binary Object Representation(CBOR), as defined in [RFC-8949](https://www.rfc-editor.org/rfc/rfc8949)| + +##### 3.2.1.30 AuthenticatorAssertionResponse + +A data model representing an [AuthenticatorAssertionResponse](https://w3c.github.io/webauthn/#authenticatorassertionresponse). + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| authenticatorData | 1 | String(29..256) | Information about the authenticator. | +| clientDataJSON | 1 | String(121..512) | base64 encoded JSON string containing information about the client. | +| signature | 1 | String(59..256) | The signature generated by the private key associated with this credential. | +| userHandle | 0..1 | String(1..88) | This field is optionally provided by the authenticator, and represents the user.id that was supplied during registration, as defined in [WebAuthN's user.id](https://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-id).| + +##### 3.2.1.31 SignedPayload + +A data model representing a Third Party Transaction request signature. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| signedPayloadType | 1 | SignedPayloadType | `FIDO` or `GENERIC` | +| genericSignedPayload | 0..1 | BinaryString(256) | Required if signedPayloadType is of type `GENERIC`. A BinaryString(256) of a signature of a sha-256 hash of the challenge. | +| fidoSignedPayload | 0..1 | FIDOPublicKeyCredentialAssertion | Required if signedPayloadType is of type `FIDO`. | + +### 3.2.2 Enumerations +#### 3.2.2.1 AuthenticationResponse +The AuthenticationResponse enumeration describes the result of authenticating verification request. +| Name | Description | +| --- | ----------- | +| VERIFIED | The challenge was correctly signed. | +| REJECTED | The challenge was not correctly signed. | +#### 3.2.2.2 AuthorizationResponseType +The AuthorizationResponseType enumeration is the same as the AuthorizationResponse enumeration described in [Section 7.5.3](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#753-authorizationresponse) of Ref. 1 above. +#### 3.2.2.3 ConsentRequestChannelType + +| Name | Description | +| --- | ----------- | +| WEB | DFSP can support authorization via a web-based login | +| OTP | DFSP can support authorization via a One Time PIN | + +#### 3.2.2.4 ConsentStatusType +The ConsentStatusType enumeration describes the allowed status values that a consent item can have. These are as follows: +| Name | Description | +| --- | ----------- | +| ISSUED | The consent has been issued by the DFSP. | +| REVOKED | The consent has been revoked. | + +#### 3.2.2.5 CredentialStatus +This contains the allowed values for the CredentialStatus +| Name | Description | +| --- | ----------- | +| PENDING | The credential has been created but not yet verified. | +| VERIFIED | Authentication service has verified the credential. | + +#### 3.2.2.6 CredentialType +The CredentialType enumeration contains the allowed values for the type of credential which is associated with a permission. +| Name | Description | +| --- | ----------- | +| FIDO | The credential is based on a FIDO challenge. Its payload is a FIDOPublicKeyCredentialAttestation object. | +| GENERIC | The credential is based on a simple public key validation. Its payload is a GenericCredential object | + +#### 3.2.2.7 PartyIdType +The PartyIdType enumeration is extended for PISPs to include a definition for the identifier which represents a link between a specific PISP and an account at a DFSP which a customer has given the PISP permission to access. + +| Name | Description | +| --- | ----------- | +| MSISDN | An MSISDN (Mobile Station International Subscriber Directory Number; that is, a phone number) is used in reference to a Party. The MSISDN identifier should be in international format according to the ITU-T E.16437 standard. Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix.| +| EMAIL | An email is used in reference to a Party. The format of the email should be according to the informational RFC 369638.| +| PERSONAL_ID | A personal identifier is used in reference to a participant. Examples of personal identification are passport number, birth certificate number, and national registration number. The identifier number is added in the PartyIdentifier element. The personal identifier type is added in the PartySubIdOrType element.| +| BUSINESS | A specific Business (for example, an organization or a company) is used in reference to a participant. The BUSINESS identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the PartySubIdOrType element should be used.| +| DEVICE | A specific device (for example, POS or ATM) ID connected to a specific business or organization is used in reference to a Party. For referencing a specific device under a specific business or organization, use the PartySubIdOrType element.| +| ACCOUNT_ID | A bank account number or FSP account ID should be used in reference to a participant. The ACCOUNT_ID identifier can be in any format, as formats can greatly differ depending on country and FSP.| +| IBAN | A bank account number or FSP account ID is used in reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without whitespace.| +| ALIAS | An alias is used in reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias is a username in the FSP system. The ALIAS identifier can be in any format. It is also possible to use the PartySubIdOrType element for identifying an account under an Alias defined by the PartyIdentifier.| +| THIRD_PARTY_LINK | A third-party link which represents an agreement between a specific PISP and a customer’s account at a DFSP. The content of the link is created by the DFSP at the time when it gives permission to the PISP for specific access to a given account.| + +#### 3.2.2.8 ScopeEnumeration + +| Name | Description | +| --- | ----------- | +| ACCOUNTS_GET_BALANCE | PISP can request a balance for the linked account | +| ACCOUNTS_TRANSFER | PISP can request a transfer of funds from the linked account in the DFSP | +| ACCOUNTS_STATEMENT | PISP can request a statement of individual transactions on a user’s account | + +#### 3.2.2.9 ServiceType +The ServiceType enumeration describes the types of role for which a DFSP may query using the /services resource. +| Name | Description | +| --- | ----------- | +| THIRD_PARTY_DFSP| DFSPs which will support linking with PISPs | +| PISP | PISPs | +| AUTH_SERVICE | Participants which provide Authentication Services | + +##### 3.2.2.10 SignedPayloadType +The SignedPayloadType enumeration contains the allowed values for the type of a signed payload +| Name | Description | +| --- | ----------- | +| FIDO | The signed payload is based on a FIDO Assertion Response. Its payload is a FIDOPublicKeyCredentialAssertion object. | +| GENERIC | The signed payload is based on a simple public key validation. Its payload is a BinaryString object | + +##### 3.2.2.11 AmountType +See [7.3.1 AmountType](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#731-amounttype) + +##### 3.2.2.12 TransactionRequestState +See [7.5.10 TransactionRequestState](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7510-transactionrequeststate) + + +## 3.3 Error Codes + +The Third Party API Error Codes are defined in [Section 7.6](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#76-error-codes) of ref 1 above. + +In addition, the Third Party API adds the following error codes, starting with the prefix `6`: + +- General Third Party Error -- **60**_xx_ + +| **Error Code** | **Name** | **Description** | /accounts | /consentRequests | /consents | /parties | /services | /thirdpartyRequests/authorizations | thirdpartyRequests/transactions | thirdpartyRequests/verifications | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **6000** | Third party error | Generic error. | X | X | X | X | X | X | X | X | +| **6001** | Third party request error | Third party request failed. | X | X | X | X | X | X | X | X | +| **6003** | Downstream Failure | The downstream request failed. | X | X | X | X | X | X | X | X | + +- Permission Error -- **61**_xx_ + +| **Error Code** | **Name** | **Description** | /accounts | /consentRequests | /consents | /parties | /services | /thirdpartyRequests/authorizations | thirdpartyRequests/transactions | thirdpartyRequests/verifications | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **6100** | Authentication rejection | Generic authentication rejection | | X | | | | X | | | +| **6101** | Unsupported scopes were requested | PISP requested scopes that the DFSP doesn’t allow/support | | X | X | | | | | | +| **6102** | Consent not granted | User did not grant consent to the PISP | | X | X | | | | | | +| **6103** | Consent not valid | Consent object is not valid or has been revoked | | X | X | | | X | X | X | +| **6104** | Third Party request rejection | The request was rejected | X | X | X | X | X | X | X | X | + +- Validation Error -- **62**_xx_ + +| **Error Code** | **Name** | **Description** | /accounts | /consentRequests | /consents | /parties | /services | /thirdpartyRequests/authorizations | thirdpartyRequests/transactions | thirdpartyRequests/verifications | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **6200** | Invalid Consent Credential | The signature of the credential submitted by the PISP is invalid | | | X | | | | | | +| **6201** | Invalid transaction signature | The signature of the verification response doesn't match the credential | | | | | | X | | X | +| **6203** | Invalid authentication token | DFSP receives invalid authentication token from PISP. | | X | | | | | | | +| **6204** | Bad callbackUri | The callbackUri is deemed invalid or untrustworthy. | | X | | | | | | | +| **6205** | No accounts found | No accounts were found for the given identifier | X | | | | | | | | + diff --git a/docs/technical/api/thirdparty/thirdparty-dfsp-v1.0.yaml b/docs/technical/api/thirdparty/thirdparty-dfsp-v1.0.yaml new file mode 100644 index 000000000..327d244dd --- /dev/null +++ b/docs/technical/api/thirdparty/thirdparty-dfsp-v1.0.yaml @@ -0,0 +1,2625 @@ +openapi: 3.0.2 +info: + title: Mojaloop Third Party API (DFSP) + version: '1.0' + description: | + A Mojaloop API for DFSPs supporting Third Party functions. + DFSPs who want to enable Payment Initiation Service Providers (PISPs) to perform actions on behalf of a DFSP's user should implement this API. + PISPs should implement the accompanying API - Mojaloop Third Party API (PISP) instead. + license: + name: Open API for FSP Interoperability (FSPIOP) (Implementation Friendly Version) + url: 'https://github.com/mojaloop/mojaloop-specification/blob/master/LICENSE.md' +servers: + - url: / +paths: + '/accounts/{ID}': + parameters: + - name: ID + in: path + required: true + schema: + type: string + description: The identifier value. + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + operationId: GetAccountsByUserId + summary: GetAccountsByUserId + description: | + The HTTP request `GET /accounts/{ID}` is used to retrieve the list of potential accounts available for linking. + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + description: | + The HTTP request `PUT /accounts/{ID}` is used to return the list of potential accounts available for linking + operationId: UpdateAccountsByUserId + summary: UpdateAccountsByUserId + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + title: AccountsIDPutResponse + type: object + description: 'The object sent in a `PUT /accounts/{ID}` request.' + properties: + accountList: + description: Information about the accounts that the DFSP associates with the identifier sent by the PISP + type: array + items: + title: Account + type: object + description: Data model for the complex type Account. + properties: + accountNickname: + title: Name + type: string + pattern: '^(?!\s*$)[\w .,''-]{1,128}$' + description: |- + The API data type Name is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. + + Regular Expression - The regular expression for restricting the Name type is "^(?!\s*$)[\w .,'-]{1,128}$". The restriction does not allow a string consisting of whitespace only, all Unicode characters are allowed, as well as the period (.) (apostrophe (‘), dash (-), comma (,) and space characters ( ). + + **Note:** In some programming languages, Unicode support must be specifically enabled. For example, if Java is used, the flag UNICODE_CHARACTER_CLASS must be enabled to allow Unicode characters. + address: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items/properties/address' + currency: + title: Currency + description: 'The currency codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic codes are used as the standard naming representation for currencies.' + type: string + minLength: 3 + maxLength: 3 + enum: + - AED + - AFN + - ALL + - AMD + - ANG + - AOA + - ARS + - AUD + - AWG + - AZN + - BAM + - BBD + - BDT + - BGN + - BHD + - BIF + - BMD + - BND + - BOB + - BRL + - BSD + - BTN + - BWP + - BYN + - BZD + - CAD + - CDF + - CHF + - CLP + - CNY + - COP + - CRC + - CUC + - CUP + - CVE + - CZK + - DJF + - DKK + - DOP + - DZD + - EGP + - ERN + - ETB + - EUR + - FJD + - FKP + - GBP + - GEL + - GGP + - GHS + - GIP + - GMD + - GNF + - GTQ + - GYD + - HKD + - HNL + - HRK + - HTG + - HUF + - IDR + - ILS + - IMP + - INR + - IQD + - IRR + - ISK + - JEP + - JMD + - JOD + - JPY + - KES + - KGS + - KHR + - KMF + - KPW + - KRW + - KWD + - KYD + - KZT + - LAK + - LBP + - LKR + - LRD + - LSL + - LYD + - MAD + - MDL + - MGA + - MKD + - MMK + - MNT + - MOP + - MRO + - MUR + - MVR + - MWK + - MXN + - MYR + - MZN + - NAD + - NGN + - NIO + - NOK + - NPR + - NZD + - OMR + - PAB + - PEN + - PGK + - PHP + - PKR + - PLN + - PYG + - QAR + - RON + - RSD + - RUB + - RWF + - SAR + - SBD + - SCR + - SDG + - SEK + - SGD + - SHP + - SLL + - SOS + - SPL + - SRD + - STD + - SVC + - SYP + - SZL + - THB + - TJS + - TMT + - TND + - TOP + - TRY + - TTD + - TVD + - TWD + - TZS + - UAH + - UGX + - USD + - UYU + - UZS + - VEF + - VND + - VUV + - WST + - XAF + - XCD + - XDR + - XOF + - XPF + - XTS + - XXX + - YER + - ZAR + - ZMW + - ZWD + required: + - accountNickname + - id + - currency + required: + - accounts + example: + - accountNickname: dfspa.user.nickname1 + id: dfspa.username.1234 + currency: ZAR + - accountNickname: dfspa.user.nickname2 + id: dfspa.username.5678 + currency: USD + responses: + '200': + description: OK + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/accounts/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + description: | + The HTTP request `PUT /accounts/{ID}/error` is used to return error information + operationId: UpdateAccountsByUserIdError + summary: UpdateAccountsByUserIdError + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + title: ErrorInformationObject + type: object + description: Data model for the complex type object that contains ErrorInformation. + properties: + errorInformation: + title: ErrorInformation + type: object + description: Data model for the complex type ErrorInformation. + properties: + errorCode: + title: ErrorCode + type: string + pattern: '^[1-9]\d{3}$' + description: 'The API data type ErrorCode is a JSON String of four characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. Each error code in the API is a four-digit number, for example, 1234, where the first number (1 in the example) represents the high-level error category, the second number (2 in the example) represents the low-level error category, and the last two numbers (34 in the example) represent the specific error.' + example: '5100' + errorDescription: + title: ErrorDescription + type: string + minLength: 1 + maxLength: 128 + description: Error description string. + extensionList: + $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - errorCode + - errorDescription + required: + - errorInformation + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /consentRequests: + parameters: + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + post: + tags: + - consentRequests + - sampled + operationId: CreateConsentRequest + summary: CreateConsentRequest + description: | + The HTTP request **POST /consentRequests** is used to request a DFSP to grant access to one or more + accounts owned by a customer of the DFSP for the PISP who sends the request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: The consentRequest to create + required: true + content: + application/json: + schema: + title: ConsentRequestsPostRequest + type: object + description: The object sent in a `POST /consentRequests` request. + properties: + consentRequestId: + title: CorrelationId + type: string + pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' + description: 'Identifier that correlates all messages of the same sequence. The API data type UUID (Universally Unique Identifier) is a JSON String in canonical format, conforming to [RFC 4122](https://tools.ietf.org/html/rfc4122), that is restricted by a regular expression for interoperability reasons. A UUID is always 36 characters long, 32 hexadecimal symbols and 4 dashes (‘-‘).' + example: b51ec534-ee48-4575-b6a9-ead2955b8069 + userId: + type: string + description: 'The identifier used in the **GET /accounts/**_{ID}_. Used by the DFSP to correlate an account lookup to a `consentRequest`' + minLength: 1 + maxLength: 128 + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + title: Scope + type: object + description: Scope + Account Identifier mapping for a Consent. + properties: + address: + title: AccountAddress + type: string + description: | + An address which can be used to identify the account. + pattern: '^([0-9A-Za-z_~\-\.]+[0-9A-Za-z_~\-])$' + minLength: 1 + maxLength: 1023 + actions: + type: array + minItems: 1 + maxItems: 32 + items: + title: ScopeAction + type: string + enum: + - ACCOUNTS_GET_BALANCE + - ACCOUNTS_TRANSFER + - ACCOUNTS_STATEMENT + description: | + The permissions allowed on a given account by a DFSP as defined in + a consent object + - ACCOUNTS_GET_BALANCE: PISP can request a balance for the linked account + - ACCOUNTS_TRANSFER: PISP can request a transfer of funds from the linked account in the DFSP + - ACCOUNTS_STATEMENT: PISP can request a statement of individual transactions on a user’s account + required: + - address + - actions + authChannels: + type: array + minLength: 1 + maxLength: 256 + items: + title: ConsentRequestChannelType + type: string + enum: + - WEB + - OTP + description: | + The auth channel being used for the consentRequest. + - "WEB" - The Web auth channel. + - "OTP" - The OTP auth channel. + callbackUri: + title: Uri + type: string + pattern: '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' + minLength: 1 + maxLength: 512 + description: | + The API data type Uri is a JSON string in a canonical format that is restricted by a regular expression for interoperability reasons. + required: + - consentRequestId + - userId + - scopes + - authChannels + - callbackUri + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/consentRequests/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + operationId: GetConsentRequestsById + summary: GetConsentRequestsById + description: | + The HTTP request `GET /consentRequests/{ID}` is used to get information about a previously + requested consent. The *{ID}* in the URI should contain the consentRequestId that was assigned to the + request by the PISP when the PISP originated the request. + tags: + - consentRequests + - sampled + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + tags: + - consentRequests + - sampled + operationId: UpdateConsentRequest + summary: UpdateConsentRequest + description: | + A DFSP uses this callback to (1) inform the PISP that the consentRequest has been accepted, + and (2) communicate to the PISP which `authChannel` it should use to authenticate their user + with. + + When a PISP requests a series of permissions from a DFSP on behalf of a DFSP’s customer, not all + the permissions requested may be granted by the DFSP. Conversely, the out-of-band authorization + process may result in additional privileges being granted by the account holder to the PISP. The + **PUT /consentRequests/**_{ID}_ resource returns the current state of the permissions relating to a + particular authorization request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentRequestsIDPutResponseWeb + type: object + description: | + The object sent in a `PUT /consentRequests/{ID}` request. + + Schema used in the request consent phase of the account linking web flow, + the result is the PISP being instructed on a specific URL where this + supposed user should be redirected. This URL should be a place where + the user can prove their identity (e.g., by logging in). + properties: + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + authChannels: + type: array + minLength: 1 + maxLength: 1 + items: + title: ConsentRequestChannelTypeWeb + type: string + enum: + - WEB + description: | + The web auth channel being used for PUT consentRequest/{ID} request. + callbackUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + authUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + required: + - scopes + - authChannels + - callbackUri + - authUri + additionalProperties: false + - title: ConsentRequestsIDPutResponseOTP + type: object + description: | + The object sent in a `PUT /consentRequests/{ID}` request. + + Schema used in the request consent phase of the account linking OTP/SMS flow. + properties: + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + authChannels: + type: array + minLength: 1 + maxLength: 1 + items: + title: ConsentRequestChannelTypeOTP + type: string + enum: + - OTP + description: | + The OTP auth channel being used for PUT consentRequest/{ID} request. + callbackUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + required: + - scopes + - authChannels + additionalProperties: false + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + patch: + tags: + - consentRequests + - sampled + operationId: PatchConsentRequest + summary: PatchConsentRequest + description: | + After the user completes an out-of-band authorization with the DFSP, the PISP will receive a token which they can use to prove to the DFSP that the user trusts this PISP. + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + title: ConsentRequestsIDPatchRequest + type: object + description: 'The object sent in a `PATCH /consentRequests/{ID}` request.' + properties: + authToken: + type: string + pattern: '^[A-Za-z0-9-_]+[=]{0,2}$' + description: 'The API data type BinaryString is a JSON String. The string is a base64url encoding of a string of raw bytes, where padding (character ‘=’) is added at the end of the data if needed to ensure that the string is a multiple of 4 characters. The length restriction indicates the allowed number of characters.' + required: + - authToken + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/consentRequests/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - consentRequests + operationId: NotifyErrorConsentRequests + summary: NotifyErrorConsentRequests + description: | + DFSP responds to the PISP if something went wrong with validating an OTP or secret. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /consents: + parameters: + - name: Content-Type + in: header + schema: + type: string + required: true + description: The `Content-Type` header indicates the specific version of the API used to send the payload body. + - name: Date + in: header + schema: + type: string + required: true + description: The `Date` header field indicates the date when the request was sent. + - name: X-Forwarded-For + in: header + schema: + type: string + required: false + description: |- + The `X-Forwarded-For` header field is an unofficially accepted standard used for informational purposes of the originating client IP address, as a request might pass multiple proxies, firewalls, and so on. Multiple `X-Forwarded-For` values should be expected and supported by implementers of the API. + + **Note:** An alternative to `X-Forwarded-For` is defined in [RFC 7239](https://tools.ietf.org/html/rfc7239). However, to this point RFC 7239 is less-used and supported than `X-Forwarded-For`. + - name: FSPIOP-Source + in: header + schema: + type: string + required: true + description: The `FSPIOP-Source` header field is a non-HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing and signature verification (see header field `FSPIOP-Signature`). + - name: FSPIOP-Destination + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-Destination` header field is a non-HTTP standard field used by the API for HTTP header based routing of requests and responses to the destination. The field must be set by the original sender of the request if the destination is known (valid for all services except GET /parties) so that any entities between the client and the server do not need to parse the payload for routing purposes. If the destination is not known (valid for service GET /parties), the field should be left empty.' + - name: FSPIOP-Encryption + in: header + schema: + type: string + required: false + description: The `FSPIOP-Encryption` header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request. + - name: FSPIOP-Signature + in: header + schema: + type: string + required: false + description: The `FSPIOP-Signature` header field is a non-HTTP standard field used by the API for applying an end-to-end request signature. + - name: FSPIOP-URI + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-URI` header field is a non-HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information, see [the API Signature document](https://github.com/mojaloop/docs/tree/master/Specification%20Document%20Set).' + - name: FSPIOP-HTTP-Method + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-HTTP-Method` header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information, see [the API Signature document](https://github.com/mojaloop/docs/tree/master/Specification%20Document%20Set).' + post: + tags: + - consents + - sampled + operationId: PostConsents + summary: PostConsents + description: | + The **POST /consents** request is used to request the creation of a consent for interactions between a PISP and the DFSP who owns the account which a PISP’s customer wants to allow the PISP access to. + parameters: + - name: Accept + in: header + required: true + schema: + type: string + description: The `Accept` header field indicates the version of the API the client would like the server to use. + - name: Content-Length + in: header + required: false + schema: + type: integer + description: |- + The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body. + + **Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes). + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentPostRequestAUTH + type: object + description: | + The object sent in a `POST /consents` request to the Auth-Service + by a DFSP to store registered Consent and credential + properties: + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and FSP for the Consent object + determined by the DFSP who creates the Consent. + scopes: + minLength: 1 + maxLength: 256 + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + credential: + allOf: + - $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential' + status: + title: ConsentStatus + type: string + enum: + - ISSUED + - REVOKED + description: |- + Allowed values for the enumeration ConsentStatus + - ISSUED - The consent has been issued by the DFSP + - REVOKED - The consent has been revoked + required: + - consentId + - scopes + - credential + - status + additionalProperties: false + - title: ConsentPostRequestPISP + type: object + description: | + The provisional Consent object sent by the DFSP in `POST /consents`. + properties: + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and the Payer DFSP for the consent object. The ID + should be reused for resends of the same consent. A new ID should be generated + for each new consent. + consentRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + The ID given to the original consent request on which this consent is based. + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + $ref: '#/paths/~1consents/post/requestBody/content/application~1json/schema/oneOf/0/properties/status' + required: + - consentId + - consentRequestId + - scopes + - status + responses: + '202': + description: Accepted + '400': + description: Bad Request + content: + application/json: + schema: + title: ErrorInformationResponse + type: object + description: Data model for the complex type object that contains an optional element ErrorInformation used along with 4xx and 5xx responses. + properties: + errorInformation: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema/properties/errorInformation' + headers: + Content-Length: + required: false + schema: + type: integer + description: |- + The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body. + + **Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes). + Content-Type: + schema: + type: string + required: true + description: The `Content-Type` header indicates the specific version of the API used to send the payload body. + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '405': + description: Method Not Allowed + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '406': + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '501': + description: Not Implemented + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '503': + description: Service Unavailable + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '/consents/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + description: | + The **GET /consents/**_{ID}_ resource allows a party to enquire after the status of a consent. The *{ID}* used in the URI of the request should be the consent request ID which was used to identify the consent when it was created. + tags: + - consents + operationId: GetConsent + summary: GetConsent + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + patch: + description: | + The HTTP request `PATCH /consents/{ID}` is used + + - In account linking in the Credential Registration phase. Used by a DFSP + to notify a PISP a credential has been verified and registered with an + Auth service. + + - In account unlinking by a hub hosted auth service and by DFSPs + in non-hub hosted scenarios to notify participants of a consent being revoked. + + Called by a `auth-service` to notify a PISP and DFSP of consent status in hub hosted scenario. + Called by a `DFSP` to notify a PISP of consent status in non-hub hosted scenario. + tags: + - consents + - sampled + operationId: PatchConsentByID + summary: PatchConsentByID + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentsIDPatchResponseVerified + description: | + PATCH /consents/{ID} request object. + + Sent by the DFSP to the PISP when a consent is verified. + Used in the "Register Credential" part of the Account linking flow. + type: object + properties: + credential: + type: object + properties: + status: + title: CredentialStatus + type: string + enum: + - VERIFIED + description: | + The status of the Credential. + - "VERIFIED" - The Credential is valid and verified. + required: + - status + required: + - credential + - title: ConsentsIDPatchResponseRevoked + description: | + PATCH /consents/{ID} request object. + + Sent to both the PISP and DFSP when a consent is revoked. + Used in the "Unlinking" part of the Account Unlinking flow. + type: object + properties: + status: + title: ConsentStatus + type: string + enum: + - REVOKED + description: |- + Allowed values for the enumeration ConsentStatus + - REVOKED - The consent has been revoked + revokedAt: + $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/completedTimestamp' + required: + - status + - revokedAt + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + description: | + The HTTP request `PUT /consents/{ID}` is used by the PISP and Auth Service. + + - Called by a `PISP` to after signing a challenge. Sent to an DFSP for verification. + - Called by a `auth-service` to notify a DFSP that a credential has been verified and registered. + tags: + - consents + - sampled + operationId: PutConsentByID + summary: PutConsentByID + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentsIDPutResponseSigned + type: object + description: | + The HTTP request `PUT /consents/{ID}` is used by the PISP to update a Consent with a signed challenge and register a credential. + Called by a `PISP` to after signing a challenge. Sent to a DFSP for verification. + properties: + scopes: + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + title: ConsentStatus + type: string + enum: + - ISSUED + description: |- + Allowed values for the enumeration ConsentStatus + - ISSUED - The consent has been issued by the DFSP + credential: + title: SignedCredential + type: object + description: | + A credential used to allow a user to prove their identity and access + to an account with a DFSP. + + SignedCredential is a special formatting of the credential to allow us to be + more explicit about the `status` field - it should only ever be PENDING when + updating a credential. + properties: + credentialType: + title: CredentialType + type: string + enum: + - FIDO + - GENERIC + description: | + The type of the Credential. + - "FIDO" - A FIDO public/private keypair + - "GENERIC" - A Generic public/private keypair + status: + title: CredentialStatus + type: string + enum: + - PENDING + description: | + The status of the Credential. + - "PENDING" - The credential has been created, but has not been verified + genericPayload: + title: GenericCredential + type: object + description: | + A publicKey + signature of a challenge for a generic public/private keypair + properties: + publicKey: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + signature: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - publicKey + - signature + additionalProperties: false + fidoPayload: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/1/properties/credential/properties/payload' + required: + - credentialType + - status + additionalProperties: false + required: + - scopes + - credential + additionalProperties: false + - title: ConsentsIDPutResponseVerified + type: object + description: | + The HTTP request `PUT /consents/{ID}` is used by the DFSP or Auth-Service to update a Consent object once it has been Verified. + Called by a `auth-service` to notify a DFSP that a credential has been verified and registered. + properties: + scopes: + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/status' + credential: + title: VerifiedCredential + type: object + description: | + A credential used to allow a user to prove their identity and access + to an account with a DFSP. + + VerifiedCredential is a special formatting of the credential to allow us to be + more explicit about the `status` field - it should only ever be VERIFIED when + updating a credential. + properties: + credentialType: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential/properties/credentialType' + status: + type: string + enum: + - VERIFIED + description: 'The Credential is valid, and ready to be used by the PISP.' + payload: + title: FIDOPublicKeyCredentialAttestation + type: object + description: | + A data model representing a FIDO Attestation result. Derived from + [`PublicKeyCredential` Interface](https://w3c.github.io/webauthn/#iface-pkcredential). + + The `PublicKeyCredential` interface represents the below fields with + a Type of Javascript [ArrayBuffer](https://heycam.github.io/webidl/#idl-ArrayBuffer). + For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + properties: + id: + type: string + description: | + credential id: identifier of pair of keys, base64 encoded + https://w3c.github.io/webauthn/#ref-for-dom-credential-id + minLength: 59 + maxLength: 118 + rawId: + type: string + description: | + raw credential id: identifier of pair of keys, base64 encoded + minLength: 59 + maxLength: 118 + response: + type: object + description: | + AuthenticatorAttestationResponse + properties: + clientDataJSON: + type: string + description: | + JSON string with client data + minLength: 121 + maxLength: 512 + attestationObject: + type: string + description: | + CBOR.encoded attestation object + minLength: 306 + maxLength: 2048 + required: + - clientDataJSON + - attestationObject + additionalProperties: false + type: + type: string + description: 'response type, we need only the type of public-key' + enum: + - public-key + required: + - id + - response + - type + additionalProperties: false + required: + - credentialType + - status + - payload + additionalProperties: false + required: + - scopes + - credential + additionalProperties: false + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + delete: + description: | + Used by PISP, DFSP + + The **DELETE /consents/**_{ID}_ request is used to request the revocation of a previously agreed consent. + For tracing and auditing purposes, the switch should be sure not to delete the consent physically; + instead, information relating to the consent should be marked as deleted and requests relating to the + consent should not be honoured. + operationId: DeleteConsentByID + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + tags: + - consents + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/consents/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - consents + operationId: NotifyErrorConsents + summary: NotifyErrorConsents + description: | + DFSP responds to the PISP if something went wrong with validating or storing consent. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /thirdpartyRequests/authorizations: + parameters: + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + post: + description: | + The HTTP request **POST /thirdpartyRequests/authorizations** is used to request the validation by a customer for the transfer described in the request. + operationId: PostThirdpartyRequestsAuthorizations + summary: PostThirdpartyRequestsAuthorizations + tags: + - authorizations + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Authorization request details + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsAuthorizationsPostRequest + description: POST /thirdpartyRequests/authorizations request object. + type: object + properties: + authorizationRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + transactionRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + challenge: + type: string + description: The challenge that the PISP's client is to sign + transferAmount: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount that will be debited from the sending customer’s account as a consequence of the transaction. + payeeReceiveAmount: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount that will be credited to the receiving customer’s account as a consequence of the transaction. + fees: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount of fees that the paying customer will be charged as part of the transaction. + payer: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0' + description: 'Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction.' + payee: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payee/allOf/0' + description: Information about the Payee in the proposed financial transaction. + transactionType: + title: TransactionType + type: object + description: Data model for the complex type TransactionType. + properties: + scenario: + title: TransactionScenario + type: string + enum: + - DEPOSIT + - WITHDRAWAL + - TRANSFER + - PAYMENT + - REFUND + description: |- + Below are the allowed values for the enumeration. + - DEPOSIT - Used for performing a Cash-In (deposit) transaction. In a normal scenario, electronic funds are transferred from a Business account to a Consumer account, and physical cash is given from the Consumer to the Business User. + - WITHDRAWAL - Used for performing a Cash-Out (withdrawal) transaction. In a normal scenario, electronic funds are transferred from a Consumer’s account to a Business account, and physical cash is given from the Business User to the Consumer. + - TRANSFER - Used for performing a P2P (Peer to Peer, or Consumer to Consumer) transaction. + - PAYMENT - Usually used for performing a transaction from a Consumer to a Merchant or Organization, but could also be for a B2B (Business to Business) payment. The transaction could be online for a purchase in an Internet store, in a physical store where both the Consumer and Business User are present, a bill payment, a donation, and so on. + - REFUND - Used for performing a refund of transaction. + example: DEPOSIT + subScenario: + title: TransactionSubScenario + type: string + pattern: '^[A-Z_]{1,32}$' + description: 'Possible sub-scenario, defined locally within the scheme (UndefinedEnum Type).' + example: LOCALLY_DEFINED_SUBSCENARIO + initiator: + title: TransactionInitiator + type: string + enum: + - PAYER + - PAYEE + description: |- + Below are the allowed values for the enumeration. + - PAYER - Sender of funds is initiating the transaction. The account to send from is either owned by the Payer or is connected to the Payer in some way. + - PAYEE - Recipient of the funds is initiating the transaction by sending a transaction request. The Payer must approve the transaction, either automatically by a pre-generated OTP or by pre-approval of the Payee, or by manually approving in his or her own Device. + example: PAYEE + initiatorType: + title: TransactionInitiatorType + type: string + enum: + - CONSUMER + - AGENT + - BUSINESS + - DEVICE + description: |- + Below are the allowed values for the enumeration. + - CONSUMER - Consumer is the initiator of the transaction. + - AGENT - Agent is the initiator of the transaction. + - BUSINESS - Business is the initiator of the transaction. + - DEVICE - Device is the initiator of the transaction. + example: CONSUMER + refundInfo: + title: Refund + type: object + description: Data model for the complex type Refund. + properties: + originalTransactionId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + refundReason: + title: RefundReason + type: string + minLength: 1 + maxLength: 128 + description: Reason for the refund. + example: Free text indicating reason for the refund. + required: + - originalTransactionId + balanceOfPayments: + title: BalanceOfPayments + type: string + pattern: '^[1-9]\d{2}$' + description: '(BopCode) The API data type [BopCode](https://www.imf.org/external/np/sta/bopcode/) is a JSON String of 3 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed.' + example: '123' + required: + - scenario + - initiator + - initiatorType + expiration: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/completedTimestamp' + description: 'The time by which the transfer must be completed, set by the payee DFSP.' + extensionList: + title: ExtensionList + type: object + description: 'Data model for the complex type ExtensionList. An optional list of extensions, specific to deployment.' + properties: + extension: + type: array + items: + title: Extension + type: object + description: Data model for the complex type Extension. + properties: + key: + title: ExtensionKey + type: string + minLength: 1 + maxLength: 32 + description: Extension key. + value: + title: ExtensionValue + type: string + minLength: 1 + maxLength: 128 + description: Extension value. + required: + - key + - value + minItems: 1 + maxItems: 16 + description: Number of Extension elements. + required: + - extension + required: + - authorizationRequestId + - transactionRequestId + - challenge + - transferAmount + - payeeReceiveAmount + - fees + - payer + - payee + - transactionType + - expiration + additionalProperties: false + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/authorizations/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + description: | + The HTTP request **GET /thirdpartyRequests/authorizations/**_{ID}_ is used to get information relating + to a previously issued authorization request. The *{ID}* in the request should match the + `authorizationRequestId` which was given when the authorization request was created. + operationId: GetThirdpartyRequestsAuthorizationsById + summary: GetThirdpartyRequestsAuthorizationsById + tags: + - authorizations + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + description: | + After receiving the **POST /thirdpartyRequests/authorizations**, the PISP will present the details of the + transaction to their user, and request that the client sign the `challenge` field using the credential + they previously registered. + + The signed challenge will be sent back by the PISP in **PUT /thirdpartyRequests/authorizations/**_{ID}_: + operationId: PutThirdpartyRequestsAuthorizationsById + summary: PutThirdpartyRequestsAuthorizationsById + tags: + - authorizations + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Signed authorization object + required: true + content: + application/json: + schema: + oneOf: + - title: ThirdpartyRequestsAuthorizationsIDPutResponseGeneric + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + title: AuthorizationResponseType + description: | + The customer rejected the terms of the transfer. + type: string + enum: + - REJECTED + required: + - responseType + - title: ThirdpartyRequestsAuthorizationsIDPutResponseFIDO + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + title: AuthorizationResponseType + description: | + The customer accepted the terms of the transfer + type: string + enum: + - ACCEPTED + signedPayload: + type: object + properties: + signedPayloadType: + $ref: '#/paths/~1thirdpartyRequests~1verifications/post/requestBody/content/application~1json/schema/oneOf/0/properties/signedPayloadType' + fidoSignedPayload: + $ref: '#/paths/~1thirdpartyRequests~1verifications/post/requestBody/content/application~1json/schema/oneOf/0/properties/fidoSignedPayload' + required: + - signedPayloadType + - fidoSignedPayload + additionalProperties: false + required: + - responseType + - signedPayload + additionalProperties: false + - title: ThirdpartyRequestsAuthorizationsIDPutResponseGeneric + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + $ref: '#/paths/~1thirdpartyRequests~1authorizations~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/1/properties/responseType' + signedPayload: + type: object + properties: + signedPayloadType: + $ref: '#/paths/~1thirdpartyRequests~1verifications/post/requestBody/content/application~1json/schema/oneOf/1/properties/signedPayloadType' + genericSignedPayload: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - signedPayloadType + - genericSignedPayload + additionalProperties: false + required: + - responseType + - signedPayload + additionalProperties: false + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/authorizations/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - thirdpartyRequests + - sampled + operationId: PutThirdpartyRequestsAuthorizationsByIdAndError + summary: PutThirdpartyRequestsAuthorizationsByIdAndError + description: | + The HTTP request `PUT /thirdpartyRequests/authorizations/{ID}/error` is used by the DFSP or PISP to inform + the other party that something went wrong with a Thirdparty Transaction Authorization Request. + + The PISP may use this to tell the DFSP that the Thirdparty Transaction Authorization Request is invalid or doesn't + match a `transactionRequestId`. + + The DFSP may use this to tell the PISP that the signed challenge returned in `PUT /thirdpartyRequest/authorizations/{ID}` + was invalid. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /thirdpartyRequests/transactions: + parameters: + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + post: + operationId: ThirdpartyRequestsTransactionsPost + summary: ThirdpartyRequestsTransactionsPost + description: The HTTP request POST `/thirdpartyRequests/transactions` is used by a PISP to initiate a 3rd party Transaction request with a DFSP + tags: + - thirdpartyRequests + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Transaction request to be created. + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsPostRequest + type: object + description: The object sent in the POST /thirdpartyRequests/transactions request. + properties: + transactionRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and the Payer DFSP for the transaction request object. The ID should be reused for resends of the same transaction request. A new ID should be generated for each new transaction request. + payee: + allOf: + - title: Party + type: object + description: Data model for the complex type Party. + properties: + partyIdInfo: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0' + merchantClassificationCode: + title: MerchantClassificationCode + type: string + pattern: '^[\d]{1,4}$' + description: 'A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, etc.' + name: + title: PartyName + type: string + minLength: 1 + maxLength: 128 + description: Name of the Party. Could be a real name or a nickname. + personalInfo: + title: PartyPersonalInfo + type: object + description: Data model for the complex type PartyPersonalInfo. + properties: + complexName: + title: PartyComplexName + type: object + description: Data model for the complex type PartyComplexName. + properties: + firstName: + title: FirstName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: First name of the Party (Name Type). + example: Henrik + middleName: + title: MiddleName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: Middle name of the Party (Name Type). + example: Johannes + lastName: + title: LastName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: Last name of the Party (Name Type). + example: Karlsson + dateOfBirth: + title: DateofBirth (type Date) + type: string + pattern: '^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$' + description: Date of Birth of the Party. + example: '1966-06-16' + required: + - partyIdInfo + description: Information about the Payee in the proposed financial transaction. + payer: + allOf: + - title: PartyIdInfo + type: object + description: Data model for the complex type PartyIdInfo. + properties: + partyIdType: + title: PartyIdType + type: string + enum: + - MSISDN + - EMAIL + - PERSONAL_ID + - BUSINESS + - DEVICE + - ACCOUNT_ID + - IBAN + - ALIAS + - CONSENT + - THIRD_PARTY_LINK + description: | + Below are the allowed values for the enumeration. + - MSISDN - An MSISDN (Mobile Station International Subscriber Directory + Number, that is, the phone number) is used as reference to a participant. + The MSISDN identifier should be in international format according to the + [ITU-T E.164 standard](https://www.itu.int/rec/T-REC-E.164/en). + Optionally, the MSISDN may be prefixed by a single plus sign, indicating the + international prefix. + - EMAIL - An email is used as reference to a + participant. The format of the email should be according to the informational + [RFC 3696](https://tools.ietf.org/html/rfc3696). + - PERSONAL_ID - A personal identifier is used as reference to a participant. + Examples of personal identification are passport number, birth certificate + number, and national registration number. The identifier number is added in + the PartyIdentifier element. The personal identifier type is added in the + PartySubIdOrType element. + - BUSINESS - A specific Business (for example, an organization or a company) + is used as reference to a participant. The BUSINESS identifier can be in any + format. To make a transaction connected to a specific username or bill number + in a Business, the PartySubIdOrType element should be used. + - DEVICE - A specific device (for example, a POS or ATM) ID connected to a + specific business or organization is used as reference to a Party. + For referencing a specific device under a specific business or organization, + use the PartySubIdOrType element. + - ACCOUNT_ID - A bank account number or FSP account ID should be used as + reference to a participant. The ACCOUNT_ID identifier can be in any format, + as formats can greatly differ depending on country and FSP. + - IBAN - A bank account number or FSP account ID is used as reference to a + participant. The IBAN identifier can consist of up to 34 alphanumeric + characters and should be entered without whitespace. + - ALIAS An alias is used as reference to a participant. The alias should be + created in the FSP as an alternative reference to an account owner. + Another example of an alias is a username in the FSP system. + The ALIAS identifier can be in any format. It is also possible to use the + PartySubIdOrType element for identifying an account under an Alias defined + by the PartyIdentifier. + - CONSENT - A Consent represents an agreement between a PISP, a Customer and + a DFSP which allows the PISP permission to perform actions on behalf of the + customer. A Consent has an authoritative source: either the DFSP who issued + the Consent, or an Auth Service which administers the Consent. + - THIRD_PARTY_LINK - A Third Party Link represents an agreement between a PISP, + a DFSP, and a specific Customer's account at the DFSP. The content of the link + is created by the DFSP at the time when it gives permission to the PISP for + specific access to a given account. + example: PERSONAL_ID + partyIdentifier: + title: PartyIdentifier + type: string + minLength: 1 + maxLength: 128 + description: Identifier of the Party. + example: '16135551212' + partySubIdOrType: + title: PartySubIdOrType + type: string + minLength: 1 + maxLength: 128 + description: 'Either a sub-identifier of a PartyIdentifier, or a sub-type of the PartyIdType, normally a PersonalIdentifierType.' + fspId: + title: FspId + type: string + minLength: 1 + maxLength: 32 + description: FSP identifier. + extensionList: + $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - partyIdType + - partyIdentifier + description: Information about the Payer in the proposed financial transaction. + amountType: + allOf: + - title: AmountType + type: string + enum: + - SEND + - RECEIVE + description: |- + Below are the allowed values for the enumeration AmountType. + - SEND - Amount the Payer would like to send, that is, the amount that should be withdrawn from the Payer account including any fees. + - RECEIVE - Amount the Payer would like the Payee to receive, that is, the amount that should be sent to the receiver exclusive of any fees. + example: RECEIVE + description: 'SEND for sendAmount, RECEIVE for receiveAmount.' + amount: + allOf: + - title: Money + type: object + description: Data model for the complex type Money. + properties: + currency: + $ref: '#/paths/~1accounts~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/accountList/items/properties/currency' + amount: + title: Amount + type: string + pattern: '^([0]|([1-9][0-9]{0,17}))([.][0-9]{0,3}[1-9])?$' + description: 'The API data type Amount is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons. This pattern does not allow any trailing zeroes at all, but allows an amount without a minor currency unit. It also only allows four digits in the minor currency unit; a negative value is not allowed. Using more than 18 digits in the major currency unit is not allowed.' + example: '123.45' + required: + - currency + - amount + description: Requested amount to be transferred from the Payer to Payee. + transactionType: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/transactionType' + description: Type of transaction. + note: + type: string + minLength: 1 + maxLength: 256 + description: A memo that will be attached to the transaction. + expiration: + type: string + description: | + Date and time until when the transaction request is valid. It can be set to get a quick failure in case the peer FSP takes too long to respond. + example: '2016-05-24T08:38:08.699-04:00' + required: + - transactionRequestId + - payee + - payer + - amountType + - amount + - transactionType + - expiration + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/transactions/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + tags: + - thirdpartyRequests + - sampled + operationId: GetThirdpartyTransactionRequests + summary: GetThirdpartyTransactionRequests + description: | + The HTTP request `GET /thirdpartyRequests/transactions/{ID}` is used to request the + retrieval of a third party transaction request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + tags: + - thirdpartyRequests + - sampled + operationId: UpdateThirdPartyTransactionRequests + summary: UpdateThirdPartyTransactionRequests + description: | + The HTTP request `PUT /thirdpartyRequests/transactions/{ID}` is used by the DFSP to inform the client about + the status of a previously requested thirdparty transaction request. + + Switch(Thirdparty API Adapter) -> PISP + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsIDPutResponse + type: object + description: 'The object sent in the PUT /thirdPartyRequests/transactions/{ID} request.' + properties: + transactionRequestState: + title: TransactionRequestState + type: string + enum: + - RECEIVED + - PENDING + - ACCEPTED + - REJECTED + description: |- + Below are the allowed values for the enumeration. + - RECEIVED - Payer FSP has received the transaction from the Payee FSP. + - PENDING - Payer FSP has sent the transaction request to the Payer. + - ACCEPTED - Payer has approved the transaction. + - REJECTED - Payer has rejected the transaction. + example: RECEIVED + required: + - transactionRequestState + example: + transactionRequestState: RECEIVED + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + patch: + operationId: NotifyThirdpartyTransactionRequests + summary: NotifyThirdpartyTransactionRequests + description: | + The HTTP request `PATCH /thirdpartyRequests/transactions/{ID}` is used to + notify a thirdparty of the outcome of a transaction request. + + Switch(Thirdparty API Adapter) -> PISP + tags: + - thirdpartyRequests + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsIDPatchResponse + type: object + description: 'The object sent in the PATCH /thirdpartyRequests/transactions/{ID} callback.' + properties: + completedTimestamp: + title: DateTime + type: string + pattern: '^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:(\.\d{3}))(?:Z|[+-][01]\d:[0-5]\d)$' + description: 'The API data type DateTime is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. The format is according to [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html), expressed in a combined date, time and time zone format. A more readable version of the format is yyyy-MM-ddTHH:mm:ss.SSS[-HH:MM]. Examples are "2016-05-24T08:38:08.699-04:00", "2016-05-24T08:38:08.699Z" (where Z indicates Zulu time zone, same as UTC).' + example: '2016-05-24T08:38:08.699-04:00' + transactionRequestState: + $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/transactionRequestState' + transactionState: + title: TransactionState + type: string + enum: + - RECEIVED + - PENDING + - COMPLETED + - REJECTED + description: |- + Below are the allowed values for the enumeration. + - RECEIVED - Payee FSP has received the transaction from the Payer FSP. + - PENDING - Payee FSP has validated the transaction. + - COMPLETED - Payee FSP has successfully performed the transaction. + - REJECTED - Payee FSP has failed to perform the transaction. + example: RECEIVED + required: + - transactionRequestState + - transactionState + example: + transactionRequestState: ACCEPTED + transactionState: COMMITTED + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/transactions/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - thirdpartyRequests + - sampled + operationId: ThirdpartyTransactionRequestsError + summary: ThirdpartyTransactionRequestsError + description: | + If the server is unable to find the transaction request, or another processing error occurs, + the error callback `PUT /thirdpartyRequests/transactions/{ID}/error` is used. + The `{ID}` in the URI should contain the `transactionRequestId` that was used for the creation of + the thirdparty transaction request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /thirdpartyRequests/verifications: + parameters: + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + post: + tags: + - thirdpartyRequests + - sampled + operationId: PostThirdpartyRequestsVerifications + summary: PostThirdpartyRequestsVerifications + description: | + The HTTP request `POST /thirdpartyRequests/verifications` is used by the DFSP to verify a third party authorization. + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: The thirdparty authorization details to verify + required: true + content: + application/json: + schema: + oneOf: + - title: ThirdpartyRequestsVerificationsPostRequestFIDO + type: object + description: The object sent in the POST /thirdpartyRequests/verifications request. + properties: + verificationRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + challenge: + type: string + description: Base64 encoded bytes - The challenge generated by the DFSP. + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + The id of the stored consent object that contains the credential with which to verify + the signed challenge against. + signedPayloadType: + title: SignedPayloadTypeFIDO + type: string + enum: + - FIDO + description: Describes a challenge that has been signed with FIDO Attestation flows + fidoSignedPayload: + title: FIDOPublicKeyCredentialAssertion + type: object + description: | + An object sent in a `PUT /thirdpartyRequests/authorization/{ID}` request. + based mostly on: https://webauthn.guide/#authentication + AuthenticatorAssertionResponse + properties: + id: + type: string + description: | + credential id: identifier of pair of keys, base64 encoded + https://w3c.github.io/webauthn/#ref-for-dom-credential-id + minLength: 59 + maxLength: 118 + rawId: + type: string + description: | + raw credential id: identifier of pair of keys, base64 encoded. + minLength: 59 + maxLength: 118 + response: + type: object + description: | + AuthenticatorAssertionResponse + properties: + authenticatorData: + type: string + description: | + Authenticator data object. + minLength: 49 + maxLength: 256 + clientDataJSON: + type: string + description: | + JSON string with client data. + minLength: 121 + maxLength: 512 + signature: + type: string + description: | + The signature generated by the private key associated with this credential. + minLength: 59 + maxLength: 256 + userHandle: + type: string + description: | + This field is optionally provided by the authenticator, and + represents the user.id that was supplied during registration. + minLength: 1 + maxLength: 88 + required: + - authenticatorData + - clientDataJSON + - signature + additionalProperties: false + type: + type: string + description: 'response type, we need only the type of public-key' + enum: + - public-key + required: + - id + - rawId + - response + - type + additionalProperties: false + required: + - verificationRequestId + - challenge + - consentId + - signedPayloadType + - fidoSignedPayload + - title: ThirdpartyRequestsVerificationsPostRequestGeneric + type: object + description: The object sent in the POST /thirdpartyRequests/verifications request. + properties: + verificationRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + challenge: + type: string + description: Base64 encoded bytes - The challenge generated by the DFSP. + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + The id of the stored consent object that contains the credential with which to verify + the signed challenge against. + signedPayloadType: + title: SignedPayloadTypeGeneric + type: string + enum: + - GENERIC + description: Describes a challenge that has been signed with a private key + genericSignedPayload: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - verificationRequestId + - challenge + - consentId + - signedPayloadType + - genericSignedPayload + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/verifications/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + tags: + - thirdpartyRequests + - sampled + operationId: GetThirdpartyRequestsVerificationsById + summary: GetThirdpartyRequestsVerificationsById + description: | + The HTTP request `/thirdpartyRequests/verifications/{ID}` is used to get + information regarding a previously created or requested authorization. The *{ID}* + in the URI should contain the verification request ID + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + tags: + - thirdpartyRequests + - sampled + operationId: PutThirdpartyRequestsVerificationsById + summary: PutThirdpartyRequestsVerificationsById + description: | + The HTTP request `PUT /thirdpartyRequests/verifications/{ID}` is used by the Auth-Service to inform + the DFSP of a successful result in validating the verification of a Thirdparty Transaction Request. + + If the validation fails, The Auth-Service MUST use `PUT /thirdpartyRequests/verifications/{ID}/error` + instead. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: The result of validating the Thirdparty Transaction Request + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsVerificationsIDPutResponse + type: object + description: 'The object sent in the PUT /thirdpartyRequests/verifications/{ID} request.' + properties: + authenticationResponse: + type: string + enum: + - VERIFIED + description: The verification passed + required: + - authenticationResponse + example: + authenticationResponse: VERIFIED + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/verifications/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - thirdpartyRequests + - sampled + operationId: PutThirdpartyRequestsVerificationsByIdAndError + summary: PutThirdpartyRequestsVerificationsByIdAndError + description: | + The HTTP request `PUT /thirdpartyRequests/verifications/{ID}/error` is used by the Auth-Service to inform + the DFSP of a failure in validating or looking up the verification of a Thirdparty Transaction Request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' diff --git a/docs/technical/api/thirdparty/thirdparty-pisp-v1.0.yaml b/docs/technical/api/thirdparty/thirdparty-pisp-v1.0.yaml new file mode 100644 index 000000000..cb9f52f27 --- /dev/null +++ b/docs/technical/api/thirdparty/thirdparty-pisp-v1.0.yaml @@ -0,0 +1,2830 @@ +openapi: 3.0.1 +info: + title: Mojaloop Third Party API (PISP) + version: '1.0' + description: | + A Mojaloop API for Payment Initiation Service Providers (PISPs) to perform Third Party functions on DFSPs' User's accounts. + DFSPs who want to enable Payment Initiation Service Providers (PISPs) should implement the accompanying API - Mojaloop Third Party API (DFSP) instead. + license: + name: Open API for FSP Interoperability (FSPIOP) (Implementation Friendly Version) + url: 'https://github.com/mojaloop/mojaloop-specification/blob/master/LICENSE.md' +servers: + - url: / +paths: + '/accounts/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + operationId: GetAccountsByUserId + summary: GetAccountsByUserId + description: | + The HTTP request `GET /accounts/{ID}` is used to retrieve the list of potential accounts available for linking. + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: | + The HTTP request `PUT /accounts/{ID}` is used to return the list of potential accounts available for linking + operationId: UpdateAccountsByUserId + summary: UpdateAccountsByUserId + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: AccountsIDPutResponse + type: object + description: 'The object sent in a `PUT /accounts/{ID}` request.' + properties: + accountList: + description: Information about the accounts that the DFSP associates with the identifier sent by the PISP + type: array + items: + title: Account + type: object + description: Data model for the complex type Account. + properties: + accountNickname: + title: Name + type: string + pattern: '^(?!\s*$)[\w .,''-]{1,128}$' + description: |- + The API data type Name is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. + + Regular Expression - The regular expression for restricting the Name type is "^(?!\s*$)[\w .,'-]{1,128}$". The restriction does not allow a string consisting of whitespace only, all Unicode characters are allowed, as well as the period (.) (apostrophe (‘), dash (-), comma (,) and space characters ( ). + + **Note:** In some programming languages, Unicode support must be specifically enabled. For example, if Java is used, the flag UNICODE_CHARACTER_CLASS must be enabled to allow Unicode characters. + address: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items/properties/address' + currency: + title: Currency + description: 'The currency codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic codes are used as the standard naming representation for currencies.' + type: string + minLength: 3 + maxLength: 3 + enum: + - AED + - AFN + - ALL + - AMD + - ANG + - AOA + - ARS + - AUD + - AWG + - AZN + - BAM + - BBD + - BDT + - BGN + - BHD + - BIF + - BMD + - BND + - BOB + - BRL + - BSD + - BTN + - BWP + - BYN + - BZD + - CAD + - CDF + - CHF + - CLP + - CNY + - COP + - CRC + - CUC + - CUP + - CVE + - CZK + - DJF + - DKK + - DOP + - DZD + - EGP + - ERN + - ETB + - EUR + - FJD + - FKP + - GBP + - GEL + - GGP + - GHS + - GIP + - GMD + - GNF + - GTQ + - GYD + - HKD + - HNL + - HRK + - HTG + - HUF + - IDR + - ILS + - IMP + - INR + - IQD + - IRR + - ISK + - JEP + - JMD + - JOD + - JPY + - KES + - KGS + - KHR + - KMF + - KPW + - KRW + - KWD + - KYD + - KZT + - LAK + - LBP + - LKR + - LRD + - LSL + - LYD + - MAD + - MDL + - MGA + - MKD + - MMK + - MNT + - MOP + - MRO + - MUR + - MVR + - MWK + - MXN + - MYR + - MZN + - NAD + - NGN + - NIO + - NOK + - NPR + - NZD + - OMR + - PAB + - PEN + - PGK + - PHP + - PKR + - PLN + - PYG + - QAR + - RON + - RSD + - RUB + - RWF + - SAR + - SBD + - SCR + - SDG + - SEK + - SGD + - SHP + - SLL + - SOS + - SPL + - SRD + - STD + - SVC + - SYP + - SZL + - THB + - TJS + - TMT + - TND + - TOP + - TRY + - TTD + - TVD + - TWD + - TZS + - UAH + - UGX + - USD + - UYU + - UZS + - VEF + - VND + - VUV + - WST + - XAF + - XCD + - XDR + - XOF + - XPF + - XTS + - XXX + - YER + - ZAR + - ZMW + - ZWD + required: + - accountNickname + - id + - currency + required: + - accounts + example: + - accountNickname: dfspa.user.nickname1 + id: dfspa.username.1234 + currency: ZAR + - accountNickname: dfspa.user.nickname2 + id: dfspa.username.5678 + currency: USD + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/accounts/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + description: | + The HTTP request `PUT /accounts/{ID}/error` is used to return error information + operationId: UpdateAccountsByUserIdError + summary: UpdateAccountsByUserIdError + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + title: ErrorInformationObject + type: object + description: Data model for the complex type object that contains ErrorInformation. + properties: + errorInformation: + title: ErrorInformation + type: object + description: Data model for the complex type ErrorInformation. + properties: + errorCode: + title: ErrorCode + type: string + pattern: '^[1-9]\d{3}$' + description: 'The API data type ErrorCode is a JSON String of four characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. Each error code in the API is a four-digit number, for example, 1234, where the first number (1 in the example) represents the high-level error category, the second number (2 in the example) represents the low-level error category, and the last two numbers (34 in the example) represent the specific error.' + example: '5100' + errorDescription: + title: ErrorDescription + type: string + minLength: 1 + maxLength: 128 + description: Error description string. + extensionList: + $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - errorCode + - errorDescription + required: + - errorInformation + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + /consentRequests: + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + post: + tags: + - consentRequests + - sampled + operationId: CreateConsentRequest + summary: CreateConsentRequest + description: | + The HTTP request **POST /consentRequests** is used to request a DFSP to grant access to one or more + accounts owned by a customer of the DFSP for the PISP who sends the request. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: The consentRequest to create + required: true + content: + application/json: + schema: + title: ConsentRequestsPostRequest + type: object + description: The object sent in a `POST /consentRequests` request. + properties: + consentRequestId: + title: CorrelationId + type: string + pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' + description: 'Identifier that correlates all messages of the same sequence. The API data type UUID (Universally Unique Identifier) is a JSON String in canonical format, conforming to [RFC 4122](https://tools.ietf.org/html/rfc4122), that is restricted by a regular expression for interoperability reasons. A UUID is always 36 characters long, 32 hexadecimal symbols and 4 dashes (‘-‘).' + example: b51ec534-ee48-4575-b6a9-ead2955b8069 + userId: + type: string + description: 'The identifier used in the **GET /accounts/**_{ID}_. Used by the DFSP to correlate an account lookup to a `consentRequest`' + minLength: 1 + maxLength: 128 + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + title: Scope + type: object + description: Scope + Account Identifier mapping for a Consent. + properties: + address: + title: AccountAddress + type: string + description: | + An address which can be used to identify the account. + pattern: '^([0-9A-Za-z_~\-\.]+[0-9A-Za-z_~\-])$' + minLength: 1 + maxLength: 1023 + actions: + type: array + minItems: 1 + maxItems: 32 + items: + title: ScopeAction + type: string + enum: + - ACCOUNTS_GET_BALANCE + - ACCOUNTS_TRANSFER + - ACCOUNTS_STATEMENT + description: | + The permissions allowed on a given account by a DFSP as defined in + a consent object + - ACCOUNTS_GET_BALANCE: PISP can request a balance for the linked account + - ACCOUNTS_TRANSFER: PISP can request a transfer of funds from the linked account in the DFSP + - ACCOUNTS_STATEMENT: PISP can request a statement of individual transactions on a user’s account + required: + - address + - actions + authChannels: + type: array + minLength: 1 + maxLength: 256 + items: + title: ConsentRequestChannelType + type: string + enum: + - WEB + - OTP + description: | + The auth channel being used for the consentRequest. + - "WEB" - The Web auth channel. + - "OTP" - The OTP auth channel. + callbackUri: + title: Uri + type: string + pattern: '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' + minLength: 1 + maxLength: 512 + description: | + The API data type Uri is a JSON string in a canonical format that is restricted by a regular expression for interoperability reasons. + required: + - consentRequestId + - userId + - scopes + - authChannels + - callbackUri + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/consentRequests/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + operationId: GetConsentRequestsById + summary: GetConsentRequestsById + description: | + The HTTP request `GET /consentRequests/{ID}` is used to get information about a previously + requested consent. The *{ID}* in the URI should contain the consentRequestId that was assigned to the + request by the PISP when the PISP originated the request. + tags: + - consentRequests + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + tags: + - consentRequests + - sampled + operationId: UpdateConsentRequest + summary: UpdateConsentRequest + description: | + A DFSP uses this callback to (1) inform the PISP that the consentRequest has been accepted, + and (2) communicate to the PISP which `authChannel` it should use to authenticate their user + with. + + When a PISP requests a series of permissions from a DFSP on behalf of a DFSP’s customer, not all + the permissions requested may be granted by the DFSP. Conversely, the out-of-band authorization + process may result in additional privileges being granted by the account holder to the PISP. The + **PUT /consentRequests/**_{ID}_ resource returns the current state of the permissions relating to a + particular authorization request. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentRequestsIDPutResponseWeb + type: object + description: | + The object sent in a `PUT /consentRequests/{ID}` request. + + Schema used in the request consent phase of the account linking web flow, + the result is the PISP being instructed on a specific URL where this + supposed user should be redirected. This URL should be a place where + the user can prove their identity (e.g., by logging in). + properties: + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + authChannels: + type: array + minLength: 1 + maxLength: 1 + items: + title: ConsentRequestChannelTypeWeb + type: string + enum: + - WEB + description: | + The web auth channel being used for PUT consentRequest/{ID} request. + callbackUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + authUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + required: + - scopes + - authChannels + - callbackUri + - authUri + additionalProperties: false + - title: ConsentRequestsIDPutResponseOTP + type: object + description: | + The object sent in a `PUT /consentRequests/{ID}` request. + + Schema used in the request consent phase of the account linking OTP/SMS flow. + properties: + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + authChannels: + type: array + minLength: 1 + maxLength: 1 + items: + title: ConsentRequestChannelTypeOTP + type: string + enum: + - OTP + description: | + The OTP auth channel being used for PUT consentRequest/{ID} request. + callbackUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + required: + - scopes + - authChannels + additionalProperties: false + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + patch: + tags: + - consentRequests + - sampled + operationId: PatchConsentRequest + summary: PatchConsentRequest + description: | + After the user completes an out-of-band authorization with the DFSP, the PISP will receive a token which they can use to prove to the DFSP that the user trusts this PISP. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: ConsentRequestsIDPatchRequest + type: object + description: 'The object sent in a `PATCH /consentRequests/{ID}` request.' + properties: + authToken: + type: string + pattern: '^[A-Za-z0-9-_]+[=]{0,2}$' + description: 'The API data type BinaryString is a JSON String. The string is a base64url encoding of a string of raw bytes, where padding (character ‘=’) is added at the end of the data if needed to ensure that the string is a multiple of 4 characters. The length restriction indicates the allowed number of characters.' + required: + - authToken + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/consentRequests/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + tags: + - consentRequests + operationId: NotifyErrorConsentRequests + summary: NotifyErrorConsentRequests + description: | + DFSP responds to the PISP if something went wrong with validating an OTP or secret. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + /consents: + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + post: + tags: + - consents + - sampled + operationId: PostConsents + summary: PostConsents + description: | + The **POST /consents** request is used to request the creation of a consent for interactions between a PISP and the DFSP who owns the account which a PISP’s customer wants to allow the PISP access to. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentPostRequestAUTH + type: object + description: | + The object sent in a `POST /consents` request to the Auth-Service + by a DFSP to store registered Consent and credential + properties: + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and FSP for the Consent object + determined by the DFSP who creates the Consent. + scopes: + minLength: 1 + maxLength: 256 + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + credential: + allOf: + - $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential' + status: + title: ConsentStatus + type: string + enum: + - ISSUED + - REVOKED + description: |- + Allowed values for the enumeration ConsentStatus + - ISSUED - The consent has been issued by the DFSP + - REVOKED - The consent has been revoked + required: + - consentId + - scopes + - credential + - status + additionalProperties: false + - title: ConsentPostRequestPISP + type: object + description: | + The provisional Consent object sent by the DFSP in `POST /consents`. + properties: + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and the Payer DFSP for the consent object. The ID + should be reused for resends of the same consent. A new ID should be generated + for each new consent. + consentRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + The ID given to the original consent request on which this consent is based. + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + $ref: '#/paths/~1consents/post/requestBody/content/application~1json/schema/oneOf/0/properties/status' + required: + - consentId + - consentRequestId + - scopes + - status + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/consents/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + description: | + The **GET /consents/**_{ID}_ resource allows a party to enquire after the status of a consent. The *{ID}* used in the URI of the request should be the consent request ID which was used to identify the consent when it was created. + tags: + - consents + operationId: GetConsent + summary: GetConsent + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + patch: + description: | + The HTTP request `PATCH /consents/{ID}` is used + + - In account linking in the Credential Registration phase. Used by a DFSP + to notify a PISP a credential has been verified and registered with an + Auth service. + + - In account unlinking by a hub hosted auth service and by DFSPs + in non-hub hosted scenarios to notify participants of a consent being revoked. + + Called by a `auth-service` to notify a PISP and DFSP of consent status in hub hosted scenario. + Called by a `DFSP` to notify a PISP of consent status in non-hub hosted scenario. + tags: + - consents + - sampled + operationId: PatchConsentByID + summary: PatchConsentByID + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentsIDPatchResponseVerified + description: | + PATCH /consents/{ID} request object. + + Sent by the DFSP to the PISP when a consent is verified. + Used in the "Register Credential" part of the Account linking flow. + type: object + properties: + credential: + type: object + properties: + status: + title: CredentialStatus + type: string + enum: + - VERIFIED + description: | + The status of the Credential. + - "VERIFIED" - The Credential is valid and verified. + required: + - status + required: + - credential + - title: ConsentsIDPatchResponseRevoked + description: | + PATCH /consents/{ID} request object. + + Sent to both the PISP and DFSP when a consent is revoked. + Used in the "Unlinking" part of the Account Unlinking flow. + type: object + properties: + status: + title: ConsentStatus + type: string + enum: + - REVOKED + description: |- + Allowed values for the enumeration ConsentStatus + - REVOKED - The consent has been revoked + revokedAt: + $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/completedTimestamp' + required: + - status + - revokedAt + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: | + The HTTP request `PUT /consents/{ID}` is used by the PISP and Auth Service. + + - Called by a `PISP` to after signing a challenge. Sent to an DFSP for verification. + - Called by a `auth-service` to notify a DFSP that a credential has been verified and registered. + tags: + - consents + - sampled + operationId: PutConsentByID + summary: PutConsentByID + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentsIDPutResponseSigned + type: object + description: | + The HTTP request `PUT /consents/{ID}` is used by the PISP to update a Consent with a signed challenge and register a credential. + Called by a `PISP` to after signing a challenge. Sent to a DFSP for verification. + properties: + scopes: + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + title: ConsentStatus + type: string + enum: + - ISSUED + description: |- + Allowed values for the enumeration ConsentStatus + - ISSUED - The consent has been issued by the DFSP + credential: + title: SignedCredential + type: object + description: | + A credential used to allow a user to prove their identity and access + to an account with a DFSP. + + SignedCredential is a special formatting of the credential to allow us to be + more explicit about the `status` field - it should only ever be PENDING when + updating a credential. + properties: + credentialType: + title: CredentialType + type: string + enum: + - FIDO + - GENERIC + description: | + The type of the Credential. + - "FIDO" - A FIDO public/private keypair + - "GENERIC" - A Generic public/private keypair + status: + title: CredentialStatus + type: string + enum: + - PENDING + description: | + The status of the Credential. + - "PENDING" - The credential has been created, but has not been verified + genericPayload: + title: GenericCredential + type: object + description: | + A publicKey + signature of a challenge for a generic public/private keypair + properties: + publicKey: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + signature: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - publicKey + - signature + additionalProperties: false + fidoPayload: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/1/properties/credential/properties/payload' + required: + - credentialType + - status + additionalProperties: false + required: + - scopes + - credential + additionalProperties: false + - title: ConsentsIDPutResponseVerified + type: object + description: | + The HTTP request `PUT /consents/{ID}` is used by the DFSP or Auth-Service to update a Consent object once it has been Verified. + Called by a `auth-service` to notify a DFSP that a credential has been verified and registered. + properties: + scopes: + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/status' + credential: + title: VerifiedCredential + type: object + description: | + A credential used to allow a user to prove their identity and access + to an account with a DFSP. + + VerifiedCredential is a special formatting of the credential to allow us to be + more explicit about the `status` field - it should only ever be VERIFIED when + updating a credential. + properties: + credentialType: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential/properties/credentialType' + status: + type: string + enum: + - VERIFIED + description: 'The Credential is valid, and ready to be used by the PISP.' + payload: + title: FIDOPublicKeyCredentialAttestation + type: object + description: | + A data model representing a FIDO Attestation result. Derived from + [`PublicKeyCredential` Interface](https://w3c.github.io/webauthn/#iface-pkcredential). + + The `PublicKeyCredential` interface represents the below fields with + a Type of Javascript [ArrayBuffer](https://heycam.github.io/webidl/#idl-ArrayBuffer). + For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + properties: + id: + type: string + description: | + credential id: identifier of pair of keys, base64 encoded + https://w3c.github.io/webauthn/#ref-for-dom-credential-id + minLength: 59 + maxLength: 118 + rawId: + type: string + description: | + raw credential id: identifier of pair of keys, base64 encoded + minLength: 59 + maxLength: 118 + response: + type: object + description: | + AuthenticatorAttestationResponse + properties: + clientDataJSON: + type: string + description: | + JSON string with client data + minLength: 121 + maxLength: 512 + attestationObject: + type: string + description: | + CBOR.encoded attestation object + minLength: 306 + maxLength: 2048 + required: + - clientDataJSON + - attestationObject + additionalProperties: false + type: + type: string + description: 'response type, we need only the type of public-key' + enum: + - public-key + required: + - id + - response + - type + additionalProperties: false + required: + - credentialType + - status + - payload + additionalProperties: false + required: + - scopes + - credential + additionalProperties: false + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + delete: + description: | + Used by PISP, DFSP + + The **DELETE /consents/**_{ID}_ request is used to request the revocation of a previously agreed consent. + For tracing and auditing purposes, the switch should be sure not to delete the consent physically; + instead, information relating to the consent should be marked as deleted and requests relating to the + consent should not be honoured. + operationId: DeleteConsentByID + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + tags: + - consents + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/consents/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + tags: + - consents + operationId: NotifyErrorConsents + summary: NotifyErrorConsents + description: | + DFSP responds to the PISP if something went wrong with validating or storing consent. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + /thirdpartyRequests/authorizations: + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + post: + description: | + The HTTP request **POST /thirdpartyRequests/authorizations** is used to request the validation by a customer for the transfer described in the request. + operationId: PostThirdpartyRequestsAuthorizations + summary: PostThirdpartyRequestsAuthorizations + tags: + - authorizations + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Authorization request details + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsAuthorizationsPostRequest + description: POST /thirdpartyRequests/authorizations request object. + type: object + properties: + authorizationRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + transactionRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + challenge: + type: string + description: The challenge that the PISP's client is to sign + transferAmount: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount that will be debited from the sending customer’s account as a consequence of the transaction. + payeeReceiveAmount: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount that will be credited to the receiving customer’s account as a consequence of the transaction. + fees: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount of fees that the paying customer will be charged as part of the transaction. + payer: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0' + description: 'Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction.' + payee: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payee/allOf/0' + description: Information about the Payee in the proposed financial transaction. + transactionType: + title: TransactionType + type: object + description: Data model for the complex type TransactionType. + properties: + scenario: + title: TransactionScenario + type: string + enum: + - DEPOSIT + - WITHDRAWAL + - TRANSFER + - PAYMENT + - REFUND + description: |- + Below are the allowed values for the enumeration. + - DEPOSIT - Used for performing a Cash-In (deposit) transaction. In a normal scenario, electronic funds are transferred from a Business account to a Consumer account, and physical cash is given from the Consumer to the Business User. + - WITHDRAWAL - Used for performing a Cash-Out (withdrawal) transaction. In a normal scenario, electronic funds are transferred from a Consumer’s account to a Business account, and physical cash is given from the Business User to the Consumer. + - TRANSFER - Used for performing a P2P (Peer to Peer, or Consumer to Consumer) transaction. + - PAYMENT - Usually used for performing a transaction from a Consumer to a Merchant or Organization, but could also be for a B2B (Business to Business) payment. The transaction could be online for a purchase in an Internet store, in a physical store where both the Consumer and Business User are present, a bill payment, a donation, and so on. + - REFUND - Used for performing a refund of transaction. + example: DEPOSIT + subScenario: + title: TransactionSubScenario + type: string + pattern: '^[A-Z_]{1,32}$' + description: 'Possible sub-scenario, defined locally within the scheme (UndefinedEnum Type).' + example: LOCALLY_DEFINED_SUBSCENARIO + initiator: + title: TransactionInitiator + type: string + enum: + - PAYER + - PAYEE + description: |- + Below are the allowed values for the enumeration. + - PAYER - Sender of funds is initiating the transaction. The account to send from is either owned by the Payer or is connected to the Payer in some way. + - PAYEE - Recipient of the funds is initiating the transaction by sending a transaction request. The Payer must approve the transaction, either automatically by a pre-generated OTP or by pre-approval of the Payee, or by manually approving in his or her own Device. + example: PAYEE + initiatorType: + title: TransactionInitiatorType + type: string + enum: + - CONSUMER + - AGENT + - BUSINESS + - DEVICE + description: |- + Below are the allowed values for the enumeration. + - CONSUMER - Consumer is the initiator of the transaction. + - AGENT - Agent is the initiator of the transaction. + - BUSINESS - Business is the initiator of the transaction. + - DEVICE - Device is the initiator of the transaction. + example: CONSUMER + refundInfo: + title: Refund + type: object + description: Data model for the complex type Refund. + properties: + originalTransactionId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + refundReason: + title: RefundReason + type: string + minLength: 1 + maxLength: 128 + description: Reason for the refund. + example: Free text indicating reason for the refund. + required: + - originalTransactionId + balanceOfPayments: + title: BalanceOfPayments + type: string + pattern: '^[1-9]\d{2}$' + description: '(BopCode) The API data type [BopCode](https://www.imf.org/external/np/sta/bopcode/) is a JSON String of 3 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed.' + example: '123' + required: + - scenario + - initiator + - initiatorType + expiration: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/completedTimestamp' + description: 'The time by which the transfer must be completed, set by the payee DFSP.' + extensionList: + title: ExtensionList + type: object + description: 'Data model for the complex type ExtensionList. An optional list of extensions, specific to deployment.' + properties: + extension: + type: array + items: + title: Extension + type: object + description: Data model for the complex type Extension. + properties: + key: + title: ExtensionKey + type: string + minLength: 1 + maxLength: 32 + description: Extension key. + value: + title: ExtensionValue + type: string + minLength: 1 + maxLength: 128 + description: Extension value. + required: + - key + - value + minItems: 1 + maxItems: 16 + description: Number of Extension elements. + required: + - extension + required: + - authorizationRequestId + - transactionRequestId + - challenge + - transferAmount + - payeeReceiveAmount + - fees + - payer + - payee + - transactionType + - expiration + additionalProperties: false + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/thirdpartyRequests/authorizations/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + description: | + The HTTP request **GET /thirdpartyRequests/authorizations/**_{ID}_ is used to get information relating + to a previously issued authorization request. The *{ID}* in the request should match the + `authorizationRequestId` which was given when the authorization request was created. + operationId: GetThirdpartyRequestsAuthorizationsById + summary: GetThirdpartyRequestsAuthorizationsById + tags: + - authorizations + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: | + After receiving the **POST /thirdpartyRequests/authorizations**, the PISP will present the details of the + transaction to their user, and request that the client sign the `challenge` field using the credential + they previously registered. + + The signed challenge will be sent back by the PISP in **PUT /thirdpartyRequests/authorizations/**_{ID}_: + operationId: PutThirdpartyRequestsAuthorizationsById + summary: PutThirdpartyRequestsAuthorizationsById + tags: + - authorizations + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Signed authorization object + required: true + content: + application/json: + schema: + oneOf: + - title: ThirdpartyRequestsAuthorizationsIDPutResponseGeneric + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + title: AuthorizationResponseType + description: | + The customer rejected the terms of the transfer. + type: string + enum: + - REJECTED + required: + - responseType + - title: ThirdpartyRequestsAuthorizationsIDPutResponseFIDO + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + title: AuthorizationResponseType + description: | + The customer accepted the terms of the transfer + type: string + enum: + - ACCEPTED + signedPayload: + type: object + properties: + signedPayloadType: + title: SignedPayloadTypeFIDO + type: string + enum: + - FIDO + description: Describes a challenge that has been signed with FIDO Attestation flows + fidoSignedPayload: + title: FIDOPublicKeyCredentialAssertion + type: object + description: | + An object sent in a `PUT /thirdpartyRequests/authorization/{ID}` request. + based mostly on: https://webauthn.guide/#authentication + AuthenticatorAssertionResponse + properties: + id: + type: string + description: | + credential id: identifier of pair of keys, base64 encoded + https://w3c.github.io/webauthn/#ref-for-dom-credential-id + minLength: 59 + maxLength: 118 + rawId: + type: string + description: | + raw credential id: identifier of pair of keys, base64 encoded. + minLength: 59 + maxLength: 118 + response: + type: object + description: | + AuthenticatorAssertionResponse + properties: + authenticatorData: + type: string + description: | + Authenticator data object. + minLength: 49 + maxLength: 256 + clientDataJSON: + type: string + description: | + JSON string with client data. + minLength: 121 + maxLength: 512 + signature: + type: string + description: | + The signature generated by the private key associated with this credential. + minLength: 59 + maxLength: 256 + userHandle: + type: string + description: | + This field is optionally provided by the authenticator, and + represents the user.id that was supplied during registration. + minLength: 1 + maxLength: 88 + required: + - authenticatorData + - clientDataJSON + - signature + additionalProperties: false + type: + type: string + description: 'response type, we need only the type of public-key' + enum: + - public-key + required: + - id + - rawId + - response + - type + additionalProperties: false + required: + - signedPayloadType + - fidoSignedPayload + additionalProperties: false + required: + - responseType + - signedPayload + additionalProperties: false + - title: ThirdpartyRequestsAuthorizationsIDPutResponseGeneric + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + $ref: '#/paths/~1thirdpartyRequests~1authorizations~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/1/properties/responseType' + signedPayload: + type: object + properties: + signedPayloadType: + title: SignedPayloadTypeGeneric + type: string + enum: + - GENERIC + description: Describes a challenge that has been signed with a private key + genericSignedPayload: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - signedPayloadType + - genericSignedPayload + additionalProperties: false + required: + - responseType + - signedPayload + additionalProperties: false + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/thirdpartyRequests/authorizations/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + tags: + - thirdpartyRequests + - sampled + operationId: PutThirdpartyRequestsAuthorizationsByIdAndError + summary: PutThirdpartyRequestsAuthorizationsByIdAndError + description: | + The HTTP request `PUT /thirdpartyRequests/authorizations/{ID}/error` is used by the DFSP or PISP to inform + the other party that something went wrong with a Thirdparty Transaction Authorization Request. + + The PISP may use this to tell the DFSP that the Thirdparty Transaction Authorization Request is invalid or doesn't + match a `transactionRequestId`. + + The DFSP may use this to tell the PISP that the signed challenge returned in `PUT /thirdpartyRequest/authorizations/{ID}` + was invalid. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + /thirdpartyRequests/transactions: + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + post: + operationId: ThirdpartyRequestsTransactionsPost + summary: ThirdpartyRequestsTransactionsPost + description: The HTTP request POST `/thirdpartyRequests/transactions` is used by a PISP to initiate a 3rd party Transaction request with a DFSP + tags: + - thirdpartyRequests + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Transaction request to be created. + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsPostRequest + type: object + description: The object sent in the POST /thirdpartyRequests/transactions request. + properties: + transactionRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and the Payer DFSP for the transaction request object. The ID should be reused for resends of the same transaction request. A new ID should be generated for each new transaction request. + payee: + allOf: + - title: Party + type: object + description: Data model for the complex type Party. + properties: + partyIdInfo: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0' + merchantClassificationCode: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/party/properties/merchantClassificationCode' + name: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/party/properties/name' + personalInfo: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/party/properties/personalInfo' + required: + - partyIdInfo + description: Information about the Payee in the proposed financial transaction. + payer: + allOf: + - title: PartyIdInfo + type: object + description: Data model for the complex type PartyIdInfo. + properties: + partyIdType: + title: PartyIdType + type: string + enum: + - MSISDN + - EMAIL + - PERSONAL_ID + - BUSINESS + - DEVICE + - ACCOUNT_ID + - IBAN + - ALIAS + - CONSENT + - THIRD_PARTY_LINK + description: | + Below are the allowed values for the enumeration. + - MSISDN - An MSISDN (Mobile Station International Subscriber Directory + Number, that is, the phone number) is used as reference to a participant. + The MSISDN identifier should be in international format according to the + [ITU-T E.164 standard](https://www.itu.int/rec/T-REC-E.164/en). + Optionally, the MSISDN may be prefixed by a single plus sign, indicating the + international prefix. + - EMAIL - An email is used as reference to a + participant. The format of the email should be according to the informational + [RFC 3696](https://tools.ietf.org/html/rfc3696). + - PERSONAL_ID - A personal identifier is used as reference to a participant. + Examples of personal identification are passport number, birth certificate + number, and national registration number. The identifier number is added in + the PartyIdentifier element. The personal identifier type is added in the + PartySubIdOrType element. + - BUSINESS - A specific Business (for example, an organization or a company) + is used as reference to a participant. The BUSINESS identifier can be in any + format. To make a transaction connected to a specific username or bill number + in a Business, the PartySubIdOrType element should be used. + - DEVICE - A specific device (for example, a POS or ATM) ID connected to a + specific business or organization is used as reference to a Party. + For referencing a specific device under a specific business or organization, + use the PartySubIdOrType element. + - ACCOUNT_ID - A bank account number or FSP account ID should be used as + reference to a participant. The ACCOUNT_ID identifier can be in any format, + as formats can greatly differ depending on country and FSP. + - IBAN - A bank account number or FSP account ID is used as reference to a + participant. The IBAN identifier can consist of up to 34 alphanumeric + characters and should be entered without whitespace. + - ALIAS An alias is used as reference to a participant. The alias should be + created in the FSP as an alternative reference to an account owner. + Another example of an alias is a username in the FSP system. + The ALIAS identifier can be in any format. It is also possible to use the + PartySubIdOrType element for identifying an account under an Alias defined + by the PartyIdentifier. + - CONSENT - A Consent represents an agreement between a PISP, a Customer and + a DFSP which allows the PISP permission to perform actions on behalf of the + customer. A Consent has an authoritative source: either the DFSP who issued + the Consent, or an Auth Service which administers the Consent. + - THIRD_PARTY_LINK - A Third Party Link represents an agreement between a PISP, + a DFSP, and a specific Customer's account at the DFSP. The content of the link + is created by the DFSP at the time when it gives permission to the PISP for + specific access to a given account. + example: PERSONAL_ID + partyIdentifier: + title: PartyIdentifier + type: string + minLength: 1 + maxLength: 128 + description: Identifier of the Party. + example: '16135551212' + partySubIdOrType: + title: PartySubIdOrType + type: string + minLength: 1 + maxLength: 128 + description: 'Either a sub-identifier of a PartyIdentifier, or a sub-type of the PartyIdType, normally a PersonalIdentifierType.' + fspId: + $ref: '#/paths/~1services~1%7BServiceType%7D/put/requestBody/content/application~1json/schema/properties/providers/items' + extensionList: + $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - partyIdType + - partyIdentifier + description: Information about the Payer in the proposed financial transaction. + amountType: + allOf: + - title: AmountType + type: string + enum: + - SEND + - RECEIVE + description: |- + Below are the allowed values for the enumeration AmountType. + - SEND - Amount the Payer would like to send, that is, the amount that should be withdrawn from the Payer account including any fees. + - RECEIVE - Amount the Payer would like the Payee to receive, that is, the amount that should be sent to the receiver exclusive of any fees. + example: RECEIVE + description: 'SEND for sendAmount, RECEIVE for receiveAmount.' + amount: + allOf: + - title: Money + type: object + description: Data model for the complex type Money. + properties: + currency: + $ref: '#/paths/~1accounts~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/accountList/items/properties/currency' + amount: + title: Amount + type: string + pattern: '^([0]|([1-9][0-9]{0,17}))([.][0-9]{0,3}[1-9])?$' + description: 'The API data type Amount is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons. This pattern does not allow any trailing zeroes at all, but allows an amount without a minor currency unit. It also only allows four digits in the minor currency unit; a negative value is not allowed. Using more than 18 digits in the major currency unit is not allowed.' + example: '123.45' + required: + - currency + - amount + description: Requested amount to be transferred from the Payer to Payee. + transactionType: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/transactionType' + description: Type of transaction. + note: + type: string + minLength: 1 + maxLength: 256 + description: A memo that will be attached to the transaction. + expiration: + type: string + description: | + Date and time until when the transaction request is valid. It can be set to get a quick failure in case the peer FSP takes too long to respond. + example: '2016-05-24T08:38:08.699-04:00' + required: + - transactionRequestId + - payee + - payer + - amountType + - amount + - transactionType + - expiration + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/thirdpartyRequests/transactions/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + tags: + - thirdpartyRequests + - sampled + operationId: GetThirdpartyTransactionRequests + summary: GetThirdpartyTransactionRequests + description: | + The HTTP request `GET /thirdpartyRequests/transactions/{ID}` is used to request the + retrieval of a third party transaction request. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + tags: + - thirdpartyRequests + - sampled + operationId: UpdateThirdPartyTransactionRequests + summary: UpdateThirdPartyTransactionRequests + description: | + The HTTP request `PUT /thirdpartyRequests/transactions/{ID}` is used by the DFSP to inform the client about + the status of a previously requested thirdparty transaction request. + + Switch(Thirdparty API Adapter) -> PISP + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsIDPutResponse + type: object + description: 'The object sent in the PUT /thirdPartyRequests/transactions/{ID} request.' + properties: + transactionRequestState: + title: TransactionRequestState + type: string + enum: + - RECEIVED + - PENDING + - ACCEPTED + - REJECTED + description: |- + Below are the allowed values for the enumeration. + - RECEIVED - Payer FSP has received the transaction from the Payee FSP. + - PENDING - Payer FSP has sent the transaction request to the Payer. + - ACCEPTED - Payer has approved the transaction. + - REJECTED - Payer has rejected the transaction. + example: RECEIVED + required: + - transactionRequestState + example: + transactionRequestState: RECEIVED + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + patch: + operationId: NotifyThirdpartyTransactionRequests + summary: NotifyThirdpartyTransactionRequests + description: | + The HTTP request `PATCH /thirdpartyRequests/transactions/{ID}` is used to + notify a thirdparty of the outcome of a transaction request. + + Switch(Thirdparty API Adapter) -> PISP + tags: + - thirdpartyRequests + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsIDPatchResponse + type: object + description: 'The object sent in the PATCH /thirdpartyRequests/transactions/{ID} callback.' + properties: + completedTimestamp: + title: DateTime + type: string + pattern: '^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:(\.\d{3}))(?:Z|[+-][01]\d:[0-5]\d)$' + description: 'The API data type DateTime is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. The format is according to [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html), expressed in a combined date, time and time zone format. A more readable version of the format is yyyy-MM-ddTHH:mm:ss.SSS[-HH:MM]. Examples are "2016-05-24T08:38:08.699-04:00", "2016-05-24T08:38:08.699Z" (where Z indicates Zulu time zone, same as UTC).' + example: '2016-05-24T08:38:08.699-04:00' + transactionRequestState: + $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/transactionRequestState' + transactionState: + title: TransactionState + type: string + enum: + - RECEIVED + - PENDING + - COMPLETED + - REJECTED + description: |- + Below are the allowed values for the enumeration. + - RECEIVED - Payee FSP has received the transaction from the Payer FSP. + - PENDING - Payee FSP has validated the transaction. + - COMPLETED - Payee FSP has successfully performed the transaction. + - REJECTED - Payee FSP has failed to perform the transaction. + example: RECEIVED + required: + - transactionRequestState + - transactionState + example: + transactionRequestState: ACCEPTED + transactionState: COMMITTED + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/thirdpartyRequests/transactions/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + tags: + - thirdpartyRequests + - sampled + operationId: ThirdpartyTransactionRequestsError + summary: ThirdpartyTransactionRequestsError + description: | + If the server is unable to find the transaction request, or another processing error occurs, + the error callback `PUT /thirdpartyRequests/transactions/{ID}/error` is used. + The `{ID}` in the URI should contain the `transactionRequestId` that was used for the creation of + the thirdparty transaction request. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/parties/{Type}/{ID}': + parameters: + - name: Type + in: path + required: true + schema: + type: string + description: 'The type of the party identifier. For example, `MSISDN`, `PERSONAL_ID`.' + - name: ID + in: path + required: true + schema: + type: string + description: The identifier value. + - name: Content-Type + in: header + schema: + type: string + required: true + description: The `Content-Type` header indicates the specific version of the API used to send the payload body. + - name: Date + in: header + schema: + type: string + required: true + description: The `Date` header field indicates the date when the request was sent. + - name: X-Forwarded-For + in: header + schema: + type: string + required: false + description: |- + The `X-Forwarded-For` header field is an unofficially accepted standard used for informational purposes of the originating client IP address, as a request might pass multiple proxies, firewalls, and so on. Multiple `X-Forwarded-For` values should be expected and supported by implementers of the API. + + **Note:** An alternative to `X-Forwarded-For` is defined in [RFC 7239](https://tools.ietf.org/html/rfc7239). However, to this point RFC 7239 is less-used and supported than `X-Forwarded-For`. + - name: FSPIOP-Source + in: header + schema: + type: string + required: true + description: The `FSPIOP-Source` header field is a non-HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing and signature verification (see header field `FSPIOP-Signature`). + - name: FSPIOP-Destination + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-Destination` header field is a non-HTTP standard field used by the API for HTTP header based routing of requests and responses to the destination. The field must be set by the original sender of the request if the destination is known (valid for all services except GET /parties) so that any entities between the client and the server do not need to parse the payload for routing purposes. If the destination is not known (valid for service GET /parties), the field should be left empty.' + - name: FSPIOP-Encryption + in: header + schema: + type: string + required: false + description: The `FSPIOP-Encryption` header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request. + - name: FSPIOP-Signature + in: header + schema: + type: string + required: false + description: The `FSPIOP-Signature` header field is a non-HTTP standard field used by the API for applying an end-to-end request signature. + - name: FSPIOP-URI + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-URI` header field is a non-HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information, see [the API Signature document](https://github.com/mojaloop/docs/tree/master/Specification%20Document%20Set).' + - name: FSPIOP-HTTP-Method + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-HTTP-Method` header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information, see [the API Signature document](https://github.com/mojaloop/docs/tree/master/Specification%20Document%20Set).' + get: + description: 'The HTTP request `GET /parties/{Type}/{ID}` (or `GET /parties/{Type}/{ID}/{SubId}`) is used to look up information regarding the requested Party, defined by `{Type}`, `{ID}` and optionally `{SubId}` (for example, `GET /parties/MSISDN/123456789`, or `GET /parties/BUSINESS/shoecompany/employee1`).' + summary: Look up party information + tags: + - parties + operationId: PartiesByTypeAndID + parameters: + - name: Accept + in: header + required: true + schema: + type: string + description: The `Accept` header field indicates the version of the API the client would like the server to use. + responses: + '202': + description: Accepted + '400': + description: Bad Request + content: + application/json: + schema: + title: ErrorInformationResponse + type: object + description: Data model for the complex type object that contains an optional element ErrorInformation used along with 4xx and 5xx responses. + properties: + errorInformation: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema/properties/errorInformation' + headers: + Content-Length: + required: false + schema: + type: integer + description: |- + The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body. + + **Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes). + Content-Type: + schema: + type: string + required: true + description: The `Content-Type` header indicates the specific version of the API used to send the payload body. + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '405': + description: Method Not Allowed + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '406': + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '501': + description: Not Implemented + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '503': + description: Service Unavailable + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + put: + description: 'The callback `PUT /parties/{Type}/{ID}` (or `PUT /parties/{Type}/{ID}/{SubId}`) is used to inform the client of a successful result of the Party information lookup.' + summary: Return party information + tags: + - parties + operationId: PartiesByTypeAndID2 + parameters: + - name: Content-Length + in: header + required: false + schema: + type: integer + description: |- + The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body. + + **Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes). + requestBody: + description: Party information returned. + required: true + content: + application/json: + schema: + title: PartiesTypeIDPutResponse + type: object + description: 'The object sent in the PUT /parties/{Type}/{ID} callback.' + properties: + party: + title: Party + type: object + description: Data model for the complex type Party. + properties: + partyIdInfo: + title: PartyIdInfo + type: object + description: Data model for the complex type PartyIdInfo. An ExtensionList element has been added to this reqeust in version v1.1 + properties: + partyIdType: + title: PartyIdType + type: string + enum: + - MSISDN + - EMAIL + - PERSONAL_ID + - BUSINESS + - DEVICE + - ACCOUNT_ID + - IBAN + - ALIAS + description: |- + Below are the allowed values for the enumeration. + - MSISDN - An MSISDN (Mobile Station International Subscriber Directory Number, that is, the phone number) is used as reference to a participant. The MSISDN identifier should be in international format according to the [ITU-T E.164 standard](https://www.itu.int/rec/T-REC-E.164/en). Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix. + - EMAIL - An email is used as reference to a participant. The format of the email should be according to the informational [RFC 3696](https://tools.ietf.org/html/rfc3696). + - PERSONAL_ID - A personal identifier is used as reference to a participant. Examples of personal identification are passport number, birth certificate number, and national registration number. The identifier number is added in the PartyIdentifier element. The personal identifier type is added in the PartySubIdOrType element. + - BUSINESS - A specific Business (for example, an organization or a company) is used as reference to a participant. The BUSINESS identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the PartySubIdOrType element should be used. + - DEVICE - A specific device (for example, a POS or ATM) ID connected to a specific business or organization is used as reference to a Party. For referencing a specific device under a specific business or organization, use the PartySubIdOrType element. + - ACCOUNT_ID - A bank account number or FSP account ID should be used as reference to a participant. The ACCOUNT_ID identifier can be in any format, as formats can greatly differ depending on country and FSP. + - IBAN - A bank account number or FSP account ID is used as reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without whitespace. + - ALIAS An alias is used as reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias is a username in the FSP system. The ALIAS identifier can be in any format. It is also possible to use the PartySubIdOrType element for identifying an account under an Alias defined by the PartyIdentifier. + partyIdentifier: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0/properties/partyIdentifier' + partySubIdOrType: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0/properties/partySubIdOrType' + fspId: + $ref: '#/paths/~1services~1%7BServiceType%7D/put/requestBody/content/application~1json/schema/properties/providers/items' + extensionList: + $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - partyIdType + - partyIdentifier + merchantClassificationCode: + title: MerchantClassificationCode + type: string + pattern: '^[\d]{1,4}$' + description: 'A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, etc.' + name: + title: PartyName + type: string + minLength: 1 + maxLength: 128 + description: Name of the Party. Could be a real name or a nickname. + personalInfo: + title: PartyPersonalInfo + type: object + description: Data model for the complex type PartyPersonalInfo. + properties: + complexName: + title: PartyComplexName + type: object + description: Data model for the complex type PartyComplexName. + properties: + firstName: + title: FirstName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: First name of the Party (Name Type). + example: Henrik + middleName: + title: MiddleName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: Middle name of the Party (Name Type). + example: Johannes + lastName: + title: LastName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: Last name of the Party (Name Type). + example: Karlsson + dateOfBirth: + title: DateofBirth (type Date) + type: string + pattern: '^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$' + description: Date of Birth of the Party. + example: '1966-06-16' + required: + - partyIdInfo + required: + - party + responses: + '200': + description: OK + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/parties/{Type}/{ID}/error': + put: + description: 'If the server is unable to find Party information of the provided identity, or another processing error occurred, the error callback `PUT /parties/{Type}/{ID}/error` (or `PUT /parties/{Type}/{ID}/{SubI}/error`) is used.' + summary: Return party information error + tags: + - parties + operationId: PartiesErrorByTypeAndID + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/parties/{Type}/{ID}/{SubId}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - name: SubId + in: path + required: true + schema: + type: string + description: 'A sub-identifier of the party identifier, or a sub-type of the party identifier''s type. For example, `PASSPORT`, `DRIVING_LICENSE`.' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + description: 'The HTTP request `GET /parties/{Type}/{ID}` (or `GET /parties/{Type}/{ID}/{SubId}`) is used to look up information regarding the requested Party, defined by `{Type}`, `{ID}` and optionally `{SubId}` (for example, `GET /parties/MSISDN/123456789`, or `GET /parties/BUSINESS/shoecompany/employee1`).' + summary: Look up party information + tags: + - parties + operationId: PartiesSubIdByTypeAndID + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: 'The callback `PUT /parties/{Type}/{ID}` (or `PUT /parties/{Type}/{ID}/{SubId}`) is used to inform the client of a successful result of the Party information lookup.' + summary: Return party information + tags: + - parties + operationId: PartiesSubIdByTypeAndIDPut + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Party information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/parties/{Type}/{ID}/{SubId}/error': + put: + description: 'If the server is unable to find Party information of the provided identity, or another processing error occurred, the error callback `PUT /parties/{Type}/{ID}/error` (or `PUT /parties/{Type}/{ID}/{SubId}/error`) is used.' + summary: Return party information error + tags: + - parties + operationId: PartiesSubIdErrorByTypeAndID + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D~1%7BSubId%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/services/{ServiceType}': + parameters: + - name: ServiceType + in: path + required: true + schema: + type: string + description: 'The type of the service identifier. For example, `THIRD_PARTY_DFSP`' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + operationId: GetServicesByServiceType + summary: GetServicesByServiceType + description: | + The HTTP request `GET /services/{ServiceType}` is used to retrieve the list of participants + that support a specified service. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + tags: + - services + - sampled + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: | + The HTTP request `PUT /services/{ServiceType}` is used to return list of participants + that support a specified service. + operationId: PutServicesByServiceType + summary: PutServicesByServiceType + tags: + - services + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: ServicesServiceTypePutResponse + type: object + description: 'The object sent in a `PUT /services/{ServiceType}` request.' + properties: + providers: + type: array + minLength: 0 + maxLength: 256 + items: + title: FspId + type: string + minLength: 1 + maxLength: 32 + description: FSP identifier. + required: + - providers + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/services/{ServiceType}/error': + parameters: + - $ref: '#/paths/~1services~1%7BServiceType%7D/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + description: | + The HTTP request `PUT /services/{ServiceType}/error` is used to return error information + operationId: PutServicesByServiceTypeAndError + summary: PutServicesByServiceTypeAndError + tags: + - services + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' diff --git a/docs/technical/api/thirdparty/transaction-patterns-linking.md b/docs/technical/api/thirdparty/transaction-patterns-linking.md new file mode 100644 index 000000000..359d7b09e --- /dev/null +++ b/docs/technical/api/thirdparty/transaction-patterns-linking.md @@ -0,0 +1,415 @@ +--- +footerCopyright: Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) | Ericsson, Huawei, Mahindra-Comviva, Telepin, and the Bill & Melinda Gates Foundation +--- + +# Transaction Patterns - Linking + +Mojaloop Third Party API + +### Table Of Contents + +1. [Preface](#Preface) + 1.1 [Conventions Used in This Document](#ConventionsUsedinThisDocument) + 1.2 [Document Version Information](#DocumentVersionInformation) + 1.3 [References](#References) +2. [Introduction](#Introduction) + 2.1 [Third Party API Specification](#ThirdPartyAPISpecification) +3. [Linking](#Linking) + 3.1 [Pre-linking](#Pre-linking) + 3.2 [Discovery](#Discovery) + 3.3 [Request consent](#Requestconsent) + 3.4 [Authentication](#Authentication) + 3.5 [Grant consent](#Grantconsent) + 3.6 [Credential registration](#Credentialregistration) +4. [Unlinking](#Unlinking) + 4.1 [Unlinking without a Switch Hosted Auth Service](#UnlinkingwithoutaSwitchHostedAuthService) + 4.2 [Unlinking with a Switch Hosted Auth Service](#UnlinkingwithaSwitchHostedAuthService) +5. [Error Scenarios](#ErrorScenarios) + 5.1 [Discovery](#Discovery-1) + 5.2 [Bad consentRequests](#BadconsentRequests) + 5.3 [Authentication](#Authentication-1) + 5.4 [Grant consent](#Grantconsent-1) + +# 1. Preface + +This section contains information about how to use this document. + +## 1.1. Conventions Used in This Document + +The following conventions are used in this document to identify the +specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics with in angle brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature and API Encryption_ should be used instead.| + +## 1.2. Document Version Information + +| Version | Date | Change Description | +| --- | --- | --- | +| **1.0** | 2021-10-03 | Initial Version + +## 1.3. References + +The following references are used in this specification: + +| Reference | Description | Version | Link | +| --- | --- | --- | --- | +| Ref. 1 | Open API for FSP Interoperability | `1.1` | [API Definition v1.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md)| + + +# 2. Introduction + +This document introduces the transaction patterns supported by the Third Party API relating +to the establishment of a relationship between a User, a DFSP and a PISP. + +The API design and architectural style of this API are based on [Section 3](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#3-api-definition) of Ref 1. above. + +## 2.1 Third Party API Specification + +The Mojaloop Third Party API Specification includes the following documents: + +- [Data Models](./data-models.md) +- [Transaction Patterns - Linking](./transaction-patterns-linking.md) +- [Transaction Patterns - Transfer](./transaction-patterns-transfer.md) +- [Third Party Open API Definition - DFSP](./thirdparty-dfsp-v1.0.yaml) +- [Third Party Open API Definition - PISP](./thirdparty-dfsp-v1.0.yaml) + + +# 3. Linking + +The goal of the linking process is to explain how users establish trust between +all three interested parties: + +1. User +2. DFSP where User has an account +3. PISP that User wants to rely on to initiate payments + +Linking is broken down into several separate phases: + +1. **Pre-linking** + In this phase, a PISP asks what DFSPs are available to link with. +2. **Request consent** + In this phase, a PISP attempts to establish trust between the 3 parties. +3. **Authentication** + In this phase, a User proves their identity to their DFSP. +4. **Grant consent** + In this phase, a PISP proves to the DFSP that the User and PISP have + established trust and, as a result, the DFSP confirms that mutual trust + exists between the 3 parties. +5. **Credential registration** + In this phase, a User establishes the credential they'll use to consent to + future transfers from the DFSP and initiated by the PISP. + +## 3.1 Pre-linking + +In this phase, a PISP Server needs to know what DFSPs are available to link +with. This is *unlikely* to be done on-demand (e.g., when a User clicks "link" +in the PISP mobile App), and far more likely to be done periodically and cached +by the PISP Server. The reason for this is simply that new DFSPs don't typically +join the Mojaloop network all that frequently, so calling this multiple times on +the same day would likely yield the same results. We recommend that the PISP +calls this request once per day to keep the list of available DFSPs up to date. + +The end-goal of this phase is for the PISP Server to have a final list of DFSPs +available and any relevant metadata about those DFPSs that are necessary to +begin the linking process. + +The PISP can display this list of DFSPs to their user, and the user can select +which DFSP they hold an account with for linking. + +![Pre-linking](./assets/diagrams/linking/0-pre-linking.svg) + +## 3.2 Discovery + +In this phase, we ask the user to select the type and value of identifier they use +with the DFSP they intend to link with. This could be a username, MSISDN (phone number), +or email address. + +The result of this phase is a list of potential accounts available for linking. +The user will then choose one or more of these source accounts and the PISP will +provide these to the DFSP when requesting consent. + +The DFSP MAY send back an `accountNickname` to the PISP in the list of accounts. This list +will be displayed to the user in the PISP application for them to select which accounts +they wish to link. A DFSP could obfuscate some of the nickname depending on their requirements +for displaying account information without authorizing the user. + +**NOTE:** When using the Web authentication channel, it's possible that the +choices made (i.e., the accounts to link with) will be overridden by the user in +a web view. In other words, the user may decide during the Authentication phase +that they actually would like to link a different account than those chosen at +the very beginning. This is perfectly acceptable and should be expected from +time to time. + +![Discovery](./assets/diagrams/linking/1-discovery.svg) + +## 3.3 Request consent + +In this phase, a PISP is asking a specific DFSP to start the process of +establishing consent between three parties: + +1. The PISP +2. The specified DFSP +3. A User that is presumed to be a customer of the DFSP in (2) + +The PISPs request to establish consent must include a few important pieces of +information: + +- The authentication channels that are acceptable to the User +- The scopes required as part of the consent (in this case, almost always just + the ability to view a balance of a specific account and send funds from an + account). + +Some information depends on the authentication channel used (either Web or OTP). +Specifically, if the web authentication channel is used, the following extra +information is required: + +- A callback URI of where a user can be redirected with any extra information. + +The end result of this phase depends on the authentication channel used: + +### 3.3.1 Web + +In the web authentication channel, the result is the PISP being instructed on +a specific URL where this supposed user should be redirected. This URL should be +a place where the user can prove their identity (e.g., by logging in). + +![Request consent](./assets/diagrams/linking/2-request-consent-web.svg) + +### 3.3.2 OTP / SMS + +In the OTP authentication channel, the DFSP sends an 'out of bound' OTP message +to their user (e.g. over SMS or Email). The PISP prompts the user for this OTP +message, and includes it in the `authToken` field in the **PATCH /consentRequests/**_{ID}_ +callback. + +![Request consent](./assets/diagrams/linking/2-request-consent-otp.svg) + +## 3.4 Authentication + +In the authentication phase, the user is expected to prove their identity to the +DFSP. Once this is done, the DFSP will provide the User with some sort of secret +(e.g., an OTP or access token). This secret will then be passed along to the +PISP so that the PISP can demonstrate a chain of trust: + +- The DFSP trusts the User +- The DFSP gives the User a secret +- The User trusts the PISP +- The User gives the PISP the secret that came from the DFSP +- The PISP gives the secret to the DFSP +- The DFSP verified that the secret is correct + +This chain results in the conclusion: The DFSP can trust the PISP is acting on +behalf of the User, and mutual trust exists between all three parties. + +The process of establishing this chain of trust depends on the authentication +channel being used: + +### 3.4.1 Web + +In the web authentication channel, the PISP uses the `authUri` field from +the **PUT /consentRequests/**_{ID}_ callback to redirect the user to the DFSP's +website where they can prove their identity (likely by a typical username and +password style login). + + +**Note:** Keep in mind that at this stage, the User may update their choices of +which accounts to link with. The result of this will be seen later on when +during the Grant consent phase, where the DFSP will provide the correct values +to the PISP in the `scopes` field. + +![Authentication (Web)](./assets/diagrams/linking/3-authentication-web.svg) + + +### 3.4.2 OTP + +When using the OTP authentication channel, the DFSP will send the User some sort +of one-time password over a pre-established channel (such as SMS). The PISP +should prompt the user for this one-time password and then provide it back +to the DFSP using the API call **PATCH /consentRequests/**_{ID}_. + +![Authentication (OTP)](./assets/diagrams/linking/3-authentication-otp.svg) +## 3.5 Grant consent + +Now that mutual trust has been established between all three parties, the DFSP +is able to create a record of that fact by creating a new Consent resource. +This resource will store all the relevant information about the relationship +between the three parties, and will eventually contain additional information +for how the User can prove that it consents to each individual transfer in the +future. + +This phase consists exclusively of the DFSP requesting that a new consent be +created. + +![Grant consent](./assets/diagrams/linking/4-grant-consent.svg) + + +## 3.6 Credential registration + +Once the consent resource has been created, the PISP will attempt to establish +with the DFSP the credential that should be used to verify that a user has +given consent for each transfer in the future. + +This will be done by storing a FIDO credential (e.g., a public key) on the Auth +service inside the consent resource. When future transfers are proposed, we will +require that those transfers be digitally signed by the FIDO credential (in this +case, the private key) in order to be considered valid. + +This credential registration is composed of three phases: (1) deriving the +challenge, (2) registering the credential, and (3) finalizing the consent. + +### 3.6.1 Deriving the challenge + +The PISP must derive the challenge to be used as an input to the FIDO Key +Registration step. This challenge must not be guessable ahead of time by +the PISP. + + +1. _Let `consentId` be the value of the `body.consentId` in the **POST /consents** request_ +2. _Let `scopes` be the value of `body.scopes` in the **POST /consents** request_ + +3. The PISP must build the JSON object `rawChallenge` +``` +{ + "consentId": , + "scopes": +} +``` + +4. Next, the PISP must convert this json object to a string representation using a [RFC-8785 Canonical JSON format](https://tools.ietf.org/html/rfc8785) + +5. Finally, the PISP must calculate a SHA-256 hash of the canonicalized JSON string. +i.e. `SHA256(CJSON(rawChallenge))` + +The output of this algorithm, `challenge` will be used as the challenge for the [FIDO registration flow](https://webauthn.guide/#registration) + + +### 3.6.2 Registering the credential + +Once the PISP has derived the challenge, the PISP will generate a new +credential on the device, digitally signing the challenge, and provide additional +information about the credential on the Consent resource: + +1. The `PublicKeyCredential` object - which contains the key's Id, and an [AuthenticatorAttestationResponse](https://w3c.github.io/webauthn/#iface-authenticatorattestationresponse) which contains the public key +2. A `credentialType` field set to `FIDO` +3. A `status` field set to `PENDING` + +> **Note:** Generic `Credential` objects +> While we are focused on FIDO first, we don't want to exclude PISPs who want +> to offer services to users over other channels, eg. USSD or SMS, for this +> reason, the API also supports a `GENERIC` Credential type, i.e.: +>``` +> CredentialTypeGeneric { +> credentialType: 'GENERIC' +> status: 'PENDING', +> payload: { +> publicKey: base64(...), +> signature: base64(...), +> } +> } +>``` + +The DFSP receives the **PUT /consents/**_{ID}_ call from the PISP, and optionally +validates the Credential object included in the request body. The DFSP then +asks the Auth-Service to create the `Consent` object, and validate the Credential. + +If the DFSP receives a **PUT /consents/**_{ID}_ callback from the Auth-Service, with a +`credential.status` of `VERIFIED`, it knows that the credential is valid according +to the Auth Service. + +Otherwise, if it receives a **PUT /consents/**_{ID}_**/error** callback, it knows that something +went wrong with registering the Consent and associated credential, and can inform +the PISP accordingly. + + +The Auth service is then responsible for calling **POST /participants/CONSENTS/**_{ID}_. +This call will associate the `consentId` with the auth-service's `participantId` and +allows us to look up the Auth service given a `consentId` at a later date. + +![Credential registration: Register](./assets/diagrams/linking/5a-credential-registration.svg) + + +### 3.6.3 Finalizing the Consent + +Once the DFSP is satisfied that the credential is valid, it calls +**POST /participants/THIRD_PARTY_LINK/**_{ID}_ for each account in the +`Consent.scopes` list. This entry is a representation of the account +link between the PISP and DFSP, which the PISP can use to specify +the _source of funds_ for the transaction request. + +Finally, the DFSP calls **PUT /consent/**_{ID}_ with the finalized Consent +object it received from the Auth Service. + + +![Credential registration: Finalize](./assets/diagrams/linking/5b-finalize_consent.svg) + + +# 4. Unlinking + +At some point in the future, it's possible that a User, PISP, or DFSP may decide +that the relationship of trust previously established should no longer exist. +For example, a very common scenario might be a user losing their mobile device +and using an interface from their DFSP to remove the link between the lost +device, the PISP, and the DFSP. + +To make this work, we simply need to provide a way for a member on the network +to remove the Consent resource and notify the other parties about the removal. + + +There are 2 scenarios we need to cater for with a **DELETE /consents/**_{ID}_ request: +1. A DFSP-hosted Auth Service, where no details about the Consent are stored in the Switch, and +2. A Switch hosted Auth Service, where the Switch hosted auth service is considered the Authoritative source on the `Consent` object + + +## 4.1 Unlinking without a Switch Hosted Auth Service +In this case, the switch passes on the **DELETE /consents/22222222-0000-0000-0000-000000000000** request to the DFSP in the `FSPIOP-Destination` header. + +![Unlinking-DFSP-Hosted](./assets/diagrams/linking/6a-unlinking-dfsp-hosted.svg) + +In the case where Unlinking is requested from the DFSP's side, the DFSP can +simply call **PATCH /consents/22222222-0000-0000-0000-000000000000** to inform the PISP of an update to the +`Consent` object. + +## 4.2 Unlinking with a Switch Hosted Auth Service + +In this instance, the PISP still addresses it's **DELETE /consents/22222222-0000-0000-0000-000000000000** call to the +DFSP in the `FSPIOP-Destination` header. + +Internally, the switch will lookup the Authoritative source of the `Consent` object, +using the ALS Call, **GET /participants/CONSENT/**_{ID}_. If it is determined that there +is a Switch hosted Auth Service which 'owns' this `Consent`, the HTTP call **DELETE /consents/**_{ID}_ +will be redirected to the Auth Service. + +![Unlinking-Switch-Hosted](./assets/diagrams/linking/6b-unlinking-hub-hosted.svg) + +# 5.Error Scenarios + +## 5.1 Discovery + +When the DFSP is unable to find a user for the identifier in **GET /accounts/**_{ID}_, +the DFSP responds with error code `6205` in **PUT /accounts/**_{ID}_**/error**. + +![Accounts error](./assets/diagrams/linking/error_scenarios/1-discovery-error.svg) + +## 5.2 ConsentRequest Errors +When the DFSP receives the **POST /consentRequests** request from the PISP, the following processing errors +could occur: + +1. DFSP does not support the specified scopes: `6101`. For example, the `userId` specified does not match the specified accounts, or the `scope.actions` field contains permissions that this DFSP does not support. +2. The PISP sent a bad callbackUri: `6204`. For example, the scheme of the callbackUri could be http, which +the DFSP may choose to not trust. +3. Any other checks or validation of the consentRequests on the DFSP's side fail: `6104`. For example, the user's account may be inactive or suspended. + +In this case, the DFSP must inform the PISP of the failure by sending a **PUT /consentRequests/**_{ID}_**/error** callback to the PISP. + +![consentRequests error](./assets/diagrams/linking/error_scenarios/2-request-consent-error.svg) + +## 5.3 Authentication + +When a PISP sends a **PATCH /consentRequests/**_{ID}_ to the DFSP, the `authToken` may be expired or invalid: + +![Authentication Invalid OTP](./assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.svg) diff --git a/docs/technical/api/thirdparty/transaction-patterns-transfer.md b/docs/technical/api/thirdparty/transaction-patterns-transfer.md new file mode 100644 index 000000000..2b46f3c01 --- /dev/null +++ b/docs/technical/api/thirdparty/transaction-patterns-transfer.md @@ -0,0 +1,380 @@ +# Transaction Patterns - Transfer + +Mojaloop Third Party API + +### Table Of Contents + +1. [Preface](#Preface) + 1.1 [Conventions Used in This Document](#ConventionsUsedinThisDocument) + 1.2 [Document Version Information](#DocumentVersionInformation) + 1.3 [References](#References) +2. [Introduction](#Introduction) + 2.1 [Third Party API Specification](#ThirdPartyAPISpecification) +3. [Transfers](#Transfers) + 3.1 [Discovery](#Discovery) + 3.2 [Agreement](#Agreement) + 3.3 [Transfer](#Transfer) +4. [Request TransactionRequest Status](#RequestTransactionRequestStatus) +5. [Error Conditions](#ErrorConditions) + 5.1 [Bad Payee Lookup](#badpayeelookup) + 5.2 [Bad Thirdparty Transaction Request](#badtptr) + 5.3 [Downstream FSPIOP-API Failure](#downstreamapifailure) + 5.4 [Invalid Signed Challenge](#invalidsignedchallenge) + 5.5 [Thirdparty Transaction Request Timeout](#thirdpartytransactionrequesttimeout) +6. [Appendix](#Appendix) + 6.1 [Deriving the Challenge](#DerivingtheChallenge) + +# 1. Preface + +This section contains information about how to use this document. + +## 1.1. Conventions Used in This Document + +The following conventions are used in this document to identify the +specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics with in angle brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature and API Encryption_ should be used instead.| + +## 1.2. Document Version Information + +| Version | Date | Change Description | +| --- | --- | --- | +| **1.0** | 2021-10-03 | Initial Version + +## 1.3. References + +The following references are used in this specification: + +| Reference | Description | Version | Link | +| --- | --- | --- | --- | +| Ref. 1 | Open API for FSP Interoperability | `1.1` | [API Definition v1.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md)| + + +# 2. Introduction + +This document introduces the transaction patterns supported by the Third Party API relating +to the initiation of a Transaction Request from a PISP. + +The API design and architectural style of this API are based on [Section 3](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#3-api-definition) of Ref 1. above. + +## 2.1 Third Party API Specification + +The Mojaloop Third Party API Specification includes the following documents: + +- [Data Models](./data-models.md) +- [Transaction Patterns - Linking](./transaction-patterns-linking.md) +- [Transaction Patterns - Transfer](./transaction-patterns-transfer.md) +- [Third Party Open API Definition - DFSP](./thirdparty-dfsp-v1.0.yaml) +- [Third Party Open API Definition - PISP](./thirdparty-dfsp-v1.0.yaml) + + +# 3. Transfers + +Transfers is broken down into the separate sections: +1. **Discovery**: PISP looks up the Payee Party to send funds to + +2. **Agreement** PISP confirms the Payee Party, and looks up the terms of the transaction. If the User accepts the terms of the transaction, they sign the transaction with the credential established in the Linking API flow + +3. **Transfer** The Payer DFSP initiates the transaction, and informs the PISP of the transaction result. + +## 3.1 Discovery + +In this phase, a user enters the identifier of the user they wish to send funds to. The PISP executes a **GET /parties/**_{Type}/{ID}_** (or **GET /parties/**_{Type}/{ID}/{SubId}_) call and awaits a callback from the Mojaloop switch. [Section 6.3](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#63-api-resource-parties) +of Ref 1. above describes the **/parties** resource in detail. + +If the **GET /parties/**_{Type}/{ID}_ request is successful, the PISP will receive a **PUT /parties** callback from the Mojaloop switch. The PISP then confirms the Payee with their user. + +Should the PISP receive a **PUT /parties/**_{Type}/{ID}_**/error** (or **PUT /parties/**_{Type}/{ID}/{SubId}_**/error**) callback, the PISP should display the relevant error to their user. + + + +![Discovery](./assets/diagrams/transfer/1-1-discovery.svg) + +## 3.2 Agreement + +### 3.2.1 Thirdparty Transaction Request + +Upon confirming the details of the Payee with their user, the PISP asks the user to enter the `amount` of funds they wish to send to the Payee, and whether or not they wish the Payee to _receive_ that amount, or they wish to _send_ that amount (`amountType` field). + +If the User has linked more than 1 account with the PISP application, the PISP application can ask the user to choose an account they wish to send funds from. Upon confirming the _source of funds_ account, the PISP can determine: +1. the `FSPIOP-Destination` as the DFSP who the User's account is linked with +2. The `payer` field of the **POST /thirdpartyRequests/transactions** request body. The `partyIdType` is `THIRD_PARTY_LINK`, the `fspId` is the fspId of the DFSP who issued the link, and the `partyIdentifier` is the `accountId` specified in the **POST /consents#scopes** body. + +> See [Grant Consent](./transaction-patterns-linking.md#Grantconsent) for more information. + +The PISP then generates a random `transactionRequestId` of type UUID (see [RFC 4122 UUID](https://tools.ietf.org/html/rfc4122)). + +![1-2-1-agreement](./assets/diagrams/transfer/1-2-1-agreement.svg) + +Upon receiving the **POST /thirdpartyRequests/transactions** call from the PISP, the DFSP performs some validation such as: +1. Determine that the `payer` identifier exists, and is one that was issued by this DFSP to the PISP specified in the `FSPIOP-Source`. +2. Confirms that the `Consent` that is identified by the `payer` identifier exists, and is valid. +3. Confirm that the User's account is active and holds enough funds to complete the transaction. +4. Any other validation that the DFSP wishes to do. + +Should this validation succeed, the DFSP will generate a unique `transactionId` for the request, and call **PUT /thirdpartyRequests/transactions/**_{ID}_ with this `transactionId` and a `transactionRequestState` of `RECEIVED`. + +This call informs the PISP that the Thirdparty Transaction Request was accepted, and informs them of the final `transactionId` to watch for at a later date. + +If the above validation fail, the DFSP should send a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** call to the PISP, +with an error message communicating the failure to the PISP. See [Error Codes](./data-models.md#errorcodes) for more information. + +### 3.2.2 Thirdparty Authorization Request + +The Payer DFSP (that is, the institution sending funds at the request of the PISP) may then issue a quotation request (**POST /quotes**) to the Payee DFSP (that is, the institution receiving the funds). Upon receiving the **PUT /quotes/**_{ID}_ callback from the Payee DFSP, the Payer DFSP needs to confirm the details of the transaction with the PISP. + +They use the API call **POST /thirdpartyRequests/authorizations**. The request body is populated with the following fields: + +- `transactionRequestId` - the original id of the **POST /thirdpartyRequests/transactions**. Used by the PISP to correlate an Authorization Request to a Thirdparty Transaction Request +- `authorizationRequestId` - a random UUID generated by the DFSP to identify this Thirdparty Authorization Request +- `challenge` - the challenge is a `BinaryString` which will be signed by the private key on the User's device. While the challenge +could be a random string, we recommend that it be derived from something _meaningful_ to the actors involved in the transaction, +that can't be predicted ahead of time by the PISP. See [Section 4.1](#DerivingtheChallenge) for an example of how the challenge +could be derived. +- `transactionType` the `transactionType` field from the original **POST /thirdpartyRequests/transactions** request + + +![1-2-2-authorization](./assets/diagrams/transfer/1-2-2-authorization.svg) + + +### 3.2.3 Signed Authorization + +Upon receiving the **POST /thirdpartyRequests/authorizations** request from the Payer DFSP, the PISP presents the terms of the proposed +transaction to the user, and asks them if they want to proceed. + +The results of the authorization request are returned to the DFSP via the **PUT /thirdpartyRequests/authorizations/**_{ID}_, where +the *{ID}* is the `authorizationRequestId`. + + +If the user rejects the transaction, the following is the payload sent in **PUT /thirdpartyRequests/authorizations/**_{ID}_: + +```json +{ + "responseType": "REJECTED" +} +``` + +![1-2-3-rejected-authorization](./assets/diagrams/transfer/1-2-3-rejected-authorization.svg) + + +Should the user accept the transaction, the payload will depend on the `credentialType` of the `Consent.credential`: + +1. If `FIDO`, the PISP asks the user to complete the [FIDO Assertion](https://webauthn.guide/#authentication) flow to sign the challenge. + The `signedPayload.fidoSignedPayload` is the `FIDOPublicKeyCredentialAssertion` returned from the FIDO Assertion process. See [3.2.3.1 Signing the Challenge FIDO](#SigningTheChallengeFIDO) + +2. If `GENERIC`, the private key created during the [credential registration process](../linking/README.md#162-registering-the-credential) is + used to sign the challenge. See [3.2.3.2 Signing the Challenge with a GENERIC Credential](#SigningTheChallengeGeneric) + +#### 3.2.3.1 Signing the Challenge FIDO + +For a `FIDO` `credentialType`, the PISP asks the user to complete the [FIDO Assertion](https://webauthn.guide/#authentication) flow to sign the challenge. The `signedPayload.value` is the [`PublicKeyCredential`](https://w3c.github.io/webauthn/#publickeycredential) returned from the FIDO Assertion process, where the `ArrayBuffer`s are parsed as base64 encoded utf-8 strings. As a `PublicKeyCredential` is the response of both the FIDO Attestation and Assertion, we define the following interface: `FIDOPublicKeyCredentialAssertion`: + + +```json +FIDOPublicKeyCredentialAssertion { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" +} +``` + +The final payload of the **PUT /thirdpartyRequests/authorizations/**_{ID}_ is then: + +```json +{ + "responseType": "ACCEPTED", + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": FIDOPublicKeyCredentialAssertion + } +} +``` + +![1-2-3-signed-authorization-fido](./assets/diagrams/transfer/1-2-3-signed-authorization-fido.svg) + + +#### 3.2.3.2 Signing the Challenge with a GENERIC Credential + +For a `GENERIC` credential, the PISP will perform the following steps: + + +1. Given the inputs: + - `challenge` (`authorizationRequest.challenge`) as a base64 encoded utf-8 string + - `privatekey` (stored by the PISP when creating the credential), as a base64 encoded utf-8 string + - SHA256() is a one way hash function, as defined in [RFC6234](https://datatracker.ietf.org/doc/html/rfc6234) + - sign(data, key) is a signature function that takes some data and a private key to produce a signature +2. _Let `challengeHash` be the result of applying the SHA256() function over the `challenge`_ +3. _Let `signature` be the result of applying the sign() function to the `challengeHash` and `privateKey`_ + +The response from the PISP to the DFSP then uses this _signature_ as the `signedPayload.genericSignedPayload` field: + + +The final payload of the **PUT /thirdpartyRequests/authorizations/**_{ID}_ is then: + +```json +{ + "responseType": "ACCEPTED", + "signedPayload": { + "signedPayloadType": "GENERIC", + "genericSignedPayload": "utf-8 base64 encoded signature" + } +} +``` + +![1-2-3-signed-authorization-generic](./assets/diagrams/transfer/1-2-3-signed-authorization-generic.svg) + + +### 3.2.4 Validate Authorization + +> __Note:__ If the DFSP uses a self-hosted authorization service, this step can be skipped. + +The DFSP now needs to check that challenge has been signed correctly, and by the private key that corresponds to the +public key that is attached to the `Consent` object. + +The DFSP uses the API call **POST /thirdpartyRequests/verifications**, the body of which is comprised of: + +- `verificationRequestId` - A UUID created by the DFSP to identify this verification request. +- `challenge` - The same challenge that was sent to the PISP in [3.2.2 Thirdparty Authorization Request](#ThirdpartyAuthorizationRequest) +- `consentId` - The `consentId` of the Consent resource that contains the credential public key with which to verify this transaction. +- `signedPayloadType` - The type of the SignedPayload, depending on the type of credential registered by the PISP +- `fidoValue` or `genericValue` - The corresponding field from the **PUT /thirdpartyRequests/authorizations** request body from the PISP. +The DFSP must lookup the `consentId` based on the `payer` details of the `ThirdpartyTransactionRequest`. + +![1-2-4-verify-authorization](./assets/diagrams/transfer/1-2-4-verify-authorization.svg) + +## 3.3 Transfer + +Upon validating the signed challenge, the DFSP can go ahead and initiate a standard Mojaloop Transaction using the FSPIOP API. + +After receiving the **PUT /transfers/**_{ID}_ call from the switch, the DFSP looks up the ThirdpartyTransactionRequestId for the given transfer, +and sends a **PATCH /thirdpartyRequests/transactions/**_{ID}_ call to the PISP. + +Upon receiving this callback, the PISP knows that the transfer has completed successfully, and can inform their user. + +![1-3-transfer](./assets/diagrams/transfer/1-3-transfer.svg) + + +# 4. Request TransactionRequest Status + +A PISP can issue a **GET /thirdpartyRequests/transactions/**_{ID}_ to find the status of a transaction request. + +![PISPTransferSimpleAPI](./assets/diagrams/transfer/get_transaction_request.svg) + +1. PISP issues a **GET /thirdpartyRequests/transactions/**_{ID}_ +1. Switch validates request and responds with `202 Accepted` +1. Switch looks up the endpoint for `dfspa` for forwards to DFSP A +1. DFSPA validates the request and responds with `202 Accepted` +1. DFSP looks up the transaction request based on its `transactionRequestId` + - If it can't be found, it calls **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** to the Switch, with a relevant error message + +1. DFSP Ensures that the `FSPIOP-Source` header matches that of the originator of the **POST /thirdpartyRequests/transactions** + - If it does not match, it calls **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** to the Switch, with a relevant error message + +1. DFSP calls **PUT /thirdpartyRequests/transactions/**_{ID}_ with the following request body: + ``` + { + transactionRequestState: TransactionRequestState + } + ``` + + Where `transactionId` is the DFSP-generated id of the transaction, and `TransactionRequestState` is `RECEIVED`, `PENDING`, `ACCEPTED`, `REJECTED`, as defined in [7.5.10 TransactionRequestState](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7510-transactionrequeststate) of the API Definition + + +1. Switch validates request and responds with `200 OK` +1. Switch looks up the endpoint for `pispa` for forwards to PISP +1. PISP validates the request and responds with `200 OK` + +# 5. Error Conditions + +After the PISP initiates the Thirdparty Transaction Request with **POST /thirdpartyRequests/transactions**, the DFSP must send either a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** or **PATCH /thirdpartyRequests/transactions/**_{ID}_ callback to inform the PISP of a final status to the Thirdparty Transaction Request. + +- **PATCH /thirdpartyRequests/transactions/**_{ID}_ is used to inform the PISP of the final status of the Thirdparty Transaction Request. This could be either a Thirdparty Transaction Request that was rejected by the user, or a Thirdparty Transaction Request that was approved and resulted in a successful transfer of funds. +- **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** is used to inform the PISP of a failed Thirdparty Transaction Request. +- If a PISP doesn't receive either of the above callbacks within the `expiration` DateTime specified in the **POST /thirdpartyRequests/transactions**, it can assume the Thirdparty Transaction Request failed, and inform their user accordingly + + +## 5.1 Unsuccessful Payee Lookup + +When the PISP performs a Payee lookup (**GET /parties/**_{Type}/{ID}_), they may receive the callback **PUT /parties/**_{Type}/{ID}_**/error**. + +See [6.3.4 Parties Error Callbacks](https://docs.mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html#634-error-callbacks) of the FSPIOP API Definition for details on how to interpret use this error callback. + +In this case, the PISP may wish to display an error message to their user informing them to try a different identifier, or try again at a later stage. +## 5.2 Bad Thirdparty Transaction Request + +When the DFSP receives the **POST /thirdpartyRequests/transactions** request from the PISP, the following processing or validation errors may occur: +1. The `payer.partyIdType` or `payer.partyIdentifier` is not valid, or not linked with a valid **Consent** that the DFSP knows about +2. The user's account identified by `payer.partyIdentifier` doesn't have enough funds to complete the transaction +3. The currency specified by `amount.currency` is not a currency that the user's account transacts in +4. `payee.partyIdInfo.fspId` is not set - it's an optional property, but payee fspId will be required to properly address quote request +5. Any other checks or verifications of the transaction request on the DFSP's side fail + +In this case, the DFSP must inform the PISP of the failure by sending a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** callback to the PISP. + +![3-2-1-bad-tx-request](./assets/diagrams/transfer/3-2-1-bad-tx-request.svg) + +The PISP can then inform their user of the failure, and can ask them to restart the Thirdparty Transaction request if desired. + + +## 5.3 Downstream FSPIOP-API Failure + +The DFSP may not want to (or may not be able to) expose details about downstream failures in the FSPIOP API to PISPs. + +For example, before issuing a **POST /thirdpartyRequests/authorizations** to the PISP, if the **POST /quotes** call with the Payee FSP fails, the DFSP sends a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** callback to the PISP. + +![3-3-1-bad-quote-request](./assets/diagrams/transfer/3-3-1-bad-quote-request.svg) + +Another example is where the **POST /transfers** request fails: + +![3-3-2-bad-transfer-request](./assets/diagrams/transfer/3-3-2-bad-transfer-request.svg) + + +## 5.4 Invalid Signed Challenge + +After receiving a **POST /thirdpartyRequests/authorizations** call from the DFSP, the PISP asks the user to sign the `challenge` using the credential that was registered during the account linking flow. + +The signed challenge is returned to the DFSP with the call **PUT /thirdpartyRequest/authorizations/**_{ID}_. + +The DFSP either: +1. Performs validation of the signed challenge itself +2. Queries the Auth-Service with the **thirdpartyRequests/verifications** resource to check the validity of the signed challenge against the publicKey registered for the Consent. + +Should the signed challenge be invalid, the DFSP sends a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** callback to the PISP. + + +### Case 1: DFSP self-verifies the signed challenge + +![3-4-1-bad-signed-challenge-self-hosted](./assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.svg) + + +### Case 2: DFSP uses the hub-hosted Auth-Service to check the validity of the signed challenge against the registered credential. + +![3-4-2-bad-signed-challenge-auth-service](./assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.svg) + +## 5.5 Thirdparty Transaction Request Timeout + +If a PISP doesn't receive either of the above callbacks within the `expiration` DateTime specified in the **POST /thirdpartyRequests/transactions**, it can assume the Thirdparty Transaction Request failed, and inform their user accordingly. + + +![3-6-tpr-timeout](./assets/diagrams/transfer/3-6-tpr-timeout.svg) + +# 6. Appendix + +## 6.1 Deriving the Challenge + +1. _Let `quote` be the value of the response body from the **PUT /quotes/**_{ID}_ call_ +2. _Let the function `CJSON()` be the implementation of a Canonical JSON to string, as specified in [RFC-8785 - Canonical JSON format](https://tools.ietf.org/html/rfc8785)_ +3. _Let the function `SHA256()` be the implementation of a SHA-256 one way hash function, as specified in [RFC-6234](https://tools.ietf.org/html/rfc6234)_ +4. The DFSP must generate the value `jsonString` from the output of `CJSON(quote)` +5. The `challenge` is the value of `SHA256(jsonString)` \ No newline at end of file diff --git a/docs/technical/api/thirdparty/transaction-patterns.md b/docs/technical/api/thirdparty/transaction-patterns.md new file mode 100644 index 000000000..5110f83e0 --- /dev/null +++ b/docs/technical/api/thirdparty/transaction-patterns.md @@ -0,0 +1,6 @@ +## Transaction Patterns + +The interactions and examples of how a DFSP and PISP will interact with the Third Party API can be found in the following Transaction Patterns Documents: + +1. [Linking](./transaction-patterns-linking.md) describes how an account link and credential can be established between a DFSP and a PISP +2. [Transfer](./transaction-patterns-transfer.md) describes how a PISP can initate a payment from a DFSP's account using the account link \ No newline at end of file diff --git a/docs/technical/business-operations-framework/Microfrontend-JAMStack.md b/docs/technical/business-operations-framework/Microfrontend-JAMStack.md new file mode 100644 index 000000000..666f21f27 --- /dev/null +++ b/docs/technical/business-operations-framework/Microfrontend-JAMStack.md @@ -0,0 +1,266 @@ +# Micro-frontend - JAMStack design +## Overview +The objective of the micro-frontend - JAMStack design is to create a framework that: + +- empowers the community to collaborate easily (by enabling independent development of components) +- makes extensions or customizations easy +- enables community members to contribute back into OSS without branching the whole codebase + +### Micro-frontends +The framework uses micro-frontends as a means of decoupling parts of the UI to enable maintainable codebases, autonomous teams, independent releases, and incremental upgrades of parts of the UI. + +### JAMStack +The [JAMStack](https://jamstack.org/) implementation reduces the role of the web server to the distribution static markup files, keeping the functionallity in JavaScript (that is running in the client browser) and in the backend API. +:::warning JAMStack stands for: + **J** - JavaScript + **A** - APIs + **M** - Static markup + ::: +This stack implementation is considered best practice as it: +- is much simpler to keep secure +- provides a good customer experience as it has fast web response times +- is inexpensive to host + +In addition, the following have also been engineered and are normally part of a JAMStack implementation: +- deployment to a content delivery network (CDN) +- atomic deploys +- uses dynamically loaded micro-frontends, so updating to the latest version is automatic + +## Technology stack + +1. **React** +The framework is based on the React library. +This is the most popular Single Page Application (SPA) library in use, and additionally this choice allows us to capitalize on other community efforts facilitating an easy conversion into this library. +It can be enhanced by using state container libraries (Redux, Flux, MobX), however there is no restriction on a specific one to use. +The micro-frontends come with preconfigured, isolated Redux stores. + +2. **Webpack 5** +Webpack 5 is currently the only JavaScript bundler that supports remote build separation. It is done by using the Module Federation Plugin. +It enables runtime composition to provide a smooth and fully transparent user experience to the users, resulting in a traditional Single Page Application. +There are additional benefits over other technologies, all that resulting in a small footprint and overall better experience for users. +Webpack 5 will implement the host / child micro-frontends integration at runtime. + +3. **CI/CD and atomic deployments** (for example, Github Actions) +Each implementation of the Business Operations Framework will need to implement their own atomic deployment solution. +The standard Business Operations project will use Github Actions to perform the task of executing a continuous integration pipeline, running the relevant tests, building the individual micro-frontend and deploying the resulting static files over a CDN and/or creating a Docker image. +Each micro-frontend is released in complete autonomy: the composed application can use the updated versions of each individual micro-frontend automatically, without involving any further coordination. + +4. **Running on a CDN** +The micro-frontends can run on a CDN. Individual builds are composed of only static files (HTML, CSS, JavaScript) and can be deployed in different locations / different URLs. +As long as they are available over a secure connection (HTTPS), micro-frontends can be served from any location and also from different CDNs. + +5. **Running in Kubernetes** +The micro-frontends can run in a Kubernetes environment. There are two approaches that can be taken here: + - The individual micro-frontends and the shell application are containerized (using, for example, Docker) and then hosted in Kubernetes. +The host and the children apps can be deployed on the same cluster or on different clusters as long as they are publicly accessible. + - Deploy a private CDN into the Kubernetes cluster, and host the static markup files on the CDN. +There are various CDNs available that are compatible with Kubernetes. + +## Webpack building + +The host and the children apps include scripts to build the distribution artifacts. The build can be done in the developer host machine, in the CI, and in Docker. + +## Micro-frontend loading + +The host is responsible for loading the children apps at runtime. It gathers information about the available children at runtime, from either an API or a registry. + +The host includes an internal engine responsible for loading only the necessary children when they need to be displayed. + +The individual micro-frontends will not be loaded when not necessary (for example, when a specific page is not accessed by the user). + +**High-level sequence diagram illustrating how microservices are loaded** +![High level sequence diagram illustrating how microservices are loaded](../../.vuepress/public/microfrontendloading.png) + +### Repository of micro-frontends +In order to provide a centralized authority responsible for controlling the individual micro-frontends meeting the necessary requirements, it is suggested to build a solution that works as a registry. + +The registry would serve the following purposes: + +1. allow the community to register the micro-frontends and specify some details +2. expose an API used by the host to retrieve information about the available micro-frontends +3. provide information around the versions of the available micro-frontends + +The registry does not exist yet, nor does it make sense to create it at this time. + +## Deployments + +The following overview diagram shows the deployment of the micro-frontends to a CDN. +::: tip NOTE +The deployment of the bounded context API is not covered in this diagram. +::: +![Overview diagram showing deployment](../../.vuepress/public/BizOps-Framework-Micro-frontend-deploy.png) + +The micro-frontends use atomic deployments and no full-build is ever required. + +Each individual micro-frontend deploys independently from the other ones. + +### Continuous Integration / Continuous Delivery (CI/CD) + +Each micro-frontend has its own CI/CD set up; there is no requirement to share the same setup or use the same CI tool. + +The CI/CD can be configured to support multiple environments, for example, DEV, QA, PROD. + +Here is an example file showing a git action workflow. + +```yml +# This is a basic workflow to help you get started with Actions + +name: CI + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the master branch +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [16.x] + + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + + # Runs a single command using the runners shell + - name: Use NodeJS ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: Cache node modules + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + # npm cache files are stored in `~/.npm` on Linux/macOS + path: '**/node_modules' + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + - run: yarn install --frozen-lockfile + - run: yarn lint + - run: yarn test + - run: yarn build +# - name: Slack Notification +# uses: rtCamp/action-slack-notify@v2.0.2 +# env: +# SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} +``` + +### CDNs + +The resulting SPA is served by a CDN or multiple CDNs. Individual micro-frontends can live in different CDNs. + +### Kubernetes + +The resulting SPA can run and be served in one or more Kubernetes environments. + +### Host application + +The host application comes with a pre-configured setup out-of-the-box. It does not need any particular configuration different from a traditional SPA more than the Webpack 5 Module Federation configuration. +It will be acting as the orchestrator, loading the remote micro-frontends and providing them with app-wide functionality, for example, authentication, RBAC, client-side routing. + +There is virtually no limit on how the host can grow and how much can be extended. +It is suggested, however, to centralize all the host-child communication and shared components in an external library so that both host and children have the same knowledge and integration will not break. + +### Versioning micro-frontends +​The suggested approach is to build a registry where individual apps are registered. The registry would allow to set some configuration on each app and keep track of all the available versions. +​ +The registry would then expose an API consumed by the host, providing information around the available micro-frontends, the versions, and the artifact locations. +​ +The registry would be administered by a trusted operator through a user interface; it would be the trusted operator's responsibility to decide which version of each individual app would be made public and available to the host to load. +It would also allow to easily test versions and roll back when necessary, all that without needing to rebuild and redeploy the apps. +​ +::: tip NOTE +The JS build artifacts created by Webpack do not include the version in the filename. It could be necessary to upgrade the build in order to differentiate versions. A simpler approach that does not require to update the build configuration would be hosting the versions on different URLs. +::: +​ +### Upgrading the host +​The host is pretty much self-isolated and the only necessary thing to do proper versioning is to use the built-in command `yarn version`. It will create a new git tag and increment the `package.json` version according to how the command is used (interactive CLI). +​ +### Upgrading the remotes +​The remotes are self-isolated and the only necessary thing to do proper versioning is to use the built-in command `yarn version`. It will create a new git tag and increment the `package.json` version according to how the command is used (interactive CLI). + +### Menu / App composition +​The host is configured to dynamically build the _Menu_ and the _Pages_ (with react-router) structure. Currently, the _Menu_ component(s) is imported from the `@modusbox/react-components` library. +​ +It is not strictly necessary to use such components and the host / remotes could use custom components, as long as they allow dynamic composition and support routing. +​​ +## Micro-frontend motivation in more detail + +​Building scalable and distributed user interfaces is complicated; logic complexity, testing setups, build and deployment costs increase over time. ​Architectural decisions taken in the initial phase can raise unnecessary complexity and highly affect development costs in later stages.​ Furthermore, a single project does not scale well with distributed teams co-working on the same codebase.​ Switching to a micro-frontend setup can solve all the above issues; it scales well, atomic deployments do not need a full build, and independent teams can use different codebases.​​ + +### What defines a micro-frontend + +​The main rules that can define a micro-frontend setup can be summarized in the following:​ + +**Single responsibility** +Defined and closed boundaries +Centralized orchestration​ +Single responsibility +​Each micro-frontend app should only provide specific business features. A micro-frontend app does not need to know about other aspects of the business and it can scale independently.​ + +**Defined and closed boundaries** +​Each micro-frontend should be isolated, own its own data, and direct communication between micro-frontends should not be possible.​ + +**Centralized orchestration** +​Each micro-frontend should be loaded, handled, and controlled by a host. Application-wide features are provided by the host (authentication, routing, and so on).​​ + +### Types of micro-frontend setups + +​There are several ways to implement micro-frontends, to list a few:​ +- Iframe composition +- Runtime composition +- Module federation (single framework) composition​ + +**Iframe composition** +​Iframe composition is possibly the oldest and easiest way to implement micro-frontends, due to old HTML support to iframes and the native context isolation it provides. Communication between the host and the micro-frontends is generally hard to achieve and also does not fit well in modern web.​ + +**Runtime composition** +​Runtime composition is the idea of dynamically loading JS scripts located over http/https urls and compose the result locally. ​While it allows you to theoretically use independent technologies for each micro-frontend, it is also very hard to maintain due to the differences between the frameworks used in the micro-frontends.​​ + +**SPA composition** +​Module federation is a technology implemented in Webpack 5 that allows you to dynamically load remote modules at runtime. When combined with a single application framework (for example, React), it allows built applications to be split into multiple micro-frontends without sacrificing the benefits an SPA provides. It also comes with the advantage of smaller build sizes.​​ + +### The chosen setup + +We have chosen to use SPA composition using Webpack 5 and React. It is worth mentioning that in order to build an SPA with multiple micro-frontends, a specific and rigorous contract between the host and the frontends needs to be implemented and respected.​ From now on we will be referring to micro-frontends in the technical form used by Webpack 5: remotes. ​The contract is defined by the following rules:​ + +- The host retrieves the list of remotes dynamically and asynchronously +- The host is responsible of loading the remotes +- The host shares some context with the remotes (routing, authentication) +- The remotes have unique names +- The remotes are deployed in different urls +- The remotes do not use global CSS rules +- The remotes export themselves as defined by the modules federation rules +- The remotes share the same React (and some library) version​ + +When these rules are respected, there is virtually no limit to how the SPA can grow.​ Most of the basic dependencies used in each frontend are provided by the host. That makes it easy when they need to be upgraded. ​Each application is built independently from the others; the CI/CD pipeline remains fast, atomic deployments do not require complex setups and each remote is released at its own pace with no need to modify the host in any way.​ + +### Live example hosted on a CDN + +Check out the following live example: [https://microfrontend-shell-boilerplate.vercel.app/](https://microfrontend-shell-boilerplate.vercel.app/) + +## Git repositories + +Here is a list of Git repositories that are part of this implementation: + + - [Micro frontend-shell-boilerplate](https://github.com/mojaloop/microfrontend-shell-boilerplate) + - [Micro frontend-boilerplate](https://github.com/mojaloop/microfrontend-boilerplate) + - [Micro frontend-utils](https://github.com/modusintegration/microfrontend-utils) +Library shared with both the shell application and the micro-frontend. + - [Reporting-Hub BizOps Role Assignment Micro-frontend](https://github.com/mojaloop/reporting-hub-bop-role-ui) + - [Reporting-Hub BizOps Transaction Tracing Micro-frontend](https://github.com/mojaloop/reporting-hub-bop-trx-ui) + diff --git a/docs/technical/business-operations-framework/README.md b/docs/technical/business-operations-framework/README.md new file mode 100644 index 000000000..b6690c1f7 --- /dev/null +++ b/docs/technical/business-operations-framework/README.md @@ -0,0 +1,58 @@ +# Introduction + +Join the collaboration for building a **“get started quickly”** set of core business processes that are easy to customize, contribute to open source, and follow best practice. + +The Business Operations Framework aims to help Hub Operators in building and deploying business process portals that support their business processes as defined in [Mojaloop business documentation](https://docs.mojaloop.io/mojaloop-business-docs/). The Business Operations Framework supports community collaboration in building a user experience (UX) for a Mojaloop Hub Operator that includes robust APIs, follows best practices, and is secure by design. The aim is to further support adoption and enhance the off-the-shelf value of the Mojaloop solution. + +The resulting user interface (UI) is not intended to be comprehensive, but to demonstrate an exemplar web experience that is easy to extend and customize. It is therefore important that Role Based Access Control (RBAC), interfacing with standard Identity Access Management (IAM) systems, API-level security control, micro-frontends and maker-checker workflows are supported. The UX architecture follows a pre-compiled bundle with a backing API pattern that can be deployed on a Content Delivery Network (CDN). + +This document provides a more detailed design, including security aspects, technologies used, and architecture patterns. + +The framework: +1. Implements a best practice RBAC and IAM integration/implementation. +2. Includes a deployment plan for including the RBAC and IAM solution into Mojaloop. +3. Includes a deployment plan for the UI portal so that it can be deployed into a CDN network. +4. Uses micro-frontends that are built from different repositories to decouple community efforts and facilitate easy extension and customizations. +5. Provides an audit trail of all activities performed. + +Three levels or degrees of control are required when configuring best practice security: +1. Daily access to IAM user interfaces where users are created, suspended, and their roles assigned. +2. Mappings of roles to permissions, which can be edited through a configuration change request. +3. Restrictions on API access on the basis of permissions available to a subject (a user or API client) through their roles. + +## Community effort – to-do list +The initial delivery of this framework includes a thin vertical slice to demonstrate the end-to-end functional implementation of the framework. Although this function that is delivered first serves an important puropse, this is not the end objective of this project. The objective is to provide a framework that other community efforts can contribute to. Here is the current to-do list of API backend process support/micro-frontends that are intended to be added to this framework by Mojaloop community implementation efforts: + +|Category|Description|Contributing Community Effort| +| --- | --- | --- | +|**Platform configuration**|Process to configure the platform so that it enforces the scheme and the scheme rules.| - | +|**Platform management**|Technical operational management controls for the platform.| Currently performed with Kibana Application Performance Monitoring (APM) and Elasticsearch. No current plan to move to framework. | +|**Liquidity management**|Process support for managing liquidity.|Financial Portal V2 - not yet part of framework.| +|**Participant lifecycle management
    (Hub view)**|Manage the onboarding and status transitions of participants.|Financial Portal V2 - not yet part of framework.| +|**Participant lifecycle management
    (DFSP view)**|Allow DFSPs to manage their status and interaction with the Hub.| - | +|**Settlement management**|Management interface for settlement.|DFSP reconciliation reports - Myanmar MFI Digitization (MMD) reports are being incorporated into the framework (accessed through an API).
    Multilateral deferred net settlement - Financal Portal V2 not yet available in framework.| +|**Transfer and transaction management**| Business Operations view of all transactions at the hub. | Financial Portal V2 - being converted into framework with enhancements. Enabling the tracing of a transfer end-to-end. | +|**Agreement (quoting) management**| - | - | +|**Account lookup and discovery management**| - | - | +|**Third-party-initiated payments management**| - | - | +|**Fees (interchange and billing) management**| - | - | +|**Reporting and analytics**| - | - | + +## Reference architecture +The reference architecture workstream has - through a collaborative process - designed the future/next version architecture of Mojaloop. The Business Operations Framework is being designed to work on the existing Mojaloop version (core v1.0). The Business Operations Framework must, however, be compatible with the reference architecture, and wherever possible, facilitate the move towards the reference architecture design. + +The following elements of the Business Operations framework project are directly contributing to the building of a reference architecture: +1. **Security bounded context** +This workstream RBAC implementation used some of the design ideas and seperations as defined in the reference architecture security bounded context. It didn't implement any of the interfaces what are necessry to consider this a security BC implementation. +2. **Reporting bounded context** +Part of the reporting bounded context is being built in this workstream. + +The split of the frontend into micro-frontends that can be built, tested, and released independently; empowering teams that create solutions within each bounded context to independently build API functionality and corresponding UI. Customizations and extensions to each bounded context are also easily supported with this design. + +Here is an overall view of how the operational APIs, experience APIs, and micro-frontends can be combined into the parts that form the Business Operations framework. + +![Architecture overview diagram compatible with the reference architecture ](../../.vuepress/public/BizOps-Framework-BizOps-Framework.png) + + +## IaC 4.xx +The next version of the "Infrastrcuture as Code" project plans on using a different set of tools than those currently in use in the Mojaloop Community; i.e. WSO2 with its Identity Server as a Key Manager (IS-KM) and the HAproxy implementations are to be replaced with Keycloak, Ambassador - Envoy tools. This design is compatible with the next IaC version. \ No newline at end of file diff --git a/docs/technical/business-operations-framework/ReportDeveloperGuide.md b/docs/technical/business-operations-framework/ReportDeveloperGuide.md new file mode 100644 index 000000000..fd6adf7ab --- /dev/null +++ b/docs/technical/business-operations-framework/ReportDeveloperGuide.md @@ -0,0 +1,319 @@ +# Report Developer Guide +This is a developer guide to building and deploying reports for the reporting REST service that is part of the deployment at the Hub. + +## Architecture +![Architecture diagram of reporting service operator](../../.vuepress/public/RestReportingArchitecture.drawio.png) +[Here](https://github.com/mojaloop/reporting) is the repository of the reporting service operator. +The reporting service operator has been designed to be accessed by either a hub operator, or a DFSP operator. +Access to the report is controlled through the RBAC integration that is part of the business operations framework. Ory Oathkeeper protects the reporting API end point, and Keto is checked by the reporting service operator for finer grained report specific authorisation. +The report data is queried from the SQL Reporting database which is at the moment a one way sync of the central ledger database. +Each report is installed on the system as a kubernetes custom resource which is a .yaml file of a particular format that is applied to the kubernetes cluster. [Here](https://github.com/mojaloop/reporting-k8s-templates) is the repository of the open sourced report templates. The custom resource definition for a report is defined [here](https://github.com/mojaloop/reporting-k8s-templates/blob/master/crds/reporting-crd.yaml) which describes the format of the custom resource. + +## RBAC +Access to the reports are controlled through the RBAC when the service is deployed through the standard IaC configuration. +This means that in order to access a report, a user will need to have the correct authorisation assigned. This is acheived through the assignement of roles to the user, and the assignment of participant access. + +The first authorisation check is made by Ory Oathkeeper which has a rule that links the +``` +reportingApi +``` +perission to assess to the reporting service API endpoint. + +The next authorisation check is made by the reporting service operator. Permission to access the particulat report is checked. The permission that is checked is defined in the custom resource. This permission is optional and will otherwise use the name (metadata) of the report as defined in the customer resource. +### Requiring DFSP permission +If the report is intended for a particular participant of DFSP, then it is imporant to use the 'dfspId' parameter. This paramter then first check for participant authoriasation before executing and producing the report. +I.e. +``` yaml + params: + - name: dfspId + required: true +``` +### Running the report +First you will need to login. The easiest way of doing this is to login to the Financial Portal. This create the authorisation and authentication cookie tokens which the report then uses. +Here is an example of accessing the report directly after loggin. +``` +https://bofportal.YourEnvironment.YourDomain.com/proxy/reports/MyReportPath?ReportParamter=25 +``` + +### report output formats +The report supports multiple output formats. To switch between these use the format paramter in the Rest query. +1. Excel file +``` +&format=xlsx +``` +2. Comma seperated values +``` +&format=csv +``` +3. JSON class format +``` +&format=json +``` +4. HTML browser format (this is the default format output) +``` +&format=html +``` + +## Kubernetes Custom Resource +All aspects of a report are controlled through the mojaloopreport custome resource file. The definition of that file looks as follows. + +### Custom Resource Definition +``` yml +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1 +metadata: + name: mojaloopreports.mojaloop.io +spec: + group: mojaloop.io + scope: Namespaced + names: + plural: mojaloopreports + singular: mojaloopreport + shortNames: + - mlreport + kind: MojaloopReport + listKind: MojaloopReportList + versions: + - name: v1 + served: true + storage: true + schema: + openAPIV3Schema: + description: MojaloopReport is the Schema for MojaloopReport API + type: object + properties: + apiVersion: + description: >- + APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the + latest internal value, and may reject unrecognized values. More + info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: >- + Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the + client submits requests to. Cannot be updated. In CamelCase. + More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: MojaloopReport.spec describes the desired state of my resource + type: object + required: + - endpoint + - queries + - template + properties: + permission: + description: Permission to be needed to access this report. This is optional. If unspecified, the name of the resource will be considered as permission. + type: string + endpoint: + description: Reporting endpoint + type: object + required: + - path + properties: + path: + description: Report URL path + type: string + params: + description: Report query params + type: array + items: + description: Query param + type: object + required: + - name + properties: + name: + description: Query param name + type: string + required: + description: Make query param required + type: boolean + default: + description: Default query param value + type: string + queries: + description: The list of queries used in ejs reporting template + type: array + items: + description: permission ID. + type: object + required: + - name + - query + properties: + name: + description: Variable name that the query result will be assigned to + type: string + query: + description: SQL query + type: string + template: + description: ejs reporting template + type: string + + status: + description: The status of this MojaloopReport resource, set by the operator. + type: object + properties: + state: + description: The state of the report. + type: string + additionalPrinterColumns: + - name: endpoint + type: string + description: Reporting endpoint + jsonPath: .spec.endpoint.path + conversion: + strategy: None +``` +Example of reports that conform to this custom resource can be found [here](https://github.com/mojaloop/reporting-k8s-templates/tree/master/templates). +Please note that these Yaml files also contain **helm directives** in these files denoted by the double curly brackets. +``` +{{ some helm directive / function }} +``` +If you intend to manually apply these files to kubernetes, these will need to be removed or replaced. + +### Kubectl +You can use the following command to apply a report custom resource to a kubernetes instance. + ``` + kubectl apply -f resources/examples/participant_list.yaml + ``` + +Let's cover some of the details in the custome resource. + +### Control how the report is called +The first part of the spec: of the report defines how the report is called. +I.e. +``` yaml +spec: + permission: report-dfsp-settlement-detail + endpoint: + path: /dfspSettlementDetail + params: + - name: settlementId + required: true + - name: fspid + required: true +``` +- **permission** this is where the RBAC permission tag for this report is defined +- **path** this is the endpoint path for this report +- **params** here the paramters for the report are defined and specified if they are required paramters or not. + +### Control where the report gets it data from +``` yaml +queries: + - name: dfspInfo + query: | + SELECT participantId, name FROM participant WHERE name = :fspid AND name != 'Hub' + - name: report + query: | + SELECT + pCPayer.participantId as payerFspid, +``` +In the queries section, any number of queries can be defined that are run against the reporting database and loaded into named json classes. +Input parameters can be used in the queries by using a colon in front of the parameter name. e.g. +``` +:paramname +``` +### Control how the reports look like +The template part of the custom resource file contains an EJS script that is use to produce the report. +These scripts look like html with styling, but contain code within script blocks +``` ejs +<% ejs script %> +``` +The EJS scripts are quite versitile and can be used to change a name text, or define formatting functions, or loops that loop through data. + +## Building your development environment +*(Installation this service locally to aid development.)* +Currently the only way to validate the report design, is to apply the report to the kubernetes that the reporting service is running in. The reporting service will initially validate the report, and then enable the endpoint. The report can be run and checked to see if it meets it's requirements. + +This document provides instructions for deploying this service locally, so that a developer can try out their designs before installing the report in a an environment +Since the reporting service follows K8S operator pattern, we need to deploy a mini Kubernetes cluster on our machine and deploy the reporting service along with some dependent services. + +### Pre-requisites +- Please make sure that you have the following softwares installed + - git + - docker + - minikube + - kubectl + - helm + - mysql-client + +### Install K8S +- Start minikube K8S cluster with the following command + ``` + minikube start --driver=docker --kubernetes-version=v1.21.5 + ``` + +### Clone the repository +- Download the repository + ``` + git clone https://github.com/mojaloop/reporting.git + cd reporting + ``` + +### Deploy helm chart +- Install helm chart using the following commands + ``` + helm dep up ./resources/test-integration/ + helm install test1 ./resources/test-integration/ --set reporting-legacy-api.image.tag=v11.0.0 + ``` +- Wait for all the services to be up + You can monitor the pods health or use the following commands to wait for the services + ``` + kubectl -n default rollout status deployment test1-reporting-legacy-api + kubectl -n default rollout status statefulset mysql + ``` + +### Restore mysql database backup +- Port forward the mysql service + ``` + kubectl port-forward -n default service/mysql 3306:3306 + ``` +- Insert sample data into database. You can change the database name and filename in the following command as per your need. + ``` + mysql -h127.0.0.1 -P3306 -uuser -ppassword default < ./resources/examples/participants_db_dump.sql + ``` + +### Load reporting template +- Adding the custom resource using the following command + ``` + kubectl apply -f resources/examples/participant_list.yaml + ``` + +### Get the report +- Port forward the reporting service + ``` + kubectl port-forward -n default service/test1-reporting-legacy-api 8080:80 + ``` +- Get the report by opening the following URL in browser + ``` + http://localhost/participant-list + ``` + +### Cleanup +- Cleanup + ``` + kubectl delete -f resources/examples/participant_list.yaml + helm uninstall test1 + minikube stop + ``` + +## Deploying to a production environment +There are multiple ways that a report custom resource can be deployed into an environment. The method that has been chosen and built into the IaC offering involves the use of a helm chart. (This aligns well with other Mojaloop components.) + +The IaC enables both a public and a private deployment of reports. The process is identical except for the repository being private and residing within organisation's source control. +At a high level the process looks as follows: +1. Branch and commit changes to the repository where the report is deployed from. +2. Create a pull request and merge the changes into the master branch of the repository. +3. Create a new release on the repository. (Depending on configuration this typically kicks off a CICD mechanism that builds and publishes the helm package.) +4. Update the IaC to depoly the new helm release version for the reports. +5. Run the appropriate pipeline to perform the deployment. + diff --git a/docs/technical/business-operations-framework/ReportingBC.md b/docs/technical/business-operations-framework/ReportingBC.md new file mode 100644 index 000000000..5b1eeff49 --- /dev/null +++ b/docs/technical/business-operations-framework/ReportingBC.md @@ -0,0 +1,498 @@ +# Reporting bounded context implementation +One of the objectives of this workstream project is to provide the ability to trace a transfer end to end. In order to deliver on this objective, part of the reporting bounded context (BC) is to be built in line with the reference architecture. + +## Design overview +Here is the overall architectural design. +![Architecture overview diagram of reporting bounded context](../../.vuepress/public/Reporting-&-Auditing-Overview.png) + +In Mojaloop, all the core services are already pushing events to Kafka on a topic (called 'topic-event'). + +There are two fundamental reporting databases: +1. **Reporting DB** +The reporting database is a relational database that keeps track of the latest state of the Mojaloop objects and makes them available through an efficent query interface. \ +\ +In the implementation of this workstream effort, a dedicated replica of the central ledger database will be used for reporting. This does not quite fit the architectural model, as a database owned by the reporting bounded context should not have external depencencies. A central ledger replica database is dependent on the schema of the central ledger and therefore has an external dependency. +::: warning Technical Debt +This should be recognized as **technical debt** that should be paid as more of the reference architecture is built. +::: +There are two approaches that can be adopted when paying this technical debt: + - Changing the replica call to a **one-way data sync** function, which would decouple the schemas of the two databases. + - Rebuilding a new designed **relational database**, which is updated based on subscribed Kafka topics. + +The best approach will depend on the state of the current Mojaloop version at the time that this debt is paid. \ +\ +2. **Event DB store** +The event DB store is a capture of the event details that can provide a more detailed reporting view of what happened. + +**Limitations of the event store effort in this workstream** +This design will be implemented on the current Mojaloop version. + +Currently, only the data required to provide end-to-end tracing of a transfer will be collected and made available through the reporting API. Extensions to this offering can easily be added by extending the event processor to process new use case messages and store them in the Mongo DB, and then configure the generic graphQL resource query in order to query the new data stores appropriately. + +## Alignment with reference architecture +Although the bounded context refers to reporting and auditing, this project only begins to tackle the reporting part of that definition. The current design is independent from other bounded contexts, which is in line with the reference architecture. +(There isn't a complete seperation as the current design is using a replica database as the reporting database. The technical debt and next steps to resolve this are described above.) + +It is important to consider how this bounded context will change as more of the reference architecture design is implemented. + +Bounded contexts will - during the reference architecture implmentation - stop storing data in the central ledger databases. + +There are three approaches that can be adopted to accommodate this change. How the reference architecture is built will determine which is the best approach: +1. Modifying the sync functionality to accomodate the bounded context new data store. +2. Extending the message event processor to capture the required information in the reporting database. +3. Calling newly defined bounded context APIs, to retrieve the required data. + +## Use cases to support the tracing of a transfer + +In order to effectively trace a transfer end to end, four use cases were defined. + +### Use case 1: Dashboard view + +**As a** Hub Operator Business Operations Specialist, +**I want** a high-level dashboard summary of the transfers moving through the hub, which is derived from a date-time range, +**So that** I can proactively monitor the health of the ecosystem. + +:::::: col-wrapper +| Data returned | +| --- | +| Transfer count | +| Transfer amount total per currency | +| Transfer count per error code | +| Transfer count per Payer DFSP | +| Transfer count per Payee DFSP | +| Transfer amount per currency per Payer DFSP | +| Transfer amount per currency per Payee DFSP | +::::::::: + +### Use case 2: Transfer list view + +**As a** Hub Operator Business Operations Specialist, +**I want to** view a list of transfers that can be filtered based on one or more of the following: +- Always required (must be provided in every call) + - Date-time range + +- Optional filters + - A specific Payee DFSP + - A specific Payee ID type + - A specific Payee + - A specific Payer DFSP + - A specific Payer ID type + - A specific Payer + - State of the transfer + - Currency + +- Nice to have filters (not a strict requirement, but should be provided if the design allows for it) + - A specific error code + - Settlement window + - Settlement batch ID: The unique identifier of the settlement batch in which the transfer was settled. If the transfer has not been settled yet, it is blank. + - Search string on messages + +**So that** I can proactively monitor the health of the ecosystem by having a more detailed view of the transfer data moving through the hub. + +:::::: col-wrapper +| Data returned | | +| --- | --- | +| Transfer ID | The unique identifier of the transfer | +| Transfer State | Indicates if the transfer has succeeded, is pending, or an error has occurred | +| Transfer Type | (For example: P2P) | +| Currency | The transfer currency | +| Amount | The transfer amount | +| Payer DFSP | | +| Payer ID Type | | +| Payer | | +| Payee DFSP | | +| Payee ID Type | | +| Payee | | +| Settlement Batch ID | The unique identifier of the settlement batch in which the transfer was settled.
    If the transfer has not been settled yet, it is blank. | +| Date Submitted | The date and time when the transfer was initiated. | +::::::::: + +### Use case 3: Transfer detail view + +**As a** Hub Operator Business Operations Specialist, +**I want to** trace a specific transfer from its transfer ID, +**So that** I can identify: + +- The timing and current state of the transfer +- Any error information that is associated with that transfer +- The associated quoting information and timing for that transfer +- The associated settlement process status and identifiers + +:::::: col-wrapper +| Data returned | | +| --- | --- | +| Transfer ID | The unique identifier of the transfer | +| Transfer State | Indicates if the transfer has succeeded, is pending, or an error has occurred | +| Transfer Type | (For example: P2P) | +| Currency | The transfer currency | +| Amount | The transfer amount | +| Settlement Batch ID | The unique identifier of the settlement batch in which the transfer was settled.
    If the transfer has not been settled yet, it is blank. | +| Payer | | +| Payer Details | The unique identifier of the Payer (typically, a MSISDN, that is, a mobile number) | +| Payer DFSP | | +| Payee DFSP | | +| Payee | | +| Payee Details | The unique identifier of the Payee (typically, a MSISDN, that is, a mobile number) | +| Transfer State | Indicates if the transfer has succeeded, is pending, or an error has occurred | +| Date Submitted | The date and time when the transfer was initiated | +::::::::: + +### Use case 4: Transfer message view + +**As a** Hub Operator Business Operations Specialist, +**I want to** view the detailed messages from its transfer ID, +**So that** I can investigate any unexpected problem associated with that transfer. + +:::::: col-wrapper +| Data returned | | +| --- | --- | +| Scheme Transfer ID | | +| TransferID | | +| QuoteID | | +| Home Transfer ID | | +| Payer and Payee Information | Id Type, Id Value, Display Name, First Name, Middle Name,
    Last Name, Date of birth, Mechant classification code,
    FSP Id, Extension List | +| Party Lookup Response | | +| Quote Request | | +| Quote Response | | +| Transfer Prepare | | +| Transfer Fulfill | | +| Error message/s | | +::::::::: + +## Business workflow +Here is a business workflow that describes how the use cases are called. +![Business workFlow](../../.vuepress/public/BusinessFlowView.png) + +## Tools chosen +### Event Data Store: MongoDB +The MongoDB database was chosen because: + - MongoDB is currently used and deployed in Mojaloop, and is an excepted open-source tool that optionally has standard companies that can provide enterprise support should it be required. + - MongoDB will meet our requirements for this project. + - Other tools were considered but were found not to meet all the requirements for an OSS tool in Mojaloop. + +### API: GraphQL +In addition to the existing reporting API, a GraphQL API will be deployed too. This new API will have the additional functionality of being able to access the event reporting database as supplementary data or standalone query data. + +The GraphQL API implementation was added for these reasons: + - A more natural RBAC modelling implementation + - Easier to mix data from different sources into a single resource + - Existing reporting solution's implementation resulted in very complex SQL statements that required specialist knowledge to build and maintain. Splitting the data into a more natural resource and subsequent SQL statement simplifies both the SQL statement and the useage of that resource. + - In the team we had an GraphQL expert who knew the best lib and tools to use. + - A generic implementation was built so that no special GraphQL knowledge would be required to extend the functionality. + +**Additional advantages of using GraphQL** + - Reusable resources/associated RBAC permissions between reports + - Complex queries are simpler to build because resources are modeled + - Mixing of data sources in a single query (for example, MySQL with MongoDB) + - No requirement for nested fetches + - No requirement for multiple fetches + - No requirement for API version. API naturally supports backward compatibility between versions. + - Self-documenting API + +**Introduction of a new technology** +The introduction of a new technology into the community does bring some risk and a requirement to learn and maintain a new technology. An attempt to reduce the impact of this has been made by implementing the API using a generic or template approach, minimizing the GraphQL knowledge requirement to implement. A GraphQL query example has additionally be supplied. + +The current GraphQL implementation is developer-friendly. + +**Reporting REST implementation** +There is a REST reporting API implementation that has been donated to the Mojaloop community. It is possible to deploy this functionality alongside the GraphQL API implmentation if it becomes neccessary to do so. + +### GraphQL API - generic resource implementation explained +At the heart of the implementation of this bounded context is a generic implementation that links a reporting data store and a query to a GraphQL data resource that has its own RBAC authorization. That is, a new customized resource can be added to this API by doing the following: + +1. Define the data store type +2. Define the query +3. Define the GraphQL resource names and fields +3. Define the user permission that is linked to this resource + +### GraphQL query examples + +**Query transfers that are filtered on a specific Payer DFSP** +```GraphQL +query GetTransfers { + transfers(filter: { + payer: "payerfsp" + }) { + transferId + createdAt + payee { + name + } + } +} +``` + +**Query a summary of the transfers** +```GraphQL +query TransferSumary2021Q1 { + transferSummary( + filter: { + currency: "USD" + startDate: "2021-01-01" + endDate: "2021-03-31" + }) { + count + payer + } +} +``` + + +## Building the event data store +The purpose the event data store is to provide a persistent storage of events of interest that are easily and efficiently found and queried for reporting. + +To achieve this with minimal structure changes from the original message, it was decided to process the message into categories and store these categories as additional metadata inside the message, which can be queried later on. Messages that do not fit within these categories are not stored and are therefore filtered out. + +Here is an example of the metadata that is added to the JSON message: + +```json{7-12} +{ + "event": { + "id" : {}, + "content" : {}, + "type" : {}, + "metadata" : {} + }, + "metadata" : { + "reporting" : { + "transactionId" : "...", + "quoteId": "...", + "eventType" : "Quote" + } + } +} +``` +Where `"eventType"` can be one of the following: +:::::: col-wrapper +::: col-third +::: + +::: col-third +| eventType | +| ------- | +|Quote | +|Transfer | +|Settlement | +::: +::::::::: + +The event stream processor will subscribe to the Kafa topic `'topic-event'`. This message queue contains all the event messages. A sigificant degree of filtering is therefore necessary. + +:::tip NOTE +The code delivering this functionality has been structured so that these filters can easily be modified or extended. +The subscribed and classified messages are represented in 'const' files so they can easily be added to or amended without detailed knowledge of the code. +::: + +### Storing only 'audit' messages + +Only Kafka messages that are of type `'audit'` will be considered for saving, that is, only if: +:::::: col-wrapper +::: col-third +::: +::: col-third +| metadata.event.type | +| ---- | +| audit | +::: +::::::::: + +## 'Transfer' messages that are stored +**ml-api-adapter** + +:::::: col-wrapper +| metadata.trace.service | +| ---- | +| ml_transfer_prepare | +| ml_transfer_fulfil | +| ml_transfer_abort | +| ml_transfer_getById | +| ml_notification_event | +::::::::: + +## 'Quote' messages that are stored +**quoting-service** +:::::: col-wrapper +::: col-third +| metadata.trace.service | +| ---- | +| qs_quote_handleQuoteRequest | +| qs_quote_forwardQuoteRequest | +| qs_quote_forwardQuoteRequestResend | +| qs_quote_handleQuoteUpdate | +| qs_quote_forwardQuoteUpdate | +| qs_quote_forwardQuoteUpdateResend | +| qs_quote_handleQuoteError | +| qs_quote_forwardQuoteGet | +| qs_quote_sendErrorCallback | +::: + +::: col-third +| metadata.trace.service | +| ---- | +| qs_bulkquote_forwardBulkQuoteRequest | +| qs_quote_forwardBulkQuoteUpdate | +| qs_quote_forwardBulkQuoteGet | +| qs_quote_forwardBulkQuoteError | +| qs_bulkQuote_sendErrorCallback | +::: + +::: col-third +| metadata.trace.service | +| ---- | +| QuotesErrorByIDPut | +| QuotesByIdGet | +| QuotesByIdPut | +| QuotesPost | +| BulkQuotesErrorByIdPut | +| BulkQuotesByIdGet | +| BulkQuotesByIdPut | +| BulkQuotesPost | +::: +::::::::: + +## 'Settlement' messages that are stored +**central-settlement** +:::::: col-wrapper +::: col-third +| metadata.trace.service | +| ---- | +| cs_process_transfer_settlement_window | +| cs_close_settlement_window | +| ... | +::: + +::: col-third +| metadata.trace.service | +| ---- | +| getSettlementWindowsByParams | +| getSettlementWindowById | +| updateSettlementById | +| getSettlementById | +| createSettlement | +| closeSettlementWindow | +| ... | +::: +::::::::: + +## Messages that currently remain unclassified and are filtered out +**account-lookup-service (not in PI - included as a reference)** +:::::: col-wrapper +::: col-third +| metadata.trace.service | +| ---- | +| ParticipantsErrorByIDPut | +| ParticipantsByIDPut | +| ParticipantsErrorByTypeAndIDPut | +| ParticipantsErrorBySubIdTypeAndIDPut | +| ParticipantsSubIdByTypeAndIDGet | +| ParticipantsSubIdByTypeAndIDPut | +| ParticipantsSubIdByTypeAndIDPost | +| ParticipantsSubIdByTypeAndIDDelete | +| ParticipantsByTypeAndIDGet | +| ParticipantsByTypeAndIDPut | +| ParticipantsByIDAndTypePost | +| ParticipantsByTypeAndIDDelete | +| ParticipantsPost | +| PartiesByTypeAndIDGet | +| PartiesByTypeAndIDPut | +| PartiesErrorByTypeAndIDPut | +| PartiesBySubIdTypeAndIDGet | +| PartiesSubIdByTypeAndIDPut | +| PartiesErrorBySubIdTypeAndIDPut | +::: + +::: col-third +| metadata.trace.service | +| ---- | +| OraclesGet | +| OraclesPost | +| OraclesByIdPut | +| OraclesByIdDelete | +::: + +::: col-third +| metadata.trace.service | +| ---- | +| postParticipants | +| getPartiesByTypeAndID | +| ... | +::: +::::::::: + +**transaction-requests-service (not in PI - included as a reference)** +:::::: col-wrapper +::: col-third +| metadata.trace.service | +| ----- | +| TransactionRequestsErrorByID | +| TransactionRequestsByID | +| TransactionRequestsByIDPut | +| TransactionRequests | +| AuthorizationsIDResponse | +| AuthorizationsIDPutResponse | +| AuthorizationsErrorByID | +::: + +::: col-third +| metadata.trace.service | +| ----- | +| forwardAuthorizationMessage | +| forwardAuthorizationError | +| ... | +::: +::::::::: + +### Useful tools + +#### Kafka explorer +The [‘kowl’](https://github.com/cloudhut/kowl) software from cloudhut is a useful tool to explore all the Kafka messages in a Mojaloop cluster. We can deploy it in the same namespace as the Mojaloop core services. + +The custom values file for the OSS deployment can be found in this [repository](https://github.com/mojaloop/deploy-config/tree/deploy/PI15.2/mojaloop/kowl-kafka-ui). +(This is private repository, you may need permission to access this link.) + +**Steps to install** +``` +helm repo add cloudhut https://raw.githubusercontent.com/cloudhut/charts/master/archives +helm repo update +helm install kowl cloudhut/kowl -f values-moja2-kowl-values.yaml +``` +**Web UI** +Open the URL configured in the `ingress` section in the `values` file. + +**Additional customization** +For information on how to add further customization, see the [reference configuration](https://github.com/cloudhut/kowl/blob/master/docs/config/kowl.yaml) provided by cloudhut. + +#### TTK golden path +The TTK golden path test cases have been designed to explore all the test outcomes possible when sending transfers. This is therefore an important tool that can be used to test that the functionality caters for all eventualities. That is, we can use the in-built TTK to execute different test-cases such as P2P happy path, negative scenarios, settlement-related use cases, and so on. + +## Event processing service + +The event processing service is responsible for subscribing to Kafka topics and filtering through the events by event type. The event type further breaks down into several parts depending on which service the events were produced from. The filtered events will then be processed depending on the context of the event structure, and reporting metadata will be created. + +Example: + +```json +{ + "event": { + "id" : {}, + "content" : {}, + "type" : {}, + "metadata" : {} + }, + "metadata" : { + "reporting" : { + "transactionId" : "...", + "quoteId": "...", + "eventType" : "Quote" + } + } +} +``` + +| eventType | Event origin | +| ------- | ------- | +|Quote | quoting-service | +|Transfer | ml-api-adapter | +|Settlement | central-settlement | + +The event processing service subscribes to the Kafka event stream to build an event transfer related store that is queryable through the operational API. This is in line with the reference architecture. diff --git a/docs/technical/business-operations-framework/SecurityBC.md b/docs/technical/business-operations-framework/SecurityBC.md new file mode 100644 index 000000000..2461fd7dc --- /dev/null +++ b/docs/technical/business-operations-framework/SecurityBC.md @@ -0,0 +1,886 @@ +# RBAC Operational API implementation +## Introduction to RBAC Operational API implementation +The objectives of this implementation is to provide an RBAC solution to support hub operations and associated functions. This guide outlines the high-level design and explains the thinking that went into the design. + +The security design: +1. implements role based access control to the current Mojaloop version +1. is compatible where possible with the reference architecture and therefore future versions of Mojaloop +1. is compatible with future Infrastructure-as-Code (IaC) deployments +1. provides activity logging that can be used in an audit + +## RBAC Implementation details +1. Users are assigned one or more roles. A user may 'take on' multiple roles, subject to defined rules. +1. Roles are assigned Permissions +1. The Identity and Access Proxy (Ory Oathkeeper) enforces access to endpoints based on permission. +1. Backend API can optionally check permissions through Keto API. +1. Mutually exclusive permission sets can be defined in the system to enforce separation of duties. + +## Enforcing Maker-Checker +There are two approaches that can be taken to enforce a maker-checker validation flow. +1. Enforce using roles and mutually exclusive permissions via security policies. I.e. Makers cannot also be checkers +1. Enforce in application layer security rules; i.e. makers cannot also be checkers within the same validation process. This is often implemented in the application layer when assigning makers and/or checkers as defined in a process flow, and by enforcing that a checker cannot be the same person as the maker in a validation flow. I.e. the code that enforces this will exist within each bounded context. + + +::: tip RBAC responsibility +To support this functionality the RBAC system must provide: +1. the User Identifier to that bounded context. +1. A means for checking authorisation if necessary. +::: + +### Providing the User Identifier +The current configuration provides the User Identifier in the header of the API calls. +Ory Oathkeeper is configured to use a 'header' mutator. This 'header' mutator will transform the request, allowing you to pass the credentials to the upstream application via the headers. For example the API backends will get the following header in the http requests. +``` +X-User: wso2-uuid +``` + +It is worth pointing out that JWT 'id_token' are also easily supported my modifying the Ory Oathkeeper mutator configuration. The 'id_token' mutator takes the authentication information (e.g. subject) and transforms it to a signed JSON Web Token, and more specifically to an OpenID Connect ID Token. The API backends can verify the token by fetching the (public) key from the /.well-known/jwks.json endpoint provided by the Ory Oathkeeper API. + +### Checking authorisation +All authorisation information is maintained within Ory Keto. Ory Keto has a standard API that can be called to check authorisation. +I.e. It answers the question: *'Does this user identifier token have this permission?'* + +## Tools / standards chosen +Here is a list of standard tools that have been chosen to implement the design. +1. **Ory Oathkeeper** +Will be used as the Identity and Access Proxy (IAP) that will check authentication and authorization before providing access to functional endpoints, that is, it will be used to enforce the access control. +2. **Ory Keto** +Will check authorization via subject-role and role-permission mappings. It uses a flexible object-, relationship-, and subject structure pioneered at Google that can model many authorization schemes, including Role Based Access Control (RBAC). +3. **Ory Kratos** +Will use Ory Kratos to create and manage the cookie authorization object. +4. **OpenID Connect** +Is the standard that has been chosen to interact with an identity management system. This is a widely supported standard, and is compatible with all the tools currently in use in the Mojaloop community, that is, WSO2 Identity Server (IS), Keycloak, and Ory Kratos. + +## Architecture overview +Here is a high-level architecture overview of the implementation of this RBAC Operational API onto the current Mojaloop version. + +![Architecture overview diagram of security bounded context implementation](../../.vuepress/public/BizOps-Framework-IaC-3.xx-&-Mojaloop-13.xx.png) + +Here is a table of the services and the roles they are playing. +| Service | Owns | Implements | +| --- | --- | +|**WSO2 IS KM**|Users| 1. User login redirection and UI that creates the cookie token
    2. Standard OpenID Connect (OIDC) authorization code flow | +|**Ory Keto**|1. The roles mapped to users
    2. The participant mapped to users| 1. API RBAC authorization check through Ory Oathkeeper
    2. API RBAC authorization check through operational API call| +|**Ory Oathkeeper**|The permissions related to API access | API gateway for operational APIs with authentication and authorization checks| +|**Ory Kratos**|Nothing|Authentication cookie| +|**BC Operational API**|The permissions related to the operational API calls|Operational API functions| +|**Shim**| nothing | Redirect to configure OIDC| +|**Operator Role**| Nothing | Update Keto to reflect role-permission assignment changes made in the role-resource file| +|**Kubernetes role-resource file**| The roles and the role-permission assignments| Edits of this file are controlled through a version control implementaiton (for example, GitHub or GitLab).| +|**Roles API**|Nothing|1. Role-user API controls
    (list of users, list of roles, list of roles assigned to users, add role to user, remove role from user)
    2. Participant-user API controls
    (list of users, list of participants, list of participants assigned to user, add participant to user, remove participant from user)| + +## How does this design align with the reference architecture? +Let's compare this RBAC Operational API implementation to the security bounded context as defined in the reference architecture. This design differs from the reference architecture in function, purpose and approach, but where appropriate has adopted some of the design ideas. This RBAC implementation's purpose is to adds a layer for security onto the operational API's of the bounded contexts. The Reference Architecture's Security Bounded Context design has been designed to accommodate for the performance requirements of the critical transactional functions of Mojaloop. +Here are the high level areas where these designs diverge: +1. The authorisation functions are centralised in this RBAC implementation. The reference architecture design requires a distributed authorisation that is implemented in each bounded context independently. This extra level of complexity is unnecessary for the operational API use case. +1. The reference architecture design requires interfaces to other bounded contexts to initiate the distributed authorisation functionality. These have not been built for the reason that there are no components that exist that could consume these interfaces. +1. The reference architecture requires the security BC to generate it's own security tokens. This RBAC implementation uses the tokens that are generated by the IAM. +1. The reference architecture requires the permissions to be distributed through the JWT to each bounded context. This is possible to configure in the current toolset, but was not. The reason being that some security experts consider this distribution of user permission sets a security vulnerability, and it was not a requirement for this current RBAC implementation. + +There are parts of the security bounded context that have been adopted in this RBAC Operational API implementation. +1. Each Bounded context owns it's own set of permissions or privileges +1. The RBAC implementation owns all the associations of privileges to users. +1. The user Role Permissions are structured so that they are easily distributed within a Kubernetes cluster. + +## Alignment with IaC 4.xxx +Here is a diagram illustrating how the high-level architecture would look if this RBAC Operational API implementation design was implemented on the next IaC version (IaC 4.xxx version) that uses Keycloak and Ambassador / Envoy amongst other changes. + +![Architecture overview diagram of security bounded context implementation](../../.vuepress/public/BizOps-Framework-IaC-4.xx-&-Mojaloop-13.xx.png) + +## Performance characterisation of the RBAC implementation +A performance characterisation of the RBAC POC implementation was performed in order to evaluate the extent of the performance overhead that the RBAC security layer has. +::: tip In summary: +The RBAC adds 10ms overhead for each API authorisation check per call. +If a particular API call requires and additional API based authorisation call, then the overhead is 20ms. + +This typically in our test queries amounted to: +1. less than 5% for single authorisation checks (Ory Oathkeeper & Ory Keto), +1. and less than 10% for double authorisation checks (Ory Oathkeeper & Ory Keto and an additional Ory Keto call). +::: + +**Characterisation test setup details** +On the same test infrastructure, identical timed calls were made to the same backend API directly and and through the RBAC implementation. +Below are the results of the test calls made to the role API with and without RBAC, and POST Transfers API with and without RBAC. The Role API has a single authorisation check that is performed through Ory Oathkeeper that calls Ory Keto. The Transfer API is a graph QL API that has an additional RBAC + +**Request Statistics** + +|Method| Name| # Requests| # Fails| Average (ms)| Min (ms)| Max (ms)| Average size| (bytes) RPS| Failures/s| +| --- | --- | --- | --- | --- | --- | --- | --- | --- | +|GET| Role API| 321| 0| 248| 221| 499| 604| 9.0| 0.0| +|GET| Role API RBAC| 320| 0| 262| 232| 418| 604| 8.9| 0.0| +|POST| Transfers API| 318| 0| 229| 184| 373| 4873| 8.9| 0.0| +|POST| Transfers API RBAC| 314| 0| 240| 194| 406| 4873| 8.8| 0.0| +| | **Aggregated**| **1273**| **0**| **245**| **184**| **499**| **2723**| **35.5**| **0.0**| + + +**Response Time Statistics** + +|Method| Name| 50%ile (ms)| 60%ile (ms)| 70%ile (ms)| 80%ile (ms)| 90%ile (ms)| 95%ile (ms)| 99%ile (ms)| 100%ile (ms)| +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +|GET| Role API| 240| 240| 240| 250| 270| 290| 400| 500| +|GET| Role API RBAC| 250| 260| 260| 270| 290| 320| 410| 420| +|POST| Transfers API| 220| 220| 240| 250| 290| 330| 360| 370| +|POST| Transfers API RBAC| 230| 240| 250| 280| 310| 330| 400| 410| +| |**Aggregated**| **240**| **250**| **250**| **260**| **290**| **320**| **400**| **500**| + +## Logging into the UI +This sequence diagram illustrates the events that occur when a browser attempt to access a backend API. +- If the browser is already logged in, then the request is forwarded. +- If the browser is not logged in, then a standard OIDC authorization flow is triggered starting with a redirect. + +![Sequence diagram illustrating how a brower logs in](../../.vuepress/public/frontend.png) + +## Querying data using the BC operational API micro-frontend +The following sequence diagram shows more details regarding interactions when: +- the bearer token is valid or invalid +- authorization passes or fails + +The micro-frontend is represented as a client. + +![Sequence diagram illustrating how an API client call has its authorization performed](../../.vuepress/public/client.png) + +In some cases there might be a requirement for a more detailed authorization check to be performed by the operational API. The next sequence diagram describes how that is implemented. + +It is important to note that not all operational APIs will require this level of authorization, and that the Ory Oathkeeper control may or may not be required in this use case. + +![Sequence diagram illustrating how an API client call has its authorization performed](../../.vuepress/public/clientgraphql.png) + +## Enforcing Seperation of Duties +This RBAC implementation supports the enforcement of separation of duties by the enforcement of mutually exclusive permissions sets. The implementation of separation of duty creates tighter security but can lead to complexity for the security administrator and the end users who use the system. Enforcing mutually exclusive permissions can reduce and help manage this complexity. + +An example of mutually exclusive permissions might be a user being able to access the Finance Portal and to carry out sensitive functions such as add/withdraw funds. This user should not also have access to audit functions. + +### Modelling the exclusion +This implementation models this requirements as a set of mutually exclusive permission - permission exclusions that are enforced globally. These exclusions are defined as two sets of permissions that are mutually exclusive which is intuitive and easy to maintain. + +*Justification* +There are three possible ways that this exclusion could have been modelled namely: +1. Permission - Permission exclusions +1. User Role - User Role exclusions +1. User Role - Permission exclusions + +Because this functionality has been added to support the segregation/separation of duties, the cleanest way of enforcing this is to have a permission pair exclusion that is globally enforced. With all the other options, there is the possibility that the exclusion can be bypassed with the addition of a new inclusive role. + +### Synthetic Roles Vs Multiple User Roles +This RBAC implementation does not implement synthetic roles, but rather uses multiple functional user roles assignments. + +*Justification* +These are two methods that can be used to model RBAC permissions with mutually exclusive permissions. +1. Dynamically building up a synthetic role for each user based on rules associated with the current assigned roles and their permissions and exclusions. +1. Defining roles that are associated with user functions. Each user therefore will need to be assigned more than one role. Roles permissions are less likely to change. + +The preference is to implement multiple functional roles. This is because it is much simpler to understand, maintain and support this method. Identifying the cause of a loss of permission in a synthetic role because of multiple role assignments and subsequent rule applications requires a detailed understanding of the process of how the synthetic roles are calculated and implemented. This complexity is avoided with the second option. + +### Multiple user role assignments required dynamic checking of exclusions +Allowing the system administrator to assign more than one role to a user is convenient, flexible and limits the number of roles required within the organisation. This also means that it is possible to violate a mutually exclusive permission by assigning users to roles. Checking and enforcing these exclusions therefore need to be dynamic. + +There are a number of places that this dynamic check needs to take place. +1. On the assignment of a role to a user +1. On the application of a new role-permission resource definition, or the application of a new security policy that may include a wholesale change of permission and role structures. +::: warning Future extension: +If it is possible that a violation can exist in the system, then each time a permission is checked, exclusion violations should also be checked. Currently this is not designed for as it is assumed that 1 & 2 are sufficiently implemented that a violation cannot exist. +It is recommended that this additional check be roadmapped for future extensions as this would ensure that no back-door override can be made to violate this separation of duties. +::: + +::: tip Note: +The change control release and testing on lower environments may not catch these violations. Testing for these violations cannot be done on lower environments without first making sure that the user access control is identical in the lower environments which is normally not the case. +::: + +**Keto relation** +Introduction of a relation that relates two permissions that cannot be held together. +``` +“permission:X excludes permission:Y#allowed” +``` + +**Permission Exclusion Custom Resource Definition** +A permission exclusion custom resources are consumed by the Role Permission Controller, which will upload the exclusions into Keto using this relation. Each will contain two sets of permissions, and holding any permission in one set will mean no permission in the other set can be held. This allows for many flexible scenarios, and the simplest scenario of “any person who can do this one thing cannot do this other thing, and vice versa” remains simple to express. + +**Role Permission Operator API Validation Check** +The Role Permission Resource Controller will provide an API that can be used to check a security permission update’s allowability before it is applied. That API will take a proposed change to a particular Role Permission resource and calculate whether or not any existing users would have mutually exclusive permissions after that change, returning the result. This API will be usable by the administrative UI and CI systems to “preflight” changes for likely problems. + +**Role Permission Operator Change Enforcement** +When a role-permission resource is changed, the role-permission operator will first lock the ability to change user role assignments, then perform the same check as the validation API does, and if the resource does not pass the check it will not accept the changes from that resource, instead maintaining the current role permission assignments, and surfacing the issue as an error in the kubernetes API for instrumentation and alerting. + +**Conflict Check on User Role Assignment** +When a user is assigned a role, the user role assignment API will validate that the change does not result in the user having two mutually excluded permissions. If it does, the change will be rejected and an error returned. + +## Assigning roles and participant access to users +This functionality is implemented in the Roles API service. The following sequence diagram describes how the user role and user participation access is queried and modified through the Roles API. +![Sequence diagram illustrating how roles and participant access is assigned to users](../../.vuepress/public/userroles.png) + +### Roles API +The following table provides a summary of Roles API resources. + +|Category|HTTP method|Endpoint| Description|Error codes| +| --- | --- | --- | --- | --- | +|**HEALTH**| | | | | +| | GET | /health | Used to return the current status of the API | 400, 401, 403, 404, 405, 406, 501, 503 | +| | GET | /metrics | Used to return metrics for the API | 400, 401, 403, 404, 405, 406, 501, 503| +|**PARTICIPANTS**| | | | | +| | GET | /participants | Used to return a list of participant IDs | 400, 401, 403, 404, 405, 406, 501, 503| +|**ROLES**| | | | | +| | GET | /roles | Used to return a list of role IDs |400, 401, 403, 404, 405, 406, 501, 503 | +|**USERS**| | | | | +| | GET | /users | Used to return a list of user IDs | 400, 401, 403, 404, 405, 406, 501, 503| +| | GET | /users/{ID} | Used to return a specifc user |400, 401, 403, 404, 405, 406, 501, 503 | +| | GET | /users/{ID}/participants | Used to return a list of participants assigned to a user |400, 401, 403, 404, 405, 406, 501, 503| +| | PATCH | /users/{ID}/participants | Used to assign a participant to a user | 400, 401, 403, 404, 405, 406, 501, 503| +| | GET | /users/{ID}/roles | Used to return a list of roles assigned to a user|400, 401, 403, 404, 405, 406, 501, 503 | +| | PATCH | /users/{ID}/roles | Used to assign a role to a user|400, 401, 403, 404, 405, 406, 501, 503 | + + +The detailed specification of the Roles API can be found [here](https://docs.mojaloop.io/role-assignment-service/ +). +The GitHub repository of the role assignment service can be found [here](https://github.com/mojaloop/role-assignment-service). + +## Assigning permissions to roles & mutually exclusive permission sets +The permission to role assignment is stored in a `.yml` file that we are calling a role-resource file (`roleresource.yml`). +Access and changes to these role-resource files will be managed through a hosted version control solution like GitHub or GitLab. This is convenient as this keeps a full history of changes and has configurable automatic and manual control points. +These role-resource files are mapped as Kubernetes custom resource definitions (CRDs) to which a role-permission operator subscribes. Changes to the role-resource files trigger the role-permission operator to update Ory Keto with the corresponding appropriate change. A role can be represented by more than one file if necessary. + +There are two types of role resource files, the first contains the role permission assignments and the second the mutually exclusive permission sets. + +Here is an example of a permission assignment role-resource file: +```yml +apiVersion: "mojaloop.io/v1" +kind: MojaloopRole +metadata: + name: arbitrary-name-here +spec: + # must match what is used in Keto, whatever that is + role: RoleIdentifier + permissions: + - permission_01 + - permission_02 + - permission_03 + - permission_04' +``` +The following sequence diagram illustrates how Ory Keto is updated. + +![Sequence diagram illustrating how roles and participant access is assigned to users](../../.vuepress/public/rolepermissions.png) + +## Ory Keto – implementation detail +Ory Keto in this design is the tool that implements the logic of whether a login token has the correct authorization to access an aspect of the system, that is, it is used to enforce RBAC. There are three parts to how this is implemented in Keto: +1. The assignment of roles to users. +This functionality will be maintained and updated from the Roles API module, which will call and update Keto accordingly. +2. The assignment of participant access to a user. +This refers to the DFSP access reports that must only be provided for the configured participants. +This functionality will also be maintained via the Roles API module, which will call and update Keto accordingly. +3. The assignment of permissions or privileges to roles. +This will be controlled through the edits of a GitHub `roleresource.yml` file. The Kubernetes role-permission operator is the service that will monitor these role-resource files, and update Keto to affect the assignments. + +### Adding roles and participant access to users in Keto +The user list (which includes both people and service accounts) will be retrieved from WSO2 Identity Server, and the participant list from the existing API for that purpose. In both cases, a durable permanent identifier should be what is then used as part of the Keto calls. + +The list of roles will be hardcoded, and every role should be given a unique short identifier that is human readable and writeable, as well as a name. The UI should display both the identifier and the name, since the identifier will be needed for use in the role-permission operator. + +There will be two Keto namespaces used for calls: role and participant. The Keto tuples used will be: +``` +role:ROLEID#member@USERID and participant:PARTICIPANTID#member@USERID +``` +(using the notation used for [Keto/Zanzibar](https://www.ory.sh/keto/docs/concepts/relation-tuples) + +The reuse of the relation `"member"` is not an issue, each relation is namespace-specific. If there is a preferred term for the participant-user relationship other than `"member"`, that word can be used instead, and should be documented here. + +To retrieve the role or participant list for a particular user, the [Query Relation Tuples API](https://www.ory.sh/keto/docs/reference/rest-api#query-relation-tuples) will be used, and the namespace, relation, and subject provided as parameters. This will provide a list of tuples in the response, with a next page token if there are additional results, and the identifiers for the participants or roles can be read from the resulting tuples. + +When a role or participant is added or removed for a user, the [create](https://www.ory.sh/keto/docs/reference/rest-api#create-a-relation-tuple) and [delete](https://www.ory.sh/keto/docs/reference/rest-api#delete-a-relation-tuple) relation tuple calls can be used, since only a single tuple is involved at a time. If the call fails, but the failure is not an HTTP 4xx, it should be retried a couple of times. + +Here is an example of the Keto API call used to add roles to users. +::: tip Example: Assign role to user in Ory Keto +PATCH /relation-tuples HTTP/1.1 +Content-Type: application/json +Accept: application/json +::: + +```json +[ + { + "action": "insert", + "relation_tuple": { + "namespace": "role", + "object": "RoleIdentifier", + "relation": "member", + "subject": "userIdentifier" + } + } +] +``` +On success, an HTTP 204 message is returned with no content. + +::: tip NOTE +We use `"member"` as the `"relation"` in our current implementation. +We use `PATCH` instead of `PUT` since `PATCH` works as a bulk create and/or delete. +::: + +### Adding permissions or privileges to roles in Keto +Adding permissions or privileges to roles in KetoThis will be done via a Kubernetes operator for a Custom Resource Definition [(CRD)](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/_print/). The operator could be implemented in most any language. Existing ModusBox operator expertise is mostly based around `kopf`, a Python framework, but there are options in Go and Node as well (and others). + +The operator should maintain a memory of all resources it manages, grouped by role. [Kopf's indexing](https://kopf.readthedocs.io/en/latest/indexing/) functionality is ideal for this. + +When a role resource is changed, the list of permissions for that role across all role resources should be compiled, and a change sent through the Keto Patch [Multiple Relation Tuples API](https://www.ory.sh/keto/docs/reference/rest-api#patch-multiple-relation-tuples) using the patch actions `insert` and `delete`. It is necessary to take all role resources into account, because there may be multiple resources for one role, and more than one may include the same permission, so deleting a role resource that maps Role X to Permission P does not necessarily mean that the Keto tuple for that role-permission connection needs to be deleted, since there may still be another role resource mapping Role X to Permission P. + +The Keto tuples will be of the form: +``` +permission:PERMISSIONID#granted@role:ROLEID#member +``` + +The specific operations on resource change are as follows: + +1. Retrieve current permissions granted for role using the [Query Relation Tuples API](https://www.ory.sh/keto/docs/reference/rest-api/#query-relation-tuples). +2. Based on stored index of roles to permissions, compute a diff from the retrieved list. +3. Execute patch from diff. +4. If there are problems, throw an exception so the problem will log and a re-sync will be attempted later. + + +Here is an example of the Keto API call used to add permissions to roles. +::: tip Example: Assign permission/privilege to a role in Ory Keto +PATCH /relation-tuples HTTP/1.1 +Content-Type: application/json +Accept: application/json +::: + +```json +[ + { + "action": "insert", + "relation_tuple": { + "namespace": "permission", + "object": "permissionIdentifier", + "relation": "granted", + "subject": "role:x#member" + } + } +] +``` +On success, an HTTP 204 message is returned with no content. + +::: tip NOTE +We use `"granted"` as the `"relation"` in our current implementation. +We use `PATCH` instead of `PUT` since `PATCH` works as a bulk create and/or delete. +::: + +### Adding mutually exclusive permisions to Keto +The mutually exclusive permission sets are also maintained and modelled in Keto using the 'excludes' relation. +Relation that relates two permissions that cannot be held together are represented with exclusion tuples: +``` +“permission:X excludes permission:Y#allowed” +``` + +::: tip NOTE +We use `"excludes"` as the `"relation"` to define mutually exclusive permissions. +::: + +### Calling the standard Keto API to check authorization +Checking to see if a user has authorization for a privilege or permission is managed by th API gateway, and if necessary can be checked by each bounded context. + +Here is an example of the Keto API call used to check for a user's authorization based on a permission/privilege. +::: tip Example: Checking for authorization in Ory Keto +POST /check HTTP/1.1 +Content-Type: application/json +Accept: application/json +::: +```json +{ + "namespace": "permission", + "object": "PermissionIdentifier", + "relation": "granted", + "subject": "UserIdentifier" +} +``` +Here is the response that comes back: +```json +{ +"allowed": true/false +} +``` +::: tip Note: +Mutally excluded permissions don't need to be check excplicitly through a Keto call because the system is maintained in such a way that role-permission assignments can only be defined if mutually exclusive permission sets are not violated. +::: + +## Ory Oathkeeper – implementation detail +### Configuring Ory Oathkeeper for BizOps + +[ORY Oathkeeper](https://www.ory.sh/oathkeeper/docs/next/) authorizes incoming HTTP requests. It can be the Policy Enforcement Point in your cloud architecture, that is, a reverse proxy in front of your upstream API or web server that rejects unauthorized requests and forwards authorized ones to your server. If you want to use another API Gateway (Kong, Nginx, Envoy, AWS API Gateway, and so on), Ory Oathkeeper can also plug into that and act as its Policy Decision Point. + + +The Ory Oathkeeper Helm chart is described at [ORY Oathkeeper Helm Chart | k8s](https://k8s.ory.sh/helm/oathkeeper.html) and defined in [k8s/helm/charts/oathkeeper at master · ory/k8s · GitHub](https://github.com/ory/k8s/tree/master/helm/charts/oathkeeper). The Ory Helm repository is documented at [ORY Helm Charts | k8s](https://k8s.ory.sh/helm/). The Ory Oathkeeper configuration reference is at [Configuration | ORY Oathkeeper](https://www.ory.sh/oathkeeper/docs/reference/configuration) but note that the Helm chart values have different ways of doing certain things. Also, every configuration value can be overridden with environment variables. + + +The Ory Oathkeeper Helm chart deploys two key components into Kubernetes: Ory Oathkeeper itself, and the Ory Oathkeeper Maester. Ory Oathkeeper is stateless and config-driven, and seamlessly reloads itself with zero downtime, anytime that config changes. Ory Oathkeeper Maester is a controller for the Rule CRD, and composes the Rule objects in Kubernetes into a single complete rules file that is loaded by Ory Oathkeeper. By default, that is a ConfigMap that Ory Oathkeeper mounts, but it can also be set to run as a sidecar and use a shared mount. + + +Ory Oathkeeper exposes two ports as two services. One service is the API service, and the other is the Proxy service. Long-term, we will be using the API service, which will be queried by the next generation API Gateway using the Access Control Decision API (see [REST API | ORY Oathkeeper](https://www.ory.sh/oathkeeper/docs/reference/api/#access-control-decision-api) ) that Ory Oathkeeper provides, but for now we will be using the Proxy service, and exposing that via Ingress. External URLs to services protected by Ory Oathkeeper will be pointed at the Ory Oathkeeper Proxy ingress, which will then proxy access to the internal services at those URLs and apply access control rules. + + +Ory Oathkeeper will be configured to generate and sign a JSON Web Token (JWT) containing claims that internal services can check and verify by pointing at the JSON Web Key Set (JWKS) that Ory Oathkeeper will publish (which is part of the configuration) at the well-known URL for JWKS on the API service (see [REST API | ORY Oathkeeper](https://www.ory.sh/oathkeeper/docs/reference/api/#lists-cryptographic-keys) ). If a service does this, then it is operating under a basic zero trust regime, as it will not be possible to call that service except with a token that has been generated by Ory Oathkeeper, and Ory Oathkeeper will only generate a token if the access rules for the given URL allow access. + + + +### Debugging +The responses and logs from Ory Oathkeeper tend to be pretty informative, so start there. Make sure you are looking at the logs for the request that matters. Ory Oathkeeper will also be logging health checks and similar. + + +Some possible debugging actions that have been found useful in different circumstances: + + +* Make a match much more permissive (replacing the entire piece beginning with `<.*>` and then having the minimum currently unique suffix is good). + +* Double-check that each internal URL is the proper internal URL by checking it is accessible inside the cluster with curl. + +* Look at the identity provider (IdP) logs. + +* Make sure that the domains and ports for introspection and the external token endpoint are identical. Keycloak at least does not like it if they are not. + +* Point the Ory Oathkeeper rule at https://httpbin.org/, usually the `/anything` path prefix which will reflect back everything it gets, making it easy to see what the service will see. + + +### Components required in addition to a Helm chart + +The following pieces will be needed in addition to the Helm chart: + +* a JWKS secret +* annotated Helm values + + +#### JWKS secret + + +A secret should be created with key `mutator.id_token.jwks.json` and the value of a JWKS suitable for use with Ory Oathkeeper. An initial one can be generated as described in [Configure and Deploy | ORY Oathkeeper](https://www.ory.sh/oathkeeper/docs/configure-deploy#cryptographic-keys). It will contain both public and private keys. + + +##### Operating with the JWKS secret + + +To rotate the secret, apply the following procedure: + +0. Note the time. +1. Add a public and private key pair to the beginning of the array in the JWKS (make sure all public JWKs have a specified unique `kid`) in the secret. All keys other than the new keys and the previous first public and private keys can be removed. This is because Ory Oathkeeper always signs with the first key. +2. Wait until all requests that Ory Oathkeeper might have received and authorized would have had their JWT handled by the backend service. The main delay here is the time for the secret update to propagate, comprising the delay of the secret manager to the updated secret and the delay of the secret to the updated volume, which is probably at most a minute or two, so wait that long after the time in step 0. +3. If the old secret is being removed (this is only necessary if a breach is suspected, otherwise step 1 is sufficient for periodic key rotation), remove it now. + +#### Annotated Helm values + + +Several places will need to be changed to the rest-of-deployment-specific URLs or other values. Those places are described in the comments in the example below, as well as other commentary. + +How to setup the Proxy ingress is undecided at the time, as it will need to change when the solution is added to the IaC 3.xxx so that area of the config is still unspecified. This leaves the ingress out by default. Changing `ingress.proxy.enabled` to `true` will enable the proxy ingress. See the linked pages at the beginning for options available for the built-in ingress configuration. + +If TLS needs to be terminated at Ory Oathkeeper, see the `tls` sections in the [config documentation](https://www.ory.sh/oathkeeper/docs/reference/configuration), and combine that with secrets and the `deployment.extraVolumes` and `deployment.extraVolumeMounts` values. +Prometheus is at `:9000/metrics` by default, if that is in use. + + +```yaml + +oathkeeper: + config: + log: + # the maximum log level, we'll stick here or maybe debug if this is overwhelming until the config is verified + # then, we'll determine what log level to set based on needs + level: trace + access_rules: + matching_strategy: regexp + authenticators: + cookie_session: + enabled: true + config: + # this should be the internal URL of the public Kratos service's whoami endpoint, which might look like the below + check_session_url: http://kratos-public/sessions/whoami + preserve_path: true + # this means we automatically sweep up all the metadata kratos provides for use + # in, for example, the JWT, if we ever have more + extra_from: "@this" + # kratos will be configured to put the subject from the IdP here + subject_from: "identity.id" + only: + - ory_kratos_session + oauth2_introspection: + enabled: true + config: + introspection_url: https://whatever/the/wso2/url/is/oauth2/introspect + introspection_request_headers: + # see https://is.docs.wso2.com/en/latest/learn/invoke-the-oauth-introspection-endpoint/ for what credentials + # will need to be configured here + # also, this does not seem to be settable via environment variable, which means it is + authorization: "Basic SOME WORKING AUTH HERE" + cache: + # disabled to make debugging easier. enable for caching. + enabled: false + ttl: "60s" + authorizers: + remote_json: + enabled: true + config: + # the check URL for Keto. This will be POST'd to. See https://www.ory.sh/keto/docs/reference/rest-api#operation/postCheck + remote: http://internal-keto-url-here/check + mutators: + id_token: + enabled: true + config: + # this should be the internal base URL for the API service, which will look something like the below + issuer_url: http://whatever-oathkeeper-internal-is-api:4456/ + errors: + fallback: + - json + handlers: + json: + # this gives API clients pretty error JSON + enabled: true + config: + verbose: true + redirect: + enabled: true + config: + # set this to whatever the main URL is, it'll ensure that browser errors redirect there + to: https://whatever-external-main-url-is/ + when: + - error: + - unauthorized + - forbidden + request: + header: + accept: + - text/html +secret: + # without this we would need to put the JWKS in the config, which would mean we couldn't rotate it just by changing the secret + manage: false + # change to whatever is used for secret name + name: oathkeeper-jwks +deployment: + extraEnv: + # for whatever reason this environment variable only gets set if the JWKS is in the config even though the rest of the secret mounting + # and such still happens + - name: MUTATORS_ID_TOKEN_CONFIG_JWKS_URL + value: file:///etc/secrets/mutator.id_token.jwks.json + + +``` + +### Rules + +Rule resources will need to be created in Kubernetes for each backend "match" (URL regex plus HTTP method(s)) protected with a permission. The example provided below provides guidance. + + +As the flexibility to define third-party services and bounded contexts increases, they can define their own rules (perhaps behind a Helm values flag), which express which permissions should be required for which URLs. + + +The biggest potential issue here is that each match MUST be unique. If a request matches multiple, Ory Oathkeeper will complain. Once a general pattern is picked that results in unique regexes, this will not happen except with user error. + +```yaml + +apiVersion: oathkeeper.ory.sh/v1alpha1 +kind: Rule +metadata: + name: a-unique-name +spec: + version: v0.36.0-beta.4 + upstream: + # set to whatever URL this request should be forwarded to + url: http://internal-url-of-backend-service/ + match: + # this might need to be http even if external is https, it depends on how ingress does things + # my recommendation is to have a given prefix, then the "everything else in the domain name" matcher + # so it doesn't need to be changed when the config is moved between various main domains + # then whatever is needed for the specific path (this is set to match all subpaths) + # regexes go in between angle brackets + url: https://example.<[^/]*>/<.*> + methods: + # whatever method(s) this rule applies to + - GET + authenticators: + - handler: oauth2_introspection + # comment out this second one to not allow browser-cookie access + - handler: cookie_session + authorizer: + handler: remote_json + config: + # these will generally be identical for all rules, + # except "object" will be changed to the permission ID that is relevant for + # this URL + payload: | + { + "namespace": "permission", + "object": "PERMISSION IDENTIFIER HERE", + "relation": "granted", + "subject_id": "{{ print .Subject }}" + } + mutators: + # change this to an empty array if the id_token isn't needed, if you want + - handler: id_token + +``` +### Configure Ory Oathkeeper to use Kratos as its cookie Authenticator +This part of the config above is applicable. Reference documentation for Ory Oathkeeper authenticators is found [here](https://www.ory.sh/oathkeeper/docs/next/pipeline/authn). + +```yaml + authenticators: + cookie_session: + enabled: true + config: + # this should be the internal URL of the public Kratos service's whoami endpoint, which might look like the below + check_session_url: http://kratos-public/sessions/whoami + preserve_path: true + # this means we automatically sweep up all the metadata kratos provides for use + # in, for example, the JWT, if we ever have more + extra_from: "@this" + # kratos will be configured to put the subject from the IdP here + subject_from: "identity.id" + only: + - ory_kratos_session + +``` + +### Configure Ory Oathkeeper to use WSO2 ISKM for token introspection +Reference documentation is found [here](https://www.ory.sh/oathkeeper/docs/next/pipeline/authn). + +```yaml + oauth2_introspection: + enabled: true + config: + introspection_url: https://whatever/the/wso2/url/is/oauth2/introspect + introspection_request_headers: + # see https://is.docs.wso2.com/en/latest/learn/invoke-the-oauth-introspection-endpoint/ for what credentials + # will need to be configured here + # also, this does not seem to be settable via environment variable, which means it is + authorization: "Basic SOME WORKING AUTH HERE" + cache: + # disabled to make debugging easier. enable for caching. + enabled: false + ttl: "60s" +``` + +### Configure Ory Oathkeeper to use Ory Keto as its authorizer +This part of the config above is applicable. +Reference documentation about Ory Oathkeeper authorizers is found [here](https://www.ory.sh/oathkeeper/docs/next/pipeline/authz). + +```yaml + authorizers: + remote_json: + enabled: true + config: + # the check URL for Keto. This will be POST'd to. See https://www.ory.sh/keto/docs/reference/rest-api#operation/postCheck + remote: http://internal-keto-url-here/check + +``` + +## Ory Kratos – implementation detail + +Ory Kratos is the part of the Ory Implementation suite that manages all the authentication flows. +It is highly configurable and can connect to a variety and multiple of authentication systems and flows. The [Kratos Documentation](https://www.ory.sh/kratos/docs/next/) explain the extent of the configuration well. I.e. it is likely to cater for your requirements. +In this workstream project, only the User Login and logout flow are required and implemented. +It is useful to know that Kratos can also provided flows for: +- **Self-service Login and Registration:** Allow end-users to create and sign into accounts (we call them identities) using Username / Email and password combinations, Social Sign In ("Sign in with Google, GitHub"), Passwordless flows, and others. +- **Multi-Factor Authentication (MFA/2FA):** Support protocols such as TOTP (RFC 6238 and IETF RFC 4226 - better known as Google Authenticator) +- **Account Verification:** Verify that an E-Mail address, phone number, or physical address actually belong to that identity. +- **Account Recovery:** Recover access using "Forgot Password" flows, Security Codes (in case of MFA device loss), etc. +- **Profile and Account Management:** Update passwords, personal details, email addresses, linked social profiles using secure flows. +- **Admin APIs:** Import, update, delete identities. +... that may become important in future version of the IaC deployment designs. + + +### Deployment details +The Kratos Helm Chart is described at [ORY Kratos Helm Chart | k8s](https://k8s.ory.sh/helm/kratos.html) and defined at [k8s/helm/charts/kratos at master · ory/k8s · GitHub](https://github.com/ory/k8s/tree/master/helm/charts/kratos). Unlike Ory Oathkeeper, it does not have any related Maester handling a CRD. It does, however, need a database (which can be MySQL, PostgreSQL, CockroachDB, or a few others). The Helm repository is the same as for Ory Oathkeeper, and documented at [ORY Helm Charts | k8s](https://k8s.ory.sh/helm/). A configuration reference is at [Configuration | Ory Kratos](https://www.ory.sh/kratos/docs/reference/configuration), but note that the Helm chart works slightly differently. + + +In addition to a database, the other major difference for Kratos is that it requires a user interface, in the form of a small web application that handles rendering the current stage of what’s happening with Kratos to the browser and also doing the necessary backend communication to make that happen securely. In our case, the UI we’ll use is very simple, and is never actually visible—all it will do is immediately forward to the one OIDC Identity Provider (IdP) we’ll have configured and receive the related callback. This UI application has already been created and open sourced in the `modusbox` repository, and releases public docker images in the GitHub docker registry. The UI can be found at [GitHub - modusbox/kratos-ui-oidcer: A Kratos UI for forwarding immediately to a single configured OIDC provider](https://github.com/modusbox/kratos-ui-oidcer), and is a very minimal Rust application with excellent test coverage and a tiny docker image (about 5 megabytes, https://github.com/modusbox/kratos-ui-oidcer/pkgs/container/oidcer ). It is referred to as 'Shim' in the above design documentation. + +For ease of hosting, Kratos and the UI should be mounted on separate paths on the same domain as the main user interface. Alternatively, it is possible to configure them on a different domain and configure Kratos to use cross-domain cookies. This document is written under the assumption the same-domain strategy is chosen. + +### Connecting to the Main UI +A client must be created in the IdP that supports OIDC authorization code grants. This client must be configured to redirect either to any URL under the main UI if it supports wildcards, or the specific URL for the path `/kratos/self-service/methods/oidc/callback/idp` (note that the last segment, `idp`, is the provider ID in the config, so both must change together). This client will be used in the helm chart values config. + +In order to connect successfully with Kratos, the Main UI must behave as follows: + +1. Make a cookies-included request to `/kratos/sessions/whoami` (documented at [HTTP API Documentation | Ory Kratos](https://www.ory.sh/kratos/docs/reference/api/#operation/toSession) ), which returns a 200 and an object containing user metadata if the user is logged in, or a 401 if they are not. +2. If the user is not logged in, either immediately redirect to or provide a link to `/kratos/self-service/registration/browser`. Note: `registration` in the URL is not a typo. This refers to registration with Kratos, which IdP users will not be initially. If the user already exists, Kratos will automatically follow the login flow instead. +3. To log out, link the user to `/kratos/self-service/browser/flows/logout` + +### Annotated Helm Values +This configuration assumes the helm deployment’s name is `kratos` and, that the Kratos service is exposed at `/kratos/` on the same domain as the main UI, and that the Kratos UI is exposed at `/auth/` on the same domain as the main UI. + +The Helm chart does support ingress creation, but is not covered in the documentation. + +```yaml +deployment: + extraVolumes: + - name: extra-config + configMap: + name: kratos-extra-config + extraVolumeMounts: + - name: extra-config + mountPath: /etc/config2 + readOnly: true +kratos: + # NOTE: helm chart deployment does not seem to automatically pick up + # on changes here + identitySchemas: + # TODO note the domain to be replaced in $id, the url doesn't need to resolve + "identity.schema.json": | + { + "$id": "http://REPLACE_THIS_WITH_SOME_MEANINGFUL_DOMAIN/schema/user", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "A user", + "type": "object", + "properties": { + "traits": { + "type": "object", + "properties": { + "email": { + "title": "E-Mail", + "type": "string", + "format": "email" + }, + "subject": { + "title": "Subject", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + } + } + } + } + } + config: + identity: + default_schema_url: file:///etc/config/identity.schema.json + courier: + smtp: + connection_uri: smtp://unused/ + # TODO the appropriate database DSN needs to go here, or be wired up via a secret and the environment variable `DSN` + dsn: TODO DATABASE DSN HERE + hashers: + argon2: + parallelism: 1 + iterations: 3 + # add resources and increase this amount, + # if using passwords (vs oidc) in a production context + memory: 17000 + salt_length: 16 + key_length: 32 + log: + # TODO adjust after successful setup, likely down to info + level: trace + selfservice: + flows: + registration: + # TODO if the place the UI goes changes, this needs to change + ui_url: /auth/ + after: + oidc: + hooks: + - hook: session + logout: + after: + # TODO the IdP's logout URL should go here, with a redirect encoded into it if that's supported (might not work the same way, this is just an example) + default_browser_return_url: https://idp.logout.url.here/logout/path?redirect_uri=https%3A%2F%2Fsomewhere.example.com%2F + methods: + oidc: + enabled: true + config: + providers: + - id: idp + provider: generic + # TODO both the client_id and client_secret need to be set appropriately to the client supporting authorization code grants with openid + # TODO these can alternatively be set via environment variable from a k8s secret + client_id: TODO + client_secret: TODO + mapper_url: file:///etc/config2/oidc.jsonnet + # TODO this should be the right IdP URL to perform OIDC discovery on + # If the IdP does not support discovery, auth_url and token_url can be set here instead + # some IdPs may also need a requested_claims, see Kratos config documentation if there seems to be an issue + issuer_url: https://some.public.idp.url.supporting.discovery/might/have/path/ + scope: + # TODO adjust requested scope based on IdP (WSO2) documentation + - openid + password: + enabled: false + # TODO set this to the base URL of the main UI + default_browser_return_url: "https://somewhere.example.com/" + serve: + public: + # TODO set this to the base URL of the main UI plus the `/kratos` path, will need to be updated if the same-domain approach is not used + base_url: "https://somewhere.example.com/kratos" + autoMigrate: true +``` +### JSonnet ConfigMap +In the Kratos Helm values, it references a ConfigMap `kratos-extra-config` that contains JSonnet (a configuration language) referencing how to transform the IdP’s claims into what Kratos stores about the person. That ConfigMap should contain a key `oidc.jsonnet` with the following contents: + +```javascript +local claims = std.extVar('claims'); + +{ + identity: { + traits: { + email: claims.email, + name: claims.name, + subject: claims.sub + }, + }, +} +``` + +The email and subject claims will probably never need to change, but with some IdPs, the name might be provided differently, in which case that part of the JSonnet will need to be updated. The keys inside `traits` are basically arbitrary (though `subject` has some dependencies elsewhere that would need to be updated), so long as they’re also updated in the schema in the config, but the values are restricted to the list of likely claims inside an OIDC ID Token, and are described in the Kratos documentation. This will probably not come up. + +### UI Deployment & Service +The service will also need to be exposed at an appropriate path, the config assumes `/auth/`, on the same domain as the main UI. + +```yaml +--- +apiVersion: v1 +kind: Service +metadata: + name: kratos-ui + labels: + app: kratos-ui +spec: + ports: + - name: http + port: 80 + targetPort: http + selector: + app: kratos-ui + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kratos-ui + labels: + app: kratos-ui +spec: + replicas: 1 + selector: + matchLabels: + app: kratos-ui + template: + metadata: + labels: + app: kratos-ui + spec: + containers: + - name: kratos-ui + image: ghcr.io/modusbox/oidcer:latest + env: + - name: ROCKET_PORT + value: "80" + - name: ROCKET_REGISTRATION_ENDPOINT + # TODO if the kratos helm chart is given a different name than kratos, + # the domain will be different here, it should be the domain of the kratos service + value: http://kratos-public/self-service/registration/flows + ports: + - name: http + containerPort: 80 + readinessProbe: + httpGet: + path: /healthz + port: 80 +``` +### Ory reference links +- **Configuring Login Sessions.** [docs here](https://www.ory.sh/kratos/docs/guides/login-session) +- **Configuring Session cookies.** Details of the cookies sessions [docs here](https://www.ory.sh/kratos/docs/guides/configuring-cookies) +- **Configuring Kratos for CORS.** [docs here](https://www.ory.sh/kratos/docs/guides/setting-up-cors) +- **Ory Kratos - Ory Oathkeeper integration (OIDC).** [Kratos docs here](https://www.ory.sh/kratos/docs/guides/zero-trust-iap-proxy-identity-access-proxy) +- **Ory Kratos - WSO2 OIDC integration.** [docs here](https://www.ory.sh/kratos/docs/guides/sign-in-with-github-google-facebook-linkedin) + diff --git a/docs/technical/business-operations-framework/SettlementBC.md b/docs/technical/business-operations-framework/SettlementBC.md new file mode 100644 index 000000000..d85b0ebc6 --- /dev/null +++ b/docs/technical/business-operations-framework/SettlementBC.md @@ -0,0 +1,201 @@ +# Settlement Operational Implementation + +## Introduction + +The objective of this design is to provide a solution that links the business process functions with core-settlement operations on the switch. + +This design is an example implementation of a Mojaloop settlement for a specific use case and is not meant to be comprehensive or cover all scenarios. This guide outlines the high-level design and explains the thinking that went into the design for a specific use-case chosen.``` +Although a version of this design is built and operational, not everything in this design document has been built. +This is an example of a settlement implementation design. The benefit of this design & design document is therefore: +- to use for demonstration; +- to use as an initial version to help 'Getting Started Quickly'; +- to use as a starting design on which improvements can be made before adopting; +- to use as a starting point to elaborate on concepts that are discussed in this design that may need to be addressed in another design. + +## Core-Settlement Operations + +This is the existing Settlement functionality provided by the supporting [Central-Settlement](https://github.com/mojaloop/central-settlement) Mojaloop Core component. Detailed information can be found in the [Mojaloop Technical Overview Documentation](https://github.com/mojaloop/documentation/tree/master/legacy/mojaloop-technical-overview/central-settlements). + +The Core-Settlement operations support the following capabilities: + +- Create a Settlement Matrix Report based on a list of Settlement-Windows +- Process Settlement Acknowledgements for an existing Settlement Matrix Report +- Manage Settlement-Windows (i.e. Create, Close, etc) +- Queries for Settlement Matrix Reports, Settlement-Windows, etc + +The OpenAPI definition is available at the [Mojaloop-Specification repository](https://github.com/mojaloop/mojaloop-specification/tree/master/settlement-api). + + +## High-level Architecture + +![High-level Settlement Architecture](../../.vuepress/public/BizOps-Framework-Settlements.png) + +### Experience layer + +The settlement experience layer is a stateless API that exposes the data to be consumed by its intended audience. Currently it's main function is to add the looked up user information into the API which is injected in the request headers by ORY Oathkeeper proxy. This function is expected to become larger as the product develops. + +### Process layer + +Process APIs provide a means of combining data and orchestrating multiple System APIs for a specific business purpose. The mojaloop central-settlement, and central-ledger API are being consumed by this process API. + +The Settlement Process API should conform to the [Mojaloop naming standards](https://docs.google.com/document/d/1AZbX0UjraytFty0IWOHpyR6z35bh0-MCFG1vGKId_5M/edit?usp=sharing), and as such the following name will be used: `settlement-process-svc`. + +## High-level Settlement Business Process + +This is a process that relies on the existing core-settlement operations to orchestrate the following capabilities: + +1. **Closing a settlement window** +The current settlement window can be closed manually as if there have been transfers linked to the settlement window. The hub operator can select the current open window, and then choose to close the window. +1. **Settlement Initiation** +Settlement Initiation is used by the hub operator to create a settlement batch which controls and drives the settlement process. +To initiate the settlement process, the hub operator selects : + - a set of settlement windows + - and optionally a settlement currency or a settlement model. (If a settlement currency is provided, then this is used to determine the settlement model.) +The position ledgers of the net credit participants are adjusted during Settlement Initiation. +**Note:** It is important to create the batch settlement object in the way that the settlement is to be completed and finalized. +1. A **Settlement initiation report** is generated and used to communicated to the settlement bank the requirements of the settlement. +1. **Settlement Finalization & settlement account re-balancing** +This process needs to occur after the settlement bank has applied the settlement changes. In this step the: + - settlement process is completed and a settlement finalization report has been received from the settlement bank. + - the net debit participants in the settlement have their position ledgers adjusted. + - the settlement ledgers are adjusted for all participants to match the transferred amount for the settlement. + - the settlement ledgers are checked against the real settlement account balances and adjustments processed to ensure that they are aligned. + +### Re-balancing function - is not best practice +It is worth noting that the re-balancing function that is defined in the above settlement finalization process is not the preferred or best-practice approach. +This approach was chosen because of regulatory requirements and limitations of mechanisms available to implement settlement between participants, i.e. it was designed to work on existing in-place financial solutions. Re-balancing has quite a few drawbacks, and is not considered best practice and should be avoided if possible. +These drawbacks are: +1. Out of sequence re-balancing results in incorrect results. This vulnerability therefore requires a business process and supportive management to enforce. +1. Reconciliation of the Mojaloop Settlement Account and the settlement bank account is difficult and complicated. This is because the re-balancing may not directly reflect the activity in the settlement bank account. The transfer amounts are linked to the timing of when the re-balancing action is applied, and when the reports and statements are generated. + +**Recommended solutions** +There are numerous other approaches to implementing settlement that do follow best practice. Please consult one of the experts in the Mojaloop community if you would like to explore this. If your requirement has similar limitations and creating a new mechanism is not an option, then there is a relatively minor adjustment that can be made to improve this solution and should be considered. +Replacing re-balancing mechanism with an import of a statement from the settlement bank account's transactions would remove the timing and reconciling problems mentioned above. + +## Detailed Sequence Diagram +![Settlement Detailed Process](../../.vuepress/public/settlementProcessAPI.svg) + +There are a couple of processes in the sequence diagram that are worth elaborating on. + +### Determining settlement Model + +This need to first determine which currencies are involved in the settlement, and then determine the appropriate list of Settlement Models which should be applied. A Settlement will be created for each of these Settlement Models. + +### Validation of the settlement finalization data + +The data that is presented as part of the settlement finalization needs a significant amount of validations on the data. +Some validations check integrity of the data, and these check will fail the process if not passed. Other validations do not prevent the process continuing, however will show warnings that need to be presented to the operator. +The continuation of the process is only possible once the operator has accepted the confirmed warnings with their resultant effects, and has provided their selected options for how the process should be applied. +It is for this reason that the validation of the data is a necessary step, and must be referenced when accepting and proceeding with the process. + +### Use cases for Finalize Settlement +**Validation scenarios** + +| Validation Description | Expected behaviour | +|---------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| +| Selected settlement ID does not match report settlement ID | Abort finalization with error | +| Sum of transfers in the report is non-zero | Abort finalization with error | +| Transfer amount does not match net settlement amount | Abort finalization with error | +| Balance not modified corresponding to transfer amount | Continue --> Adjust Settlement Account Balance to align | +| Balance provided in the report is not a positive value | Continue --> Set settlement balance to zero; set NCD = 0; disable participant POSITION account | +| Accounts in settlement not present in report | Abort finalization with error | +| Accounts in report not present in settlement | Abort finalization with error | +| Participant identifiers do not match - participant ID, account ID and participant name must match | Abort finalization with error | +| Account type should be POSITION | Abort finalization with error | +| New balance amount not valid for currency | Abort finalization with error | +| Transfer amount not valid for currency | Abort finalization with error | +| Account ID does not exist in switch | Abort finalization with error | +| Attempted to finalize an aborted settlement | Abort finalization with error | +| Error processing adjustment for participant | Continue with other participants - notify user of error | +| Error attempting to set settlement state to PS_TRANSFERS_RECORDED | Continue with other participants - notify user of error | +| Error attempting to set settlement state to PS_TRANSFERS_RESERVED | Continue with other participants - notify user of error | +| Error attempting to set settlement state to PS_TRANSFERS_COMMITTED | Continue with other participants - notify user of error | +| Errors attempting to settle accounts | Continue with other participants - notify user of error | +| Error attempting to set NDC | Continue with other participants - notify user of error | +| Error attempting to process funds in/out | Continue with other participants - notify user of error | +| Balance unchanged after processing funds in/out | Continue with other participants - notify user of error | +| Incorrect resulting balance after processing funds in/out | Continue with other participants - notify user of error | +| Failed to record settlement participant account state | Continue with other participants - notify user of error | + +### Audit information in the current Mojaloop version + +The process being performed is captured in the settlement reason field, and is therefore available in the audit reports. +Additionally the user and the references are captured in the extension lists. These too can be queried in the audit reports. + +### RBAC + +In order to make full use of the RBAC controls, the above four processes will be implemented as separate API endpoint & HTTP method combinations. This is to allow a different permissions to be associated with each process. + +## Multi-currency support + +Multi-currency settlement execution is determined by two factors: + +1. How the Settlement Models are constructed? + Settlement Models can be linked to a currency or left un-linked and applicable to all currencies. +1. How the settlements are initiated? + Settlement can be initiated with optionally a currency, or optionally a settlement model. + +As it is not easy to separate a settlement once it has been initiated, it is preferable to decide how settlement should be applied, and then design the system accordingly. + +--- +**NOTE** +Running a single currency multi-lateral deferred net settlement model, and using test currencies to perform regular platform health tests. Would prefer to have all settlements of test currencies to be created separately to the real currency. Would prefer not to have to select a currency or settlement model when initiating a settlement. +This can be achieved by creating separate settlement models I.e. one for each test currency, and one for the real currency. +The default action on initiating the settlement with transaction in both currencies, would be that separate settlements are initiated. (The determine settlement model function would find both settlement models.) +___ + + +## Error Cases +### Initiate Settlement + +**Detailed Initiate Settlement Sequence Diagram** + +![Initiate Settlement Process with Errors](../../.vuepress/public/settlementProcessInitiationErrors.svg) + +**Initiate Settlement Error Codes** + +| Error Description | Error Code | HTTP Code | Category | +|------------------------------------------------------------------------|-------------|------------------|-----------------------------------------------------------| +| Settlement ID not found | 3100 | 400 | Request Validation Error | +| Currency not valid | 3100 | 400 | Request Validation Error | +| SettlementModel not found | 3100 | 400 | Request Validation Error | +| Not able to create settlement | 2000 | 500 | Internal Server Error | +| Not able to update settlement state | 2000 | 500 | Internal Server Error | +| Technical error while communicating with Mojaloop services | 1000 | 500 | Technical Error | + + +### Finalize Settlement + +**Detailed Finalize Settlement Sequence Diagram** + +![Initiate Settlement Process with Errors](../../.vuepress/public/settlementProcessFinaliseErrors.svg) + +**Finalize Settlement Validation Error Codes** + +| Error Description | Error Code | HTTP Code | Category | +|------------------------------------------------------------------------|-------------|------------------|-----------------------------------------------------------| +| Settlement ID not found | 3100 | 400 | Request Validation Error | +| Participant IDs not found | 3000 | 400 | Request Validation Error | +| Participant Account IDs not found | 3000 | 400 | Request Validation Error | +| Technical error while communicating with Mojaloop services | 1000 | 500 | Technical Error | +| Selected settlement ID does not match report settlement ID | 3100 | 500 | Process Validation Error | +| Participant IDs in report not matching participant IDs in settlement | 3000 | 500 | Process Validation Error | +| Accounts in the report not matching with accounts in the settlement | 3000 | 500 | Process Validation Error | +| Sum of transfers in the report is non-zero | 3100 | 500 | Process Validation Error | +| Transfer amount does not match net settlement amount | 3100 | 500 | Process Validation Error | +| New balance amount not valid for currency | 3100 | 500 | Process Validation Error | +| Transfer amount not valid for currency | 3100 | 500 | Process Validation Error | +| Settlement is in ABORTED or invalid state | 3100 | 500 | Process Validation Error | +| Transfer amount not valid for currency | 3100 | 500 | Process Validation Error | + +**Finalize Settlement Confirmation Error Codes** + +| Error Description | Error Code | HTTP Code | Category | +|------------------------------------------------------------------------|-------------|------------------|-----------------------------------------------------------| +| Finalisation ID not found | 3100 | 400 | Request Validation Error | +| Settlement ID not found | 3100 | 400 | Request Validation Error | +| Technical error while communicating with Mojaloop services | 1000 | 500 | Technical Error | +| Error while funds in/out | 2001 | 500 | Internal Server Error | +| Not able to update settlement state | 2001 | 500 | Internal Server Error | +| Balances not matching after settlement | 2001 | 500 | Internal Server Error | +| Balances not matching after re-balancing | 2001 | 500 | Internal Server Error | diff --git a/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-fulfil-2.1.0.plantuml b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-fulfil-2.1.0.plantuml new file mode 100644 index 000000000..1939a92da --- /dev/null +++ b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-fulfil-2.1.0.plantuml @@ -0,0 +1,174 @@ +/' + License + -------------- + Copyright © 2020 Mojaloop Foundation + The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 + (the "License") and you may not use these files except in compliance with the [License](http://www.apache.org/licenses/LICENSE-2.0). + You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the [License](http://www.apache.org/licenses/LICENSE-2.0). + + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- + '/ + + +@startuml fx-fulfil-request +' declate title +title 2.1.0. FXP sends an Fulfil Success FX Conversion Request + +autonumber + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +control "FXP1\nFXP" as FXP1 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "topic-transfer-fulfil" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +control "Settlement Model\nHandler" as SETMODEL_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant FXP1 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_SETMODEL + participant SETMODEL_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate SETMODEL_HANDLER +activate POS_HANDLER +group FXP1 sends a fulfil success FX conversion request + FXP1 <-> FXP1: Retrieve fulfilment string generated during\nthe FX quoting process or regenerate it using\n**Local secret** and **ILP Packet** as inputs + note right of FXP1 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "conversionState": "" + "fulfilment": , + "completedTimestamp": , + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + end note + FXP1 ->> MLAPI: PUT - /fxTransfers/ + activate MLAPI + MLAPI -> MLAPI: Schema validation\n + break Schema validation failed + MLAPI -->> FXP1: Respond HTTP - 400 (Bad Request) + end + MLAPI -> MLAPI: Validate incoming request \n(e.g transfer has not timed out, completedTimestamp is not in the future)\nError codes: 2001, 3100 + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: fx_commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Fulfil event for Payee\nError code: 2001 + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all)\nError code: 2001 + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> FXP1: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Success) {[[https://github.com/mojaloop/documentation/tree/master/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.svg 2.1.1]]} \n + FULF_HANDLER -> TOPIC_SETMODEL: Produce message + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_SETMODEL <- SETMODEL_HANDLER: Consume message + ref over TOPIC_SETMODEL, SETMODEL_HANDLER: Settlement Model Handler Consume (Success)\n + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Success)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'fx_commit' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'fx_commit' + ||| + ref over FXP1, TOPIC_NOTIFICATIONS: Send notification to Participant (FXP)\n + NOTIFY_HANDLER -> FXP1: Send callback notification + end + ||| +end +deactivate POS_HANDLER +deactivate FULF_HANDLER +deactivate NOTIFY_HANDLER +@enduml \ No newline at end of file diff --git a/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-fulfil-2.1.0.svg b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-fulfil-2.1.0.svg new file mode 100644 index 000000000..c338b9c10 --- /dev/null +++ b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-fulfil-2.1.0.svg @@ -0,0 +1,330 @@ + + + + + + + + + + + + 2.1.0. FXP sends an Fulfil Success FX Conversion Request + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + FXP1 + FXP + + + FXP1 + FXP + + + ML API Adapter + + + ML API Adapter + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + topic-transfer-fulfil + + + topic-transfer-fulfil + Fulfil Event Handler + + + Fulfil Event Handler + + + + + topic- + settlement-model + + + topic- + settlement-model + Settlement Model + Handler + + + Settlement Model + Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + Position Handler + + + Position Handler + + + + + topic- + notification + + + topic- + notification + + + + + + + + + FXP1 sends a fulfil success FX conversion request + + + + + 1 + Retrieve fulfilment string generated during + the FX quoting process or regenerate it using + Local secret + and + ILP Packet + as inputs + + + Headers - transferHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } + + Payload - transferMessage: + { + "conversionState": "<transferState>" + "fulfilment": <IlpFulfilment>, + "completedTimestamp": <DateTime>, + "extensionList": { + "extension": [ + { + "key": <string>, + "value": <string> + } + ] + } + } + + + + 2 + PUT - /fxTransfers/<ID> + + + + + 3 + Schema validation + + + + break + [Schema validation failed] + + + + 4 + Respond HTTP - 400 (Bad Request) + + + + + 5 + Validate incoming request + (e.g transfer has not timed out, completedTimestamp is not in the future) + Error codes: + 2001, 3100 + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + type: fulfil, + action: fx_commit, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 6 + Route & Publish Fulfil event for Payee + Error code: + 2001 + + + + + 7 + Ensure event is replicated as configured (ACKS=all) + Error code: + 2001 + + + 8 + Respond replication acknowledgements have been received + + + + 9 + Respond HTTP - 200 (OK) + + + 10 + Consume message + + + ref + Fulfil Handler Consume (Success) { + + 2.1.1 + + } + + + + 11 + Produce message + + + 12 + Produce message + + + 13 + Consume message + + + ref + Settlement Model Handler Consume (Success) + + + + 14 + Consume message + + + ref + Position Handler Consume (Success) + + + + 15 + Produce message + + + 16 + Consume message + + + opt + [action == 'fx_commit'] + + + ref + Send notification to Participant (Payer) + + + + 17 + Send callback notification + + + 18 + Consume message + + + opt + [action == 'fx_commit'] + + + ref + Send notification to Participant (FXP) + + + + 19 + Send callback notification + + diff --git a/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.0.plantuml b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.0.plantuml new file mode 100644 index 000000000..0f0fb7018 --- /dev/null +++ b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.0.plantuml @@ -0,0 +1,186 @@ +/'***** + License + -------------- + Copyright © 2020 Mojaloop Foundation + The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 + (the "License") and you may not use these files except in compliance with the [License](http://www.apache.org/licenses/LICENSE-2.0). + You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the [License](http://www.apache.org/licenses/LICENSE-2.0). + + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- + ******'/ + +@startuml PayerFSP-fx-conversion-prepare-request + +!$payerCurrency = "" +!$payeeCurrency = "" +!$dfsp1Id = "" +!$fxpID = "" +!$payerMSISDN = "" +!$payeeMSISDN = "" +!$payeeReceiveAmount = "" +!$payerSendAmount = "" +!$payeeFee = "" +!$targetAmount = "" +!$fxpChargesSource = "" +!$fxpChargesTarget = "" +!$fxpSourceAmount = "" +!$fxpTargetAmount = "" +!$conversionRequestId = "" +!$conversionId = "" +!$homeTransactionId = "" +!$quoteId = "" +!$transactionId = "" +!$quotePayerExpiration = "" +!$quotePayeeExpiration = "" +!$commitRequestId = "" +!$determiningTransferId = "" +!$transferId = "" +!$fxCondition = "" +!$condition = "" + +' declate title +title 1.1.0. DFSP1 sends an FX Conversion prepare request to FXP1 + +autonumber + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +control "FXP1\nFXP" as FXP1 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "topic-transfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Event Handler" as PREP_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant FXP1 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate PREP_HANDLER +activate POS_HANDLER +group DFSP1 sends an FX Conversion request to FXP1 + note right of DFSP1 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload: + { + "commitRequestId": "$commitRequestId", + "determiningTransferId": "$determiningTransferId", + "initiatingFsp": "$dfsp1Id", + "counterPartyFsp": "$fxpID", + "amountType": "SEND", + "sourceAmount": { + "currency": "$payerCurrency", + "amount": "$fxpSourceAmount" + }, + "targetAmount": { + "currency": "$payeeCurrency", + "amount": "$fxpTargetAmount" + }, + "condition": "$fxCondition" + } + end note + DFSP1 ->> MLAPI: POST - /fxTransfers + activate MLAPI + MLAPI -->> DFSP1: Respond HTTP - 202 (Accepted) + alt Schema validation error + MLAPI-->>DFSP1: Respond HTTP - 400 (Bad Request) + end + note right of MLAPI #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: prepare, + action: fx_prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_TRANSFER_PREPARE: Route & Publish FX Prepare event for Payer + activate TOPIC_TRANSFER_PREPARE + TOPIC_TRANSFER_PREPARE <-> TOPIC_TRANSFER_PREPARE: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_TRANSFER_PREPARE --> MLAPI: Replication acknowledgements have been received + deactivate TOPIC_TRANSFER_PREPARE + alt Error publishing event + MLAPI-->>DFSP1: Respond HTTP - 500 (Internal Server Error)\n**Error code:** 2003 + end + deactivate MLAPI + ||| + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume message + ref over TOPIC_TRANSFER_PREPARE, PREP_HANDLER, TOPIC_TRANSFER_POSITION : Prepare Handler Consume\n + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, POS_HANDLER : Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + ref over FXP1, TOPIC_NOTIFICATIONS : Send notification to Participant (FXP)\n + NOTIFY_HANDLER -> FXP1: Send callback notification + ||| +end +deactivate POS_HANDLER +deactivate PREP_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.0.svg b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.0.svg new file mode 100644 index 000000000..d5d22010d --- /dev/null +++ b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.0.svg @@ -0,0 +1,252 @@ + + + + + + + + + + + + 1.1.0. DFSP1 sends an FX Conversion prepare request to FXP1 + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + FXP1 + FXP + + + FXP1 + FXP + + + ML API Adapter + + + ML API Adapter + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + topic-transfer-prepare + + + topic-transfer-prepare + Prepare Event Handler + + + Prepare Event Handler + + + + + topic-transfer-position + + + topic-transfer-position + Position Event Handler + + + Position Event Handler + + + + + Notification-Topic + + + Notification-Topic + + + + + + + + DFSP1 sends an FX Conversion request to FXP1 + + + Headers - transferHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } + + Payload: + { + "commitRequestId": "<UUID>", + "determiningTransferId": "<UUID>", + "initiatingFsp": "<DFSP1>", + "counterPartyFsp": "<fxpId>", + "amountType": "SEND", + "sourceAmount": { + "currency": "<ISO currency code>", + "amount": "<number>" + }, + "targetAmount": { + "currency": "<ISO currency code>", + "amount": "<number>" + }, + "condition": "<ILP condition>" + } + + + + 1 + POST - /fxTransfers + + + + 2 + Respond HTTP - 202 (Accepted) + + + alt + [Schema validation error] + + + + 3 + Respond HTTP - 400 (Bad Request) + + + Message: + { + id: <transferMessage.commitRequestId> + from: <transferMessage.initiatingFsp>, + to: <transferMessage.counterPartyFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <UUID>, + type: prepare, + action: fx_prepare, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 4 + Route & Publish FX Prepare event for Payer + + + + + 5 + Ensure event is replicated as configured (ACKS=all) + Error code: + 2003 + + + 6 + Replication acknowledgements have been received + + + alt + [Error publishing event] + + + + 7 + Respond HTTP - 500 (Internal Server Error) + Error code: + 2003 + + + 8 + Consume message + + + ref + Prepare Handler Consume + + + + 9 + Produce message + + + 10 + Consume message + + + ref + Position Handler Consume + + + + 11 + Produce message + + + 12 + Consume message + + + ref + Send notification to Participant (FXP) + + + + 13 + Send callback notification + + diff --git a/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.1.a.plantuml b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.1.a.plantuml new file mode 100644 index 000000000..9ce0b9424 --- /dev/null +++ b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.1.a.plantuml @@ -0,0 +1,273 @@ +/'***** + License + -------------- + Copyright © 2020 Mojaloop Foundation + The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 + (the "License") and you may not use these files except in compliance with the [License](http://www.apache.org/licenses/LICENSE-2.0). + You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the [License](http://www.apache.org/licenses/LICENSE-2.0). + + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- + ******'/ + +@startuml prepare-handler-consume +' declate title +title 1.1.1.a. FX Prepare Handler Consume (single message) + +autonumber + +' declare actors +collections "topic-transfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Event Handler" as PREP_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Position DAO" as POS_DAO +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate PREP_HANDLER +group Prepare Handler Consume + note left of PREP_HANDLER #lightgrey + Event is automatically replicated + to the events topic (topic-events) + end note + + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume Prepare event message + activate TOPIC_TRANSFER_PREPARE + deactivate TOPIC_TRANSFER_PREPARE + + break + group Filter Event + PREP_HANDLER <-> PREP_HANDLER: Filter event - Rules: type == 'prepare' && action == 'fx_prepare'\nError codes: 2001 + end + end + + group Validate Prepare Transfer + PREP_HANDLER <-> PREP_HANDLER: Schema validation of the incoming message + PREP_HANDLER <-> PREP_HANDLER: Verify the message's signature (to be confirmed in future requirement) + note right of PREP_HANDLER #lightgrey + The above validation steps are already handled by + the ML-Adapter for the open source implementation. + It may need to be added in future for custom adapters. + end note + + group Duplicate Check + ||| + PREP_HANDLER -> DB: Request Duplicate Check + ref over PREP_HANDLER, DB: Request Duplicate Check\n + DB --> PREP_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE + group Process Duplication + alt hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of PREP_HANDLER #lightgrey + Validate Prepare Transfer (failure) - Modified Request + end note + else hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break + PREP_HANDLER -> DB: stateRecord = await getFxTransferById(commitRequestId) + activate DB + hnote over DB #lightyellow + fxTransferStateChange + end note + DB --> PREP_HANDLER: Return stateRecord + deactivate DB + alt [COMMITTED, ABORTED].includes(stateRecord.transferStateEnumeration) + ||| + + PREP_HANDLER -> TOPIC_NOTIFICATIONS: Produce message [functionality = TRANSFER, action = PREPAPE_DUPLICATE] + else + note right of PREP_HANDLER #lightgrey + Ignore - resend in progress + end note + end + end + end + end + else hasDuplicateId == FALSE + group Validate Prepare Request + group Validate Payer + PREP_HANDLER -> PREP_HANDLER: Validate FSPIOP-Source header matches initiatingFsp + PREP_HANDLER -> PREP_HANDLER: Validate payload.sourceAmount and payload.targetAmount scale and precision + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payer Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payer participant is active + PREP_HANDLER <-> PREP_HANDLER: Validate Payer participant position account for the source currency [exists, active] + end + group Validate Payee + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payee Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payee participant is active + PREP_HANDLER <-> PREP_HANDLER: Validate Payee participant position account for the target currency [exists, active] + end + group Validate Condition and Expiration + PREP_HANDLER <-> PREP_HANDLER: Validate cryptographic condition + PREP_HANDLER <-> PREP_HANDLER: Validate expiration [payload.expiration is valid ISO date and not in the past] + end + group Validate Different FSPs (if ENABLE_ON_US_TRANSFER == false) + PREP_HANDLER <-> PREP_HANDLER: Validate Payer and Payee FSPs are different + end + alt Validate Prepare Transfer (success) + group Persist Transfer State (with transferState='RECEIVED-PREPARE') + PREP_HANDLER -> DB: Request to persist transfer\nError codes: 2003 + activate DB + hnote over DB #lightyellow + fxTransfer + fxTransferParticipant + fxTransferStateChange + fxTransferExtension + end note + DB --> PREP_HANDLER: Return success + deactivate DB + end + else Validate Prepare Transfer (failure) + group Persist Transfer State (with transferState='INVALID') (Introducing a new status INVALID to mark these entries) + PREP_HANDLER -> DB: Request to persist transfer\n(when Payee/Payer/crypto-condition validation fails)\nError codes: 2003 + activate DB + hnote over DB #lightyellow + fxTransfer + fxTransferParticipant + fxTransferStateChange + fxTransferExtension + fxTransferError + end note + DB --> PREP_HANDLER: Return success + deactivate DB + end + end + end + end + end + + alt Validate Prepare Transfer (success) + group Hydrate Transfer Prepare Message + PREP_HANDLER -> PARTICIPANT_DAO: Get participant and currency for FX transfer (with 'payload.determiningTransferId') + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request participant and currency + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return participant and currency + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return participant and currency + deactivate PARTICIPANT_DAO + + end + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: fx_prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer\nError codes: 2003 + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Prepare Transfer (failure) + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": + "errorDescription": "", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: fx_prepare, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + PREP_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError codes: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end +end +deactivate PREP_HANDLER +@enduml + diff --git a/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.1.a.svg b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.1.a.svg new file mode 100644 index 000000000..06c43df70 --- /dev/null +++ b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.1.a.svg @@ -0,0 +1,469 @@ + + + + + + + + + + + + 1.1.1.a. FX Prepare Handler Consume (single message) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + topic-transfer-prepare + + + topic-transfer-prepare + Prepare Event Handler + + + Prepare Event Handler + + + + + topic-transfer-position + + + topic-transfer-position + + + Notification-Topic + + + Notification-Topic + Position DAO + + + Position DAO + + + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + Prepare Handler Consume + + + Event is automatically replicated + to the events topic (topic-events) + + + 1 + Consume Prepare event message + + + break + + + Filter Event + + + + + 2 + Filter event - Rules: type == 'prepare' && action == 'fx_prepare' + Error codes: + 2001 + + + Validate Prepare Transfer + + + + + 3 + Schema validation of the incoming message + + + + + 4 + Verify the message's signature (to be confirmed in future requirement) + + + The above validation steps are already handled by + the ML-Adapter for the open source implementation. + It may need to be added in future for custom adapters. + + + Duplicate Check + + + 5 + Request Duplicate Check + + + ref + Request Duplicate Check + + + + 6 + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + alt + [hasDuplicateId == TRUE] + + + Process Duplication + + + alt + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + Validate Prepare Transfer (failure) - Modified Request + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + break + + + 7 + stateRecord = await getFxTransferById(commitRequestId) + + fxTransferStateChange + + + 8 + Return stateRecord + + + alt + [[COMMITTED, ABORTED].includes(stateRecord.transferStateEnumeration)] + + + 9 + Produce message [functionality = TRANSFER, action = PREPAPE_DUPLICATE] + + + + Ignore - resend in progress + + [hasDuplicateId == FALSE] + + + Validate Prepare Request + + + Validate Payer + + + + + 10 + Validate FSPIOP-Source header matches initiatingFsp + + + + + 11 + Validate payload.sourceAmount and payload.targetAmount scale and precision + + + 12 + Request to retrieve Payer Participant details (if it exists) + + + 13 + Request Participant details + + participant + participantCurrency + + + 14 + Return Participant details if it exists + + + 15 + Return Participant details if it exists + + + + + 16 + Validate Payer participant is active + + + + + 17 + Validate Payer participant position account for the source currency [exists, active] + + + Validate Payee + + + 18 + Request to retrieve Payee Participant details (if it exists) + + + 19 + Request Participant details + + participant + participantCurrency + + + 20 + Return Participant details if it exists + + + 21 + Return Participant details if it exists + + + + + 22 + Validate Payee participant is active + + + + + 23 + Validate Payee participant position account for the target currency [exists, active] + + + Validate Condition and Expiration + + + + + 24 + Validate cryptographic condition + + + + + 25 + Validate expiration [payload.expiration is valid ISO date and not in the past] + + + Validate Different FSPs (if ENABLE_ON_US_TRANSFER == false) + + + + + 26 + Validate Payer and Payee FSPs are different + + + alt + [Validate Prepare Transfer (success)] + + + Persist Transfer State (with transferState='RECEIVED-PREPARE') + + + 27 + Request to persist transfer + Error codes: + 2003 + + fxTransfer + fxTransferParticipant + fxTransferStateChange + fxTransferExtension + + + 28 + Return success + + [Validate Prepare Transfer (failure)] + + + Persist Transfer State (with transferState='INVALID') (Introducing a new status INVALID to mark these entries) + + + 29 + Request to persist transfer + (when Payee/Payer/crypto-condition validation fails) + Error codes: + 2003 + + fxTransfer + fxTransferParticipant + fxTransferStateChange + fxTransferExtension + fxTransferError + + + 30 + Return success + + + alt + [Validate Prepare Transfer (success)] + + + Hydrate Transfer Prepare Message + + + 31 + Get participant and currency for FX transfer (with 'payload.determiningTransferId') + + + 32 + Request participant and currency + + participant + participantCurrency + + + 33 + Return participant and currency + + + 34 + Return participant and currency + + + Message: + { + id: <transferMessage.commitRequestId> + from: <transferMessage.initiatingFsp>, + to: <transferMessage.counterPartyFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <hydratedTransferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: fx_prepare, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 35 + Route & Publish Position event for Payer + Error codes: + 2003 + + [Validate Prepare Transfer (failure)] + + + Message: + { + id: <transferMessage.commitRequestId> + from: <ledgerName>, + to: <transferMessage.initiatingFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": <possible codes: [2003, 3100, 3105, 3106, 3202, 3203, 3300, 3301]> + "errorDescription": "<refer to section 35.1.3 for description>", + "extensionList": <transferMessage.extensionList> + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: fx_prepare, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 36 + Publish Notification (failure) event for Payer + Error codes: + 2003 + + diff --git a/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.2.a.plantuml b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.2.a.plantuml new file mode 100644 index 000000000..cd55802c7 --- /dev/null +++ b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.2.a.plantuml @@ -0,0 +1,312 @@ +/'***** + License + -------------- + Copyright © 2020 Mojaloop Foundation + The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 + (the "License") and you may not use these files except in compliance with the [License](http://www.apache.org/licenses/LICENSE-2.0). + You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the [License](http://www.apache.org/licenses/LICENSE-2.0). + + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- + ******'/ + +@startuml position-handler-consume +' declate title +title 1.1.2.a. Position Handler Consume (single message) + +autonumber + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +entity "Position DAO" as POS_DAO +entity "Settlement DAO" as SETTLEMENT_DAO +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant PARTICIPANT_DAO + participant SETTLEMENT_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + note left of POS_HANDLER #lightgrey + Event is automatically replicated + to the events topic (topic-events) + end note + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'fx_prepare' + POS_HANDLER -> POS_HANDLER: Validate 'payload.commitRequestId' or 'message.value.content.uriParams.id' is not empty\n**Error code:** 2003 + end + end + + alt Calulate & Validate Latest Position (success) + group Calculate position and persist change + POS_HANDLER -> SETTLEMENT_DAO: Request active settlement models + activate SETTLEMENT_DAO + SETTLEMENT_DAO -> DB: Retrieve active settlement models + activate DB + hnote over DB #lightyellow + settlementModel + end note + DB --> SETTLEMENT_DAO: Return active settlement models + deactivate DB + SETTLEMENT_DAO --> POS_HANDLER: Return active settlement models + deactivate SETTLEMENT_DAO + POS_HANDLER -> POS_HANDLER: Select currency matching or default settlement model for POSITION ledger account type\n**Error code:** 6000 + + POS_HANDLER -> PARTICIPANT_DAO: Request Payer Participant position account by name and currency + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Retrieve Payer Participant position account by name and currency + activate DB + hnote over DB #lightyellow + participant + participantCurrency + end note + DB --> PARTICIPANT_DAO: Return Payer Participant position account by name and currency + deactivate DB + PARTICIPANT_DAO --> POS_HANDLER: Return Payer Participant position account by name and currency + deactivate PARTICIPANT_DAO + + POS_HANDLER -> DB: Retrieve transfer state from DB by 'commitRequestId' + activate DB + hnote over DB #lightyellow + fxTransferStateChange + end note + DB --> POS_HANDLER: Retrieve transfer state from DB + deactivate DB + DB --> POS_HANDLER: Return transfer state + + POS_HANDLER -> PARTICIPANT_DAO: Request position limits for Payer Participant + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request position limits for Payer Participant + activate DB + hnote over DB #lightyellow + participant + participantLimit + end note + DB --> PARTICIPANT_DAO: Return position limits + deactivate DB + deactivate DB + PARTICIPANT_DAO --> POS_HANDLER: Return position limits + deactivate PARTICIPANT_DAO + + alt Validate transfer state (transferState='RECEIVED_PREPARE') + POS_HANDLER <-> POS_HANDLER: Update transfer state to RESERVED + POS_HANDLER <-> POS_HANDLER: Calculate latest position for prepare + POS_HANDLER <-> POS_HANDLER: Validate calculated latest position (lpos) against the net-debit cap (netcap) - Rule: lpos < netcap + + POS_HANDLER -> POS_DAO: Request payer participant position for the transfer currency and settlement currency + activate POS_DAO + POS_DAO -> DB: Retrieve payer participant position for the transfer currency and settlement currency + hnote over DB #lightyellow + participantPosiiton + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return payer participant position for the transfer currency and settlement currency + deactivate POS_DAO + + POS_HANDLER <-> POS_HANDLER: Update participant position (increase reserved position by transfer amount) + POS_HANDLER -> DB: Persist payer participant position in DB + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB -> POS_HANDLER: Return success + deactivate DB + + POS_HANDLER -> PARTICIPANT_DAO: Request payer participant limit by currency + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Retrieve payer participant limit by currency + activate DB + hnote over DB #lightyellow + participant + participantCurrency + participantLimit + end note + DB --> PARTICIPANT_DAO: Return payer participant limit by currency + deactivate DB + PARTICIPANT_DAO --> POS_HANDLER: Return payer participant limit by currency + deactivate PARTICIPANT_DAO + + POS_HANDLER <-> POS_HANDLER: Calculate latest available position based on payer limit and payer liquidity cover + + alt Validate position limits (success) + POS_HANDLER <-> POS_HANDLER: Update transfer state to RESERVED + POS_HANDLER -> DB: Update participant position + activate DB + hnote over DB #lightyellow + participantPosition + end note + deactivate DB + + POS_HANDLER -> DB: Persist transfer state change (RESERVED) to DB + activate DB + hnote over DB #lightyellow + fxTransferStateChange + end note + deactivate DB + + POS_HANDLER -> DB: Insert participant position change record + activate DB + hnote over DB #lightyellow + participantPositionChange + end note + deactivate DB + else Validate position limits (failure) + POS_HANDLER -> DB: Persist transfer state change (ABORTED_REJECTED) to DB, **Error codes:** 4001, 4200 + activate DB + hnote over DB #lightyellow + fxTransferStateChange + end note + deactivate DB + end + else transferState !='RECEIVED_PREPARE' + POS_HANDLER <-> POS_HANDLER: Update transfer state to ABORTED_REJECTED + POS_HANDLER -> DB: Persist aborted transfer state + activate DB + hnote over DB #lightyellow + fxTransferStateChange + end note + deactivate DB + end + + alt Transfer state is RESERVED + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event to FXP + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": , + "errorDescription": "", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: prepare, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer. **Error code:** 2001 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + + end + else Calculate & Validate Latest Position (failure) + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": , + "errorDescription": "", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: prepare, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer **Error codes:** 4001, 4200 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + deactivate POS_HANDLER + end +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.2.a.svg b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.2.a.svg new file mode 100644 index 000000000..b814e89ed --- /dev/null +++ b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-prepare-1.1.2.a.svg @@ -0,0 +1,481 @@ + + + + + + + + + + + + 1.1.2.a. Position Handler Consume (single message) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + topic-transfer-position + + + topic-transfer-position + Position Event Handler + + + Position Event Handler + + + + + Notification-Topic + + + Notification-Topic + Position DAO + + + Position DAO + + + Participant DAO + + + Participant DAO + + + Settlement DAO + + + Settlement DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + + + + + + + + Position Handler Consume + + + Event is automatically replicated + to the events topic (topic-events) + + + 1 + Consume Position event message for Payer + + + break + + + Validate Event + + + + + 2 + Validate event - Rule: type == 'position' && action == 'fx_prepare' + + + + + 3 + Validate 'payload.commitRequestId' or 'message.value.content.uriParams.id' is not empty + Error code: + 2003 + + + alt + [Calulate & Validate Latest Position (success)] + + + Calculate position and persist change + + + 4 + Request active settlement models + + + 5 + Retrieve active settlement models + + settlementModel + + + 6 + Return active settlement models + + + 7 + Return active settlement models + + + + + 8 + Select currency matching or default settlement model for POSITION ledger account type + Error code: + 6000 + + + 9 + Request Payer Participant position account by name and currency + + + 10 + Retrieve Payer Participant position account by name and currency + + participant + participantCurrency + + + 11 + Return Payer Participant position account by name and currency + + + 12 + Return Payer Participant position account by name and currency + + + 13 + Retrieve transfer state from DB by 'commitRequestId' + + fxTransferStateChange + + + 14 + Retrieve transfer state from DB + + + 15 + Return transfer state + + + 16 + Request position limits for Payer Participant + + + 17 + Request position limits for Payer Participant + + participant + participantLimit + + + 18 + Return position limits + + + 19 + Return position limits + + + alt + [Validate transfer state (transferState='RECEIVED_PREPARE')] + + + + + 20 + Update transfer state to RESERVED + + + + + 21 + Calculate latest position for prepare + + + + + 22 + Validate calculated latest position (lpos) against the net-debit cap (netcap) - Rule: lpos < netcap + + + 23 + Request payer participant position for the transfer currency and settlement currency + + + 24 + Retrieve payer participant position for the transfer currency and settlement currency + + participantPosiiton + + + 25 + Return payer participant position for the transfer currency and settlement currency + + + + + 26 + Update participant position (increase reserved position by transfer amount) + + + 27 + Persist payer participant position in DB + + participantPosition + + + 28 + Return success + + + 29 + Request payer participant limit by currency + + + 30 + Retrieve payer participant limit by currency + + participant + participantCurrency + participantLimit + + + 31 + Return payer participant limit by currency + + + 32 + Return payer participant limit by currency + + + + + 33 + Calculate latest available position based on payer limit and payer liquidity cover + + + alt + [Validate position limits (success)] + + + + + 34 + Update transfer state to RESERVED + + + 35 + Update participant position + + participantPosition + + + 36 + Persist transfer state change (RESERVED) to DB + + fxTransferStateChange + + + 37 + Insert participant position change record + + participantPositionChange + + [Validate position limits (failure)] + + + 38 + Persist transfer state change (ABORTED_REJECTED) to DB, + Error codes: + 4001, 4200 + + fxTransferStateChange + + [transferState !='RECEIVED_PREPARE'] + + + + + 39 + Update transfer state to ABORTED_REJECTED + + + 40 + Persist aborted transfer state + + fxTransferStateChange + + + alt + [Transfer state is RESERVED] + + + Message: + { + id: <transferMessage.commitRequestId> + from: <transferMessage.initiatingFsp>, + to: <transferMessage.counterPartyFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: transfer, + action: prepare, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 41 + Publish Notification event to FXP + + + + Message: + { + id: <transferMessage.commitRequestId> + from: <switch>, + to: <transferMessage.initiatingFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": <error code>, + "errorDescription": "<error description>", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: prepare, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 42 + Publish Notification (failure) event for Payer. + Error code: + 2001 + + [Calculate & Validate Latest Position (failure)] + + + Message: + { + id: <transferMessage.transferId> + from: <ledgerName>, + to: <transferMessage.payerFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": <error code>, + "errorDescription": "<error description>", + "extensionList": <transferMessage.extensionList> + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: prepare, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 43 + Publish Notification (failure) event for Payer + Error codes: + 4001, 4200 + + diff --git a/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-reject-2.2.0.a.plantuml b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-reject-2.2.0.a.plantuml new file mode 100644 index 000000000..ae16da1ca --- /dev/null +++ b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-reject-2.2.0.a.plantuml @@ -0,0 +1,173 @@ +/'***** + License + -------------- + Copyright © 2020 Mojaloop Foundation + The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 + (the "License") and you may not use these files except in compliance with the [License](http://www.apache.org/licenses/LICENSE-2.0). + You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the [License](http://www.apache.org/licenses/LICENSE-2.0). + + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- +******'/ + +@startuml fx-conversion-abort-request + +title 2.2.0.a. FXP1 sends a PUT call on /error end-point for an FX conversion request + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +control "FXP1\nFXP" as FXP1 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "transfer-fulfil-topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant FXP1 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate POS_HANDLER +group FXP1 sends a Fulfil Success Transfer request + FXP1 <-> FXP1: During processing of an incoming\nPOST /fxTransfers request, some processing\nerror occurred and an Error callback is made + note right of FXP1 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - errorMessage: + { + errorInformation + { + "errorCode": , + "errorDescription": + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + } + end note + FXP1 ->> MLAPI: PUT - /fxTransfers//error + activate MLAPI + MLAPI -> MLAPI: Schema validation + alt Schema validation (failure) + MLAPI -> FXP1: Respond HTTP - 400 (Bad Request) + end + MLAPI -> MLAPI: Validate incoming message (e.g error code is valid)\n**Error codes:** 3100 + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: fx_abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Abort/Reject event for FXP\nError code: 2001 + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all)\nError code: 2001 + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> FXP1: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Reject/Abort)\n + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Abort)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'fx_abort' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'fx_abort' + ||| + ref over FXP1, TOPIC_NOTIFICATIONS: Send notification to Participant (FXP)\n + NOTIFY_HANDLER -> FXP1: Send callback notification + end + ||| +end +deactivate POS_HANDLER +deactivate FULF_HANDLER +deactivate NOTIFY_HANDLER +@enduml \ No newline at end of file diff --git a/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-reject-2.2.0.a.svg b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-reject-2.2.0.a.svg new file mode 100644 index 000000000..208a3245f --- /dev/null +++ b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-fx-reject-2.2.0.a.svg @@ -0,0 +1,285 @@ + + + + + + + + + + + + 2.2.0.a. FXP1 sends a PUT call on /error end-point for an FX conversion request + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + FXP1 + FXP + + + FXP1 + FXP + + + ML API Adapter + + + ML API Adapter + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + transfer-fulfil-topic + + + transfer-fulfil-topic + Fulfil Event Handler + + + Fulfil Event Handler + + + + + topic-transfer-position + + + topic-transfer-position + Position Event Handler + + + Position Event Handler + + + + + Notification-Topic + + + Notification-Topic + + + + + + + + FXP1 sends a Fulfil Success Transfer request + + + + + 1 + During processing of an incoming + POST /fxTransfers request, some processing + error occurred and an Error callback is made + + + Headers - transferHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } + + Payload - errorMessage: + { + errorInformation + { + "errorCode": <errorCode>, + "errorDescription": <errorDescription> + "extensionList": { + "extension": [ + { + "key": <string>, + "value": <string> + } + ] + } + } + } + + + + 2 + PUT - /fxTransfers/<ID>/error + + + + + 3 + Schema validation + + + alt + [Schema validation (failure)] + + + 4 + Respond HTTP - 400 (Bad Request) + + + + + 5 + Validate incoming message (e.g error code is valid) + Error codes: + 3100 + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <errorMessage> + }, + metadata: { + event: { + id: <uuid>, + type: fulfil, + action: fx_abort, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 6 + Route & Publish Abort/Reject event for FXP + Error code: + 2001 + + + + + 7 + Ensure event is replicated as configured (ACKS=all) + Error code: + 2001 + + + 8 + Respond replication acknowledgements have been received + + + + 9 + Respond HTTP - 200 (OK) + + + 10 + Consume message + + + ref + Fulfil Handler Consume (Reject/Abort) + + + + 11 + Produce message + + + 12 + Consume message + + + ref + Position Handler Consume (Abort) + + + + 13 + Produce message + + + 14 + Consume message + + + opt + [action == 'fx_abort'] + + + ref + Send notification to Participant (Payer) + + + + 15 + Send callback notification + + + 16 + Consume message + + + opt + [action == 'fx_abort'] + + + ref + Send notification to Participant (FXP) + + + + 17 + Send callback notification + + diff --git a/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-prepare-1.1.4.a-v2.0.plantuml b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-prepare-1.1.4.a-v2.0.plantuml new file mode 100644 index 000000000..cbdee28bf --- /dev/null +++ b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-prepare-1.1.4.a-v2.0.plantuml @@ -0,0 +1,110 @@ +/'***** + License + -------------- + Copyright © 2020 Mojaloop Foundation + The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Mojaloop Foundation for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + + * Steven Oderayi + -------------- + ******'/ + +@startuml send-notification-to-participant-single-message-v2_0 +' declate title +title 1.1.4.a. Send notification to Participant (Payer/Payee/FXP) (single message) v2.0 + +autonumber + +' Actor Keys: +' actor - Payer DFSP, Payee DFSP +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "Payer DFSP\nParticipant" as PAYER_DFSP +actor "Payee DFSP/FXP\nParticipant" as PAYEE_DFSP_OR_FXP +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Financial Service Provider (Payer)" #lightGray + participant PAYER_DFSP +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant TOPIC_NOTIFICATIONS + participant CSAPI + participant PARTICIPANT_DAO + participant DB +end box + +box "Financial Service Provider (Payee or FXP)" #lightGray + participant PAYEE_DFSP_OR_FXP +end box + +' start flow +activate NOTIFY_HANDLER +group Send notification to Participants + note left of NOTIFY_HANDLER #lightgray + Event is automatically replicated + to the events topic (topic-events) + end note + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume Notification event + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + + note right of NOTIFY_HANDLER #lightgray + The endpoint details are cached, when the cache + expires, the details are fetched again + end note + NOTIFY_HANDLER -> CSAPI: Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints\nError code: 2003 + + activate CSAPI + CSAPI -> PARTICIPANT_DAO: Fetch Endpoint details for Participant\nError code: 2003 + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch Endpoint details for Participant + activate DB + hnote over DB #lightyellow + participantEndpoint + end note + DB -> PARTICIPANT_DAO: Retrieved Endpoint details for Participant + deactivate DB + PARTICIPANT_DAO --> CSAPI: Return Endpoint details for Participant + deactivate PARTICIPANT_DAO + CSAPI --> NOTIFY_HANDLER: Return Endpoint details for Participant\nError codes: 3202, 3203 + deactivate CSAPI + NOTIFY_HANDLER -> PAYER_DFSP: Notification with Prepare/fulfil result/error to \nPayer DFSP to specified Endpoint - PUT \nError code: 1001 + NOTIFY_HANDLER <-- PAYER_DFSP: HTTP 200 OK + alt event.action === 'reserve' + alt event.status === 'success' + NOTIFY_HANDLER -> PAYEE_DFSP_OR_FXP: Notification to with succesful fulfil result (committed) to Payee DFSP/FXP to specified Endpoint - PATCH \nError code: 1001 + ||| + NOTIFY_HANDLER <-- PAYEE_DFSP_OR_FXP: HTTP 200 OK + end + end +end +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-prepare-1.1.4.a-v2.0.svg b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-prepare-1.1.4.a-v2.0.svg new file mode 100644 index 000000000..2d85604fd --- /dev/null +++ b/docs/technical/central-fx-transfers/assets/diagrams/sequence/seq-prepare-1.1.4.a-v2.0.svg @@ -0,0 +1,164 @@ + + + + + + + + + + + + 1.1.4.a. Send notification to Participant (Payer/Payee/FXP) (single message) v2.0 + + Financial Service Provider (Payer) + + ML API Adapter Service + + Central Service + + Financial Service Provider (Payee or FXP) + + + + + + + + + + + + + + + + Payer DFSP + Participant + + + Payer DFSP + Participant + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + + + Notification-Topic + + + Notification-Topic + Central Service API + + + Central Service API + + + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + Payee DFSP/FXP + Participant + + + Payee DFSP/FXP + Participant + + + + + + + + + + Send notification to Participants + + + Event is automatically replicated + to the events topic (topic-events) + + + 1 + Consume Notification event + + + The endpoint details are cached, when the cache + expires, the details are fetched again + + + 2 + Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints + Error code: + 2003 + + + 3 + Fetch Endpoint details for Participant + Error code: + 2003 + + + 4 + Fetch Endpoint details for Participant + + participantEndpoint + + + 5 + Retrieved Endpoint details for Participant + + + 6 + Return Endpoint details for Participant + + + 7 + Return Endpoint details for Participant + Error codes: + 3202, 3203 + + + 8 + Notification with Prepare/fulfil result/error to + Payer DFSP to specified Endpoint - PUT + Error code: + 1001 + + + 9 + HTTP 200 OK + + + alt + [event.action === 'reserve'] + + + alt + [event.status === 'success'] + + + 10 + Notification to with succesful fulfil result (committed) to Payee DFSP/FXP to specified Endpoint - PATCH + Error code: + 1001 + + + 11 + HTTP 200 OK + + diff --git a/docs/technical/central-fx-transfers/transfers/1.1.0-fx-prepare-transfer-request.md b/docs/technical/central-fx-transfers/transfers/1.1.0-fx-prepare-transfer-request.md new file mode 100644 index 000000000..c93519d36 --- /dev/null +++ b/docs/technical/central-fx-transfers/transfers/1.1.0-fx-prepare-transfer-request.md @@ -0,0 +1,13 @@ +# FX Prepare Transfer Request + +Sequence design diagram for FX Prepare Transfer Request process. + +## References within Sequence Diagram + +* [FX Prepare Handler Consume (1.1.1.a)](1.1.1.a-fx-prepare-handler-consume.md) +* [FX Position Handler Consume (1.1.2.a)](1.1.2.a-fx-position-handler-consume.md) +* [Send notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v2.0.md) + +## Sequence Diagram + +![seq-fx-prepare-1.1.0.svg](../assets/diagrams/sequence/seq-fx-prepare-1.1.0.svg) diff --git a/docs/technical/central-fx-transfers/transfers/1.1.1.a-fx-prepare-handler-consume.md b/docs/technical/central-fx-transfers/transfers/1.1.1.a-fx-prepare-handler-consume.md new file mode 100644 index 000000000..f494d5661 --- /dev/null +++ b/docs/technical/central-fx-transfers/transfers/1.1.1.a-fx-prepare-handler-consume.md @@ -0,0 +1,7 @@ +# FX Prepare Handler Consume + +Sequence design diagram for FX Prepare Handler Consume process. + +## Sequence Diagram + +![seq-fx-prepare-1.1.1.a.svg](../assets/diagrams/sequence/seq-fx-prepare-1.1.1.a.svg) diff --git a/docs/technical/central-fx-transfers/transfers/1.1.2.a-fx-position-handler-consume.md b/docs/technical/central-fx-transfers/transfers/1.1.2.a-fx-position-handler-consume.md new file mode 100644 index 000000000..a23fc2316 --- /dev/null +++ b/docs/technical/central-fx-transfers/transfers/1.1.2.a-fx-position-handler-consume.md @@ -0,0 +1,7 @@ +# FX Position Handler Consume + +Sequence design diagram for FX Position Handler Consume process. + +## Sequence Diagram + +![seq-fx-prepare-1.1.2.a.svg](../assets/diagrams/sequence/seq-fx-prepare-1.1.2.a.svg) diff --git a/docs/technical/central-fx-transfers/transfers/1.1.4.a-send-notification-to-participant-v2.0.md b/docs/technical/central-fx-transfers/transfers/1.1.4.a-send-notification-to-participant-v2.0.md new file mode 100644 index 000000000..c57569a2f --- /dev/null +++ b/docs/technical/central-fx-transfers/transfers/1.1.4.a-send-notification-to-participant-v2.0.md @@ -0,0 +1,7 @@ +# Send Notification to Participant v2.0 + +Sequence design diagram for the Send Notification to Participant request. + +## Sequence Diagram + +![seq-prepare-1.1.4.a-v2.0.svg](../assets/diagrams/sequence/seq-prepare-1.1.4.a-v2.0.svg) diff --git a/docs/technical/central-fx-transfers/transfers/2.1.0-fx-fulfil-transfer-request.md b/docs/technical/central-fx-transfers/transfers/2.1.0-fx-fulfil-transfer-request.md new file mode 100644 index 000000000..018e242fb --- /dev/null +++ b/docs/technical/central-fx-transfers/transfers/2.1.0-fx-fulfil-transfer-request.md @@ -0,0 +1,13 @@ +# Fulfil Transfer Request success + +Sequence design diagram for the Fulfil Success Transfer request. + +## References within Sequence Diagram + + +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v2.0.md) + +## Sequence Diagram + +![seq-fx-fulfil-2.1.0.svg](../assets/diagrams/sequence/seq-fx-fulfil-2.1.0.svg) diff --git a/docs/technical/central-fx-transfers/transfers/2.2.0-fx-fulfil-reject-transfer.md b/docs/technical/central-fx-transfers/transfers/2.2.0-fx-fulfil-reject-transfer.md new file mode 100644 index 000000000..bbbbafd59 --- /dev/null +++ b/docs/technical/central-fx-transfers/transfers/2.2.0-fx-fulfil-reject-transfer.md @@ -0,0 +1,7 @@ +# FXP sends a Fulfil Abort FX Transfer request + +Sequence design diagram for the Fulfil Reject FX Transfer process. + +## Sequence Diagram + +![seq-fx-reject-2.2.0.a.svg](../assets/diagrams/sequence/seq-fx-reject-2.2.0.a.svg) diff --git a/docs/technical/central-fx-transfers/transfers/README.md b/docs/technical/central-fx-transfers/transfers/README.md new file mode 100644 index 000000000..692cfb683 --- /dev/null +++ b/docs/technical/central-fx-transfers/transfers/README.md @@ -0,0 +1,8 @@ +# Mojaloop FX Transfer Operations + +Operational processes that are core to enabling FX transfers: + +- FX Prepare process +- FX Fulfil process +- Notifications process +- FX Reject/Abort process diff --git a/docs/technical/faqs.md b/docs/technical/faqs.md new file mode 100644 index 000000000..afb76ba68 --- /dev/null +++ b/docs/technical/faqs.md @@ -0,0 +1,158 @@ +# Frequently Asked Questions + +This document contains some of the frequently asked technical questions from the community. + +## 1. What is supported? + +Currently the Central ledger components are supported by the team. The DFSP components are outdated and thus the end-to-end environment and full setup is challenging to install. + +### 2. Can we connect directly to Pathfinder in a development environment? + +For the local and test environment, we recommend interfacing with the 'mock-pathfinder' service instead. Pathfinder is a 'paid by usage' service. + +Access the https://github.com/mojaloop/mock-pathfinder repository to download and install mock-pathfinder. Run command npm install in mock-pathfinder directory to install dependencies after this update Database_URI in mock-pathfinder/src/lib/config.js. + +### 3. Should i register DFSP via url http://central-directory/commands/register or i need to update configuration in default.json? + +You should register using the API provided, using postman or curl. Client is using LevelOne code. Needs to implement the current Mojaloop release with the current Postman scripts. + +### 4. Status of the pod pi3-kafka-0 is still on CrashLoopBackOff? + +- More background related to the question: + + When I tired to get logs of the container centralledger-handler-admin-transfer, I get the following error: + Error from server (BadRequest): container "centralledger-handler-admin-transfer" in pod "pi3-centralledger-handler-admin-transfer-6787b6dc8d-x68q9" is waiting to start: PodInitializing + And the status of the pod pi3-kafka-0 is still on CrashLoopBackOff. + I am using a vps on ubuntu 16.04 with RAM 12GB, 2vCores, 2.4GHz, Rom 50GB at OVH for the deployment. + +Increased RAM to 24 GB and CPU to 4 resolved the issues. Appears to be a timeout on Zookeeper due depletion of available resources, resulting in the services shutting down. + +### 5. Why am I getting an error when we try to create new DFSP using Admin? + +Please insure you are using the most current Postman scripts available on https://github.com/mojaloop/mock-pathfinder repository. + + +### 6. Can I spread Mojaloop components over different physical machines and VM's? + +You should be able to setup on different VM's or physical machines. The distribution pretty much depend on your requirements and would be implementation specific. We utilise Kubernetes to assist with the Container Orchestration. This enables us to schedule the deployments through the Kubernetes runtime to specific machines if required, and request specific resources if required. The helm charts in the helm repository could be used as guideline to how best allocate and group the components in your deployment. Naturally you would need to update the configurations to complement your custom implementation. + +### 7. Can we expect all the endpoints defined in the API document are implemented in Mojaloop? + +The Mojaloop Specification API for transfers and the Mojaloop Open Source Switch implementation are independent streams, though obviously the implementation is based on the Specification. Based on the use-cases prioritized for a time-frame and based on the end-points needed to support those use-cases, implementation will be done. If a few end-points are not prioritized then implementation for them may not be available. However, I think the goal is to eventually support all the end-points specified though it may take time. Thanks for the collection. We do have some of these on the ‘postman’ repo in the mojaloop GitHub org. + +### 8. Does Mojaloop store the payment initiator FSP’s quote/status info? + +At the moment, the Mojaloop Open source Switch implementation does *not* store Quotes related information. The onus is on the Payer, Payee involved in the process to store the relevant information. + +### 9. Does Mojaloop handle workflow validation? + +Not at the moment, but this may happen in the future. Regarding correlating requests that are related to a specific transfer, you may look at the ‘transaction’ end-point/resource in the Specification for more information on this. In addition to this, I can convey that some background work is ongoing regarding the specification to make this correlation more straight-forward and simpler i.e., to correlate quote and transfer requests that come under a single transaction. + + +### 10. How to register a new party in Mojaloop? + +There is no POST on /parties resource, as specified in section 6.1.1 of the API Defintion. Please refer to section: 6.2.2.3 `POST /participants//` in the API Defintion. + +” _The HTTP request `POST /participants//` (or `POST /participants///`) is used to create information on the server regarding the provided identity, defined by ``, ``, and optionally `` (for example, POST_ + _/participants/MSISDN/123456789 or POST /participants/BUSINESS/shoecompany/employee1). See Section 5.1.6.11 for more information regarding addressing of a Party._ ”. + +### 11. Does the participant represent an account of a customer in a bank? + +For more on this, please refer to this doc (Section 3..2): https://github.com/mojaloop/mojaloop-specification/blob/develop/Generic%20Transaction%20Patterns.pdf. + +” _In the API, a Participant is the same as an FSP that is participating in an Interoperability Scheme. The primary purpose of the logical API resource Participants is for FSPs to find out in which other FSP a counterparty in an interoperable financial transaction is located. There are also services defined for the FSPs to provision information to a common system._ ” + +In essence, a participant is any FSP participating in the Scheme (usually not a customer). For account lookup, a directory service such as *Pathfinder* can be used, which provides user lookup and the mapping. If such a directory service is not provided, an alternative is provided in the Specification, where the Switch hosts an Account Lookup Service (ALS) but to which the participants need to register parties. I addressed this earlier. But one thing to note here is that the Switch does not store the details, just the mapping between an ID and an FSP and then the calls to resolve the party are sent to that FSP. + +https://github.com/mojaloop/mojaloop-specification CORE RELATED (Mojaloop): + +This repo contains the specification document set of the Open API for FSP Interoperability - mojaloop/mojaloop-specification. + +### 12. How to register _trusted_ payee to a payer, to skip OTP? + +To skip the OTP, the initial request on the /transactionRequests from the Payee can be programmatically (or manually for that matter) made to be approved without the use of the /authorizations endpoint (that is need for OTP approval). Indeed the FSP needs to handle this, the Switch does not. This is discussed briefly in section 6.4 of the Specification. + +### 13. Receiving a 404 error when attempting to access or load kubernetes-dashboard.yaml file? + +From the official kubernetes github repository in the README.md, the latest link to use is "https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml". Be sure to always verify 3rd party links before implementing. Open source applications are always evolving. + +### 14. When installing nginx-ingress for load balancing & external access - Error: no available release name found? + +Please have a look at the following addressing a similar issue. To summarise - it is most likely an RBAC issue. Have a look at the documentation to set up Tiller with RBAC. https://docs.helm.sh/using_helm/#role-based-access-control goes into detail about this. The issue logged: helm/helm#3839. + +### 15. Received "ImportError: librdkafka.so.1: cannot open shared object file: No such file or directory" when running `npm start' command. + +Found a solution here https://github.com/confluentinc/confluent-kafka-python/issues/65#issuecomment-269964346 +GitHub +ImportError: librdkafka.so.1: cannot open shared object file: No such file or directory · Issue #65 · confluentinc/confluent-kafka-python +Ubuntu 14 here, pip==7.1.2, setuptools==18.3.2, virtualenv==13.1.2. First, I want to build latest stable (seems it's 0.9.2) librdkafka into /opt/librdkafka. curl https://codeload.github.com/ede... + +Here are the steps to rebuild librdkafka: + +git clone https://github.com/edenhill/librdkafka && cd librdkafka && git checkout ` + +cd librdkafka && ./configure && make && make install && ldconfig + +After that I'm able to import stuff without specifying LD_LIBRARY_PATH. +GitHub +edenhill/librdkafka +The Apache Kafka C/C++ library. Contribute to edenhill/librdkafka development by creating an account on GitHub. + +### 16. Can we use mojaloop as open-source mobile wallet software or mojaloop does interoperability only? + +We can use mojaloop for interoperability to support mobile wallet and other such money transfers. This is not a software for a DFSP (there are open source projects that cater for these such as Finserv etc). Mojaloop is for a Hub/Switch primarily and an API that needs to be implemented by a DFSP. But this is not for managing mobile wallets as such. + +### 17. Describe companies that helps to deploy & support for mojaloop? + +Mojaloop is an open source software and specification. + +### 18. Can you say something about mojaloop & security? + +The Specification is pretty standard and has good security standards. But these need to be implemented by the adopters and deployers. Along with this, the security measures need to be coupled with other Operational and Deployment based security measures. Moreover, the coming few months will focus on security perspective for the Open Source community. + +### 19. What are the benefit(s) from using mojaloop as interoperabilty platform? + +Benefits: Right now for example, an Airtel mobile money user can transfer to another Airtel mobile money user only. With this, he/she can transfer to any Financial service provider such as another mobile money provider or any other bank account or Merchant that is connected to the Hub, irrespective of their implementation. They just need to be connected to the same Switch. Also, this is designed for feature phones so everyone can use it. + +### 20. What are the main challenges that companies face using mojaloop? + +At this point, the main challenges are around expectations. Expectations of the adopters of mojaloop and what really mojaloop is. A lot of adopters have different understanding of what mojaloop is and about its capabilities. If they have a good understanding, a lot of current challenges are mitigated.. +Yes, forensic logging is a security measure as well for auditing purposes which will ensure there is audit-able log of actions and that everything that is a possible action of note is logged and rolled up, securely after encryption at a couple of levels. + +### 21. Is forensic logging/audit in mojaloop , is it related with securing the inter-operability platform? + +This also ensures all the services always run the code they’re meant to run and anything wrong/bad is stopped from even starting up. Also, for reporting and auditors, reports can have a forensic-log to follow. + +### 22. How do the financial service providers connect with mojaloop? + +There is an architecture diagram that presents a good view of the integration between the different entities. https://github.com/mojaloop/docs/blob/master/Diagrams/ArchitectureDiagrams/Arch-Flows.svg. + +### 23. Is there any open source ISO8583-OpenAPI converter/connector available? + +I don't believe a generic ISO8583 `<-> Mojaloop integration is available currently. We're working on some "traditional payment channel" to Mojaloop integrations (POS and ATM) which we hope to demo at the next convening. These would form the basis for an ISO8583 integration we might build and add to the OSS stack but bare in mind that these integrations will be very use case specific. + +### 24. How do I know the end points to setup postman for testing the deployment? + +On the Kubernetes dashboard, select the correct NAMESPACE. Go to Ingeresses. Depending on how you deployed the helm charts, look for 'moja-centralledger-service'. Click on edit, and find the tag ``. This would contain the endpoint for this service. + +### 25. Why are there no reversals allowed on a Mojaloop? + +*Irrevocability* is a core Level One Principle (edited) and not allowing reversals is essential for that. Here is the section from the API Definition addressing this: + +_*6.7.1.2 Transaction Irrevocability*_ +_The API is designed to support irrevocable financial transactions only; this means that a financial transaction cannot be changed, cancelled, or reversed after it has been created. This is to simplify and reduce costs for FSPs using the API. A large percentage of the operating costs of a typical financial system is due to reversals of transactions._ +_As soon as a Payer FSP sends a financial transaction to a Payee FSP (that is, using POST /transfers including the end-to-end financial transaction), the transaction is irrevocable from the perspective of the Payer FSP. The transaction could still be rejected in the Payee FSP, but the Payer FSP can no longer reject or change the transaction. An exception to this would be if the transfer’s expiry time is exceeded before the Payee FSP responds (see Sections 6.7.1.3 and 6.7.1.5 for more information). As soon as the financial transaction has been accepted by the Payee FSP, the transaction is irrevocable for all parties._ + +However, *Refunds* is a use case supported by the API. + +### 26. ffg. error with microk8s installation "MountVolume.SetUp failed"? + +Would appear if it is a space issue, but more the 100GiB of EBS storage was allocated. +The issue resolved itself after 45 minutes. Initial implementation of the mojaloop project can take a while to stabilize. + +### 27. Why am I getting this error when trying to create a participant: "Hub reconciliation account for the specified currency does not exist"? + +You need to create the corresponding Hub accounts (HUB_MULTILATERAL_SETTLEMENT and HUB_RECONCILIATION) for the specified currency before setting up the participants. +In this Postman collection you can find the requests to perform the operation in the "Hub Account" folder: https://github.com/mojaloop/postman/blob/master/OSS-New-Deployment-FSP-Setup.postman_collection.json + +Find also the related environments in the Postman repo: https://github.com/mojaloop/postman diff --git a/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/ML2RA_bc_accLookDiscvry_Apr22-b400.png b/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/ML2RA_bc_accLookDiscvry_Apr22-b400.png new file mode 100644 index 000000000..818a34706 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/ML2RA_bc_accLookDiscvry_Apr22-b400.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/aldGetParticipant_20210825.png b/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/aldGetParticipant_20210825.png new file mode 100644 index 000000000..21d61c305 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/aldGetParticipant_20210825.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/aldGetParty_20210825.png b/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/aldGetParty_20210825.png new file mode 100644 index 000000000..175ca5e37 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/aldGetParty_20210825.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/aldPartyParticipantAssoc_20220919.png b/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/aldPartyParticipantAssoc_20220919.png new file mode 100644 index 000000000..edfac583f Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/aldPartyParticipantAssoc_20220919.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/aldPartyParticipantDisassoc_20220919.png b/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/aldPartyParticipantDisassoc_20220919.png new file mode 100644 index 000000000..ccb1b42a2 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/assets/aldPartyParticipantDisassoc_20220919.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/index.md b/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/index.md new file mode 100644 index 000000000..761369b79 --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/accountLookupAndDiscovery/index.md @@ -0,0 +1,73 @@ +# Account Lookup And Discovery BC + +The Accounts Lookup and Discovery BC is responsible for locating and associating participants and parties with party or participant triggered transactions. + +## Terms + +The following terms are used in this BC, also known as a domain. + +| Term | Description | +|---|---| +| **Participant** | Financial Services Provider | +| **Party** | FSP Customer | + +## Functional Overview + +![Use Case - Functional Overview](./assets/ML2RA_bc_accLookDiscvry_Apr22-b400.png) +>BC Functional Diagram: Account Lookup and Discovery Overview + +## Use Cases + +#### Party/Participant Associate + +#### Description + +Where a Participant DFSP requests a given Party ID to be associated with a Participant (itself). + +***Note:*** *Checks and validations of the KYC (Know You Customer) details are not covered here and are left to processes outside of the Mojaloop API calls and should be covered by the Scheme, to ensure that association (or disassociation) requests are valid.* + +#### Flow Diagram + +![Use Case - Party/Participant Associate](./assets/aldPartyParticipantAssoc_20220919.png) +>UC Flow Diagram: Party/Participant Associate + +### Party/Participant Disassociate + +#### Description + +Where a Participant DFSP requests an existing association between a given Party ID and a Participant (itself) to be removed. + +#### Flow Diagram + +![Use Case - Party/Participant Disassociate](./assets/aldPartyParticipantDisassoc_20220919.png) +>UC Workflow Diagram: Party/Participant Disassociate + + + + +### Get Participant + +#### Description + +Where a Participant DFSP requests Participant association information based on a Party identifier, this UC is used by the switch to validate the request and provide the requested association data to the requesting DFSP. + +#### Flow Diagram + +![Use Case - Get Participant](./assets/aldGetParticipant_20210825.png) +>UC Flow Diagram: Get Participant + +### Get Party + +#### Description + +Where a participant DFSP queries another participant DFSP for the details of a Party which the second DFSP holds, this UC is used to validate the request and provide the requested Party data to the requesting DFSP. + +#### Flow Diagram + +![Use Case - Get Party](./assets/aldGetParty_20210825.png) +>UC Flow Diagram: Get Party + + + + +[^1]: Common Interfaces: [Mojaloop Common Interface List](../../commonInterfaces.md) diff --git a/docs/technical/reference-architecture/boundedContexts/accountsAndBalances/assets/ML2RA_A&B-bcAccBal-FunctionalOverview_Mar22-c.png b/docs/technical/reference-architecture/boundedContexts/accountsAndBalances/assets/ML2RA_A&B-bcAccBal-FunctionalOverview_Mar22-c.png new file mode 100644 index 000000000..4da5a26b9 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/accountsAndBalances/assets/ML2RA_A&B-bcAccBal-FunctionalOverview_Mar22-c.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/accountsAndBalances/index.md b/docs/technical/reference-architecture/boundedContexts/accountsAndBalances/index.md new file mode 100644 index 000000000..4503991da --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/accountsAndBalances/index.md @@ -0,0 +1,121 @@ +# Accounts and Balances BC + +The Accounts and Balances BC acts as the "central ledger" for the system. It interacts primarily with the Settlements BC, Participants Lifecycle BC and Transfers BCs, and is a directed sub-system, which means that it is a dependency of the BCs that use it as a "financial system of record" for the financial accounting. + +**Note:** + +The Accounts and Balances BC contains a limited amount of logic to ensure that **(a)** the correct relationships are created and maintained between entities when an external BC creates, updates, queries or closes accounts and **(b)** the correct account limits are enforced (i.e. set and not exceeded) when an external BC attempts to create journal entries and **\(c\)** avoids duplicate ledger entries by using *Universal Unique Identifiers (UUID)* for unique journal entry identifiers. + +## Terms + +Terms with specific and commonly accepted meaning within the Bounded Context in which they are used. + +| Term | Description | +|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Account** | Refers to a General Ledger account, a record in an accounting system that records the debit or credit entries that represent a financial transaction. | +| **Journal Entry** | Credit/Debit financial records against Account. | +| **Balance** | The amount available in an account, when the debits and credits have been factored in. | + +## Functional Overview - Accounts and Balances + +![Functional Overview - Accounts and Balances](./assets/ML2RA_A&B-bcAccBal-FunctionalOverview_Mar22-c.png) +>BC Functional Diagram: Accounts & Balances Overview + +## Use Cases + +### Create Account + +#### Description + +The workflow provided by this UC enables the Switch to create new participant/transfer/settlement accounts in the System Ledger. (Participant Account creation occurs from both the Participant Lifecycle Management and the Settlement BCs. Examples of both have been provided in the Flow Diagrams below). + +Further, the workflow provides for specification of credit/debit Journal Entry limits, and to ensure that the Account is unique in the System Ledger. + +#### Flow Diagram + +Account creation from [Participant Lifecycle Management BC](../participantLifecycleManagement/index.md) + + + +![Use Case - PLCM BC](../participantLifecycleManagement/assets/ML2RA_PLM-ucAddParticipantAccountInit_Apr22-a_P1-1429.png) +![Use Case - Add Participant Account - Approval (P2)](../participantLifecycleManagement/assets/ML2RA_PLM-ucAddParticipantAccountAppro_Apr22-a_P2-1429.png) +>UC Workflow Diagram: Add Participant Accounts + +Account creation from [Settlements BC](../settlements/index.md) + +![Use Case - Settlements BC](../settlements/assets/ML2RA_SET-ucBootStrapSettleModViaConfig_Mar22-b.png) +>UC Workflow Diagram: Bootstrap (Startup) Settlement Model via Configuration + +### Close Account + +#### Description + +Close a participant account in the System Ledger and prevent new journal entries from impacting it.
    (Still to be determined: Drain collateral CR balances to another account automatically?) + +### Query Account + +#### Description + +Query the status and balance for participant account. + +#### Flow Diagram + +Query liquidity CR/DR limits from [Participant Lifecycle Management BC](../participantLifecycleManagement/index.md) + + + +![Use Case - PLCM BC](../participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityCoverQuery_Apr22-a_1429.png) +>UC Workflow Diagram: Liquidity Cover Queries + +### Query Journal Entries + +#### Description + +Query Journal debit/credit Entries for an Account. + +### Insert Journal Entry + +#### Description + +Insert a participant journal entry into the System Ledger specifying the debit and credit accounts (There are three ways through which participant journal entries can be made. See the Flow Diagrams below for a description of each.) +Respond with the updated account balance. + +#### Flow Diagram + +Journal Entry insertion from [Transfers BC](../transfers/index.md) + +![Use Case - Transfers BC](../transfers/assets/ML2RA_Trf_ucPerformTrfUniMode_Mar22a.png) +>UC Workflow Diagram: Perform Transfer (Universal Mode) + +Journal Entry insertion from [Settlements BC](../settlements/index.md) using `Deferred Net Settlement` (DNS) model + +![Use Case - Settlements BC](../settlements/assets/ML2RA_SET-ucDeferNetSettle_Mar22-a-P1-2.png) +>UC Workflow Diagram: Deferred Net Settlement - 19/10/2021 + +Journal Entry insertion from [Settlements BC](../settlements/index.md) using `Immediate Gross Settlement` (IGS) model + +![Use Case - Settlements BC](../settlements/assets/ML2RA_SET-ucInstantGrossSettle_Mar22-a.png) +>UC Workflow Diagram: Immediate Gross Settlement + +## Canonical Model + +- Account + - accountId + - ledgerAccountType + - ledgerAccountState + - debitLimit + - creditLimit + - debitBalance + - creditBalance +- Journal Entry + - journalEntryId + - debitAccountId + - creditAccountId + - journalEntryType + - transferAmount + - transferTimestamp + + + + +[^1]: Common Interfaces: [Mojaloop Common Interface List](../../commonInterfaces.md) diff --git a/docs/technical/reference-architecture/boundedContexts/auditing/assets/ML2RA_Audit_bcFunctionalOverview_Mar22_1450.png b/docs/technical/reference-architecture/boundedContexts/auditing/assets/ML2RA_Audit_bcFunctionalOverview_Mar22_1450.png new file mode 100644 index 000000000..8e5c8c2d9 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/auditing/assets/ML2RA_Audit_bcFunctionalOverview_Mar22_1450.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/auditing/assets/ML2RA_Audit_ucAuditingBCStartup_Mar22_1450.png b/docs/technical/reference-architecture/boundedContexts/auditing/assets/ML2RA_Audit_ucAuditingBCStartup_Mar22_1450.png new file mode 100644 index 000000000..c2392091e Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/auditing/assets/ML2RA_Audit_ucAuditingBCStartup_Mar22_1450.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/auditing/assets/ML2RA_Audit_ucEventBasedAudit_Mar22_1450.png b/docs/technical/reference-architecture/boundedContexts/auditing/assets/ML2RA_Audit_ucEventBasedAudit_Mar22_1450.png new file mode 100644 index 000000000..67bb2b3b0 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/auditing/assets/ML2RA_Audit_ucEventBasedAudit_Mar22_1450.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/auditing/assets/ML2RA_Audit_ucSyncRPCAudit_Mar22_1450.png b/docs/technical/reference-architecture/boundedContexts/auditing/assets/ML2RA_Audit_ucSyncRPCAudit_Mar22_1450.png new file mode 100644 index 000000000..6ec6a7dd0 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/auditing/assets/ML2RA_Audit_ucSyncRPCAudit_Mar22_1450.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/auditing/index.md b/docs/technical/reference-architecture/boundedContexts/auditing/index.md new file mode 100644 index 000000000..76b8654c8 --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/auditing/index.md @@ -0,0 +1,67 @@ +# Auditing BC + +The Auditing BC is responsible for maintaining an immutable record of all of the transactions that take place on the Switch. The Architecture comprises of five main components: + +* Central Forensic Logging Service +* Services +* Immutable Datastore +* Key Management System +* Cryptographic[^1] Provider Modular + +Authorized users are able to interrogate the Auditing BC via an Operation API exposed for this purpose for details of audit-worthy events. + +## Terms + +Terms with specific and commonly accepted meaning within the Bounded Context in which they are used. + +| Term | Description | +|---|---| +| **KMS** | Key Management System - Provides encryption/decription and Certificate Authority services to the Switch environment (issue, sign, and verification via the Security BC) | +| **CPM** | Crypto Provider Module - Manages the cryptographic techniques and methodologies employed by the Switch to provide end-to-end encryption and decryption services for any stored or transmitted data. | + +## Functional Overview + +![Use Case - Auditing System Functional Overview](./assets/ML2RA_Audit_bcFunctionalOverview_Mar22_1450.png) +> BC Functional Diagram: Auditing Systen Functional Overview + +## Use Cases + +### Auditing BC Startup + +#### Description + +The Auditing BC Startup UC is triggered during startup (intervals or events) and fetches all of the Public Keys in use by the various Switch Participant BCs from the Security BC that provide KMS services for all of the participant BCs of the Switch. + +#### Flow Diagram + +![Use Case - Auditing BC Startup](./assets/ML2RA_Audit_ucAuditingBCStartup_Mar22_1450.png) +> UC Workflow Diagram: Auditing BC Startup + +### Sync/RPC Audit + +#### Description + +The Sync/RPC Audit UC is activated for audit-worthy events triggered during a transaction noted by a participating BC. The participating BC proceeds to notify the Audit BC via a synchronous RPC audit call. The Audit entry is locally signed by the notifying BC. Upon receipt, the Audit BC runs through a number of procedures that include running though a KMS procedure with the Security BC, and persisting the record to an Append-only Store. + +#### Flow Diagram + +![Use Case - Sync/RPC Audit](./assets/ML2RA_Audit_ucSyncRPCAudit_Mar22_1450.png) +>UC Workflow Diagram: Sync/RPC Audit + +### Event Based Audit + +#### Description + +The Event Based Audit UC is triggered when a participating BC includes local auditing capability, notes an audit-worthy event, and creates a locally signed audit event, which it publishes, and then pushes either a single Event or an Event-batch to the Auditing BC. The Event is validated during a procedure with the Security BC, and persisted to the Append-Only Store. + +#### Flow Diagram + +![Use Case - Event Based Audit](./assets/ML2RA_Audit_ucEventBasedAudit_Mar22_1450.png) +> UC Workflow Diagram: Event Based Audit + + +## Notes + +[^1]: Cryptographic refers to algorithmic techniques and methodologies that are employed by systems to prevent unauthorised systems or persons from accessing, identifying, or using stored data. For further reading please refer to the accompanying Wikipedia article: [Cryptography, From Wikipedia, the free encyclopedia](https://en.wikipedia.org/wiki/Cryptography) + +[^2]: Common Interfaces: [Mojaloop Common Interface List](../../refarch/commonInterfaces.md) diff --git a/docs/technical/reference-architecture/boundedContexts/commonInterfaces/index.md b/docs/technical/reference-architecture/boundedContexts/commonInterfaces/index.md new file mode 100644 index 000000000..f27949892 --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/commonInterfaces/index.md @@ -0,0 +1,151 @@ +# Common Interface List + +The Common Interface List includes a list of all of the common interfaces that are in use in the Mojaloop 2.0 Reference Architecture presently. Common Interfaces are used by several Bounded Contexts, hence the name. + +Each Common Interface listed includes the following information: source or publisher event name or endpoint, communications style, publisher/provider Bounded Context, a description of the interface function, and a checklist of Bounded Contexts where it is being used. + +## Common Interfaces + +| Event name OR endpoint | Comms Style | Publisher/Provider BC | Description | FSP Interop API BC | Admin/Operation API BC | Participant Lifecycle Management BC | Transfers BC | Accounts & Balances BC | Settlements BC | Account Lookup BC | Agreements / Quotes BC | 3rd Party Initiated Payments | Notifications & Alerts BC | Scheduling BC | Auding BC | Security - authZ BC | Security - authN BC | Security - auditing BC | Security - loging BC | Security - crypto BC | +|------------------------------------------------------|-------------|-------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|------------------------|-------------------------------------|--------------|------------------------|----------------|-------------------|------------------------|------------------------------|---------------------------|---------------|-----------|---------------------|---------------------|------------------------|----------------------|----------------------| +| TransferCommittedFulfiled | Event | Transfers BC | Transfer Committed event indicating the final outcome of the Transfer Commited stage of a transfer has been processed by the Transfers BC | x | | x | | | | | | | | | | | | | | | +| LiquidityThresholdExceeded | gRPC | Transfers BC | An event thrown when a given participant's liquidity threshold is exceeded and a action should be taken | | | X | | | | | | | | | | | | | | | +| TransferPrepared | Event | Transfers BC | Transfer Prepared event indicating the final outcome of the Transfer Prepare stage of a transfer has been processed by the Transfers BC | x | | | | | | | | | | | | | | | | | +| TransferQueryResponse | Event | Transfers BC | Event containing response as a result of a TransferQueryReceived event | x | | | | | | | | | | | | | | | | | +| TransferRejectRequestProcessed | Event | Transfers BC | Event confirming that a Transfer Reject request was processed by the Transfers BC | x | | | | | | | | | | | | | | | | | +| TransferPrepareRequestTimedout | Event | Transfers BC | Event for a Transfer Timeout when a transfer was still being prepared. | x | | | | | | | | | | | | | | | | | +| TransferFulfilComitRequestTimedout | Event | Transfers BC | Event for a Transfer Timeout when a transfer was in a final prepared state (i.e. waiting for a fulfilment, or rejection to be reveived). | x | | | | | | | | | | | | | | | | | +| TransferPrepareDuplicateCheckFailed | Event | Transfers BC | Event representing a failed duplicate check validation failure as a result of processing a TransferPrepareAccountAllocated event. | x | | | | | | | | | | | | | | | | | +| TransferPrepareLiquidityCheckFailed | Event | Transfers BC | Event representing a failed liquidity check validation failure as a result of processing a TransferPrepareAccountAllocated event. | x | | | | | | | | | | | | | | | | | +| TransferPrepareInvalidPayerCheckFailed | Event | Transfers BC | Event representing a failed Payer Participant check validation failure as a result of processing a TransferPrepareAccountAllocated event. | x | | | | | | | | | | | | | | | | | +| TransferPrepareInvalidPayeeCheckFailed | Event | Transfers BC | Event representing a failed Payee Participant check validation failure as a result of processing a TransferPrepareAccountAllocated event. | x | | | | | | | | | | | | | | | | | +| TransferPrepareAccountsAllocated | Event | Settlements BC | Transfer Prepare request event with enriched information containing the applicable accounts for liquidity validation/allocation for each participant | | | | x | | | | | | | | | | | | | | +| /random-number-gen | Event | Security BC - crypto | random number generator. Can be used to generate (1) id (2) secret and (3) FIDO challenge | x | x | | | | | | | | | | | x | x | | | x | +| /hash-gen | HTTP/Rest | Security BC - crypto | Hash generation. Can be used to hash random numbers and user info. Hash is used for basic authentication and signature verification. | x | x | | | | | | | | | | | x | x | | | x | +| /signature-gen | HTTP/Rest | Security BC - crypto | generate signature. used to sign audit records for immutability. | | | | | | | | | | | | x | x | x | x | x | | +| /signature-ver | HTTP/Rest | Security BC - crypto | verify siganture. used for FIDO authentication and authorization. This is also used to validate audit record on retrieval. | x | x | | | | | | | | | | x | x | x | x | x | | +| /encrypt | HTTP/Rest | Security BC - crypto | generic encryption | | | | | | | | | | | | x | | | x | x | x | +| /decrypt | HTTP/Rest | Security BC - crypto | generic decryption | | | | | | | | | | | | x | | | x | x | x | +| /pin-translation | HTTP/Rest | Security BC - crypto | translate banking PIN block from one encryption zone to another. Can be used for Interbank ATM or POS transaction. | | | | | | | | | | | | | | | | | x | +| /fido-register | HTTP/Rest | Security BC - crypto | Composite Crypto function. stores authenticator ECC public key alongside user infor. | x | x | | | | | | | | | | | | | | | | +| /fido-authenticate | HTTP/Rest | Security BC - crypto | authenticate FIDO signature | x | x | | | | | | | | | | | | | | | | +| /fido-authorize | HTTP/Rest | Security BC - crypto | authorize FIDO transaction after gesture (pressed button, finger print, etc) | x | x | | | | | | | | | | | | | | | | +| /kms-key-definition | HTTP/Rest | Security BC - crypto | cryptographic key definition (key usage, duration, label) | | | | | | | | | | | | | | | | | x | +| /kms-aes-key-gen | HTTP/Rest | Security BC - crypto | Cryptographic key generation for symetric encryption | | | | | | | | | | | | | | | | | x | +| /kms-ecc-key-gen | HTTP/Rest | Security BC - crypto | Cryptogrphic key generation for Eliptic Curve key pair generation. | | | | | | | | | | | | | | | | | x | +| /crypto-adapter-set | HTTP/Rest | Security BC - crypto | Cryptographic Provider/adapter set (AWS, AZURE, on-prem HSM, software local libraries ... etc) | | | | | | | | | | | | | | | | | x | +| /iam-token-verifty | HTTP/Rest | Security BC - crypto | basic authentication token verification. Composite call to AIM adapter. | x | x | | x | | | | | | | | | | | | | x | +| /kms-pem-gen | HTTP/Rest | Security BC - crypto | PKI keys for client authention and CLI functions. | x | x | | | | | | | | | | | | | | | x | +| /ssl-terminate | HTTP/Rest | Security BC - crypto | SLL termination | | | | | | | | | | | | | | | | | x | +| /kms-load-key | HTTP/Rest | Security BC - crypto | load cryptographic keys in key store | | | | | | | | | | | | | | | | | x | +| /app-authorize | HTTP/Rest | Security BC - authZ | Calls AuthZ BC to verify the authorization token. This also calls IAM function to verify roles. | x | x | | | | | | | | | | | x | | | | x | +| /app-fido-authorize | HTTP/Rest | Security BC - authZ | Calls Cyrpto BC to authorize transaction | x | x | | | | | | | | | | | | | | | x | +| /app-pem-auth | HTTP/Rest | Security BC - authZ | Uses PKI private and public key to authenticate APIs calls. uses the user IAM profile (user info + role) to auhorize. | | | | | | | | | | | | | | x | | | x | +| /app-basic-auth | HTTP/Rest | Security BC - authN | Calls AuthZ BC to verify id and secret. Returns authorization token | x | x | | | | | | | | | | | | x | | | x | +| CreateScheduleReminder | gRPC | Scheduling BC | Create a schedule reminder with the necessary information to create a event or api callback once the reminder has elapsed | | | | x | | | | | | | | | | | | | | +| DeleteScheduleReminder | gRPC | Scheduling BC | Event indicating that a timeout has occured for a scheduled reminder | | | | x | | | | | | | | | | | | | | +| POST /config/schemas/ | HTTP/Rest | Platform Configuration | (upsert) To publish the initial or new versions of a BC configuration managment object schema at bootstrap - includes version number | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | +| GET /config/schemas/ | HTTP/Rest | Platform Configuration | To get schema and current configurations of a all bounded contexts | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | +| GET /config/schemas/:boundedContextId | HTTP/Rest | Platform Configuration | To get schema and current configurations of a specifric bounded context | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | +| ConfigurationValuesChanged | Event | Platform Configuration | Event sent when changes happend on a configuration - should include at least the bounded context ID, maybe the key names with changed values | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | +| POST /config/schemas/:boundedContextId | HTTP/Rest | Platform Configuration | To publish the initial or new versions of a BC configuration managment object schema at bootstrap - includes version number | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | +| POST /config/secrets/ | HTTP/Rest | Platform Configuration | (upsert) To publish the list of expected secrets (keys) a bounded context requires to operate - send at bootstrap - includes version number | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | +| GET /config/secrets/ | HTTP/Rest | Platform Configuration | To a list of secret keys each BC needs to operate - from all bounded contexts | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | +| GET /config/secrets/:boundedContextId | HTTP/Rest | Platform Configuration | To a list of secret keys each BC needs to operate - from a specifric bounded context | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | +| GET /config/secrets/:boundedContextId/values | HTTP/Rest | Platform Configuration | This call can only be performed by the owner bouded context (verify sig) and should return the secrets along with the keys for that bounded context | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | +| SecretsValuesChanged | Event | Platform Configuration | Event sent when changes happend on a secret - should include at least the bounded context ID, maybe the key names with changed secrets | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | +| UpdateParticipantAccountThreshold | gRPC | Participant Lifecycle Management BC | Updates the thresholds of the accounts specified | | | | | X | | | | | | | | | | | | | +| GetParticipantsTransfersData | gRPC | Participant Lifecycle Management BC | Query Service to attain Participant information for Transfer purposes (i.e. validations, etc) | | | | x | | | | | | | | | | | | | | +| GetParticipantCallbackInfo | gRPC | Participant Lifecycle Management BC | API to query Participant information for Callbacks. Example of the FSPIOP Interop APIs BC using this to query the necessary information required for it to produce a NotifyRequested event. | x | | | | | | | | | | | | | | | | | +| GetParticipantQuoteData | gRPC | Participant Lifecycle Management BC | Query Service to attain Participant information for Quote purposes (i.e. validations, etc) | | | | | x | | | | | | | | | | | | | +| CreateParticipant | HTTP/Rest | Participant Lifecycle Management BC | Request to create a new participant with a single payload defining ALL the relevant details of the Participant | | X | | | | | | | | | | | | | | | | +| GetPendingParticipants | HTTP/Rest | Participant Lifecycle Management BC | Retrieves all the participants that are in the PEND-APPROVAL state, i.e. Participants that have not yet been approved or rejected | | X | | | | | | | | | | | | | | | | +| ApproveParticipant | HTTP/Rest | Participant Lifecycle Management BC | Approve OR Reject - Participant that is in a state of pending approval | | X | | | | | | | | | | | | | | | | +| CreateParticipantAccountsWithLimits | gRPC | Participant Lifecycle Management BC | Notify that the participant has been created and subsequint accounts with limits be created aswell | | | | | X | | | | | | | | | | | | | +| ParticipantCreated | Event | Participant Lifecycle Management BC | Notifies that the participant has been created, accounts and limis included. | | | | | | X | | | | | | | | | | | | +| ManageFunds | HTTP/Rest | Participant Lifecycle Management BC | Call to either Withdraw or Deposit funds. | | X | | | | | | | | | | | | | | | | +| GetPendingManageFunds | HTTP/Rest | Participant Lifecycle Management BC | Request all manage funds requests that have to be approved | | X | | | | | | | | | | | | | | | | +| ApproveManageFunds | HTTP/Rest | Participant Lifecycle Management BC | Approve OR Reject - Deposit or withdraw request | | X | | | | | | | | | | | | | | | | +| ManageFundsCreditDebitPairInstruction | gRPC | Participant Lifecycle Management BC | Update the accounting with the relevant credit and debit entries. | | | | | X | | | | | | | | | | | | | +| ReserveLiquidityCover | HTTP/Rest | Participant Lifecycle Management BC | Request to reserve an amount of liquidity cover either a value or a % | | X | | | | | | | | | | | | | | | | +| GetPendingLiquidityCoverReservations | HTTP/Rest | Participant Lifecycle Management BC | Get LiquidityCover requests that are currently awaiting approval | | X | | | | | | | | | | | | | | | | +| ApproveLiquidityCoverReservation | HTTP/Rest | Participant Lifecycle Management BC | Approve OR Reject - Liquidity Cover Reservation | | X | | | | | | | | | | | | | | | | +| UpdateParticipantState | HTTP/Rest | Participant Lifecycle Management BC | Request to change the current state of a given participant | | X | | | | | | | | | | | | | | | | +| GetPendingStateUpdates | HTTP/Rest | Participant Lifecycle Management BC | Gets all partacipants with status change requests that are pending approval | | X | | | | | | | | | | | | | | | | +| ApproveParticipantStateUpdate | HTTP/Rest | Participant Lifecycle Management BC | Approve OR Reject - Participant state change | | X | | | | | | | | | | | | | | | | +| ParticipantStateUpdated | gRPC | Participant Lifecycle Management BC | Notify BC's that the state of a participant has changed | | | | X | | X | | | | X | | | X | X | X | X | | +| ParticipantLiquidityThresholdExceeded | Event | Participant Lifecycle Management BC | A notification should be sent that a given participant's liquidity threshold is exceeded. | | | | | | | | | | X | | | | | | | | +| AddParticipantAccount | HTTP/Rest | Participant Lifecycle Management BC | Request to create a new account for a given participant | | X | | | | | | | | | | | | | | | | +| GetPendingParticipantsAccounts | HTTP/Rest | Participant Lifecycle Management BC | Gets all participants and accounts that require approval to be created | | X | | | | | | | | | | | | | | | | +| ApproveParticipantAccount | HTTP/Rest | Participant Lifecycle Management BC | Approve OR Reject - Participant account create request | | X | | | | | | | | | | | | | | | | +| CreateParticipantAccountWithLimits | gRPC | Participant Lifecycle Management BC | Creates the relevant accounts within the Accounts and Balances BC | | | | | X | | | | | | | | | | | | | +| ParticipantAccountAdded | Event | Participant Lifecycle Management BC | Event to notify that the participant account has been created | | | | | | X | | | | | | | | | | | | +| UpdateAccountStatus | HTTP/Rest | Participant Lifecycle Management BC | Request to either enable or disable the participant's account based on the information passed | | X | | | | | | | | | | | | | | | | +| GetPendingAccountsWithStatusUpdates | HTTP/Rest | Participant Lifecycle Management BC | Get all accounts that are pending approval for a status change | | X | | | | | | | | | | | | | | | | +| ApproveAccountStatusUpdate | HTTP/Rest | Participant Lifecycle Management BC | Approve OR Reject - Participant account status change | | X | | | | | | | | | | | | | | | | +| Enabled/DisabledParticipantAccount | gRPC | Participant Lifecycle Management BC | Either enables or disables the account based on the information passed | | | | | X | | | | | | | | | | | | | +| ParticipantAccountEnabled | Event | Participant Lifecycle Management BC | Notify that a participant's account has been enabled | | | | | | X | | | | | | | | | | | | +| ParticipantAccountDisabled | Event | Participant Lifecycle Management BC | Notify that a participant's account has been disabled | | | | | | X | | | | | | | | | | | | +| UpdateAccountLimit | HTTP/Rest | Participant Lifecycle Management BC | Request to update the limits on a given participant's account | | X | | | | | | | | | | | | | | | | +| GetPendingAccountsWithLimitUpdates | HTTP/Rest | Participant Lifecycle Management BC | Get all accounts with pending updates to the limits | | X | | | | | | | | | | | | | | | | +| ApproveAccountLimitUpdate | HTTP/Rest | Participant Lifecycle Management BC | Approve OR Reject - Update account limit request | | X | | | | | | | | | | | | | | | | +| UpdateParticipantAccountLimit | gRPC | Participant Lifecycle Management BC | Update the limits on a given participant's account | | | | | X | | | | | | | | | | | | | +| ParticipantAccountLimitUpdated | Event | Participant Lifecycle Management BC | Event to notify that the participant account's limit has been created | | | | | | X | | | | | | | | | | | | +| UpdateAccountThreshold | HTTP/Rest | Participant Lifecycle Management BC | Request to update the threshold for a given participant account | | X | | | | | | | | | | | | | | | | +| GetPendingAccountsWithThresholdUpdates | HTTP/Rest | Participant Lifecycle Management BC | Get all the accounts with pending threshold updates | | X | | | | | | | | | | | | | | | | +| ApproveAccountThresholdUpdate | HTTP/Rest | Participant Lifecycle Management BC | Approve OR Reject - Participant account threshold update | | X | | | | | | | | | | | | | | | | +| ParticipantAccountThresholdUpdated | Event | Participant Lifecycle Management BC | Event to notify that the accounts' threshold was updated | | | | | | X | | | | | | | | | | | | +| UpdateEndpoints | HTTP/Rest | Participant Lifecycle Management BC | Request to update the endpoints of a given participant | | X | | | | | | | | | | | | | | | | +| GetPendingEndpointUpdates | HTTP/Rest | Participant Lifecycle Management BC | Gets all the participant endpoint update requests that are pending approval | | X | | | | | | | | | | | | | | | | +| ApproveEndpointsUpdate | HTTP/Rest | Participant Lifecycle Management BC | Approve OR Reject - Participant Endupoint Update | | X | | | | | | | | | | | | | | | | +| ParticipantEndpointsUpdated | Event | Participant Lifecycle Management BC | An event to notify that the Participant's endpoint have been updated | | | | X | X | X | X | X | X | | | | | | | | | +| GetParticipantInfo | gRPC | Participant Lifecycle Management BC | Gets all information regarding to a given Participant | X | | | | | | X | X | X | | | | | | | | | +| GetParticipantInfo | HTTP/Rest | Participant Lifecycle Management BC | Gets all information regarding to a given Participant | | X | | | | | | | | | | | | | | | | +| GetLiquidityCoverCurrentState | HTTP/Rest | Participant Lifecycle Management BC | Request to get the current state of liquidity cover | | X | | | | | | | | | | | | | | | | +| NotifyReport | Event | Notifications & Alerts BC | Notification Report event containing a report of the notification, indicating if it was successful (with an applicable response from the destination) or failed with an applicable error/reason | | | | x | | | | | | | | | | | | | | +| /log-read-build-log | HTTP/Rest | Logging BC | log consumer. provides endpoint for applications write log topic. Building logs | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | +| /read-log | HTTP/Rest | Logging BC | read logs. Optionally calls Crypto BC to decrypt and or verify siganture | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | +| NotifyRequested | Event | FSP Interop API BC | Notification Request event containing the FSPIOP forwarding request or callback that will be send to a specific participant | | | | x | | | | | | | | | | | | | | +| TransferPrepareRequested | Event | FSP Interop API BC | Transfer Prepare request event | | | | | | x | | | | | | | | | | | | +| TransferPrepareCallbackReport | Event | FSP Interop API BC | Transfer Prepare Callback report for the Payee participant | | | | x | | | | | | | | | | | | | | +| TransferFulfilCommittedRequested | Event | FSP Interop API BC | Transfer Fulfilment request event indicating that a "commit" was processed by the Payee participant | | | | x | | | | | | | | | | | | | | +| TransferFulfilCommittedCallbackReport | Event | FSP Interop API BC | Transfer Fulfil Callback report for the Payer/Payee participant | | | | x | | | | | | | | | | | | | | +| TransferQueryReceived | Event | FSP Interop API BC | Event indicating containing information for a Transfer Query | | | | x | | | | | | | | | | | | | | +| TransferQueryResponseCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Transfer Query Response callback a Participant participant | | | | x | | | | | | | | | | | | | | +| TransferRejectRequested | Event | FSP Interop API BC | Event for a Transfer Reject from a Payee participant | | | | x | | | | | | | | | | | | | | +| TransferRejectRequestProcessedCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Transfer Reject Response callback to a Payer participant | | | | x | | | | | | | | | | | | | | +| TransferPrepareRequestTimedoutCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Transfer Timeout Response callback to a Payer participant | | | | x | | | | | | | | | | | | | | +| TransferFulfilCommitRequestTimedoutCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Transfer Timeout Response callback to a Payer/Payee participants | | | | x | | | | | | | | | | | | | | +| TransferPrepareDuplicateCheckFailedCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Transfer Prepare Duplicate Check Failed Response callback to a Payer/Payee participants | | | | x | | | | | | | | | | | | | | +| TransferPrepareLiquidityCheckFailedCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Transfer Prepare Liquidity Check Failed Response callback to a Payer/Payee participants | | | | x | | | | | | | | | | | | | | +| TransferPrepareInvalidPayerCheckFailedCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Transfer Payer Participant Check Failed Response callback to a Payer/Payee participants | | | | x | | | | | | | | | | | | | | +| TransferPrepareInvalidPayeeCheckFailedCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Transfer Payee Participant Check Failed Response callback to a Payer/Payee participants | | | | x | | | | | | | | | | | | | | +| QuoteRequestReceived | Event | FSP Interop API BC | Event containing a Quote Request from a Payer participant | | | | | | | | x | | | | | | | | | | +| QuoteReceivedCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Quote Request to a Payee participants | | | | | | | | x | | | | | | | | | | +| QuoteResponseReceived | Event | FSP Interop API BC | Event containing a Quote Request Response from a Payee participant | | | | | | | | x | | | | | | | | | | +| QuoteAcceptedCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Quote Respose to a Payer participants | | | | | | | | x | | | | | | | | | | +| InvalidQuoteRequestCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Invalid Quote Request to a Payer participants | | | | | | | | x | | | | | | | | | | +| InvalidFSPInQuoteRequestCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Invalid FSP in Quote Request to a Payer participants | | | | | | | | x | | | | | | | | | | +| RuleViolatedInQuoteRequestCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Rule Violated in Quote Request to a Payer participants | | | | | | | | x | | | | | | | | | | +| RuleViolatedInQuoteResponseCallbackReport | Event | FSP Interop API BC | Event containing callback response report for a Rule Violated in Quote Response to a Payer participants | | | | | | | | x | | | | | | | | | | +| /app-fido-register | HTTP/Rest | FSP Interop API BC | Calls Cyrpto BC to register user | x | x | | | | | | | | | | | | | | | x | +| /audit-log-write | Event | Auditing BC | Writes audit entries into Kafka audit topic. Consumer calls Crypto BC to encrypt and / or sign logging records. | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | +| /audit-read-build-audit-log | HTTP/Rest | Auditing BC | audit consumer. provides endpoint for applications write audit topic. Building logs | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | +| /read-audit-log | HTTP/Rest | Auditing BC | read audit logs. calls Crypto BC to decrypt and or verify siganture | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | +| QuoteRequestAccepted | Event | Agreements/Quotes BC | Event for a Quote Request being processed by the Transfers BC | x | | | | | | | | | | | | | | | | | +| QuoteResponseAccepted | Event | Agreements/Quotes BC | Event for a Quote Response being processed by the Transfers BC | x | | | | | | | | | | | | | | | | | +| InvalidQuoteRequest | Event | Agreements/Quotes BC | Event representing a quote validation failure as a result of processing a QuoteReuestReceived event. | x | | | | | | | | | | | | | | | | | +| InvalidFSPInQuoteRequest | Event | Agreements/Quotes BC | Event representing an invalid FSP in Quote Request failure as a result of processing a QuoteReuestReceived event. | x | | | | | | | | | | | | | | | | | +| RuleViolatedInQuoteRequest | Event | Agreements/Quotes BC | Event representing an Rule Violated in Quote Request failure as a result of processing a QuoteReuestReceived event. | x | | | | | | | | | | | | | | | | | +| RuleViolatedInQuoteResponse | Event | Agreements/Quotes BC | Event representing an Rule Violated in Quote Response failure as a result of processing a QuoteReuestReceived event. | x | | | | | | | | | | | | | | | | | +| /app-register | HTTP/Rest | Admin/Operation API BC | Calls Crypto BC to obtain id and secret | x | x | | | | | | | | | | | | x | | | x | +| GetLiquidityCoverHistory | HTTP/Rest | Admin/Operation API BC | Request the account position history | | X | | | | | | | | | | | | | | | | +| GetReservations | HTTP/Rest | Admin/Operation API BC | Request the reservations | | X | | | | | | | | | | | | | | | | +| GetCurrentLiquidityPosition | gRPC | Accounts & Balances BC | Get the current liquidity position for validation to update liquidity cover reservastion | | | X | | | | | | | | | | | | | | | +| RecordLiquidityReservationEntries | gRPC | Accounts & Balances BC | Records the relevant entries for the liquidity cover reservations | | | X | | | | | | | | | | | | | | | +| RequestAccountsPositions | gRPC | Accounts & Balances BC | Get account positions for a given participant | | | X | | | | | | | | | | | | | | | +| RequestAccountPositionHistory | gRPC | Accounts & Balances BC | Get accounts position history for a given participant | | | X | | | | | | | | | | | | | | | +| RequestReservationAccounts | gRPC | Accounts & Balances BC | Request the accounts related to reservations' | | | X | | | | | | | | | | | | | | | +| ProcessTransferPrepare | gRPC | Accounts & Balances BC | Process Transfer Prepare request for debiting the Payer liquidity, and crediting the Payer position via reservation of funds | | | | x | | | | | | | | | | | | | | +| ProcessTransferFulfil | gRPC | Accounts & Balances BC | Process Transfer Fulfil request for debiting the Payer reserved funds, and crediting the Payee liquidity | | | | x | | | | | | | | | | | | | | + | /log-write | Event | | Writes log entries into Kafka logging topic. Consumer optionally calls Crypto BC to encrypt and / or sign logging records. | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | diff --git a/docs/technical/reference-architecture/boundedContexts/commonTermsConventions/index.md b/docs/technical/reference-architecture/boundedContexts/commonTermsConventions/index.md new file mode 100644 index 000000000..d188a1d1e --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/commonTermsConventions/index.md @@ -0,0 +1,19 @@ +# Common Terms and Conventions Used + +The Reference Architecture Team have made use of Common Terms and Conventions throughout the design and documentation for the Mojaloop 2.0 Reference Architecture model.

    Please make use of this list to familiarise yourself with any terms that may be unfamiliar, or forgotten. The list includes references to third-party reference articles and documents that are listed in the Further Reading section of this document. + +| **Convention/Term** | **Description** | +| :------------------------ | :-------------------------- | +| **Actors** | Human or external system Use Case participant. All Use Cases are driven by Actors.| +| **BC** | Bounded Context: A bounded-context is a component of Design-Driven Development and typically contains a single, or multiple subdomains. Bounded Contexts are Solution Space entities, and contain a single solution applicable to a single, or multiple, subdomain/s.

    (*For additional insights, please see: [DDD Inspired Architecture Overview](../../introduction/#ddd-inspired-architecture-overview) section in the Solution Space overview, or our [Further Reading: Reference Articles and Documents](../../furtherReading/#reference-articles-and-documents)*)| +| **UC** | Use Case: A Use Case is a list of actions or steps describing interactions between an Actor (human or external system) and a system to achieve a particular objective. An example of a Use Case from Mojaloop is "Perform Transfer with Payee Confirmation".

    (*For additional insights, please see the "Use Case", Wikipedia article reference in the [Further Reading: Reference Articles and Documents](../../furtherReading/#reference-articles-and-documents) section of this document*)| +| **Sync** | Synchronous communications, one or two way, part of the originating process. Signified by a solid line in the UC schematics. Typically used for Messages that need to be included in a particular UC workflow in order for it to execute successfully. An example of synch Messaging is a query from the Transfers BC to the Participant Lifecycle Management BC to get Participant data if not cached to complete a Transfer request.| +| **Async** | Asynchronous communications, one or two way, not part of the originating process. Signified by a dotted line in the UC schematics. Typically used for Events which are used to indicate something that has happened, and is immutable and won't change, for example callback reports.| +| **POST** | Utilized to create new resources. In particular, it's used to create subordinate resources. That is, subordinate to some other (e.g. parent) resource. IOW, when creating a new resource, POST to the parent and the service takes care of associating the new resource with the parent, assigning an ID (new resource URI), etc. On successful creation, the system will return a Location header with a link to the newly-created resource with the 201 HTTP status.

    (*For additional insights, please see the "Restful API Tutor", document reference in the [Further Reading: Reference Articles and Documents](../../furtherReading/#reference-articles-and-documents) section of this document*)| +| **GET** | Utilized to read (or retrieve) a representation of a resource. In the "happy" (or non-error) path, GET returns a representation in XML or JSON and an HTTP response code of 200 (OK). In an error case, it most often returns a 404 (NOT FOUND) or 400 (BAD REQUEST).

    (*For additional insights, please see the "Restful API Tutor", document reference in the [Further Reading: Reference Articles and Documents](../../furtherReading/#reference-articles-and-documents) section of this document*)| +| **PUT** | Utilized for update capabilities, PUT-ing to a known resource URI with the request body containing the newly-updated representation of the original resource. In some instances PUT can also be utilized to create new resources, however owing to complexity, this is not recommended (POST should be used instead).

    (*For additional insights, please see the "Restful API Tutor", document reference in the [Further Reading: Reference Articles and Documents](../../furtherReading/#reference-articles-and-documents) section of this document*)| +| **200 (OK)** | HTTP Status code indicating "Success". The request has succeeded. Typically the information returned with the status code is dependent upon the method used in the request. For example, in Mojaloop the methods most commonly used are POST, GET, PUT. For POST, the response would describe or include the result of the action, for GET the requested entity is sent in the response, and for a PUT request, the response would be similar to a POST request.

    (*For additional insights, please see the "Restful API Tutor", document reference in the [Further Reading: Reference Articles and Documents](../../furtherReading/#reference-articles-and-documents) section of this document*)| +| **201 (Created)** | HTTP Status code indicating "Created" or fulfilled. This means that the request has been fulfilled and that the new resource is accessible via the URI returned in the entity response. The origin server will create the resource before returning a 201 code, and if it is not able to do so immediately, will return a 202 (Accepted) instead.

    (*For additional insights, please see the "Restful API Tutor", document reference in the [Further Reading: Reference Articles and Documents](../../furtherReading/#reference-articles-and-documents) section of this document*)| +| **202 (Accepted)** | HTTP Status code indicating that a request has been accepted for processing, but has not been completed. The request may or may not be acted upon when system allows as it may be disallowed when processing occurs. As the operation is asynchronous, there is also not facility for resending the status code, regardless of outcome. The 202 response is deliberately non-committal to enable a request to be processes without requiring the agent to remain connected until such time as it does. The response should include an indication of system status, and either a pointer to a monitoring platform, or an indication of when the request will be acted upon.

    (*For additional insights, please see the "Restful API Tutor", document reference in the [Further Reading: Reference Articles and Documents](../../furtherReading/#reference-articles-and-documents) section of this document*)| +| **OHS** | Open Host Service: Describes documentation of methods to employ to successfully integrate downstream systems into an existing upstream system without requiring any mods to be made to the upstream platform. Typically support is provided for multiple client-types, and will have no particular interest in specific clients. The downstream system will be required to understand the upstream published documentation. OHS and PL are commonly paired by upstream systems.

    Currently utilized in the following entities: FSPIOP External API; ISO External API; Notifications & Alerts BC; PISP ML External API; PISP ISO External API; Scheduling BC; Transfers & Transactions BC; Agreement (Quoting) BC; Accounts & Balances BC; Settlements BC; Participant Lifecycle Management; Account Lookup & Discovery BC)

    (*For additional insights, please see the "Strategic Domain-Driven Design", article reference in the [Further Reading: Reference Articles and Documents](../../furtherReading/#reference-articles-and-documents) section of this document*)| +| **PL** | Published Language: Described as the closest relative to open host service and often used together. PL uses a documented language, for example XML, for basic I/O operations to the system for which it is being utilized. No particular library or implementation spec is required for connecting to the system provided one conforms to the published language. It is not necessary to run only web services with a Published Language. One can also do things like upload a file to a particular folder, which then triggers an operation that stores the content of the file at an application specified location.

    Currently utilized in the following entities: FSPIOP External API; ISO External API

    (*For additional insights please see the "Strategic Domain-Driven Design", article reference in the [Further Reading: Reference Articles and Documents](../../furtherReading/#reference-articles-and-documents) section of this document*))| diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-0-0-notifications.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-0-0-notifications.jpg new file mode 100644 index 000000000..887629575 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-0-0-notifications.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-0-functional-overview.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-0-functional-overview.jpg new file mode 100644 index 000000000..e48567cd4 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-0-functional-overview.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-1-party-participant-associate.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-1-party-participant-associate.jpg new file mode 100644 index 000000000..a2568a5ac Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-1-party-participant-associate.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-2-party-participant-disassociate.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-2-party-participant-disassociate.jpg new file mode 100644 index 000000000..061048844 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-2-party-participant-disassociate.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-3-get-participant.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-3-get-participant.jpg new file mode 100644 index 000000000..4bc8cc587 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-3-get-participant.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-4-get-party.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-4-get-party.jpg new file mode 100644 index 000000000..55fcff12a Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/0-4-get-party.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-1-calculate-quote-happy-path.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-1-calculate-quote-happy-path.jpg new file mode 100644 index 000000000..4914c1d68 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-1-calculate-quote-happy-path.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-2-get-quote-happy-path.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-2-get-quote-happy-path.jpg new file mode 100644 index 000000000..b5c5b3316 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-2-get-quote-happy-path.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-3-calculate-quote-invalid-quote-request.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-3-calculate-quote-invalid-quote-request.jpg new file mode 100644 index 000000000..cfb317673 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-3-calculate-quote-invalid-quote-request.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-4-calculate-quote-invalid-fsps.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-4-calculate-quote-invalid-fsps.jpg new file mode 100644 index 000000000..5b67c0f66 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-4-calculate-quote-invalid-fsps.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-5-calculate-quote-invalid-scheme-rules-request.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-5-calculate-quote-invalid-scheme-rules-request.jpg new file mode 100644 index 000000000..d581b8c66 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-5-calculate-quote-invalid-scheme-rules-request.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-6-calculate-quote-invalid-scheme-rules-response.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-6-calculate-quote-invalid-scheme-rules-response.jpg new file mode 100644 index 000000000..a9c4f9a77 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/1-6-calculate-quote-invalid-scheme-rules-response.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-1-perform-transfer-universal-mode.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-1-perform-transfer-universal-mode.jpg new file mode 100644 index 000000000..3b467d937 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-1-perform-transfer-universal-mode.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-10-perform-transfer-duplicate-none-matching.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-10-perform-transfer-duplicate-none-matching.jpg new file mode 100644 index 000000000..29c57e3e6 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-10-perform-transfer-duplicate-none-matching.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-11-perform-transfer-payer-insuficiant-liquidity.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-11-perform-transfer-payer-insuficiant-liquidity.jpg new file mode 100644 index 000000000..26163264b Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-11-perform-transfer-payer-insuficiant-liquidity.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-12-perform-transfer-prepare-rejected.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-12-perform-transfer-prepare-rejected.jpg new file mode 100644 index 000000000..4183a0928 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-12-perform-transfer-prepare-rejected.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-13-perform-transfer-prepare-validation-failure-invalid-payer-participant.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-13-perform-transfer-prepare-validation-failure-invalid-payer-participant.jpg new file mode 100644 index 000000000..b53949758 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-13-perform-transfer-prepare-validation-failure-invalid-payer-participant.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-14-perform-transfer-prepare-validation-failure-invalid-payee-participant.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-14-perform-transfer-prepare-validation-failure-invalid-payee-participant.jpg new file mode 100644 index 000000000..13a4f7c4a Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-14-perform-transfer-prepare-validation-failure-invalid-payee-participant.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-2-perform-transfer-payee-confirmation.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-2-perform-transfer-payee-confirmation.jpg new file mode 100644 index 000000000..245172f56 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-2-perform-transfer-payee-confirmation.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-3-query-get-transfer.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-3-query-get-transfer.jpg new file mode 100644 index 000000000..27f9b5405 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-3-query-get-transfer.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-4-perform-transfer-duplicate-post.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-4-perform-transfer-duplicate-post.jpg new file mode 100644 index 000000000..ef3cfc3dc Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-4-perform-transfer-duplicate-post.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-5-perform-transfer-duplicate-post-ignor.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-5-perform-transfer-duplicate-post-ignor.jpg new file mode 100644 index 000000000..a7a8cdabd Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-5-perform-transfer-duplicate-post-ignor.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-6-perform-transfer-payeefsp-rejects-transfer.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-6-perform-transfer-payeefsp-rejects-transfer.jpg new file mode 100644 index 000000000..f08f8c2fc Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-6-perform-transfer-payeefsp-rejects-transfer.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-7-perform-transfer-timeout-prepare.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-7-perform-transfer-timeout-prepare.jpg new file mode 100644 index 000000000..f21f280b7 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-7-perform-transfer-timeout-prepare.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-8-perform-transfer-timeout-pre-committed.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-8-perform-transfer-timeout-pre-committed.jpg new file mode 100644 index 000000000..118dbdb1f Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-8-perform-transfer-timeout-pre-committed.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-9-perform-transfer-timeout-post-commit.jpg b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-9-perform-transfer-timeout-post-commit.jpg new file mode 100644 index 000000000..1f88fa39b Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/assets/2-9-perform-transfer-timeout-post-commit.jpg differ diff --git a/docs/technical/reference-architecture/boundedContexts/fspInteropApi/index.md b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/index.md new file mode 100644 index 000000000..8e275f1dc --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/fspInteropApi/index.md @@ -0,0 +1,377 @@ +# FSP Interoperability API BC + +The FSP Interoperability API Bounded Context provides access to the internal operations and resources that the Mojaloop Ecosystem provides to a given Participant. This Bounded Context is responsible for providing a Participant with interfaces whit which the Participant can perform and execute tasks on Mojaloop. It is also responsible for providing communication back to the Participant regarding different notifications and system messages that a participant should expect to receive. + +## Functional Overview + +The FSP IOP API interacts with many different bounded contexts and thus the simplified view is provided here, for further reading on the events and connections that the FSP IOP API provides and consumes please review the Mojaloop Common Interfaces [^1]. The bounded contexts that are integrated with the FSP IOP API are: + +- Account Lookup & Discovery Bounded Context [^14] +- Notifications and Alerts Bounded Context [^27] +- Participant Lifecycle Management Bounded Context [^26] +- Quoting\Agreement Bounded Context [^19] +- Transfers Bounded Context [^22] +- Settlement Bounded Context [^21] + +![Use Case - FSP Interoperability API Functional Overview](./assets/0-0-functional-overview.jpg) + +> FSP Interoperability API Functional Overview + +## Terms + +Terms with specific and commonly accepted meaning within the Bounded Context in which they are used. + +| Term | Description | +| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **(D)FSP** | (Digital) Financial Service Provider | +| **Participant** | Financial Service Provider (FSP) that has registered on the Mojaloop ecosystem. Allowing said FSP to be able to transact with other Participants | +| **FSP IOP API** | Financial Service Provider Interoperability Application Programming Interface, the API that provides access to functions and features of the Mojaloop Ecosystem. | +| **Payer** | The payer of electronic funds in a payment transaction. | +| **Payer FSP** | Payer's Financial Service Provider. | +| **Payee** | The recipient of electronic funds in a payment transaction. | +| **Payee FSP** | Payee's Financial Service Provider. | + +## Use Cases + +### Note + +Use case definitions stipulated in the Open API for FSP Interoperability Specification [^2] have not been altered, and thus the Reference Architecture has been designed to only change the background orchestration of the internal Mojaloop services and Bounded Contexts. + +### Notifications BC - Send Notification + +#### Description + +Notifications pertain to ALL below use cases as a response to requests received in various forms. While the FSP IOP API is busy processing a request received, it might need to sends a request to the requesting DFSP or any other relevant DFSPs. The FSP IOP API will then query the Participant Lifecycle Management Bounded Context [^26] for the Callback URIs for the given participant that the notification needs to be sent to. The FSP IOP API will then send the notification request to the Notification and Alerts Bounded Context [^27]. + +#### Flow Chart + +![Use Case - Notifications BC - Send Notification](./assets/0-0-0-notifications.jpg) + +> + +## Account Lookup & Discovery BCs + +### Party/Participant Associate + +#### Description + +Associate transfer/s Participant/s and/or parties based on the POST Participant request [^5] (POST /participants/{Type}/{ID}). The FSP IOP API then sends a request to the Account Lookup & Discovery BC [^14] which will process the request and respond with a success event. The FSP IOP API then sends a notification PUT Participant response [^15] (PUT /participants/{Type}/{ID}). + +#### Flow Diagram + +![Use Case - Account Lookup & Discovery BC - Party/Participant Associate](./assets/0-1-party-participant-associate.jpg) + +> + +### Party/Participant Disassociate + +#### Description + +Disassociate Participant/s and/or parties based on the DELETE Participant request [^6] (DELETE /participants/{Type}/{ID}). The FSP IOP API sends the request to the Account Lookup & Discovery BC [^14] to disassociate the party. The success response is then received by the FSP IOP API and then responds to the caller by sending a notification PUT Participant response [^15] (PUT /participants/{Type}/{ID}). + +#### Flow Diagram + +![Use Case - Account Lookup & Discovery BC - Party/Participant Disassociate](./assets/0-2-party-participant-disassociate.jpg) + +> + +### Get Participant + +#### Description + +Retrieve participant information based on the GET Participant request [^7] (GET /participants/{Type}/{ID}) , which supplies the ID and structure. The FSP IOP API sends the request to the Account Lookup & Discovery BC [^14] to determine whether the desired participant exists. The FSP IOP API then responds to the requestor with a PUT Participant response [^15] (PUT /participants/{Type}/{ID}). + +#### Flow Diagram + +![Use Case - Account Lookup & Discovery BC - Get Participant](./assets/0-3-get-participant.jpg) + +> + +### Get Party + +#### Description + +Retrieve party information based on the ID passed with the GET Party request [^8] (GET /parties/{Type}/{ID}). The FSP IOP API then sends a request to the Account Lookup & Discovery BC [^14] to determine the target FSP to forward the GET request to. The target FSP then responds with a PUT parties request. The information is then sent to the Account Lookup & Discovery BC to be cached before the PUT Party response [^17] (PUT /parties/{Type}/{ID}) is sent to the original sender of the GET request. + +#### Flow Diagram + +![Use Case - Account Lookup & Discovery BC - Get Party](./assets/0-4-get-party.jpg) + +> + +## Agreement (Quoting) BC + +### Calculate Quote - Happy Path + +#### Description + +When a quote is sent using the POST Quote request [^3] (POST /quotes), the FSP IOP API will sends the request to the Quoting/Agreement BC [^19] to validate the quote. The FSP IOP API will then send the POST Quote to the Payee FSP, which in turn responds with a PUT Quote response [^18] (PUT /quotes/{ID}) and updated relevant information. The FSP IOP API sends the accepted quote to the The Quoting/Agreement BC [^19] to persist the quote information. The FSP IOP API will then forwards the PUT quote request to the Payer FSP and consider the quote successful. + +#### Flow Diagram + +![Use Case - Agreement BC - Calculate Quote - Happy Path](./assets/1-1-calculate-quote-happy-path.jpg) + +> + +### Get Quote - Happy Path + +#### Description + +This allows a FSP to get quote information of an existing quote. The GET Quote request [^4] (GET /quotes/{ID}) is sent to the FSP IOP API that queries the Quoting/Agreement BC [^19] for existing quotes. When the quote is retrieved the information is send back to the requesting FSP by sending the PUT Quote response [^18] (PUT /quotes/{ID}). + +#### Flow Diagram + +![Use Case - Agreement BC - Get Quote - Happy Path](./assets/1-2-get-quote-happy-path.jpg) + +> + +### Calculate Quote - Invalid Quote Request + +#### Description + +When a POST Quote request [^3] (POST /quotes) is , the FSP IOP API sends the request to the Quoting/Agreement BC [^19] for processing. The quote then fails validation the Quoting/Agreement BC [^19] responds with an error response that the FSP IOP API notifies the requesting FSP through the use of the PUT Quote Error response [^20] (PUT /quotes/{ID}/error). + +#### Flow Diagram + +![Use Case - Agreement BC - Calculate Quote - Invalid Quote Request](./assets/1-3-calculate-quote-invalid-quote-request.jpg) + +> + +### Calculate Quote - Invalid FSPs + +#### Description + +When a POST Quote request [^3] (POST /quotes) is sent but the FSP IOP API sends the request to the Quoting/Agreement BC [^19] for processing and it cannot determine that both participants are valid FSPs then an error response is then sent to the FSP IOP API. The FSP IOP API then notifies the requesting FSP through the use of the PUT Quote Error response [^20] (PUT /quotes/{ID}/error). + +#### Flow Diagram + +![Use Case - Agreement BC - Calculate Quote - Invalid FSPs](./assets/1-4-calculate-quote-invalid-fsps.jpg) + +> + +### Calculate Quote - Invalid Scheme Rules detected in Request + +#### Description + +When the Payer FSP sends a POST Quote request [^3] (POST /quotes) the FSP IOP API sends the request to the Quoting/Agreement BC [^19] for processing and the quote does not adhere to the scheme rules defined then an error response is then sent to the FSP IOP API. The FSP IOP API then notifies the Payer FSP through the use of the PUT Quote Error response [^20] (PUT /quotes/{ID}/error) + +#### Flow Diagram + +![Use Case - Agreement BC - Calculate Quote - Invalid Scheme Rules detected in Request](./assets/1-5-calculate-quote-invalid-scheme-rules-request.jpg) + +> + +### Calculate Quote - Invalid Scheme Rules detected in Response + +#### Description + +When the Payer FSP sends a POST Quote request [^3] (POST /quotes) the FSP IOP API sends the request to the Quoting/Agreement BC [^19] for processing and it succeeds initial processing. The FSP IOP API sends the request POST quote request to the Payee FSP. The Payee FSP should react with a accepted quote by sending PUT Quote request [^18] (PUT /quotes/{ID}). The response is sent to Quoting/Agreement BC [^19] for further processing and validation. When the Bounded Context detects that the quote does not adhere to the scheme rules defined then an error response is then sent to the FSP IOP API. The FSP IOP API then notifies both the Payer FSP and the Payee FSP through the use of the PUT Quote Error response [^20] (PUT /quotes/{ID}/error). + +#### Flow Diagram + +![Use Case - Agreement BC - Calculate Quote - Invalid Scheme Rules detected in Response](./assets/1-6-calculate-quote-invalid-scheme-rules-response.jpg) + +> Agreement BC - Calculate Quote - Invalid Scheme Rules detected in Response + +## Transfers BC + +### Perform Transfer (Universal Mode) + +#### Description + +The Payer FSP sends a POST Transfers request [^9] (POST /transfers) to the FSP IOP API. The FSP IOP API then sends an event to the Settlements Bounded Context [^21]. The FSP IOP API waits for an event from the Transfers Bounded Context [^22], to indicate that the transfer has been prepared, to send a POST request to the Payee FSP. The Payee FSP then responds with a PUT Transfers request [^23] (PUT /transfers/{ID}) (transferState = committed) to the FSP IOP API which in turn commits the transfer fulfillment. The PUT transfer is then send to the Payer FSP. + +#### Flow Diagram + +![Use Case - Transfers BC - Perform Transfer (Universal Mode)](./assets/2-1-perform-transfer-universal-mode.jpg) + +> + +### Perform Transfer with Payee Confirmation + +#### Description + +The Payer FSP sends a POST Transfers request [^9] (POST /transfers) to the FSP IOP API. The FSP IOP API then sends an event to the Settlements Bounded Context [^21]. The FSP IOP API waits for an event from the Transfers Bounded Context [^22], to indicate that the transfer has been prepared, to send a POST request to the Payee FSP. The Payee FSP then responds with a PUT Transfers request [^23] (PUT /transfers/{ID}) (transferState = reserved) to the FSP IOP API which in turn reservers the transfer fulfillment. The PUT transfer is then send to the Payer FSP. The Payee FSP then receives a PATCH Transfers request [^24] (PATCH /transfers/{ID}) to notify the state change of the transfer. + +#### Flow Diagram + +![Use Case - Transfers BC - Perform Transfer with Payee Confirmation](./assets/2-2-perform-transfer-payee-confirmation.jpg) + +> + +### Query Get Transfer + +#### Description + +Gets the transfer info based on the transfer ID used in GET Transfer request [^11] (GET /transfers/{ID}) and receives a PUT Transfers request [^23] (PUT /transfers/{ID}) to get the relevant information about the transfer. + +#### Flow Diagram + +![Use Case - Transfers BC - Query Get Transfer](./assets/2-3-query-get-transfer.jpg) + +> + +### Perform Transfer - Duplicate Post (Resend) + +#### Description + +POST Transfers request [^9] (POST /transfers) has already been processed and a status report is returned to the Payer FSP by receiving a PUT Transfers request [^23] (PUT /transfers/{ID}). + +#### Flow Diagram + +![Use Case - Transfers BC - Perform Transfer - Duplicate Post (Resend)](./assets/2-4-perform-transfer-duplicate-post.jpg) + +> Transfers BC - Perform Transfer - Duplicate Post (Resend) + +### Perform Transfer - Duplicate Post (Ignore) + +#### Description + +POST Transfers request [^9] (POST /transfers) has already been processed but no response is needed or requested. + +#### Flow Diagram + +![Use Case - Transfers BC - Perform Transfer - Duplicate Post (Ignore)](./assets/2-5-perform-transfer-duplicate-post-ignor.jpg) + +> + +### Perform Transfer - Payee DFSP Rejects Transfer + +#### Description + +The Payer FSP sends a POST Transfers request [^9] (POST /transfers) to the FSP IOP API. The Api then prepares the transfer and then sends the POST request through to the Payee FSP. The Payee FSP then declines the transfer by sending a PUT Transfer error request [^25] (PUT /transfers/{ID}/error) to the FSP IOP API. The FSP IOP API then notifies the Transfers Bounded Context [^22] that the transfer has been rejected and sends a PUT Transfer error request [^25] (PUT /transfers/{ID}/error) to the Payer FSP. + +#### Flow Diagram + +![Use Case - Transfers BC - Perform Transfer - Payee DFSP Rejects Transfer](./assets/2-6-perform-transfer-payeefsp-rejects-transfer.jpg) + +> + +### Perform Transfer - Timeout (Prepare) + +#### Description + +POST Transfers request [^9] (POST /transfers) gets rejected because the transfer timed out [^13] while funds are being prepared. The FSP IOP API sends a PUT Transfer error request [^25] (PUT /transfers/{ID}/error) request to the Payer FSP to notify of the error. + +#### Flow Diagram + +![Use Case - Transfers BC - Perform Transfer - Timeout (Prepare)](./assets/2-7-perform-transfer-timeout-prepare.jpg) + +> + +### Perform Transfer - Timeout (Pre-Committed) + +#### Description + +The Payer FSP sends a POST Transfers request [^9] (POST /transfers) to the FSP IOP API. The FSP IOP API then sends an event to the Settlements Bounded Context [^21]. The FSP IOP API waits for an event from the Transfers Bounded Context [^22], to indicate that the transfer has been prepared, to send a POST request to the Payee FSP. The Payee FSP then responds with a PUT Transfers request [^23] (PUT /transfers/{ID}) (transferState = committed) to the FSP IOP API which in turn commits the transfer fulfillment. The transfer times out [^13] while/before the funds are committed and causes the transfer to be rejected. The FSP IOP API then notifies both the Payer and Payee FSPs with a PUT Transfer error request [^25] (PUT /transfers/{ID}/error). + +#### Flow Diagram + +![Use Case - Transfers BC - Perform Transfer - Timeout (Pre-Committed)](./assets/2-8-perform-transfer-timeout-pre-committed.jpg) + +> + +### Perform Transfer - Timeout (Post-Committed) + +#### Description + +The Payer FSP sends a POST Transfers request [^9] (POST /transfers) to the FSP IOP API. The FSP IOP API then sends an event to the Settlements Bounded Context [^21]. The FSP IOP API waits for an event from the Transfers Bounded Context [^22], to indicate that the transfer has been prepared, to send a POST request to the Payee FSP. The Payee FSP then responds with a PUT Transfers request [^23] (PUT /transfers/{ID}) (transferState = committed) to the FSP IOP API which in turn commits the transfer fulfillment. The transfer times out [^13] after the funds are committed and causes the transfer to be rejected. + +#### Flow Diagram + +![Use Case - Transfers BC - Perform Transfer - Timeout (Post-Committed)](./assets/2-9-perform-transfer-timeout-post-commit.jpg) + +> + +### Perform Transfer - Duplicate Post (None Matching) + +#### Description + +POST Transfers request [^9] (POST /transfers) has already been processed and a status report is returned to the Payer FSP by receiving a PUT Transfer error request [^25] (PUT /transfers/{ID}/error). + +#### Flow Diagram + +![Use Case - Example REPLACE ME](./assets/2-10-perform-transfer-duplicate-none-matching.jpg) + +> + +### Perform Transfer - Payer FSP Insufficient Liquidity + +#### Description + +The Payer FSP sends a POST Transfers request [^9] (POST /transfers) to the FSP IOP API. The FSP IOP API then sends an event to the Settlements Bounded Context [^21]. The FSP IOP API waits for an event from the Transfers Bounded Context [^22], to indicate that the transfer has been prepared, but receives a Liquidity check failure for the Payer FSP. The FSP OIP API then sends a PUT [^25] transfers error request to the Payer FSP to notify of the error. + +#### Flow Diagram + +![Use Case - Transfers BC - Perform Transfer - Payer FSP Insufficient Liquidity](./assets/2-11-perform-transfer-payer-insuficiant-liquidity.jpg) + +> + +### Perform Transfer - Transfer Prepare Rejected + +#### Description + +The Payer FSP sends a POST Transfers request [^9] (POST /transfers) to the FSP IOP API. The Api then prepares the transfer and then sends the POST request through to the Payee FSP. The Payee FSP then declines the transfer by sending a PUT Transfer error request [^25] (PUT /transfers/{ID}/error) to the FSP IOP API. The FSP IOP API then notifies the Transfers Bounded Context [^22] that the transfer has been rejected and sends a PUT Transfer error request [^25] (PUT /transfers/{ID}/error) to the Payer FSP. + +#### Flow Diagram + +![Use Case - Transfers BC - Perform Transfer - Transfer Prepare Rejected](./assets/2-12-perform-transfer-prepare-rejected.jpg) + +> + +### Perform Transfer - Transfer Prepare Validation Failure (Invalid Payer Participant) + +#### Description + +The Payer FSP sends a POST Transfers request [^9] (POST /transfers) to the FSP IOP API. The Transfers Bounded Context [^22] notifies the FSP IOP API that the Payer FSP is invalid. Depending on the reason for the Payer FSP being invalid the FSP IOP API will send a PUT Transfer error request [^25] (PUT /transfers/{ID}/error) to the Payer FSP. + +#### Flow Diagram + +![Use Case - Transfers BC - Perform Transfer - Transfer Prepare Validation Failure (Invalid Payer Participant)](./assets/2-13-perform-transfer-prepare-validation-failure-invalid-payer-participant.jpg) + +> + +### Perform Transfer - Transfer Prepare Validation Failure (Invalid Payee Participant) + +#### Description + +The Payer FSP sends a POST Transfers request [^9] (POST /transfers) to the FSP IOP API. The Transfers Bounded Context [^22] notifies the FSP IOP API that the Payee FSP is invalid. The FSP IOP API will send a PUT Transfer error request [^25] (PUT /transfers/{ID}/error) to the Payer FSP to notify about the failure. + +#### Flow Diagram + +![Use Case - Transfers BC - Perform Transfer - Transfer Prepare Validation Failure (Invalid Payer Participant)](./assets/2-14-perform-transfer-prepare-validation-failure-invalid-payee-participant.jpg) + +> + +## Notes + +### Structure validation on internal events + +Many use cases stipulate that the request structure and semantics should be validated when receiving a event from an internal Bounded Context. This does not happen on a per request basis but rather is a requirement to be met when the building phase of the Reference Architecture is underway. What we are trying to say by showing that is that internally all events and available resources should be standardized and verified. + +[^1]: [Mojaloop Common Interface List](../../commonInterfaces.md) +[^2]: [Open API for FSP Interoperability Specification Documentation](https://docs.mojaloop.io/mojaloop-specification/) +[^3]: [Post Quote - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6532-post-quotes) +[^4]: [Get Quote - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6531-get-quotesid) +[^5]: [Post Participant - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6233-post-participantstypeid) +[^6]: [Delete Participant - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6234-delete-participantstypeid) +[^7]: [Get Participant - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6231-get-participantstypeid) +[^8]: [Get Parties - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6331-get-partiestypeid) +[^9]: [Post Transfers - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6732-post-transfers) +[^10]: [Commit Notification - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6726-commit-notification) +[^11]: [Get Transfers - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6731-get-transfersid) +[^12]: [Transaction Irrevocability - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.#6722-transaction-irrevocability) +[^13]: [Transfers Timeout and Expiry - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6724-timeout-and-expiry) +[^14]: [Account Lookup and Discovery Bounded Context](../accountLookupAndDiscovery/index.md) +[^15]: [Put Participant - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6242-put-participantsid) +[^17]: [Put Party- Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6341-put-partiestypeid) +[^18]: [Put Quote - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6541-put-quotesid) +[^19]: [Quoting\Agreement Bounded Context](../quotingAgreement/index.md) +[^20]: [Put Quote Error - Definition](https://docs.mojmojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6551-put-quotesiderror) +[^21]: [Settlements Bounded Context](../settlements/index.md) +[^22]: [Transfers Bounded Context](../transfers/index.md) +[^23]: [Put Transfers - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6741-put-transfersid) +[^24]: [Patch Transfers - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6733-patch-transfersid) +[^25]: [Put Transfers Error - Definition](https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#6751-put-transfersiderror) +[^26]: [Participant Lifecycle Management Bounded Context](../participantLifecycleManagement/index.md) +[^27]: [Notification and Alerts Bounded Context](../notificationsAndAlerts/index.md) diff --git a/docs/technical/reference-architecture/boundedContexts/index.md b/docs/technical/reference-architecture/boundedContexts/index.md new file mode 100644 index 000000000..e04fd4a32 --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/index.md @@ -0,0 +1,23 @@ +# Bounded Context + +In this section we take a deep dive into each of the identified Bounded Contexts indicating their purpose (description), Subdomains spanned, Use Cases that each Bounded Context addresses, and concluding remarks where they have been included. + + \ No newline at end of file diff --git a/docs/technical/reference-architecture/boundedContexts/logging/assets/ML2RA_Logging_ucEventBasedLogging_Apr22-b-1450.png b/docs/technical/reference-architecture/boundedContexts/logging/assets/ML2RA_Logging_ucEventBasedLogging_Apr22-b-1450.png new file mode 100644 index 000000000..577e56490 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/logging/assets/ML2RA_Logging_ucEventBasedLogging_Apr22-b-1450.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/logging/index.md b/docs/technical/reference-architecture/boundedContexts/logging/index.md new file mode 100644 index 000000000..1b529688c --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/logging/index.md @@ -0,0 +1,20 @@ +# Logging BC + +The Logging Bounded Context is used to store technical information to assist debugging, troubleshooting and problem resolution. Logs are consumed from any other Bounded Context [^1] and stored for querying and reporting. The log information is stored as "technicalities" and should any loss of data take place, then there should be no other consequence than losing technical ability to understand how the system behaves. All system activities are logged and persisted to allow the Auditing Bounded Context [^2] to perform queries against the log data. + +Bounded Contexts should publish the events in a defined format and using whatever mechanism is available from the Logging Bounded Context. The structure implicitly has an abstraction layer built into the event received byt the Logging Bounded Context which in turn is then used to persist the log data. + +## Use Cases + +### Event Based Logging + +#### Flow Diagram + +![Use Case - Event Based Logging](./assets/ML2RA_Logging_ucEventBasedLogging_Apr22-b-1450.png) +>UC Workflow Diagram: Event Based Logging + + +## Notes + +[^1]: [Mojaloop Common Interface List](../../refarch/commonInterfaces.md) +[^2]: [Auditing Bounded Context](../auditing/index.md) diff --git a/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/assets/alertNotification.png b/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/assets/alertNotification.png new file mode 100644 index 000000000..607842c5a Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/assets/alertNotification.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/assets/alertRegistration.png b/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/assets/alertRegistration.png new file mode 100644 index 000000000..754ec79dc Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/assets/alertRegistration.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/assets/sendAsyncNotificationWithDeliveryReport.png b/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/assets/sendAsyncNotificationWithDeliveryReport.png new file mode 100644 index 000000000..b858925b7 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/assets/sendAsyncNotificationWithDeliveryReport.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/assets/sendSyncNotificationWithDeliveryReport.png b/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/assets/sendSyncNotificationWithDeliveryReport.png new file mode 100644 index 000000000..b188e7f71 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/assets/sendSyncNotificationWithDeliveryReport.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/index.md b/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/index.md new file mode 100644 index 000000000..4bc36afa1 --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/notificationsAndAlerts/index.md @@ -0,0 +1,62 @@ +# Notifications and Alerts BC + +The Notifications and Alerts BC acts as the notification-engine of the Mojaloop platform. It provides supporting capabilities for reliable FSPIOP Callbacks by ensuring that delivery reports are made available for compensating actions, and audit purposes. Similarly, these capabilities can be leveraged for sending alerts reliably to internal sub-systems or external consumers. + +Reliability is ensured by several mechanisms: + +- Each Notification command contains + - all the necessary information (headers, payload, transport, etc) required by the BC to deliver it + - retry and delivery configuration on how the Notification BC should handle delivery failures +- Notification or Alert reports are persisted and are queryable. + +## Terms + +Terms with specific and commonly accepted meaning within the Bounded Context in which they are used. + +| Term | Description | +|---|---| +| **Notification** | An outbound notification send by the Notifications and Alerts BC normally to an external destination containing contextual headers and payloads. An example of this being the FSPIOP Callbacks as part of the Mojaloop API Specification. | +| **Alert** | Similar to a notification except an Alert is normally used to inform internal sub-systems (i.e. other BC) or a Hub Operator of an "observed" Canonical Event. An example of this being that an FSP has exceeded their available liquidity. | +| **Delivery Report** | A report produced by the Notifications and Alerts BC containing delivery information about a specific Notification or Alert, such as the status of the delivery, the response received by the destination, the number of retries, and information about failures. This report can be either by a domain event, and/or a synchronous response to an API request. | +| **Canonical Event** | This is any Domain Event produced by a Bounded Context | + +## Use Cases + +### Send Asynchronous Notifications with Delivery Report + +#### Flow Diagram + +![Use Case - Send Async Notifications with Delivery Report](./assets/sendAsyncNotificationWithDeliveryReport.png) + +### Send Synchronous Notifications with Delivery Report + +#### Flow Diagram + +![Use Case - Send Sync Notifications with Delivery Report](./assets/sendSyncNotificationWithDeliveryReport.png) + + + +### Alert Registration + +#### Description + +Hub Operators or Sub-systems will be able to call the Alert Registration API to subscribe to specific notification alerts. The AlertRegister operation will include: + +- Domain Message/Event to be monitored +- End-point / Transport information for Notification Delivery +- Template for the Notification Alert that will be used to generate the actual Notification + +#### Flow Diagram + +![Use Case - Send Sync Notifications with Delivery Report](./assets/alertRegistration.png) + +### Alert Notifications + +#### Flow Diagram + +![Use Case - Send Sync Notifications with Delivery Report](./assets/alertNotification.png) + + + diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-bcOverviewFlowDiagram_Apr22-a_1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-bcOverviewFlowDiagram_Apr22-a_1429.png new file mode 100644 index 000000000..c16848a1b Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-bcOverviewFlowDiagram_Apr22-a_1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucAddParticipantAccountAppro_Apr22-a_P2-1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucAddParticipantAccountAppro_Apr22-a_P2-1429.png new file mode 100644 index 000000000..adbfe0d98 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucAddParticipantAccountAppro_Apr22-a_P2-1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucAddParticipantAccountInit_Apr22-a_P1-1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucAddParticipantAccountInit_Apr22-a_P1-1429.png new file mode 100644 index 000000000..ec745aaa8 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucAddParticipantAccountInit_Apr22-a_P1-1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucCreateParticipantAppro_Apr22-a_P2-1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucCreateParticipantAppro_Apr22-a_P2-1429.png new file mode 100644 index 000000000..b4abeaf4f Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucCreateParticipantAppro_Apr22-a_P2-1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucCreateParticipantInit_Apr22-a_P1-1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucCreateParticipantInit_Apr22-a_P1-1429.png new file mode 100644 index 000000000..177241a98 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucCreateParticipantInit_Apr22-a_P1-1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucGetParticipant_Apr22-a_1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucGetParticipant_Apr22-a_1429.png new file mode 100644 index 000000000..eea3ac385 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucGetParticipant_Apr22-a_1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityCoverQuery_Apr22-a_1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityCoverQuery_Apr22-a_1429.png new file mode 100644 index 000000000..bc50ae969 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityCoverQuery_Apr22-a_1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityCoverReserveAppro_Apr22-a_P2-1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityCoverReserveAppro_Apr22-a_P2-1429.png new file mode 100644 index 000000000..109050536 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityCoverReserveAppro_Apr22-a_P2-1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityCoverReserveInit_Apr22-a_P1-1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityCoverReserveInit_Apr22-a_P1-1429.png new file mode 100644 index 000000000..bd4f49e56 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityCoverReserveInit_Apr22-a_P1-1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityLimit&ThresholdReset_Apr22-a_1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityLimit&ThresholdReset_Apr22-a_1429.png new file mode 100644 index 000000000..3bcd8009c Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityLimit&ThresholdReset_Apr22-a_1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityLimitedExceeded_Apr22-a_1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityLimitedExceeded_Apr22-a_1429.png new file mode 100644 index 000000000..d3b2129d3 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityLimitedExceeded_Apr22-a_1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityThresholdExceeded_Apr22-a_1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityThresholdExceeded_Apr22-a_1429.png new file mode 100644 index 000000000..a833e5ae6 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucLiquidityThresholdExceeded_Apr22-a_1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucManageFundsAppro_Apr22-a_P2-1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucManageFundsAppro_Apr22-a_P2-1429.png new file mode 100644 index 000000000..4d429dc37 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucManageFundsAppro_Apr22-a_P2-1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucManageFundsInit_Apr22-a_P1-1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucManageFundsInit_Apr22-a_P1-1429.png new file mode 100644 index 000000000..fcde920b2 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucManageFundsInit_Apr22-a_P1-1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucUpdateEndpointAppro_Apr22-a_P2-1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucUpdateEndpointAppro_Apr22-a_P2-1429.png new file mode 100644 index 000000000..26d13ab31 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucUpdateEndpointAppro_Apr22-a_P2-1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucUpdateEndpointsInit_Apr22-a_P1-1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucUpdateEndpointsInit_Apr22-a_P1-1429.png new file mode 100644 index 000000000..b9e206363 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucUpdateEndpointsInit_Apr22-a_P1-1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucUpdateParticipantStatusAppro_Apr22-a_P2-1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucUpdateParticipantStatusAppro_Apr22-a_P2-1429.png new file mode 100644 index 000000000..54033e161 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucUpdateParticipantStatusAppro_Apr22-a_P2-1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucUpdateParticipantStatusInit_Apr22-a_P1-1429.png b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucUpdateParticipantStatusInit_Apr22-a_P1-1429.png new file mode 100644 index 000000000..be01060f0 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/assets/ML2RA_PLM-ucUpdateParticipantStatusInit_Apr22-a_P1-1429.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/index.md b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/index.md new file mode 100644 index 000000000..63416fc0e --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/participantLifecycleManagement/index.md @@ -0,0 +1,192 @@ +# Participant Lifecycle Management BC + +The Participant Lifecycle Bounded Context's primary concern regards anything to do with the management of a Participant within the Mojaloop Environment. When we are defining the Participant Lifecycle Management Bounded Context there are a few key concepts that should be clearly defined. + +#### Maker-Checker Process +The Maker-Checker Process establishes the 6 eye verification and ensure that no write action takes place without being validated by some one with adiquite permissions. These permissions are defined by the Participant Lifecycle Management Bounded Context but are configurable and assignable as needed by the Scheme Rules. It is recommended that the users/roles that receive the maker permissions do not receive the checker permissions, and that the checker permissions are assigned to different users/roles. It will still be possible to assign both responsibilities to the same users/roles but this then voids the security that is provided by the maker-checker process that the system was built to support. + +#### Participant States +The participant state management allows the admin operators to control permissions for a given participant based on their state. During the Platform Configuration phase, the Participant Lifecycle Management Bounded Context expects participant states to be defined and configured with either roles/permissions. The participant states can then be assigned to a given participant through the Participant Status Management process. + +## Terms + +Terms with specific and commonly accepted meaning within the Bounded Context in which they are used. + +| Term | Description | +| ----------- | ------------ | +| **Participant** | Financial Service Provider that register on the Mojaloop ecosystem. Allowing said FSP to be able to transact with other Participants | +| **Maker** | Representative that is responsible for creating data structures through the use of request. | +| **Checker** | Representative that is responsible for approving and accepting data that has been requested to be created. | + +## Functional Overview + +Please review the common interfaces page to see how these interaction take place. [^1] + +![Use Case - Example REPLACE ME](./assets/ML2RA_PLM-bcOverviewFlowDiagram_Apr22-a_1429.png) +>BC Workflow Diagram: Functional Overview + +## Use Cases + +### Create Participant (Single Step Registration) + +#### Description + +The workflow provided by this UC enables the BC to employ a process through which to create a Participant on the Mojaloop ecosystem, this usually requires all the information that relates to the participant and the initial accounts needed. + +#### Flow Diagram + +![Use Case - Create Pariticipant Initial](./assets/ML2RA_PLM-ucCreateParticipantInit_Apr22-a_P1-1429.png) +![UC - Create Participant Approve](./assets/ML2RA_PLM-ucCreateParticipantAppro_Apr22-a_P2-1429.png) +>UC Workflow Diagram: Create Participant + +### Manage Funds + +#### Description + +The workflow provided by this UC enables the BC to employ a process through which to either withdraw or deposit funds to the Participant's account(s). + +#### Flow Diagram + +![Use Case - Manage Funds - Initial](./assets/ML2RA_PLM-ucManageFundsInit_Apr22-a_P1-1429.png) +![Use Case - Manage Funds - Approve](./assets/ML2RA_PLM-ucManageFundsAppro_Apr22-a_P2-1429.png) +>UC Workflow Diagram: Manage Funds + +### Update Endpoints + +#### Description + +The workflow provided by this UC enables the BC to employ a process through which to update the endpoint of a given participant. When the request has been approved the endpoint will be called on a keep alive path to ensure connectivity. + +#### Flow Diagram + +![Use Case - Update Endpoints - Initial](./assets/ML2RA_PLM-ucUpdateEndpointsInit_Apr22-a_P1-1429.png) +![Use Case - Update Endpoints - Initial](./assets/ML2RA_PLM-ucUpdateEndpointAppro_Apr22-a_P2-1429.png) +>UC Workflow Diagram: Update Endpoints + +### Update Participant Status + +#### Description + +The workflow provided by this UC enables the BC to employ a process through which to change the status of a given participant to enforce different roles/scheme rules on the participant. + +#### Flow Diagram + +![Use Case - Update Participant Status - Initial](./assets/ML2RA_PLM-ucUpdateParticipantStatusInit_Apr22-a_P1-1429.png) +![Use Case - Update Participant Status - Approve](./assets/ML2RA_PLM-ucUpdateParticipantStatusAppro_Apr22-a_P2-1429.png) +>UC Workflow Diagram: Update Participant Status + +### Get Participant + +#### Description + +The workflow provided by this UC enables the BC to employ a process through which to get information with about a given participant. + +#### Flow Diagram + +![Use Case - Get Participant](./assets/ML2RA_PLM-ucGetParticipant_Apr22-a_1429.png) +>UC Workflow Diagram: Get Participant + +### Add Participant Accounts + +#### Description + +The workflow provided by this UC enables the BC to employ a process through which to control different aspects of a Participant's accounts, from creating an account, enabling/disabling and updating the limits and threshold warnings of an account. + +- Add Participant Account +- Update Participant Account Status (Enable/Disable) +- Update Liquidity Limits and Warning Thresholds + +#### Flow Diagram + + + +![Use Case - Add Participant Accounts - Initial](./assets/ML2RA_PLM-ucAddParticipantAccountInit_Apr22-a_P1-1429.png) +![Use Case - Add Participant Accounts - Approve](./assets/ML2RA_PLM-ucAddParticipantAccountAppro_Apr22-a_P2-1429.png) +>UC Workflow Diagram: Add Participant Accounts + +### Liquidity Cover Reserve + +#### Description + +The workflow provided by this UC enables the BC to employ a process through which to reserve liquidity cover for a Participant and notify the Accounts and Balances BC about the update. + +#### Flow Diagram + +![Use Case - Reserve Liquidity Cover - Initial](./assets/ML2RA_PLM-ucLiquidityCoverReserveInit_Apr22-a_P1-1429.png) +![Use Case - Reserve Liquidity Cover - Approve](./assets/ML2RA_PLM-ucLiquidityCoverReserveAppro_Apr22-a_P2-1429.png) +>UC Workflow Diagram: Liquidity Cover Reserve + +### Liquidity Threshold Exceeded + +#### Description + +The workflow provided by this UC enables the BC to employ a process through which to notify the participant that a preset liquidity threshold has been reached and action might be required. + +#### Flow Diagram + +![Use Case - Liquidity Threshold Exceeded](./assets/ML2RA_PLM-ucLiquidityThresholdExceeded_Apr22-a_1429.png) +>UC Workflow Diagram: Liquidity Threshold Exceeded + +### Liquidity Limit Exceeded + +#### Description + +The workflow provided by this UC enables the BC to employ a process through which to notify the participant when they have reached the preset liquidity limit of an account. + +#### Flow Diagram + +![Use Case - Liquidity Limit Exceeded](./assets/ML2RA_PLM-ucLiquidityLimitedExceeded_Apr22-a_1429.png) +>UC Workflow Diagram: Liquidity Limit Exceeded + +### Liquidity Threshold & Limit Reset + +#### Description + +The workflow provided by this UC enables the BC to employ a process through which reset the liquidity limit or threshold notification checks when successful transfers have been executed and the participant account position is in a positive state. + +#### Flow Diagram + +![Use Case - Liquidity Threshold & Limit Reset](./assets/ML2RA_PLM-ucLiquidityLimit&ThresholdReset_Apr22-a_1429.png) +>UC Workflow Diagram: Liquidity Threshold and Limit Reset + +### Liquidity Cover Query + +#### Description + +The workflow provided by this UC enables the BC to employ a process through which to query the current liquidity of a participant account, along with additional read operations that are related to the participant's liquidity. + +#### Flow Diagram + + + +![Use Case - Liquidity Cover Query](./assets/ML2RA_PLM-ucLiquidityCoverQuery_Apr22-a_1429.png) +>UC Workflow Diagram: Liquidity Cover Queries + +## Canonical Model + +- Participant + - id + - participantAlias + - endpointURL + - state + - Accounts[] + - accountID + - ledgerAccountType + - accountCurrency + - isActive + - warningThreshold + - limit + - type + - value + +## Concluding Comments + +**Participant Accounts:** Participants can only have one account per allowed currency. +**Update Position Use Case:** Has been changed to the Manage Funds use case +**Maker/Checker Operations:** Retry count has no effect on the way we process/re-process requests. + + + +## Notes + +[^1]: Common Interfaces: [Mojaloop Common Interface List](../../boundedContexts/commonInterfaces.md) diff --git a/docs/technical/reference-architecture/boundedContexts/platformMonitoring/assets/useCaseExample.png b/docs/technical/reference-architecture/boundedContexts/platformMonitoring/assets/useCaseExample.png new file mode 100644 index 000000000..fd9ae7373 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/platformMonitoring/assets/useCaseExample.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/platformMonitoring/index.md b/docs/technical/reference-architecture/boundedContexts/platformMonitoring/index.md new file mode 100644 index 000000000..1fa059c56 --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/platformMonitoring/index.md @@ -0,0 +1,23 @@ +# {name} BC + +{overview} + +## Terms + +Terms with specific and commonly accepted meaning within the Bounded Context in which they are used. + +| Term | Description | +|---|---| +| Term1 | Description1 | + +## Use Cases + +### Perform Transfer (universal mode) + +![Use Case - Example REPLACE ME](./assets/useCaseExample.png) +> example image - replace + + +## Notes + +[^1]: Common Interfaces: [Mojaloop Common Interface List](../../commonInterfaces.md) diff --git a/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteHappyPath_20210825.png b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteHappyPath_20210825.png new file mode 100644 index 000000000..ce5c78a4d Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteHappyPath_20210825.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteInvalidFSPs_20210825.png b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteInvalidFSPs_20210825.png new file mode 100644 index 000000000..80bbd8d7a Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteInvalidFSPs_20210825.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteInvalidQuoteRequest_20210825.png b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteInvalidQuoteRequest_20210825.png new file mode 100644 index 000000000..5cb2262e8 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteInvalidQuoteRequest_20210825.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteInvalidSchemeRulesRequest_20210825.png b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteInvalidSchemeRulesRequest_20210825.png new file mode 100644 index 000000000..b98cbc26e Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteInvalidSchemeRulesRequest_20210825.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteInvalidSchemeRulesResponse_20210825.png b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteInvalidSchemeRulesResponse_20210825.png new file mode 100644 index 000000000..a023e3df6 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaCalculateQuoteInvalidSchemeRulesResponse_20210825.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaFunctionalOverview_20210825.png b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaFunctionalOverview_20210825.png new file mode 100644 index 000000000..72ac92834 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaFunctionalOverview_20210825.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaGetQuoteHappyPath.png b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaGetQuoteHappyPath.png new file mode 100644 index 000000000..5c67aa42b Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaGetQuoteHappyPath.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaTransfersVelocityRuleEval-Trigger_20210825.png b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaTransfersVelocityRuleEval-Trigger_20210825.png new file mode 100644 index 000000000..f4386a449 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/assets/qtaTransfersVelocityRuleEval-Trigger_20210825.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/quotingAgreement/index.md b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/index.md new file mode 100644 index 000000000..f330347b5 --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/quotingAgreement/index.md @@ -0,0 +1,120 @@ +# Quoting/Agreements BC + +The Quoting and Agreements Bounded Context provides Participants with quotations for undertaking transfers, and records the participant accept/reject responses. + +## Terms + +The following terms are used in this BC, also known as a domain. + +| Term | Description | +|---|---| +| **(D)FSP** | (Digital) Financial Services Provider | +| **Participant** | Financial Services Provider | + +## Functional Overview + +![Use Case - Functional Overview](./assets/qtaFunctionalOverview_20210825.png) + +## Use Cases + +### Calculate Quote - Happy Path + +#### Description + +This process obtains an array of relevant Participant data including status flags, calculates the cost of Transfer including fees, and provides it to the Participant/s. It also able to support the storing of Participants requests & responses (i.e. accept or reject the quote). + +#### Flow Diagram + +![Use Case - Calculate Quote - Happy Path](./assets/qtaCalculateQuoteHappyPath_20210825.png) + +### Get Quote - Happy Path + +#### Description + +Process to obtain and deliver existing Quote details to Participant/s on request. + +#### Flow Diagram + +![Use Case - Example REPLACE ME](./assets/qtaGetQuoteHappyPath.png) + +### Calculate Quote - Invalid Quote Request + +#### Description + +Process that enables the system to invalidate quote requests by monitoring and responding to invalid Request Events, FSPs, or duplicate requests. + +#### Flow Diagram + +![Use Case - Calculate Quote - Invalid Quote Request](./assets/qtaCalculateQuoteInvalidQuoteRequest_20210825.png) + +### Calculate Quote - Invalid FSPs + +#### Description + +Process that enables the system to invalidate FSP quote requests where the FSP details mismatch the original Quote for either one or both Participants. + +#### Flow Diagram + +![Use Case - Calculate Quote - Invalid FSPs](./assets/qtaCalculateQuoteInvalidFSPs_20210825.png) + +### Calculate Quote - Invalid Scheme Rules Detected In Request + +#### Description + +Process to enable the system to invalidate quote requests where Scheme Rules are violated, by one or more Participants, for example where Quote Period Limit reached. + +#### Flow Diagram + +![Use Case - Calculate Quote - Invalid Scheme Rules detected in Request](./assets/qtaCalculateQuoteInvalidSchemeRulesRequest_20210825.png) + +### Calculate Quote - Invalid Scheme Rules Detected In Response + +#### Desciption + +Process to enable the system to invalidate quote reponses where Scheme Rules are violated by one or more Participants, for example, where invalid terms are detected. + +#### Flow Diagram + +![Use Case - Calculate Quote - Invalid Scheme Rules detected in response](./assets/qtaCalculateQuoteInvalidSchemeRulesResponse_20210825.png) + +## Canonical Quote Model + +The canonical model stores the following details of quotations in the Quotes & Agreements BC: + +- Quote ID +- Transaction ID +- Participants + - payerId + - payeeId +- Payer + - Participant + - participantId + - roleType (e.g. payer) + - Amount Requested (initial amount) + - Value (number) + - Currency (ISO currency code) + - Amount to send (including fees, etc.) + - Value (number) + - Currency (ISO currency code) +- Payee(s) (one or more - should all be added to the "Amount to send") + - '#' + - Participant + - participantId + - roleType (Identify why this "payee" is receiving this amount, i.e.: fee, recipient, etc.) + - reason + - Amount to receive + - value (number) + - currency (ISO currency code) +- Extensions + +## Concluding comments + +- No red flag issues have been observed in the overall BC and Reference Architecture design. +- We need to better understand/clarify the "GET" via "POST" pattern: + - Should a "GET" event be a simple Restful "GET", or does the system need to support the "GET" from duplicate posts? + - Are we required to serve "GET" requests that include FSP details at a later date? + + + + +[^1]: Common Interfaces: [Mojaloop Common Interface List](../../commonInterfaces.md) diff --git a/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_eventBasedReporting_Apr22-b.png b/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_eventBasedReporting_Apr22-b.png new file mode 100644 index 000000000..db2b6246a Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_eventBasedReporting_Apr22-b.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_functionalOverview_Apr22-b.png b/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_functionalOverview_Apr22-b.png new file mode 100644 index 000000000..723f9b87e Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_functionalOverview_Apr22-b.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_pullReporting_Apr22-b.png b/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_pullReporting_Apr22-b.png new file mode 100644 index 000000000..5223a2137 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_pullReporting_Apr22-b.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_pushReporting_Apr22-b.png b/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_pushReporting_Apr22-b.png new file mode 100644 index 000000000..13a7d81ae Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_pushReporting_Apr22-b.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_reportDashboardConsumption_Apr22-b.png b/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_reportDashboardConsumption_Apr22-b.png new file mode 100644 index 000000000..98d2ece29 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/reporting/assets/ML2RA_Rpts_reportDashboardConsumption_Apr22-b.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/reporting/index.md b/docs/technical/reference-architecture/boundedContexts/reporting/index.md new file mode 100644 index 000000000..d895c3a83 --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/reporting/index.md @@ -0,0 +1,101 @@ +# Reporting BC + +## Overview + +### Strategy & Rules + +The Reporting strategy for this Reference Architecture, is to describe the generic mechanisms by which client BCs' data can be persisted, and kept up to date, in a Reporting Data Store, so users and systems, can later consume this data directly from the Reporting Data Store, or through any Reporting and/or Dashboarding tools connected to the Reporting Data Store. + +- This Reporting Data Store must be write-only from the switch's perspective and read-only by external components. +- The data models on the Reporting Data Store can be different from the internal operational data models that the switch uses; where relevant, for performance or other reasons, multiple models of the same data can be made available in the Reporting Data Store - akin to multiple projections or views. +- A Client BC Reporting Component provided by the switch, will be translating internal events and internal data models to the external data store models - This component can be replaced or, there can even exist many of these for a single Client BC. +- Such component must exists in the Reporting BC for any Client BC's who's data is made available in the Reporting Data Store. +- Any direct data sending, or fetching, from the source Client BC, or its internal data stores, to the Reporting Data Store, constitutes a violation of the decoupling principle and will negatively affect the maintainability of the system by virtue of its tight coupling. + +### Reporting strategies: + +- Event based - Preferred way - On the Reporting BC sits a component (event handler) that is listening to relevant event from its correspondent BC and transforms those events into reporting data store entries - there can be many of these components per Client BC, however, each should be the only one responsible for writing a subset of the reporting data +- Push - The Client BC will call the correspondent Client BC Reporting Component API to send data, this API will be transforming the data and persisting it to the reporting store ([^1] with the source BC, ie, there should be a API per source BC) +- Pull - On the reporting BC sits a Client BC Reporting Component (timer based) that calls an API on the source BC to retrieve its data, that is then persistent to the reporting store ([^1] with the source BC) + +**For performance critical BC we should always try to use the event driven reporting strategy.** + +### Absolutely minimum rules to observe: + +- Only the Reporting Data Store can be used for reporting and dashboarding. External systems are forbidden direct access to Bounded Contexts' own data stores. Operational access for external systems will be available via the Operational or [Interop APIs](/refarch/boundedContexts/fspInteropApi/). +- Client BC's internal source data cannot be "passed" directly to the Reporting Data Store - There must be a translation between the source data structure and the reporting data structure, even if there are no structure changes. Objective is to not have a dependency on the source BC data structure on the reporting side. + +### To Do + +- Decide which initial reports and dashboards should be included as part of the base reporting functionality +- Chose a open source reporting and dashboarding tools to deliver this base functionality +- Compliance / Assurance Reporting - define some of these base reports (KYC, AML) +- Discuss “Process Monitoring (and SLA's)” and decide if this can be done on top of the reporting layer (the definition of the critical numbers, SLI’s & SLO’s, is done via platform configuration) +- Add link to the Operational API BC in the rules section above + +## Terms + +Terms with specific and commonly accepted meaning within the Bounded Context in which they are used. + +| Term | Description | +|---|---| +| **Client BC** | Source (or owner) Bounded Context of data being persisted in the Reporting Data Store| +| **Reporting Data Store** | External data store(s) (can be multiple) where reporting data produced by the Client BC Reporting Components is persisted and kept up to date| +| **Client BC Reporting Component** | This component, can take the form or a service, and will be responsible for the translation of the internal model to the external model(s) stored in the Reporting Data Store | +| **Reporting or dashboard Tool** | External tools that use data in the Reporting Data Store as source to produce reports, dashboards or any other reporting related task | + +## Functional Overview + +![Reporting Functional Overview diagram](./assets/ML2RA_Rpts_functionalOverview_Apr22-b.png) +> BC Function Diagram: Functional Overview + +## Use Cases + +### Event based Reporting (preferred way) + +#### Description + +Strategy to feed the Reporting Data Store by having Client BC Reporting Component listening to the internal events and persisting the related reporting data. + +#### Flow Diagram + +![Event Based Reporting use case diagram](./assets/ML2RA_Rpts_eventBasedReporting_Apr22-b.png) +> UC Workflow Diagram: Event Based Reporting (Preferred Way) + +### Pull based Reporting + +#### Description + +Strategy to feed the Reporting Data Store by having Client BC Reporting Component fetching data from the Client BC API. + +#### Flow Diagram + +![Pull Based Reporting use case diagram](./assets/ML2RA_Rpts_pullReporting_Apr22-b.png) +> UC Workflow Diagram: Pull Reporting + +### Push based Reporting + +#### Description + +Strategy to feed the Reporting Data Store by having the Client BC sending to the Client BC Reporting Component API the data to be reported, and the Client BC Reporting Component translating and persisting it. + +#### Flow Diagram + +![Push Based Reporting use case diagram](./assets/ML2RA_Rpts_pushReporting_Apr22-b.png) +> UC Workflow Diagram: Push Reporting + +### User Report and Dashboard Consumption + +#### Description + +Example of how a user can consume reports nd dashboards + +#### Flow Diagram + +![User Report and Dashboard Consumption diagram](./assets/ML2RA_Rpts_reportDashboardConsumption_Apr22-b.png) +> UC Workflow Diagram: User Reporting & Consumption Dashboard + + +## Notes + +[^1]: Common Interfaces: [Mojaloop Common Interface List](../../refarch/commonInterfaces.md) diff --git a/docs/technical/reference-architecture/boundedContexts/scheduling/assets/schedulingCreateReminder_20211021.png b/docs/technical/reference-architecture/boundedContexts/scheduling/assets/schedulingCreateReminder_20211021.png new file mode 100644 index 000000000..6db98ef15 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/scheduling/assets/schedulingCreateReminder_20211021.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/scheduling/assets/schedulingDeleteRecurringReminder_20211021.png b/docs/technical/reference-architecture/boundedContexts/scheduling/assets/schedulingDeleteRecurringReminder_20211021.png new file mode 100644 index 000000000..43a900f75 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/scheduling/assets/schedulingDeleteRecurringReminder_20211021.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/scheduling/assets/schedulingReminderTriggered_20211021.png b/docs/technical/reference-architecture/boundedContexts/scheduling/assets/schedulingReminderTriggered_20211021.png new file mode 100644 index 000000000..00de4e46d Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/scheduling/assets/schedulingReminderTriggered_20211021.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/scheduling/assets/useCaseExample.png b/docs/technical/reference-architecture/boundedContexts/scheduling/assets/useCaseExample.png new file mode 100644 index 000000000..fd9ae7373 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/scheduling/assets/useCaseExample.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/scheduling/index.md b/docs/technical/reference-architecture/boundedContexts/scheduling/index.md new file mode 100644 index 000000000..6b7ff1edb --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/scheduling/index.md @@ -0,0 +1,131 @@ +# Scheduling BC + +Multiple processes and events in BCs across the Mojaloop Switch platform require functionality to trigger at specific times, or in accordance with a schedule. In order to support this requirement across the Switch, and avoid building scheduling functionality into multiple BCs, a single Scheduling BC will be introduced and implemented for the Switch platform. + +In order to schedule a process or event, a Client BC submits a request to the Scheduling BC to create a reminder for a specific time or time schedule. The Scheduling BC maintains a schedule of all of the reminders that it receives, and, as the time for reminders is reached, it sends notification of the reminder to the appropriate Client BC. + +In addition, the Scheduling BC will also provide services to the Switch to enable Client BCs and Switch Admins to manage reminders that are set within the Scheduling BC. + +## Terms + +The following common term/s are in use in this BC: + +| Term | Description | +|---|---| +| **Client BC** | Any other BC making use of the Scheduling BC Services | + +## Use Cases + + +The status of the UCs for the Scheduling BC is as follows: + +| Available UCs | | | Planned UCs | | +| --- | :-- | --- | --- | :-- | +| **Use Case** | **Description** | | **Use Case** | **Description** | +| **Create Reminder** | Client BC requests a reminder to be created | | **Client Reminder Query** | Client BC queries its own reminders | +| **Delete Reminder** | Client BC requests a reminder to be deleted | | **Admin Reminder Query** | Platform Admin queries all reminders | +| **Reminder Trigger** | Scheduling BC executes reminder trigger when the time comes | | | +| **Update Reminder** | *Not provided. Recommended solution: delete and create a new Reminder* | | | | | + + +### Create Reminder + +#### Description +The workflow provided by this UC enables the Switch to handle authorised Client BC requests to create Reminders. + +#### Flow Diagram + +![Create Reminder](./assets/schedulingCreateReminder_20211021.png) +> +### Reminder Triggered + +#### Description +The workflow provided by this UC enables the Switch to handle reminders messaged from the Scheduling BC to a Client BC to execute a task, or as a reminder only. + +#### Flow Diagram + +![Reminder Triggered](./assets/schedulingReminderTriggered_20211021.png) +> +### Delete (Recurring) Reminder + +#### Description +The workflow provided by this UC enables the switch to handle messages from authorised Client BCs to the Scheduling BC to delete a Reminder. In the event that the Scheduling BC is unable to process the instruction, it sends an Alert message to the Notifications BC. + +#### Flow Diagram + +![Delete (Recurring) Reminder](./assets/schedulingDeleteRecurringReminder_20211021.png) +> + + +## Notes + +#### Create Reminder - Required data + +The Create Reminder request needs to include the following data: + +| Data | Description | +| --- | ---- | +| **Identifier** | name/id | +| **Cron Definition** | recurring?, time interval? | +| **Trigger Transport** | HTTP Callback/Event; Callback URL or Event Topic | +| **Special Payload** | opaque for the scheduling BC | +| **Recovery Conditions** | retry, reschedule, abort, abandon | +| **Alerts** | notification, logging on exceptions | +| **Actions** | register of automatable/schedulable BC processes | + +#### Scheduling BC - Requirements + +The Scheduling BC must meet the following requirements: + +* Reminders must be triggered once only + +* BC must keep track of triggered Reminders + +* BC must keep track of Create/Read/Delete actions + + * Updates will be facilitated through Delete/Create actions as noted in the [Use Case Available UCs](#use-cases) list + +* Job batches + +* Offer multiple interface options (gRPC, REST, HTTP, etc.) + +* Reminders should be triggered with an HTTP callback, not a gRPC call, or to a specific topic + +* It should have no ability to process logic external to the Scheduling BC itself + +* Make use of Linux-based UTC timestamps only in order to avoid synchronization issues + +***Note:*** *It is assumed that the underlying system will keep perfect time.* + +#### Scheduling BC - Outstanding requirements + +Access requirements for the Scheduling BC still require definition. + +#### Scheduling BC - Exceptions + +* Malformed instructions + * Invalid date/time, including times in the past + * Invalid BC or command +* Failed execution (identified through call-back) +* Insufficient authority for the Client BC to perform the CRD operation +* Failure to process/execute Reminder + +#### Questions + +A number of questions came up during the Reference Architecture Work Sessions and, as some were felt to have potential value from which others would benefit, we have included them below: + +* After the scheduled task has been initiated, does the Scheduling BC remain responsible for tracking its progress? + + * Answer: No. When the Reminder is due, it is communicated to the Client BC using the precribed method, and thereafter, the Scheduling BC responsibility for the reminder is passed back to the Client BC. + +* Is the Client BC or the person who scheduled a Reminder noted as the "User" by the Scheduling BC? IOW, whose ID is stamped on the process audit trail? + + * Answer: This should be determined by the Client BC, based on its action on receipt of the Reminder. \ No newline at end of file diff --git a/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucAuthModel_Apr22_1829.png b/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucAuthModel_Apr22_1829.png new file mode 100644 index 000000000..8c67da4bb Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucAuthModel_Apr22_1829.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucBcBootstrap-OncePerNewVer_Apr22_1829.png b/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucBcBootstrap-OncePerNewVer_Apr22_1829.png new file mode 100644 index 000000000..3bf4c83db Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucBcBootstrap-OncePerNewVer_Apr22_1829.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucBcStartup_Apr22_1829.png b/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucBcStartup_Apr22_1829.png new file mode 100644 index 000000000..f268daee4 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucBcStartup_Apr22_1829.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucExampleApiQueryCall_Apr22_1829.png b/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucExampleApiQueryCall_Apr22_1829.png new file mode 100644 index 000000000..b67ea6e1a Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucExampleApiQueryCall_Apr22_1829.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucRolePriviledgeAssoc_Apr22_1829.png b/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucRolePriviledgeAssoc_Apr22_1829.png new file mode 100644 index 000000000..798b8681b Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucRolePriviledgeAssoc_Apr22_1829.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucUserOpsLogin(AuthN)_Apr22_1829.png b/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucUserOpsLogin(AuthN)_Apr22_1829.png new file mode 100644 index 000000000..807c85f63 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/security/assets/ML2RA_SecAuth-ucUserOpsLogin(AuthN)_Apr22_1829.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/security/index.md b/docs/technical/reference-architecture/boundedContexts/security/index.md new file mode 100644 index 000000000..68642b23f --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/security/index.md @@ -0,0 +1,94 @@ +# Security BC + +## Overview + +The protocol is request and response based, and the used transport protocol is secure Hypertext Transfer Protocol Secure (HTTPS). All services use the HTTP POST and GET methods. Both the request and response bodies are encoded in JSON-formatted text. + +## Terms + +Terms with specific and commonly accepted meaning within the Security Bounded Context. + +| Module | Description | +|---|---| +| **Crypto providers** | Adapter that will provide cryptographic services and Key Management Services | +| **IAM** | Identity and Access Management. Adapter that will provide services for user management, menus, profiles, roles and permissions. | +| **AuthN** | Authentication module. Requires userid and password and returns a JWT token | +| **AuthZ** | Authorization module. Requires JWT and certificate (public key). Verifies JWT ROLES and signature | +| **JWT** | JSON Web Token. Returned after a successful user authentication. Contains user details, ROLES and signature. | +| **KMS** | Key Management System. Manages cryptographic keys lifecycle (definition, creation and retirement). It is part of the Cyrpto subsystem | + +## Use Cases + +### BC User / Operator login (AuthN) + +#### Description + +The login function requires that the user id and a secret key be passed in the http body. The response contains a signed JWT token. The signature is generated by the Crypto subsystem. The login is performed by the Authorization services or IAM. + +#### Flow Diagram + +![Use Case - BC User / Operator Login (AuthN)](./assets/ML2RA_SecAuth-ucUserOpsLogin(AuthN)_Apr22_1829.png) +> UC Workflow Diagram: BC User/Operator Login (AuthN) + +### BC Authorization Model (AuthZ) + +#### Description + +IAM will provide users / groups, roles and privileges associations. Each BC will also have a list of related roles. When an API function or microservice +is called, the JWT signature is verified using the public key and the role provided in the JWT is compared to the role associated with the BC. If the signature verification and the role are successfully verified, the API function or microservice is executed. + +#### Flow Diagram + +![Use Case - BC Authorization Model (AuthZ)](./assets/ML2RA_SecAuth-ucAuthModel_Apr22_1829.png) +> UC Workflow Diagram: BC Authorization Model (AuthZ) + +### BC Bootstrap + +#### Description + +At bootstrap, the BC will send the list of possible privileges. This is done once per deployement of a new version. + +#### Flow Diagram + +![Use Case - BC Bootstrap](./assets/ML2RA_SecAuth-ucBcBootstrap-OncePerNewVer_Apr22_1829.png) +> UC Workflow Diagram: BC Bootstrap + +### BC Startup + +#### Description + +At startup the BC will request authentication issuer public keys from Security BC Crypto / KMS subsystems and the list of roles / privileges Security BC IAM subsystem. A local crypto library signature verification function will verfiy the JWT signature and the roles in the JWT will be compared with the local list of roles obtained from the central authorization service. + +##### Flow Diagram + +![Use Case - BC Startup](./assets/ML2RA_SecAuth-ucBcStartup_Apr22_1829.png) +> UC Workflow Diagram: BC Startup + +### Role / Privilege association + +#### Description + +Roles are associated with a number of privileges. + +#### Flow Diagram + +![Use Case - BC Startup](./assets/ML2RA_SecAuth-ucRolePriviledgeAssoc_Apr22_1829.png) +> UC Workflow Diagram: Role / Priviledge Association + +### Example Query / call + +#### Description + +Client Authorization should be performed by using an access token. A client first needs to request the Authorization Service to create an access token for the user who requests to access the interface. The user is authenticated in the Authorization Service. The created access token is then used for authorization in the interface. +To use the access token, the client must set the Authorization HTTP header to Bearer [access_token] in each request to the interface. + +#### Flow Diagram + +![Use Case - Example API Query/Call](./assets/ML2RA_SecAuth-ucExampleApiQueryCall_Apr22_1829.png) +> UC Workflow Diagram: Example API Query/Call + + + \ No newline at end of file diff --git a/docs/technical/reference-architecture/boundedContexts/settlements/assets/ML2RA_SET-ucBootStrapSettleModViaConfig_Mar22-b.png b/docs/technical/reference-architecture/boundedContexts/settlements/assets/ML2RA_SET-ucBootStrapSettleModViaConfig_Mar22-b.png new file mode 100644 index 000000000..9b04df7c1 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/settlements/assets/ML2RA_SET-ucBootStrapSettleModViaConfig_Mar22-b.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/settlements/assets/ML2RA_SET-ucDeferNetSettle_Mar22-a-P1-2.png b/docs/technical/reference-architecture/boundedContexts/settlements/assets/ML2RA_SET-ucDeferNetSettle_Mar22-a-P1-2.png new file mode 100644 index 000000000..8c8b1977f Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/settlements/assets/ML2RA_SET-ucDeferNetSettle_Mar22-a-P1-2.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/settlements/assets/ML2RA_SET-ucInstantGrossSettle_Mar22-a.png b/docs/technical/reference-architecture/boundedContexts/settlements/assets/ML2RA_SET-ucInstantGrossSettle_Mar22-a.png new file mode 100644 index 000000000..911db5bfe Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/settlements/assets/ML2RA_SET-ucInstantGrossSettle_Mar22-a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/settlements/assets/settleAbortSettle_20210827.png b/docs/technical/reference-architecture/boundedContexts/settlements/assets/settleAbortSettle_20210827.png new file mode 100644 index 000000000..5016294ea Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/settlements/assets/settleAbortSettle_20210827.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/settlements/assets/settleCreateSettleAccountsNewPart_20210827.png b/docs/technical/reference-architecture/boundedContexts/settlements/assets/settleCreateSettleAccountsNewPart_20210827.png new file mode 100644 index 000000000..8c27bfe78 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/settlements/assets/settleCreateSettleAccountsNewPart_20210827.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/settlements/assets/settleCreateUpdateModel_20210827.png b/docs/technical/reference-architecture/boundedContexts/settlements/assets/settleCreateUpdateModel_20210827.png new file mode 100644 index 000000000..054b6a2f2 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/settlements/assets/settleCreateUpdateModel_20210827.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/settlements/assets/settleFunctionalOverview_20210826.png b/docs/technical/reference-architecture/boundedContexts/settlements/assets/settleFunctionalOverview_20210826.png new file mode 100644 index 000000000..153e4c753 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/settlements/assets/settleFunctionalOverview_20210826.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/settlements/index.md b/docs/technical/reference-architecture/boundedContexts/settlements/index.md new file mode 100644 index 000000000..c2e2462ca --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/settlements/index.md @@ -0,0 +1,87 @@ +# Settlements BC + +The Settlements BC is integral to settling Participant transfers using either Deferred Net Settlement or Immediate Gross Settlement methods. It is responsible for creating settlement windows, identifying and deploying the required settlement method (DNS/IGS), settling, closing, and updating batches, and recording all deposits and withdrawals to the appropriate ledger accounts in the Accounts and Balances BC. + +## Terms + +The following terms are used in this BC, also known as a domain. + +| Term | Description | +| -------- | ------------ | +| **DNS** | Deferred Net Settlement | +| **IGS/RTGS** | Immediate Gross Settlement/Real-Time Gross Settlement | +| **Operator** | Person or System issuing instructions/requests | +| **Participant** | FSP/PISP or FSP Customer | +| **Account** | Ledger Journal Account (Cr/Dr) | + +## Functional Overview + +![Use Case - Functional Overview](./assets/settleFunctionalOverview_20210826.png) +> + +## Use Cases + +### Deferred Net Settlement (DNS) + +#### Description +Method of deferring payments to enable settlement on multiple batches according a predetermined schedule. This is useful for environments involving multiple Participants to a transaction requiring a balance of payment due settlement approach. + +#### Flow Diagram + +![Use Case - Deferred Net Settlement (DNS)](./assets/ML2RA_SET-ucDeferNetSettle_Mar22-a-P1-2.png) +>UC Workflow Diagram: Deferred Net Settlement - 19/10/2021 + +### Immediate Gross Settlement (IGS) + +#### Description +Method to enable immediate settlement of batches. This is useful for SME environments where quick payment turnarounds are often desirable in order to maximize their liquidity. IGS is also known as Real-Time Gross Settlement (RTGS) + +#### Flow Diagram + +![Use Case - Immediate Gross Settlement (IGS)](./assets/ML2RA_SET-ucInstantGrossSettle_Mar22-a.png) +>UC Workflow Diagram: Immediate Gross Settlement + +### Abort Settlement + +#### Description +Method that enables the Settlement BC to abort a settlement as required, reversing Participant settlement accounts, updating the settlement status for settlement windows, and updating the settlement state. + +#### Flow Diagram + +![Use Case - Abort Settlement](./assets/settleAbortSettle_20210827.png) +> + +### Create/Update the Settlement Model (DNS/IGS) + +#### Description +Method that enables the Settlement BC to create or update the settlement method for a settlement batch based on the Participant Account Type. Useful in instances where mixed Settlement Methods are required. + +#### Flow Diagram + +![Use Case - Create/Update the Settlement Model (DNS/IGS)](./assets/settleCreateUpdateModel_20210827.png) +> + +### Bootstrap (Startup) Settlement Model via Configuration + +#### Description +Method that configures the Settlement Method (DNS/IGS) based upon the system startup configuration. Useful in instances where all Settlement Models are the same, such as all DNS, or all IGS. + +#### Flow Diagram + +![Use Case - Bootstrap (Startup) Settlement Model via Configuration](./assets/ML2RA_SET-ucBootStrapSettleModViaConfig_Mar22-b.png) +>UC Workflow Diagram: Bootstrap (Startup) Settlement Model via Configuration + +### Create Settlement related accounts for newly created Particpants + +#### Description +The system creates settlement accounts for new Participants to enable fund transfers to managed by the Switch. This enables the Switch to exercise end-to-end management of all transfers irrespective of settlement method. + +#### Flow Diagram + +![Use Case - Create Settlement related accounts for newly created Particpants](./assets/settleCreateSettleAccountsNewPart_20210827.png) +> + + + + +[^1]: Common Interfaces: [Mojaloop Common Interface List](../../commonInterfaces.md) diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucCredentialRegError_Mar22-a_P1&2.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucCredentialRegError_Mar22-a_P1&2.png new file mode 100644 index 000000000..94ef957ff Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucCredentialRegError_Mar22-a_P1&2.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucDfspRejectsOtpAuthTokenFromPisp_Mar22-a_P1&2.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucDfspRejectsOtpAuthTokenFromPisp_Mar22-a_P1&2.png new file mode 100644 index 000000000..f45af2d12 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucDfspRejectsOtpAuthTokenFromPisp_Mar22-a_P1&2.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucLinkAccnts-AccntDiscoveryFail_Mar22-a.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucLinkAccnts-AccntDiscoveryFail_Mar22-a.png new file mode 100644 index 000000000..f40d264f8 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucLinkAccnts-AccntDiscoveryFail_Mar22-a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucLinkAccnts-DfspRejectConsentReq_Mar22-a.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucLinkAccnts-DfspRejectConsentReq_Mar22-a.png new file mode 100644 index 000000000..6aa565e7d Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucLinkAccnts-DfspRejectConsentReq_Mar22-a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucPispGetDfspAccList&Id_Feb22-a.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucPispGetDfspAccList&Id_Feb22-a.png new file mode 100644 index 000000000..5e3b6a184 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucPispGetDfspAccList&Id_Feb22-a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucUnlinkAccnts-ConsentNotFound_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucUnlinkAccnts-ConsentNotFound_Mar22a.png new file mode 100644 index 000000000..90da29fc6 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucUnlinkAccnts-ConsentNotFound_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucUnlinkAccntsDownstrmFail_Mar22-a_P1&2.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucUnlinkAccntsDownstrmFail_Mar22-a_P1&2.png new file mode 100644 index 000000000..dad5d2724 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL-ucUnlinkAccntsDownstrmFail_Mar22-a_P1&2.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL_ucDfspIssueConsent_Feb22a_P1&2.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL_ucDfspIssueConsent_Feb22a_P1&2.png new file mode 100644 index 000000000..1cd3f6cfa Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL_ucDfspIssueConsent_Feb22a_P1&2.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL_ucPispConsentRequest_Feb22a.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL_ucPispConsentRequest_Feb22a.png new file mode 100644 index 000000000..841a8b8c7 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL_ucPispConsentRequest_Feb22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL_ucPispGetSupportedDFSPs_Feb22a.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL_ucPispGetSupportedDFSPs_Feb22a.png new file mode 100644 index 000000000..de4844fc8 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL_ucPispGetSupportedDFSPs_Feb22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL_ucUnlinkAccounts-HubHostAuth_Feb22-a_P1&2.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL_ucUnlinkAccounts-HubHostAuth_Feb22-a_P1&2.png new file mode 100644 index 000000000..7ab02a922 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaL_ucUnlinkAccounts-HubHostAuth_Feb22-a_P1&2.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucPayToPisp-PispAsPayee_Mar22-b_P1-2.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucPayToPisp-PispAsPayee_Mar22-b_P1-2.png new file mode 100644 index 000000000..fcb9eb8ca Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucPayToPisp-PispAsPayee_Mar22-b_P1-2.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucPispBulkTransactReq_Mar22-a_P1-4.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucPispBulkTransactReq_Mar22-a_P1-4.png new file mode 100644 index 000000000..fc5c3934c Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucPispBulkTransactReq_Mar22-a_P1-4.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucThirdPartyInitTransactReq_Mar22-a_P1P2P3bP4.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucThirdPartyInitTransactReq_Mar22-a_P1P2P3bP4.png new file mode 100644 index 000000000..48601bc8c Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucThirdPartyInitTransactReq_Mar22-a_P1P2P3bP4.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-AuthInvalid_Mar22-a-P1-3.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-AuthInvalid_Mar22-a-P1-3.png new file mode 100644 index 000000000..c426cf207 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-AuthInvalid_Mar22-a-P1-3.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-BadPartyLookup_Mar22-b.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-BadPartyLookup_Mar22-b.png new file mode 100644 index 000000000..4900cf6d5 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-BadPartyLookup_Mar22-b.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-BadTransactReq_Mar22-b.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-BadTransactReq_Mar22-b.png new file mode 100644 index 000000000..817f487b9 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-BadTransactReq_Mar22-b.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-DownStreamFspiopFail_Mar22-b-P1-2.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-DownStreamFspiopFail_Mar22-b-P1-2.png new file mode 100644 index 000000000..8d26fbfad Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-DownStreamFspiopFail_Mar22-b-P1-2.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-dfspTimeout_Mar22-a-P1-3.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-dfspTimeout_Mar22-a-P1-3.png new file mode 100644 index 000000000..5890e84aa Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-dfspTimeout_Mar22-a-P1-3.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-rejectedByUser_Mar22-a-P1-3.png b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-rejectedByUser_Mar22-a-P1-3.png new file mode 100644 index 000000000..de4c47de3 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/assets/ML2RA_3PaT-ucTransactReqFail-rejectedByUser_Mar22-a-P1-3.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/index.md b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/index.md new file mode 100644 index 000000000..b2c5c062d --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/thirdPartyApi/index.md @@ -0,0 +1,261 @@ +# Third Party API BC + +The Third Party API BC has been implemented with the Mojaloop 2.0 Reference Architecture to enable third-party PISP Operators (typically applications) to interact with the platform. Please note that unless otherwise stipulated, all BC references pertain to the various Mojaloop components or Bounded Contexts (BCs). + +## Terms + +The following common terms are used in this BC: + +| Term | Description | +| ---- | ------------ | +| **PISP** | Payment Initiation Service Provider (e.g. PayPal, ApplePay, GooglePay, etc.) | +| **DFSP** | Digital Financial Service Provider (e.g. Bank, Mobile Money Operator) | +| **User** | DFSP/PISP client (as indicated) | + +## Use Cases + +**Note:** Our Use Cases cover two specific scenarios: + +| Scenarios | Description | +| --------- | ----------- | +| [Linking](#linking-scenarios) | PISP Housekeeping activities | +| [Transfer](#transfer-scenarios) | PISP Transfer initiation activities | + +## Linking Scenarios + +### PISP Gets supported DFSPs + +#### Description + +The workflow provided by this UC enables the Switch to handle authorized PISP User requests to obtain a list of DFSP Account Holders supported by the system. + +#### Flow Diagram + +![Use Case - PISP Gets supported DFSPs](./assets/ML2RA_3PaL_ucPispGetSupportedDFSPs_Feb22a.png) +>UC Workflow Diagram: PISP Gets supported DFSPs + +### PISP Gets list of accounts for a DFSP + Identifier + +#### Description + +The workflow provided by this UC enables the Switch to handle instances where authorized PISP Users wish to lookup their DFSP Account Holder account details using their DFSP Account Holder Identifier to do so. Typically the Identifier is embedded into a PISP-originated app or process. + +#### Flow Diagram + +![Use Case - PISP Gets list of accounts for a DFSP + Identifier](./assets/ML2RA_3PaL-ucPispGetDfspAccList&Id_Feb22-a.png) +>UC Workflow Diagram: PISP Gets list of accounts for a DFSP + Identifier + +### PISP Consent Request + +#### Description + +The workflow provided by this UC enables the Switch to handle instances where an authorised PISP User notifies their DFSP Account Holder of their intention to link one or more of their accounts to a PISP via a Consent Request. The request is fulfilled via an out-of-band [Issue Consent](#dfsp-issue-consent) process upon receipt of an authorization confirmation request response. The result of this process is the establishment of a trust relationship between the PISP User, the PISP, and the DFSP Account Holder. The Switch updates participant account details accordingly. + +#### Flow Diagram + +![Use Case - PISP Consent Request](./assets/ML2RA_3PaL_ucPispConsentRequest_Feb22a.png) +>UC Workflow Diagram: PISP Consent Request + +### DFSP Issue Consent + +#### Description + +The workflow provided by this UC enables the Switch to handle instances in which a DFSP Account Holder responds to a Consent Request received from an authorised and authenticated PISP User. The DFSP Account Holder issues a request to the PISP via the Switch for the PISP User to create an identifying Credential on their device. Upon receipt of the identifying Credential, verified by the issuing DFSP Account Holder, both the Switch and the DFSP Account Holder Account records are updated with the PISP User Credential and linked Accounts, and the PISP User is notified that their DFSP Account Holder Account/s has/have been successfully linked to their PISP profile. + +***Note:*** *The Consent Issue is in response to a Consent Request made by an authorised PISP User to link one or more of their DFSP Account Holder Accounts to their PISP profile and follows the workflow noted in the [PISP Consent Request](#pisp-consent-request) UC above* + +#### Flow Diagram + +![Use Case - DFSP Issue Consent](./assets/ML2RA_3PaL_ucDfspIssueConsent_Feb22a_P1&2.png) +>UC Worflow Diagram - DFSP Issue Consent + +### Unlink Accounts: Hub Hosted Auth + +#### Description + +The workflow provided by this UC enables the Switch to handle an authorised PISP/DFSP Account Holder request to revoke consent for a DFSP Account Holder Account to be linked to their PISP Profile, which the Switch acts upon by updating the system Account Lookup Service to disassociate the PISP Participant/DFSP Account association, and notifying both the DFSP Account Holder (who removes the ALS Participant entry and Link from their system), and the PISP Host who sends a fulfilment notification to the User. + +#### Flow Diagram + +![Use Case - Unlink Accounts - Hub Hosted Auth](./assets/ML2RA_3PaL_ucUnlinkAccounts-HubHostAuth_Feb22-a_P1&2.png) +>UC Workflow Diagram: Unlink Accounts - Hub Hosted Auth + +### Link Accounts - Account Discovery Failure + +#### Description + +The workflow provided by this UC enables the Switch to handle instances in which an authorised PISP User initiates a request to link a DFSP Account to their PISP Profile using an invalid DFSP/Identifier pair not recognized by the DFSP. The DFSP messages the Switch with an error, which notifies the appropriate PISP, and the User receives a message to try another DFSP/Indentifier pair. + +#### Flow Diagram + +![Use Case - Link Accounts - Account Discovery Failure](./assets/ML2RA_3PaL-ucLinkAccnts-AccntDiscoveryFail_Mar22-a.png) +>UC Workflow Diagram: Link Accounts - Account Discovery Failure + +### Link Accounts - DFSP Rejects Consent Request + +#### Description + +The workflow provided by this UC enables the Switch to correctly handle instances where an authorized PISP User requests one or more accounts to be linked to their PISP Profile by the DFSP Account Holder. Where the DFSP Account Holder denies consent for the linking to go ahead for whatever reason, e.g.: a selected account does not support linking, it will message the Switch with an error condition. The Switch notifies the appropriate PISP, and the PISP User receives a message, in-app or otherwise, to retry their request as the previous account linking request failed. + +#### Flow Diagram + +![Use Case - Link Accounts - DFSP Rejects Consent Request](./assets/ML2RA_3PaL-ucLinkAccnts-DfspRejectConsentReq_Mar22-a.png) +>UC Workflow Diagram: Link Accounts - DFSP Rejects Consent Request + +### Credential Registration Error + +#### Description + +The workflow provided by this UC enables the Switch to handle instances where a DFSP Account Holder provides a PISP with a request for a (PISP) User to create a device-embedded credential in order to confirm a Consent Request, and where the credential, which when sent to the DFSP includes either an invalid signed challenge or signed metadata that is rejected. In this instance the DFSP messages the error condition to the Switch, which messages the appropriate PISP who notifies the (PISP) User that the Consent credential was rejected. + +#### Flow Diagram + +![Use Case - Credential Registration Error](./assets/ML2RA_3PaL-ucCredentialRegError_Mar22-a_P1&2.png) +>UC Workflow Diagram: Credential Registration Error + +### Unlink Accounts - Consent not found + +#### Description + +The workflow provided by this UC enables the Switch to handle instances where an authorized PISP User is asked to confirm a consent request issued via either the PISP or DFSP Account Holder to unlink their DFSP Account from their PISP Profile. The Switch refers the consent request response to the Consent Oracle for confirmation of the Consent Owner ID. In instances where the Oracle is unable to confirm the ID of the Consent Owner, the request is failed. The PISP User is alerted via the DFSP Account Holder or PISP profile holder, that the DFSP Account that they sought to unlink from their PISP profile was not found. + +#### Flow Diagram + +![Use Case - Unlink Accounts - Consent not found](./assets/ML2RA_3PaL-ucUnlinkAccnts-ConsentNotFound_Mar22a.png) +>UC Workflow Diagram: Unlink Accounts - Consent Not Found + +### DSPF Rejects OTP/Auth Token from PISP + +#### Description + +The workflow provided by this UC enables the Switch to handle instances where an authorised PISP User requests one or more of their DFSP Account Holder Accounts to be linked to their PISP Profile. The request is directed by the Switch to the DFSP Account Holder who issues an OTP/Web Login Flow to the PISP User for verification purposes which is returned via the PISP to the Switch, and then to the DFSP Account Holder for consent. In instances where the response token is altered or expired, the DFSP Account Holder issues a error condition message to the Switch and the PISP User is notified that the DFSP Account linking request failed. + +#### Flow Diagram + +![Use Case - DFSP Rejects OTP/Auth Token from PISP](./assets/ML2RA_3PaL-ucDfspRejectsOtpAuthTokenFromPisp_Mar22-a_P1&2.png) +>UC Workflow Diagram: DFSP Rejects OTP/Auth Token from PISP + +### Unlink Accounts - Downstream Failure + +#### Description + +The workflow provided by this UC enables the Switch to handle instances in which an authorised PISP User's DFSP Account unlink consent confirmation fails the Switch's Authentication/Authorisation process for whatever reason, example: a downstream FSPIOP API error. The error is messaged by the Switch to the DFSP Account Holder who will review the error and determine how to respond. Where an error has occured, the PISP User is notified by the Switch via the PISP that their request to unlink their DFSP Account failed. + +#### Flow Diagram + +![Use Case - Unlink Accounts - Downstream Failure](./assets/ML2RA_3PaL-ucUnlinkAccntsDownstrmFail_Mar22-a_P1&2.png) +>UC Workflow Diagram: Unlink Accounts - Downstream Failure + +## Transfer Scenarios + +***Note:*** *In the interests of compacting this workflow description, the reader should note that the Third Party API and the 3rd-Party Initiated Payments BCs work in concert to maintain Participant Information. The interaction between the two BCs will not be specifically noted, but is as follows: where the Third Party API BC updates the Transaction state, and where the Participant Information is not cached, the 3rd-Party Initiated Payments BC will request the missing Participant Information from the Participant Lifecycle Management BC and deliver it to the Third Party API BC for inclusion in the Transaction information being presented to the DFSP/PISP systems.* + +### Third Party Initiated Transaction Request + +#### Description + +The workflow provided by this UC enables the Switch to permit authorized PISP Users/Apps to issue a request to a DFSP to execute a transaction on behalf of an Account Holder, typically the PISP User/App, in favor of a third-party recipient or recipients. The transaction is vetted via a DFSP confirmation request to the Account Holder, and concluded upon successful receipt of confirmation. The Switch, per DFSP instructions, manages the transaction and updates all accounts accordingly. + +Some suggested applications of Third Party Payment Initiation UC include: + + - Peer to Peer Payments (e.g.: GPay in India) + - Online checkouts for seamless end-user user experience (UX) (e.g.: PayPal) + - Payroll Clearing Software + +#### Flow Diagram + +![Use Case - Third Party Initiated Transaction Request](./assets/ML2RA_3PaT-ucThirdPartyInitTransactReq_Mar22-a_P1P2P3bP4.png) +>UC Workflow Diagram: Third Party Initiated Transaction Request + +### PISP Bulk Transaction Request + +#### Description + +The workflow provided by this UC enables the Switch to permit authorized PISP Users/Apps to issue a request to a DFSP to execute a number of bulk transactions on behalf of an Account Holder, typically the PISP User/App, in favor of a group of third-party recipients. The transaction is vetted via a DFSP confirmation request sent to the Account Holder, and concluded upon successful receipt of confirmation. The Switch, per DFSP instructions, manages the transaction and updates all accounts accordingly. + +#### Flow Diagram + +![Use Case - Example REPLACE ME](./assets/ML2RA_3PaT-ucThirdPartyInitTransactReq_Mar22-a_P1P2P3bP4.png) +>UC Workflow Diagram: PISP Bulk Transaction Request + +### Pay To A PISP - PISP As A Payee + +#### Description + +The workflow provided by this UC enables the Switch to permit authorized DFSP Users to initiate and execute payments in favor of PISPs as Payees via the Switch. The workflow provides support for payments for both single or multiple PISP Payee/s. + +#### Flow Diagram + +![Use Case - Pay to a PISP - PISP as a Payee](./assets/ML2RA_3PaT-ucPayToPisp-PispAsPayee_Mar22-b_P1-2.png) +>UC Workflow Diagram: Pay To A PISP - PISP As Payee + +### Third Party Transaction Request Failed - Bad Party Lookup + +#### Description + +The workflow provided by this UC enables the Switch to handle instances where an authorised PISP User initiates a transaction using an invalid Participant Identifier. The Switch encounters the error during the Get Parties stage of the transaction preparation, and automatically terminates the request with notification sent to the request originating User indicating the failure and the reason. + +#### Flow Diagram + +![Use Case - Example REPLACE ME](./assets/ML2RA_3PaT-ucTransactReqFail-BadPartyLookup_Mar22-b.png) +>UC Workflow Diagram: Third Party Transaction Request Failed - Bad Party Lookup + +### Third Party Transaction Request Failed - Bad Transaction Request + +#### Description + +The workflow provided by this UC enables the Switch to handle instances where an authorised PISP User initiates a Third Party Transaction Request, correctly confirms the Payee details, but the Payee DFSP fails to locate a valid Agreement for the transaction. The Switch rejects the request and sends notification to the request originating User indicating the failure and suggested follow-up actions. + +#### Flow Diagram + +![Use Case - Third Party Transaction Request Failed - Bad Transaction Request](./assets/ML2RA_3PaT-ucTransactReqFail-BadTransactReq_Mar22-b.png) +>UC Workflow Diagram: Third Party Transaction Request Failed - Bad Transaction Request + +### Third Party Transaction Request Failed - Downstream FSPIOP Failure + +#### Description +The workflow provided by this UC enables the Switch to handle instances where an authorized PISP User requests and confirms a transaction request, which when forwarded to the DFSP Account Holder fails for some reason during the quote process. The Switch is alerted to the failure, and provides a notification to the PISP User via their PISP App/Process. + +#### Flow Diagram + +![Use Case - Third Party Transaction Request Failed - downstream FSPIOP failure](./assets/ML2RA_3PaT-ucTransactReqFail-DownStreamFspiopFail_Mar22-b-P1-2.png) +>UC Workflow Diagram: Third Party Transaction Request Failed - Downstream FSPIOP Failure + +### Third Party Transaction Request Failed - Authorization Was Invalid + +#### Description + +The workflow provided by this UC enables the Switch to handle instances where a third-party transaction journey is initiated, then authorised by a PISP User on request from the DFSP Account Holder, and the Switch detects that the DFSP Challenge response received contained an invalid signature. The Switch can then verify that the error has occurred and notify the DFSP Account Holder who in turn cancels the transaction and the notifies the PISP User via the Switch and their PISP profile holder. + +#### Flow Diagram + +![Use Case - Third Party Transaction Request Failed - authorization was invalid](./assets/ML2RA_3PaT-ucTransactReqFail-AuthInvalid_Mar22-a-P1-3.png) +>UC Workflow Diagram: Third Party Transaction Request Failed - Authorization Was Invalid + +### Third Party Transaction Request Rejected by user + +#### Description + +The workflow provided by this UC enables the Switch to handle instances where a PISP User initiates and confirms a transaction via their PISP, but then declines to complete it upon receipt of the DFSP Account Holder quotation acceptance and signature challenge. Once the transaction is declined, the PISP notifies the DFSP Account Holder via the Switch, who proceeds to cancel the transaction and send a transaction cancellation confirmation notification to the originating PISP. + +#### Flow Diagram + +![Use Case - Third Party Transaction Request Rejected by user](./assets/ML2RA_3PaT-ucTransactReqFail-rejectedByUser_Mar22-a-P1-3.png) +>UC Workflow Diagram: Third Party Transaction Request Rejected By User + +### Third Party Transaction Request Failed - DFSP timeout + +#### Description + +The workflow provided by this UC enables the Switch to handle instances where a PISP User initiates and confirms a transaction via their PISP, but then fails to respond to the DFSP Account Holder quotation acceptance and signature challenge within a predetermined timeout period. Once the timeout is exceeded, the PISP notifies the DFSP Account Holder via the Switch that the required response was not received, and the DFSP cancels the transaction, sending a notification to the PISP User advising them that their transaction request failed. + +#### Flow Diagram + +![Use Case - Third Party Transaction Request Failed - DFSP timeout](./assets/ML2RA_3PaT-ucTransactReqFail-dfspTimeout_Mar22-a-P1-3.png) +>UC Workflow Diagram: Third Party Transaction Request Failed - DFSP Timeout + + + \ No newline at end of file diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPayerFspInsufficientLiquid_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPayerFspInsufficientLiquid_Mar22a.png new file mode 100644 index 000000000..363b750a4 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPayerFspInsufficientLiquid_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfBulk_2022-03-22-a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfBulk_2022-03-22-a.png new file mode 100644 index 000000000..4a8c4de05 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfBulk_2022-03-22-a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfDuplicPostIgnor_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfDuplicPostIgnor_Mar22a.png new file mode 100644 index 000000000..ec6365184 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfDuplicPostIgnor_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfDuplicPostResend_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfDuplicPostResend_Mar22a.png new file mode 100644 index 000000000..1487e20c6 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfDuplicPostResend_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfPayeeConfirm_Mar22a-P1-2.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfPayeeConfirm_Mar22a-P1-2.png new file mode 100644 index 000000000..8f9d61adb Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfPayeeConfirm_Mar22a-P1-2.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfPayeeFspReject_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfPayeeFspReject_Mar22a.png new file mode 100644 index 000000000..a85064494 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfPayeeFspReject_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfTimeoutDuplicPostNoMatch_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfTimeoutDuplicPostNoMatch_Mar22a.png new file mode 100644 index 000000000..10256bae5 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfTimeoutDuplicPostNoMatch_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfTimeoutPostCommit_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfTimeoutPostCommit_Mar22a.png new file mode 100644 index 000000000..1a9ffefbb Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfTimeoutPostCommit_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfTimeoutPreCommit_Mar22b-P1-2.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfTimeoutPreCommit_Mar22b-P1-2.png new file mode 100644 index 000000000..2f11f3088 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfTimeoutPreCommit_Mar22b-P1-2.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfTimeoutPrepare_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfTimeoutPrepare_Mar22a.png new file mode 100644 index 000000000..7d17ba4cf Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfTimeoutPrepare_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfUniMode_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfUniMode_Mar22a.png new file mode 100644 index 000000000..a8e55e640 Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucPerformTrfUniMode_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucQueryTrfGET_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucQueryTrfGET_Mar22a.png new file mode 100644 index 000000000..0bfbd6a1f Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucQueryTrfGET_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucTransferPrepReject_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucTransferPrepReject_Mar22a.png new file mode 100644 index 000000000..88d4cc4ce Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucTransferPrepReject_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucTransferPrepValidationFail-InvalidPayee_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucTransferPrepValidationFail-InvalidPayee_Mar22a.png new file mode 100644 index 000000000..9ff7d8fda Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucTransferPrepValidationFail-InvalidPayee_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucTransferPrepValidationFail-InvalidPayer_Mar22a.png b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucTransferPrepValidationFail-InvalidPayer_Mar22a.png new file mode 100644 index 000000000..4239eb31e Binary files /dev/null and b/docs/technical/reference-architecture/boundedContexts/transfers/assets/ML2RA_Trf_ucTransferPrepValidationFail-InvalidPayer_Mar22a.png differ diff --git a/docs/technical/reference-architecture/boundedContexts/transfers/index.md b/docs/technical/reference-architecture/boundedContexts/transfers/index.md new file mode 100644 index 000000000..cb839102a --- /dev/null +++ b/docs/technical/reference-architecture/boundedContexts/transfers/index.md @@ -0,0 +1,261 @@ +# Transfers BC + +The Transfers BC is responsible for orchestrating transfer requests. It works in concert with a number of other BCs, notably Settlements, Scheduling, Participant Lifecycle Management, Accounts & Balances, and the FSPIOP. + +## Terms + +The following terms are used in this BC, also known as a domain. + +| Term | Description | +|---|---| +| **Accounts** | Refers to accounts used in all transfer activities. They are used to record credit and debit positions, either temporarily in the case of accounts allocated for transfer purposes, or permanently in the case of final transfer updates to participant accounts. | +| **Participant/Actor** | Typically refers to DFSP Payer/Payee parties using Mojaloop. | +| **IGS** | Transfer settle method - Immediate Gross Settlement. This process is typically used in high volume environments such as retail, and is used by individual and shared accounts. In shared account environments, the system is capable of updating Participants balances by updating the proportional value of each Participants holds of the total funds available in the account | +| **DNS** | Transfer settlement method - Deferred Net Settlement. This process is frequently used in enviroments where a party of Participants engage in a single Transfer requiring settlement to all Participants. A typical example might include a scenario where raw materials are sold by Participant A to Participant B to manufacture into a finished product, which is then sold by Participant B back to Participant A. The switch calculates the proportional value that each Participant to the transaction is due, and settles this amount when the Settlement Window closes. | + +## Functional Overview - Transfers - Bulk + +![Functional Overview - Transfers - Bulk](./assets/ML2RA_Trf_ucPerformTrfBulk_2022-03-22-a.png) +>UC Workflow Diagram: Functional Overview - Transfers - Bulk + +## Use Cases + +### Perform Transfer (universal mode) + +#### Description + +The workflow provided by this UC enables the BC to effect a Transfer using a method that excludes Actor intervention. + +#### Flow Diagram + +![Perform Transfer (Universal Mode)](./assets/ML2RA_Trf_ucPerformTrfUniMode_Mar22a.png) +>UC Workflow Diagram: Perform Transfer (Universal Mode) + +### Perform Transfer with Payee Confirmation + +#### Description + +The workflow provided by this UC enables the BC to effect a Transfer using a method that includes Actor intervention. + +#### Flow Diagram + +![Use Case - Perform Transfer with Payee Confirmation](./assets/ML2RA_Trf_ucPerformTrfPayeeConfirm_Mar22a-P1-2.png) +>UC Workflow Diagram: Perform Transfer With Payee Confirmation + +### Query (GET) Transfer + +#### Description + +The workflow provided by this UC enables the BC to effect a method by which a Participant status report Query can be completed. + +#### Flow Diagram + +![Use Case - Query (GET) Transfer](./assets/ML2RA_Trf_ucQueryTrfGET_Mar22a.png) +>UC Flow Diagram: Query (GET) Transfer + +### Perform Transfer - Duplicate POST (Resend) + +#### Description + +The workflow provided by this UC enables the BC to effect a method by which a Duplicate Transfer request is completed. + +#### Flow Diagram + +![Use Case - Perform Transfer - Duplicate POST (Resend)](./assets/ML2RA_Trf_ucPerformTrfDuplicPostResend_Mar22a.png) +>UC Workflow Diagram: Perform Transfer - Duplicate POST (Resend) + +### Perform Transfer - Duplicate POST (Ignore) + +#### Description + +The workflow provided by this UC enables the BC to effect a method through which to ignore a Duplicate Transfer request. + +#### Flow Diagram + +![Use Case - Perform Transfer - Duplicate POST (Ignore)](./assets/ML2RA_Trf_ucPerformTrfDuplicPostIgnor_Mar22a.png) +>UC Workflow Diagram: Perform Transfer - Duplicate POST (Ignore) + +## Non-Happy Path Use Case Variations + +### Perform Transfer - PayeeFSP Rejects Transfer + +#### Description + +The workflow provided by this UC enables the BC to effect a method through which a Transfer request rejected by the Payee is terminated. + +#### Flow Diagram + +![Use Case - Perform Transfer - PayeeFSP Rejects Transfer](./assets/ML2RA_Trf_ucPerformTrfPayeeFspReject_Mar22a.png) +>UC Workflow Diagram: Perform Transfer - PayeeFSP Rejects Transfer + +### Perform Transfer - Timeout (Prepare) + +#### Description + +The workflow provided by this UC enables the BC to effect a method to terminate a Transfer Prepare request where a timeout threshold is exceeded. + +#### Flow Diagram + +![Use Case - Perform Transfer - Timeout (Prepare)](./assets/ML2RA_Trf_ucPerformTrfTimeoutPrepare_Mar22a.png) +>UC Workflow Diagram: Perform Transfer - Timeout (Prepare) + +### Perform Transfer - Timeout (Pre-Committed) + +#### Description + +The workflow provided by this UC enables the BC to effect a method through which to terminate a Pre-Committed Transfer request where a timeout threshold is exceeded. + +#### Flow Diagram + +![Use Case - Perform Transfer - Timeout (Pre-Committed)](./assets/ML2RA_Trf_ucPerformTrfTimeoutPreCommit_Mar22b-P1-2.png) +>UC Workflow Diagram: Perform Transfer - Timeout (Pre-Committed) + +### Perform Transfer - Timeout (Post-Committed) + +#### Description + +The workflow provided by this UC enables the BC to effect a method through which to terminate a Post-Committed Transfer request where a timeout is exceeded. + +#### Flow Diagram + +![Use Case - Perform Transfer - Timeout (Post-Committed)](./assets/ML2RA_Trf_ucPerformTrfTimeoutPostCommit_Mar22a.png) +>UC Workflow Diagram: Perform Transfer - Timeout (Post-Committed) + +### Perform Transfer - Duplicate POST (None Matching) + +#### Description + +The workflow provided by this UC enables the BC to effect a method through which to terminate a Non-Matching Duplicate Transfer request where a timeout is exceeded. + +#### Flow Diagram + +![Use Case - Perform Transfer - Duplicate POST (None Matching)](./assets/ML2RA_Trf_ucPerformTrfTimeoutDuplicPostNoMatch_Mar22a.png) +>UC Workflow Diagram: Perform Transfer - Duplicate POST (None Matching) + +### Perform Transfer - Payer FSP Insufficient Liquidity + +#### Description + +The workflow provided by this UC enables the BC to effect a method through which to terminate a Transfer request that is failed due to the Payer having insufficient liquidity to cover the transaction fully. + +#### Flow Diagram + +![Use Case - Perform Transfer - Payer FSP Insufficient Liquidity](./assets/ML2RA_Trf_ucPayerFspInsufficientLiquid_Mar22a.png) +>UC Workflow Diagram: Perform Transfer - Payer FSP Insufficient Liquidity + +### Perform Transfer - Transfer Prepare Validation Failure (Invalid Payer Participant) + +#### Description + +The workflow provided by this UC enables the BC to effect a method through which to terminate a Transfer Prepare request where the transaction validation is failed due to an invalid/non-existent Payer. + +#### Flow Diagram + +![Use Case - Perform Transfer - Transfer Prepare Validation Failure (Invalid Payer Participant)](./assets/ML2RA_Trf_ucTransferPrepValidationFail-InvalidPayer_Mar22a.png) +>UC Workflow Diagram: Perform Transfer - Transfer Prepare Validation Failure (Invalid Payer Participant) + +### Perform Transfer - Transfer Prepare Validation Failure (Invalid Payee Participant) + +#### Description + +The workflow provided by this UC enables the BC to effect a method through which to terminate a Transfer Prepare request where the transaction validation is failed due to an invalid/non-existent Payee. + +#### Flow Diagram + +![Use Case - Perform Transfer - Transfer Prepare Validation Failure (Invalid Payee Participant)](./assets/ML2RA_Trf_ucTransferPrepValidationFail-InvalidPayee_Mar22a.png) +>UC Workflow Diagram: Perform Transfer - Transfer Prepare Validation Failure (Invalid Payee Participant) + +### Query (GET) Transfer - Validation Failure (Invalid Payer Participant) + +#### Description + +The workflow provided by this UC enables the BC to effect a method through which to terminate a Transfer status query where validation fails due to an invalid/non-existent Payer. + + + +### Query (GET) Transfer - Validation Failure (Invalid Payee Participant) + +#### Description + +The workflow provided by this UC enables the BC to effect a method through which to terminate a Transfer status query where validation fails due to an invalid/non-existent Payee. + + + +### Query (GET) Transfer - Validation Failure (Transfer Identifier Not Found) + +#### Description + +The workflow provided by this UC enables the BC to effect a method through which to terminate a Transfer status query where validation fails due to a Transfer Identifier Token not being found. + + + +## Canonical Model + +Mojaloop uses two canonical models to manage funds transfers, one for non-bulk transfers, and one for bulk transfers. + +### Standard Canonical Model + +* Transfer + * transferId + * transferType + * quoteld (optional) + * settlementModelId + * Participants + * Payer + * participantId + * Accounts + * Debit + * accountId + * accountType + * currency + * Credit + * accountId + * accountType + * currency + * Payee + * ParticipantId + * Accounts + * Debit + * accountId + * accountType + * currency + * Credit + * accountId + * accountType + * currency + * Amount (Amount to transfer) + * value (number) + * currency (ISO currency code) + * expiration (ISO dateTime) + * ilpPacket + * Extensions + +### Bulk Canonical Model + +* Transfers + * bulkId + * bulkQuoteId + * Transfers[] + * Transfer* (see above) + +## Concluding Comments + +* The Payer FSP should not be permitted to unilaterally time-out a transfer (irrespective of its expiration time), but should respect the Switch's timeout decisions. +* Validation of cryptographic conditions and fulfillment would be managed by the Transfers BC as it is a fundamental component of the "transfer" process (i.e.: function is not specific to the FSPIOP language) +* The Transfers BC will apply the same validation pattern as the Quoting & Party BC to validate Participants, to determine the ability of an Account to transact, or if a Participant is enabled as mutually exclusive. +* The Transfers BC is the single "source of truth" for all transfers, and is thus responsible for persisting the state/s of transfer's. +* Disabling Participants already in a "prepared" state should not hinder processing of current transfers, however new transfer instructions received by the Transfers BC via the TransferPrepareAccountAllocated events should be declined. + + + + +[^1]: Common Interfaces: [Mojaloop Common Interface List](../../commonInterfaces.md) diff --git a/docs/technical/reference-architecture/furtherReading/README.md b/docs/technical/reference-architecture/furtherReading/README.md new file mode 100644 index 000000000..ec9b22012 --- /dev/null +++ b/docs/technical/reference-architecture/furtherReading/README.md @@ -0,0 +1,55 @@ +# Further Reading + +## Team Resources + +During the Reference Architecture planning work sessions, the Team made use of different resources to build and retain a record of discussions and to build the Use Case Models required to support all of the possible stakeholder requirements for the new architecture. + +Please feel free to visit the Team’s resources using the links provided. + +**P.S.** One resource that you might find particularly useful is Miro, where we keep a record of all of the Bounded Context Use Cases in use by the system. + +***Note:** Please bear in mind that the Reference Architecture document is a living document, and as a result is updated from time to time for various reasons. This means that the resources that we have shared with you are still in use and will change occasionally.* + +| Resource | Purpose | Link/URL | +| --- | --- | --- | +| Miro | Build Use Case flow diagrams | [Miro - Mojaloop Reference Architecture](https://miro.com/app/board/o9J_lJyA1TA=/) | +| Google Docs | Session work notes for the team providing details of Reference Architecture for inclusion in the proposal and introductory documentation. | [Mojaloop 2.0 Reference Architecture Work Sessions](https://docs.google.com/document/d/1Nm6B_tSR1mOM0LEzxZ9uQnGwXkruBeYB2slgYK1Kflo/edit#heading=h.vymmtvqaio5b) | +| Google Sheets | Record of Common Interfaces in use in the Switch architecture, along with various other bits and pieces. | [Mojaloop 2.0 Reference Architecture](https://docs.google.com/spreadsheets/d/1ITmAesHjRZICC0EUNV8vUVV8VDnKLjbSKu_dzhEa5Fw/edit#gid=1810993431) + +## Reference Articles and Documents + +The resources below were sourced to provide additional insight into the architecture models that have been implemented. + +| Resource | Details | +| --- | --- | +|[*Domain-Driven Design*, from Wikipedia, the free encyclopedia](https://en.wikipedia.org/wiki/Domain-driven_design) | Publisher: Wikipedia, the free encyclopedia; Author: Community; Date: non-specific; ±7mins to read | +| [*Domain, Subdomain, Bounded Context, Problem/Solution Space in DDD: Clearly Defined*](https://medium.com/nick-tune-tech-strategy-blog/domains-subdomain-problem-solution-space-in-ddd-clearly-defined-e0b49c7b586c) | Publisher: Medium.com; Author: Nick Tune; Date: 11/07/2020; ±7mins to read | +| [*Strategic Domain-Driven Design*](https://microservices.io/patterns/decomposition/decompose-by-subdomain.html) | Publisher: Vaadin.com; Author: Petter Holmstrom | +| [*Pattern: Decompose by Subdomain Context*](https://microservices.io/patterns/decomposition/decompose-by-subdomain.html) | Publisher: Microservices Architecture; Author: Chris Richardson | +| [*Rest API Tutorial*](https://www.restapitutorial.com/) | Publisher: Self-published; Author: Todd Fredrich; License: [Creative Commons Attribution ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/) | +| [*Use Case*, from Wikipedia, the free encyclopedia](https://en.wikipedia.org/wiki/Use_case) | In brief, and quoting from the opening blurb of the Wikipedia article, a use case is a list of actions or event steps typically defining the interactions between a role (known in the Unified Modeling Language (UML) as an actor) and a system to achieve a goal. The actor can be a human or other external system. In systems engineering, use cases are used at a higher level than within software engineering, often representing missions or stakeholder goals. The detailed requirements may then be captured in the Systems Modeling Language (SysML) or as contractual statements. | + +## Project Iteration Convenings + +The resources below are inclusions to the Mojaloop Technical Convenings by the Reference Architecture Team starting at the beginning of 2021. Resources include notes, slides, and video recordings. + +| Project Iteration (PI) | Period | Description | Link/URL | +| --- | --- | --- | --- | +| PI-13 | January 2021 | Mojaloop Performance, Scalability and Architecture Update | [PI-13 Slides & Recording](https://community.mojaloop.io/t/mojaloop-performance-scalability-and-architecture-update/240) | +| PI-14 | April 2021 | Opening and Mojaloop Reference Architecture and TigerBeetle | [PI-14 Recording (YouTube)](https://www.youtube.com/watch?v=UHxULJXIzj8) | +| PI-15 | July 2021 | Reference Architecture v1.0 | [PI-15 Resources](https://mojaloopcommunitymeeting.us2.pathable.com/meetings/virtual/ookcbEc6aDZgwyo2n) / [PI-15 Video Library (YouTube)](https://www.youtube.com/playlist?list=PLSamWCIlxVXujHm4CWfyl6uLzcXJE1Zi_) | +| PI-16 | October 2021 | Reference Architecture and V2 update | [PI-16 Agenda](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/pi_16_october_2021) / [PI-16 Video Library](https://mojaloop.io/video/pi-16-mojaloop-community-meeting-technical-sessions-october-2021/) | +| PI-17 | January 2022 | Reference Architecture: Documentation and v.Next Updates | [PI-17 Reference Architecture Presentation (YouTube)](https://youtu.be/kqbEVbglBEM) | + + \ No newline at end of file diff --git a/docs/technical/reference-architecture/gettingStarted/README.md b/docs/technical/reference-architecture/gettingStarted/README.md new file mode 100644 index 000000000..687ff3899 --- /dev/null +++ b/docs/technical/reference-architecture/gettingStarted/README.md @@ -0,0 +1,6 @@ +# Getting Started + +To help get you started with the Mojaloop Reference Architecture, select which of the options below best suits your needs: + +1. [Sub-menu](./subMenu/) +2. [Contribute to Mojaloop](https://docs.mojaloop.io/documentation/) diff --git a/docs/technical/reference-architecture/gettingStarted/subMenu/README.md b/docs/technical/reference-architecture/gettingStarted/subMenu/README.md new file mode 100644 index 000000000..ffdfdf924 --- /dev/null +++ b/docs/technical/reference-architecture/gettingStarted/subMenu/README.md @@ -0,0 +1,11 @@ +# Sub Menu + +Some text. + +## Sub title 1 + +Some more text. + +## Sub title 2 + +Some more text. diff --git a/docs/technical/reference-architecture/glossary/README.md b/docs/technical/reference-architecture/glossary/README.md new file mode 100644 index 000000000..ebf7390bd --- /dev/null +++ b/docs/technical/reference-architecture/glossary/README.md @@ -0,0 +1,14 @@ +# TBD Placeholder + + \ No newline at end of file diff --git a/docs/technical/reference-architecture/howToImplement/README.md b/docs/technical/reference-architecture/howToImplement/README.md new file mode 100644 index 000000000..cd51378ea --- /dev/null +++ b/docs/technical/reference-architecture/howToImplement/README.md @@ -0,0 +1,2 @@ +# TBD Placeholder for vNext Implementation architecture + diff --git a/docs/technical/reference-architecture/index.md b/docs/technical/reference-architecture/index.md new file mode 100644 index 000000000..98f223627 --- /dev/null +++ b/docs/technical/reference-architecture/index.md @@ -0,0 +1,17 @@ +--- +home: true +heroImage: /mojaloop_logo_med.png +tagline: This is the official Reference Architecture documentation for the Mojaloop project. + + +actionText: Introduction → +actionLink: /introduction/ + +features: +- title: What it is + details: In a software system, a Reference Architecture is a set of software design documents, that capture the essence of the product and provide guidance to its technical evolution. The Reference Architecture is the architectural vision of the perfect design. +- title: Objectives + details: Identify abstractions, interfaces and standardization opportunities; Solutions and patterns to common problems; Enforces technical design principles; Provides guidance to the implementation architectures; Foster's innovation and contribution, by defining what can be done and how +- title: Benefits + details: Foundation for a Technical Roadmap; Guidance to decision-making regarding technology choices and implementation strategies; Alignment between technical vision and product vision +--- diff --git a/docs/technical/reference-architecture/introduction/assets/process.png b/docs/technical/reference-architecture/introduction/assets/process.png new file mode 100644 index 000000000..55e8cf7ed Binary files /dev/null and b/docs/technical/reference-architecture/introduction/assets/process.png differ diff --git a/docs/technical/reference-architecture/introduction/index.md b/docs/technical/reference-architecture/introduction/index.md new file mode 100644 index 000000000..004ac437c --- /dev/null +++ b/docs/technical/reference-architecture/introduction/index.md @@ -0,0 +1,109 @@ +# Introduction + +## What is a Reference Architecture? + +In a software system, the Reference Architecture is a set of software design documents that capture the essence of the product and provide guidance to its technical evolution. + +This concept can be further simplified: + +_**The Reference Architecture is the architectural vision of the perfect design.**_ + +In normal conditions that perfect design is never achieved, partly because there is neither enough time nor resources to fully implement it, partly because that design can iterate and improve faster than it can be implemented. +It is the nature of a Reference Architecture to be a living document that is continuously updated and enhanced. + +## What are the objectives of the Reference Architecture + +The main objectives of the Reference Architecture are to: + +* Identify abstractions, interfaces and standardization opportunities +* Propose solutions and patterns to common problems +* Help enforcing technical design principles +* Provide guidance to the implementation architectures +* Foster innovation and contribution, by defining what can be done and how + +## What are the benefits of having a Reference Architecture + +The first benefit is that it is the perfect foundation for a Technical Roadmap. By having the future vision in perspective, a phased Technical Roadmap can easily be created from it, ensuring resources and attention are focused on the long term value. + +Another important benefit is the guidance it provides to decision-making regarding technology choices and implementation strategies. +With the Reference Architecture in mind we can frame any development decision as tactical or strategic: + +* Tactical - something that is required right now which may have exceptions to the Reference Architecture for the sake of a high-value urgent requirement. These exceptions should be documented as technical debt which can be addressed in future. +* Strategic - something that is long-lasting and should be implemented in accordance to the Reference Architecture - should take the implementation closer to it. + +Last but not less important, it ensures alignment between the technical vision and the more important product vision (see below regarding the process and ways of working). + +## Process of creating and maintaining the Reference Architecture + +While creating the initial version of the Reference Architecture, the team followed these steps: + +1. Problem Space mapping - Document the different problem domains and subdomains, and how they are classified according to their importance +2. Solution Space Context mapping - Group similar problems together based on their purpose and context +3. Individual use case mapping - Discuss and document use cases in detail taking into consideration the entire solution + +## How to keep a Reference Architecture up-to-date + +The diagram below shows where a reference architecture exists in reference to other processes of the Mojaloop Platform; what it must incorporate and understand, not only the vision and the principles, but also the requirements, previous experience and even forster technical innovation. + +![Perform Transfer (Universal Mode)](./assets/process.png) +> Introduction (Mojaloop 2.0 Reference Architecture): How to keep the Reference Architecture up to date + + +## Principles guiding this architecture + +The Mojaloop 2.0 Reference Architecture design has been guided by Domain-Driven Design[^1] principles, and inspired by SOLID[^2] object-oriented programming principles for building software applications, especially the single responsibility principle (SRP). + +To provide an understanding of the architecture interpretation by Mojaloop, we include a brief overview of Domain Driven Design architecture. + +### DDD Inspired Architecture Overview + +The DDD Inspired architecture implementation for Mojaloop includes the following concepts: + +* **Problem Space** - Typically DDD-architecture recognises business requirements as belonging to separate domains. For example an eCommerce system is seen as a **_Domain_**. But an eCommerce system has several components in order to work such as an inventory, a shopping cart, checkout, etc. Each component is categorised as a **_Subdomain_** that contributes value to the domain which is the eCommerce system. Mojaloop uses a single domain - it is a switch. + + The Problem Space is one of two containers where all of the identified business problems (improvements/services) that need to be solved are contained. Depending on the complexity of the Business Problem (improvement), or indeed the scale of problems needing to be solved, it is possible to devolve the initial subdomain structure into additional Subdomains. Each problem is assigned to its own Subdomain. Care should be exercised however, to ensure that each Subdomain is absolutely necessary, and focused on delivering value to the domain to avoid an unnecessary and confusing plethora of Subdomains filling the Problem Space. + + Each improvement/service thus contained in a separate Subdomain allows for different teams to develop manageable chunks of the system which is more efficient and less risk-prone than building an entire system in one structure. A sizable benefit to this approach is that the entire development process can be centered around improving and adding value to the platform, and not just adding features. + + Typically, the Problem Space includes three containers which broadly indicate how, or what is going to be used to solve a particular problem, to which a fourth container has been added for Non-Functional Requirements (NFRs) - + + * Core - solutions dependent on internal builds for completion. + * Supporting - solutions that can be implemented using off the shelf products - for example, secure login. + * Generic - solutions that can use off the shelf products, but which need additional coding to implement, not just integration - for example, reporting and authentication + * Non-functional Requirements (NFRs) - solutions that are required to address common needs, but that do not contribute directly to the value of the product + +* **Solution Space** - A second major component of DDD-Architecture is the Solution Space. It differs from the Problem-Space in that its focus is not on what to solve, but how a problem (improvement/service) is going to be solved, and how the multiple solutions relate to each other. The Solution Space thus necessarily includes more technical information and details for how the problems should be solved. + + * The Solution Space introduces a number of elements to aid and align problem-solving development efforts + + * Bounded Contexts were introduced to group cohesive sets of solutions with its specific language. + + Often mapping between Bounded Contexts and Subdomains will not be one-to-one. As Subdomains belong to the Problem Space and Bounded Contexts to the Solution Space, it is quite possible that scenarios will occur where a Subdomain are solved by more than one Bounded Context, or where a Bounded Context may solve multiple Subdomains. + + Typically, and definitely in the Mojaloop environment, solutions are designed and implemented without knowledge of specific infrastructure dependencies or other inner workings of other Bounded Contexts. This approach aids security, amongst other things by ensuring that each Bounded Context is only aware of its own environment, and its interfaces. Communications between Bounded Contexts are all conducted via APIs and secured messaging. Examples of Bounded Contexts (BCs) from the Mojaloop environment include Accounts \& Balances, Transfers \& Transactions, etc. + +* **_Ubiquitous Language_** is an approach to encourage explicit, and commonly understood, language that everyone uses when describing problems and solutions, from end users to developers. There are two main objectives for a Ubiquitous Language: + + 1. It ensures that unique terms are identified and understood to have a single meaning by all parties within its Bounded Context. An example might include the word, “Account”, which could be understood as an Account Profile by one party, and a reference to an Accounting System Account by another. This is not a recommendation to search for an impossible, project or company-wide, universal set of unambiguous terms; instead it assures that each Bounded Context has its own set of terms. + 2. It ensures that the terms of the Ubiquitous Language are present from the user interface, to documentation, to other project related materials, and even in the code. The ubiquitous usage of the same terms everywhere, including in code, guarantees that everyone has the same understanding of the problems and solutions being described and solved. + +* **_Cross Cutting Concerns_**[^3] are aspects of a software solution that must be solved by multiple Bounded Contexts (or functions/modules) and include items such as auditing, security, authentication, and platform (Business and Technical) configuration management. Our approach to these Cross Cutting Concerns, was to separate them from the BC's. Most Cross Cutting Concerns have a distributed nature in this design, with central components and client libraries. These are represented in this documentation as equivalent to Bounded Contexts. + +### SOLID Principles + +In addition to DDD-architecture, Mojaloop’s architecture approach has also been inspired by SOLID principles: + +* Single responsibility and internal interfaces provide the ability to implement additional Domains, such as ISO, without needing to change the core architecture +* Software entities should be extended but never modified. The rule is never hack core, always extend through add-on modules or nodes +* Functions using references to base classes should be able to use objects of derived classes without being aware of it +* Several client-specific interfaces are better than a single all-purpose interface +* Build dependencies on abstractions, not concretions + + +### Notes + +[^1]: Further reading: [Domain-driven design From Wikipedia, the free encyclopedia](https://en.wikipedia.org/wiki/Domain-driven_design) + +[^2]: Further reading: [SOLID From WIkipedia, the free encyclopedia](https://en.wikipedia.org/wiki/SOLID) + +[^3]: Further reading: [Cross-cutting Concern](https://en.wikipedia.org/wiki/Cross-cutting_concern#:~:text=Cross%2Dcutting%20concerns%20are%20parts,oriented%20programming%20or%20procedural%20programming.) - Publisher: Wikipedia, the free encyclopedia diff --git a/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_Core_Apr22c_1670.png b/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_Core_Apr22c_1670.png new file mode 100644 index 000000000..6402dc462 Binary files /dev/null and b/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_Core_Apr22c_1670.png differ diff --git a/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_Generic_Apr22c_1670.png b/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_Generic_Apr22c_1670.png new file mode 100644 index 000000000..17b11b5ab Binary files /dev/null and b/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_Generic_Apr22c_1670.png differ diff --git a/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_NFRs_Apr22c_1670.png b/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_NFRs_Apr22c_1670.png new file mode 100644 index 000000000..523373d7a Binary files /dev/null and b/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_NFRs_Apr22c_1670.png differ diff --git a/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_SolutionSpace_Apr22a.png b/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_SolutionSpace_Apr22a.png new file mode 100644 index 000000000..4034289ad Binary files /dev/null and b/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_SolutionSpace_Apr22a.png differ diff --git a/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_Supporting_Apr22c_1670.png b/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_Supporting_Apr22c_1670.png new file mode 100644 index 000000000..8ad905989 Binary files /dev/null and b/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_Supporting_Apr22c_1670.png differ diff --git a/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_newUnclassified_Apr22c_1670.png b/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_newUnclassified_Apr22c_1670.png new file mode 100644 index 000000000..5d2299425 Binary files /dev/null and b/docs/technical/reference-architecture/refarch/assets/ML2RA_in_RefArchOver_newUnclassified_Apr22c_1670.png differ diff --git a/docs/technical/reference-architecture/refarch/index.md b/docs/technical/reference-architecture/refarch/index.md new file mode 100644 index 000000000..9697a7531 --- /dev/null +++ b/docs/technical/reference-architecture/refarch/index.md @@ -0,0 +1,113 @@ +# Mojaloop Reference Architecture Overview + +## Problem Space (_Problem space identification and map)_ + +As noted in the DDD-architecture overview, the Problem Space contains a number of solution-oriented containers identified by the system architects’ team which are being used to categorise subdomains where problems (improvements) have been identified. + +### Core Problems + +#### Description + +A number of Core Problems (improvements) have been identified by (Business/Developers/Both Business & Developers). In order to implement the improvements, “internal” development teams will be tasked with developing the required solutions. Typically the Subdomains thus identified generate significant value for the Mojaloop system, therefore care is taken to ensure that the services they provide are not compromised. Examples of Core Problem Subdomains include: Participant Lifecycle Management, Settlements, and Scheduling. + +#### High-Level Map + +![Core Problems](./assets/ML2RA_in_RefArchOver_Core_Apr22c_1670.png) +> Reference Architecture (Mojaloop): Core Problems + +### Generic Problems + +#### Description + +A number of Generic Problems (improvements) have been identified by (Business/Developers/Both Business & Developers). In order to implement the improvements, off-the-shelf solutions will be implemented that require no further customization. They will require integration with the Mojaloop. Examples of Generic problem subdomains include Authentication, FRMS, and Platform Monitoring. + +#### High-Level Map + +![Generic Problems](./assets/ML2RA_in_RefArchOver_Generic_Apr22c_1670.png) +> Reference Architecture (Mojaloop): Generic Problems + +### Supporting Problems + +#### Description + +A number of Supporting Problems (improvements) have been identified by (Business/Developers/Both Business & Developers). In order to implement the improvements, off-the-shelf solutions will be implemented, however in order to fully integrate them with the Mojaloop system and satisfy the identified problems (improvements) additional customization will be required for each of the integrated solutions. Examples of Supporting Problem Subdomains include Access Policy Management, Reporting, and Authorization (Access Policy content verification). + +#### High-Level Map + +![Supporting Problems](./assets/ML2RA_in_RefArchOver_Supporting_Apr22c_1670.png) +> Reference Architecture (Mojaloop): Supporting Problems + +### Non-Functional Requirements + +#### Description + +A number of Non-Functional Requirements have been identified by (Business/Developers/Both Business & Developers). Whilst they do not add direct value to Mojaloop, they are required in order to fulfil a number of business-related problems (improvements). Examples of Non-Functional Requirements include security which does not occupy its own subdomain. All system Subdomains will need to include elements of code pertaining to security in fulfillment of this requirement, alternatively, a central security management service will be implemented that includes centrally managed and constructed security profiles for each Subdomain in the system which they will download upon joining the Domain, or upon initiation, and/or which will be pushed down to them from the central service when updates occur. + +#### High-Level Map + +![Non-Functional Requirements](./assets/ML2RA_in_RefArchOver_NFRs_Apr22c_1670.png) +> Reference Architecture (Mojaloop): Non-Functional Requirements + +### New and Unclassified (non-domain) + +#### Description + +A number of New and Unclassified (non-domain) problems have been identified by both Business and Developers). Once Business and the System Architects have identified the required solution in order to solve the problem, they will be classified into one of the Problem containers and fulfilled in accordance with its processes. + +#### High-Level Map + +![New & Unclassified Problems](./assets/ML2RA_in_RefArchOver_newUnclassified_Apr22c_1670.png) +> Reference Architecture (Mojaloop): New and Unclassified Problems + +## Solution Space (_High level description and the context map)_ + +#### Description + +The Solution Space defined by DDD-architecture is focused on how the business problems (improvements) identified in the Problem Space are going to be solved. As a result it necessarily contains more information and technical details than the Problem Space. It includes elements such as Ubiquitous Language, Bounded Contexts, and Cross-Cutting Concerns. + +#### High-Level Map + +![Solution Space](./assets/ML2RA_in_RefArchOver_SolutionSpace_Apr22a.png) +> Reference Architecture (Mojaloop): Solution Space + +### Ubiquitous Language + +#### Description + +A challenge that most teams face is maintaining a clear understanding of terms that may not be unique with a particular Domain. A classic example of a non-unique term is “account”: this term could refer to a set of financial accounts, entity profile, or a login name. + +As noted in the overview, Ubiquitous Language is used to aid in the elimination of confusion and miscommunication between business and technical teams working to solve a business problem or group of business problems. Whilst it is possible that that each Domain/Subdomain may contain terms that are not unique, as noted above, within a particular context, and in the instance of DDD-architecture, that would be a Bounded Context, it is important to ensure that all terms are unique, clearly understood by all participants, and correctly applied. + +For insights and a description of each of the unique language terms used in the Mojaloop Domain, please refer to the [Glossary](../glossary/README.md) appended to this document. + +### Bounded Contexts + +The following Bounded Contexts have been identified and implemented in Mojaloop: + +> This is a high-level description of each of the Bounded Contexts that have been identified and included in the Mojaloop Reference Architecture. A more detailed view follows in the [Bounded Context](../boundedContexts/index.md) section of this document. + +| Bounded Context | Purpose | Bounded Context | Purpose | +| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Settlements | Performs Settlements
    Configures settlement models
    Calculate Settlements | Participant Lifecycle Management | Participant Onboarding
    Participant Lifecycle Management
    Participant Self-service
    Participant Self-service UI | +| Account Lookup & Discovery | Internal Oracle core
    Account lookup / discovery
    Bulk transactions
    Duplicate Identifier management
    Inter-scheme connections (incl. settlements) cross-border | Accounts & Balances | System of record of DFSP participant financial activity & balance | +| Transfers & Transactions | Transfer processing
    Liquidity check for each transfer
    Bulk transactions
    Multi-currency, incl.multi-hop transactions | Agreement (Quoting) | Agreement /quoting (core)
    Bulk transactions
    Multi-currency, incl.multi-hop transactions
    Scheme Rule/Patterns Enforcement Happens in each BC | +| Scheduling | Scheduling time-based events of API calls (Core) | Notifications & Alerts | Notification state - priority & SLA aware (Core)
    Trigger & alert management (Core)
    Notifications delivery - priority and SLA aware (Generic) | +| FSP Interop APIs | ISO External API (Bulk; API, Callbacks triggering (transfers only, Missing in AS-IS) | Third Party Initiated Payments | PISP Account Linking
    Consent Management
    3rd Party Payment Initiation (Core) | +| Third party API | | PISP Mojaloop External API
    PISP ISO External API | | + +### Cross cutting concerns + +The following Cross cutting concerns have been identified in Mojaloop: + +| Cross Cutting Concern BC | Purpose | +| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| AuthZ & AuthN and Identity Management BC | Manage all aspects of both user and system authentication (AuthN) and authorization (AuthZ). Planned solutions will fit into the Generic and Supporting categories | +| Cryptographic BC | Manage all cryptographic related services including Key and Certificate Management and Storage Systems. Planned solutions will fit into the Generic category. | +| Reporting and Auditing BC | Manage all audit and reporting services including Compliance and Assurance Reporting, Forensic Event Logging and KMS, Forensic Event Log Access and Management, Process Monitoring and SLAs, and System Auditing. (Each BC will include auditing capability. The Reporting and Auditing BC will retain logs from all of the BCs). Planned solutions will fit into all of the Problem Space categories: Core, Supporting, and Generic. | +| Platform Configuration (Business) BC | Manage Scheme rule/patterns management process (Note; Scheme rule/patterns enforcement is maintained in each BC), Scheme mandated transaction patterns, application management and security, identity and access management (including user and team management), bizops API linking consent management, and access policy management. Planned solutions will fit into all of the Problem Space categories: Core, Supporting, and Generic | +| Technical Platform Management BC | Manage platform monitoring, and platform management. Planned solutions will fit into the Generic category. | + + + \ No newline at end of file diff --git a/docs/technical/technical/account-lookup-service/README.md b/docs/technical/technical/account-lookup-service/README.md new file mode 100644 index 000000000..4475e8255 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/README.md @@ -0,0 +1,128 @@ +--- +version: 1.1 +--- + + +# Account Lookup Service + +The **Account Lookup Service** (**ALS**) _(refer to section `6.2.1.2`)_ as per the [Mojaloop {{ $page.frontmatter.version }} Specification](/api) implements the following use-cases: + +* Participant Look-up +* Party Look-up +* Manage Participants Registry information + * Adding Participant Registry information + * Deleting Participant Registry information + +Use-cases that have been implemented over and above for Hub Operational use: +* Admin Operations + * Manage Oracle End-point Routing information + * Manage Switch End-point Routing information + +## 1. Design Considerations + +### 1.1. Account Lookup Service (ALS) +The ALS design provides a generic Central-Service component as part of the core Mojaloop. The purpose of this component is to provide routing and alignment to the Mojaloop API Specification. This component will support multiple Look-up registries (Oracles). This ALS will provide an Admin API to configure routing/config for each of the Oracles similiar to the Central-Service API for the End-point configuration for DFSP routing by the Notification-Handler (ML-API-Adapter Component). The ALS will in all intense purpose be a switch with a persistence store for the storage/management of the routing rules/config. + +#### 1.1.1. Assumptions + +* The ALS design will only cater for a single switch for the time being. +* Support for multiple switches will utilise the same DNS resolution mechanism that is being developed for the Cross Border/Network design. + +#### 1.1.2. Routing + +The routing configuration will be based on the following: +* PartyIdType - See section `7.5.6` of the Mojaloop Specification +* Currency - See section `7.5.5` of the Mojaloop Specification. Currency code defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic string. This will be optional, however `isDefault` indicator must be set to `true` if the `Currency` is not provided. +* isDefault - Indicator that a specific Oracle is the default provider for a specific PartyIdType. Note that there can be many default Oracles, but there can only be a single Oracle default for a specific PartyIdType. The default Oracle for a specific PartyIdType will only be selected if the originating request does not include a Currency filter. + + +### 1.2. ALS Oracle +The ALS Oracle be implemented as either a **Service** or **Adapter** (semantic dependant on use - Mediation = Adapter, Service = Implementation) will provide a look-up registry component with similar functionality of the `/participants` Mojaloop API resources. It has however loosely based on the ML API specification as it's interface implements a sync pattern which reduces the correlation/persistence requirements of the Async Callback pattern implemented directly by the ML API Spec. This will provide all ALS Oracle Services/Adapters with a standard interface which will be mediated by the ALS based on its routing configuration. +This component (or back-end systems) will also be responsible for the persistence & defaulting of the Participant details. + +## 2. Participant Lookup Design + +### 2.1. Architecture overview +![Architecture Flow Account-Lookup for Participants](./assets/diagrams/architecture/arch-flow-account-lookup-participants.svg) + +_Note: The Participant Lookup use-case similarly applies to for a Payee Initiated use-case such as transactionRequests. The difference being that the Payee is the initiation in the above diagram._ + +### 2.2. Sequence diagrams + +#### 2.2.1. GET Participants + +- [Sequence Diagram for GET Participants](als-get-participants.md) + +#### 2.2.2. POST Participants + +- [Sequence Diagram for POST Participants](als-post-participants.md) + +#### 2.2.3. POST Participants (Batch) + +- [Sequence Diagram for POST Participants (Batch)](als-post-participants-batch.md) + +#### 2.2.4. DEL Participants + +- [Sequence Diagram for DEL Participants](als-del-participants.md) + +## 3. Party Lookup Design + +### 3.1. Architecture overview +![Architecture Flow Account-Lookup for Parties](./assets/diagrams/architecture/arch-flow-account-lookup-parties.svg) + +### 3.2. Sequence diagram + +#### 3.2.1. GET Parties + +- [Sequence Diagram for GET Parties](als-get-parties.md) + +## 4. ALS Admin Design + +### 4.1. Architecture overview +![Architecture Flow Account-Lookup for Admin Get Oracles](./assets/diagrams/architecture/arch-flow-account-lookup-admin.svg) + +### 4.2. Sequence diagram + +#### 4.2.1 GET Oracles + +- [Sequence Diagram for GET Oracles](als-admin-get-oracles.md) + +#### 4.2.2 POST Oracle + +- [Sequence Diagram for POST Oracle](als-admin-post-oracles.md) + +#### 4.2.3 PUT Oracle + +- [Sequence Diagram for PUT Oracle](als-admin-put-oracles.md) + +#### 4.2.4 DELETE Oracle + +- [Sequence Diagram for DELETE Oracle](als-admin-del-oracles.md) + +#### 4.2.5 DELETE Endpoint Cache + +- [Sequence Diagram for DELETE Endpoint Cache](als-del-endpoint.md) + +## 5. Database Design + +### 5.1. ALS Database Schema + +#### Notes +- `partyIdType` - Values are currently seeded as per section _`7.5.6`_ [Mojaloop {{ $page.frontmatter.version }} Specification](./api). +- `currency` - See section `7.5.5` of the Mojaloop Specification. Currency code defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic string. This will be optional, and must provide a "default" config if no Currency is either provided or provide a default if the Currency is provided, but only the "default" End-point config exists. +- `endPointType` - Type identifier for the end-point (e.g. `URL`) which provides flexibility for future transport support. +- `migration*` - Meta-data tables used by Knex Framework engine. +- A `centralSwitchEndpoint` must be associated to the `OracleEndpoint` by the Admin API upon insertion of a new `OracleEndpoint` record. If the `centralSwitchEndpoint` is not provided as part of the API Request, then it must be defaulted. + +![Acount Lookup Service ERD](./assets/entities/AccountLookupService-schema.png) + +* [Acount Lookup Service DBeaver ERD](./assets/entities/AccountLookupDB-schema-DBeaver.erd) +* [Acount Lookup Service MySQL Workbench Export](./assets/entities/AccountLookup-ddl-MySQLWorkbench.sql) + +## 6. ALS Oracle Design + +Detail design for the Oracle is out of scope for this document. The Oracle design and implementation is specific to each Oracle's requirements. + +### 6.1. API Specification + +Refer to **ALS Oracle API** in the [API Specifications](../../api/README.md#als-oracle-api) section. diff --git a/docs/technical/technical/account-lookup-service/als-admin-del-oracles.md b/docs/technical/technical/account-lookup-service/als-admin-del-oracles.md new file mode 100644 index 000000000..3dd7369f3 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/als-admin-del-oracles.md @@ -0,0 +1,8 @@ +# DELETE Oracles + +Design for the Deletion of an Oracle Endpoint by a Hub Operator. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.svg) + diff --git a/docs/technical/technical/account-lookup-service/als-admin-get-oracles.md b/docs/technical/technical/account-lookup-service/als-admin-get-oracles.md new file mode 100644 index 000000000..f0c687f5e --- /dev/null +++ b/docs/technical/technical/account-lookup-service/als-admin-get-oracles.md @@ -0,0 +1,8 @@ +# GET Oracles + +Design for getting a list of all Oracle Endpoints by the Hub Operator with the option of querying but currency and/or type. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.svg) + diff --git a/docs/technical/technical/account-lookup-service/als-admin-post-oracles.md b/docs/technical/technical/account-lookup-service/als-admin-post-oracles.md new file mode 100644 index 000000000..c78539207 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/als-admin-post-oracles.md @@ -0,0 +1,8 @@ +# POST Oracles + +Design for the creation of an Oracle Endpoint by a Hub Operator. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.svg) + diff --git a/docs/technical/technical/account-lookup-service/als-admin-put-oracles.md b/docs/technical/technical/account-lookup-service/als-admin-put-oracles.md new file mode 100644 index 000000000..d7e0de1ad --- /dev/null +++ b/docs/technical/technical/account-lookup-service/als-admin-put-oracles.md @@ -0,0 +1,8 @@ +# PUT Oracles + +Design for the Update of an Oracle Endpoint by a Hub Operator. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.svg) + diff --git a/docs/technical/technical/account-lookup-service/als-del-endpoint.md b/docs/technical/technical/account-lookup-service/als-del-endpoint.md new file mode 100644 index 000000000..431848981 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/als-del-endpoint.md @@ -0,0 +1,8 @@ +# DELETE Endpoint Cache + +Design for the disabling of an Oracle by the Hub Operator. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.svg) + diff --git a/docs/technical/technical/account-lookup-service/als-del-participants.md b/docs/technical/technical/account-lookup-service/als-del-participants.md new file mode 100644 index 000000000..54eebd7c5 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/als-del-participants.md @@ -0,0 +1,11 @@ +# DEL Participants + +Design for the deletion of a Participant by a DFSP. + +## Notes +- Reference section 6.2.2.4 - Note: The ALS should verify that it is the Party’s current FSP that is deleting the FSP information. ~ This has been addressed in the design by insuring that the Party currently belongs to the FSPs requesting the deletion of the record. Any other validations are out of scope for the Switch and should be addressed at the schema level. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.svg) + diff --git a/docs/technical/technical/account-lookup-service/als-get-participants.md b/docs/technical/technical/account-lookup-service/als-get-participants.md new file mode 100644 index 000000000..d3986bfaa --- /dev/null +++ b/docs/technical/technical/account-lookup-service/als-get-participants.md @@ -0,0 +1,8 @@ +# GET Participants + +Design for the retrieval of a Participant by a DFSP. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.svg) + diff --git a/docs/technical/technical/account-lookup-service/als-get-parties.md b/docs/technical/technical/account-lookup-service/als-get-parties.md new file mode 100644 index 000000000..ae5577fc3 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/als-get-parties.md @@ -0,0 +1,8 @@ +# GET Parties + +Design for the retrieval of a Party by a DFSP. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.svg) + diff --git a/docs/technical/technical/account-lookup-service/als-post-participants-batch.md b/docs/technical/technical/account-lookup-service/als-post-participants-batch.md new file mode 100644 index 000000000..32087549f --- /dev/null +++ b/docs/technical/technical/account-lookup-service/als-post-participants-batch.md @@ -0,0 +1,14 @@ +# Sequence Diagram for POST Participants (Batch) + +Design for the creation of a Participant by a DFSP via a batch request. + +## Notes +- Operation only supports requests which contain: + - All Participant's FSPs match the FSPIOP-Source7 + - All Participant's will be of the same Currency, per the `POST /participants` call in the [Mojaloop FSPIOP API](/api/fspiop/v1.1/api-definition.html#post-participants) +- Duplicate POST Requests with matching TYPE and optional CURRENCY will be considered an __update__ operation. The existing record must be completely **replaced** in its entirety. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.svg) + diff --git a/docs/technical/technical/account-lookup-service/als-post-participants.md b/docs/technical/technical/account-lookup-service/als-post-participants.md new file mode 100644 index 000000000..8f3caff9e --- /dev/null +++ b/docs/technical/technical/account-lookup-service/als-post-participants.md @@ -0,0 +1,8 @@ +# POST Participant + +Design for the creation of a Participant by a DFSP via a request. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.svg) + diff --git a/assets/diagrams/.gitkeep b/docs/technical/technical/account-lookup-service/assets/.gitkeep similarity index 100% rename from assets/diagrams/.gitkeep rename to docs/technical/technical/account-lookup-service/assets/.gitkeep diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-admin.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-admin.svg new file mode 100644 index 000000000..d46ffa284 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-admin.svg @@ -0,0 +1,3 @@ + + +
    Account Lookup Service Admin
    (ALS)
    Account Lookup Service Adm...
    HUB
    Backend



    HUB...
    Account Lookup Admin
    Account Lookup Admin
    HUB Operator
    HUB Operator
    A1. Request Oracle Endpoints 
    GET /oracles
    A1. Requ...
    A1.3. Return List of Oracles
    A1.3. Re...
    ALS
    DB
    ALS...
    Key
    Key
    A1.2. Lookup All Oracle Registry Service End-points 
    API
    Internal Use-Only
    API...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-participants.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-participants.svg similarity index 100% rename from mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-participants.svg rename to docs/technical/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-participants.svg diff --git a/mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-parties.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-parties.svg similarity index 100% rename from mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-parties.svg rename to docs/technical/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-parties.svg diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.puml b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.puml new file mode 100644 index 000000000..3a6a6eecb --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.puml @@ -0,0 +1,92 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.4 Delete Oracle Endpoint + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS Admin Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service Admin API" as ALSADM +control "DELETE Oracle Handler" as ORC_HANDLER +database "ALS Store" as DB + +box "Account Lookup Service" #LightYellow +participant ALSADM +participant ORC_HANDLER +participant DB +end box + +' start flow + +activate OPERATOR +group Get Oracle Endpoint + OPERATOR -> ALSADM: Request to Delete Oracle Endpoint -\nDELETE /oracles/{ID} + activate ALSADM + + ALSADM -> ORC_HANDLER: Delete Oracle Endpoint + + activate ORC_HANDLER + ORC_HANDLER -> DB: Update existing Oracle Endpoint By ID + hnote over DB #lightyellow + Update isActive = false + end note + alt Delete existing Oracle Endpoint (success) + activate DB + DB -> ORC_HANDLER: Return Success + deactivate DB + + ORC_HANDLER -> ALSADM: Return success response + deactivate ORC_HANDLER + ALSADM --> OPERATOR: Return HTTP Status: 204 + + deactivate ALSADM + deactivate OPERATOR + end + alt Delete existing Oracle Endpoint (failure) + DB -> ORC_HANDLER: Throws Error (Not Found) + ORC_HANDLER -> ALSADM: Throw Error + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + ALSADM --> OPERATOR: Return HTTP Status: 502 + end +end + +@enduml diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.svg new file mode 100644 index 000000000..c15d79f0e --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.svg @@ -0,0 +1,111 @@ + + 7.3.4 Delete Oracle Endpoint + + + 7.3.4 Delete Oracle Endpoint + + Account Lookup Service + + + + + + + + + + + + HUB OPERATOR + + + HUB OPERATOR + + + Account Lookup Service Admin API + + + Account Lookup Service Admin API + + + DELETE Oracle Handler + + + DELETE Oracle Handler + + + ALS Store + + + ALS Store + + + + + + + + + Get Oracle Endpoint + + + 1 + Request to Delete Oracle Endpoint - + DELETE /oracles/{ID} + + + 2 + Delete Oracle Endpoint + + + 3 + Update existing Oracle Endpoint By ID + + Update isActive = false + + + alt + [Delete existing Oracle Endpoint (success)] + + + 4 + Return Success + + + 5 + Return success response + + + 6 + Return + HTTP Status: + 204 + + + alt + [Delete existing Oracle Endpoint (failure)] + + + 7 + Throws Error (Not Found) + + + 8 + Throw Error + + + Message: + { + "errorInformation": { + "errorCode": <Error Code>, + "errorDescription": <Msg>, + } + } + + + 9 + Return + HTTP Status: + 502 + + diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.puml b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.puml new file mode 100644 index 000000000..b800d83f9 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.puml @@ -0,0 +1,116 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.1 Get All Oracle Endpoints + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS Admin Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service Admin API" as ALSADM +control "Get Oracles Handler" as ORC_HANDLER +database "ALS Store" as DB + +box "Account Lookup Service" #LightYellow +participant ALSADM +participant ORC_HANDLER +participant DB +end box + +' start flow + +activate OPERATOR +group Get Oracle Endpoints + OPERATOR -> ALSADM: Request to GET all Oracle Endpoints -\nGET /oracles?currency=USD&type=MSISDN + activate ALSADM + + ALSADM -> ORC_HANDLER: Get Oracle Endpoints + activate ORC_HANDLER + ORC_HANDLER -> DB: Get oracle endpoints + activate DB + + alt Get Oracle Endpoints (success) + DB --> ORC_HANDLER: Return Oracle Endpoints + deactivate DB + + deactivate DB + ORC_HANDLER -> ALSADM: Return Oracle Endpoints + deactivate ORC_HANDLER + note left of ALSADM #yellow + Message: + { + [ + { + "oracleId": , + "oracleIdType": , + "endpoint": { + "value": , + "endpointType": + }, + "currency": , + "isDefault": + } + ] + } + end note + ALSADM --> OPERATOR: Return HTTP Status: 200 + + deactivate ALSADM + deactivate OPERATOR + end + + alt Get Oracle Endpoints (failure) + DB --> ORC_HANDLER: Throw Error + deactivate DB + ORC_HANDLER -> ALSADM: Throw Error + deactivate ORC_HANDLER + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + + ALSADM --> OPERATOR: Return HTTP Status: 502 + + deactivate ALSADM + deactivate OPERATOR + + + end +end + +@enduml diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.svg new file mode 100644 index 000000000..9a1ab4649 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.svg @@ -0,0 +1,126 @@ + + 7.3.1 Get All Oracle Endpoints + + + 7.3.1 Get All Oracle Endpoints + + Account Lookup Service + + + + + + + + + + + + HUB OPERATOR + + + HUB OPERATOR + + + Account Lookup Service Admin API + + + Account Lookup Service Admin API + + + Get Oracles Handler + + + Get Oracles Handler + + + ALS Store + + + ALS Store + + + + + + + + + Get Oracle Endpoints + + + 1 + Request to GET all Oracle Endpoints - + GET /oracles?currency=USD&type=MSISDN + + + 2 + Get Oracle Endpoints + + + 3 + Get oracle endpoints + + + alt + [Get Oracle Endpoints (success)] + + + 4 + Return Oracle Endpoints + + + 5 + Return Oracle Endpoints + + + Message: + { + [ + { + "oracleId": <string>, + "oracleIdType": <PartyIdType>, + "endpoint": { + "value": <string>, + "endpointType": <EndpointType> + }, + "currency": <Currency>, + "isDefault": <boolean> + } + ] + } + + + 6 + Return + HTTP Status: + 200 + + + alt + [Get Oracle Endpoints (failure)] + + + 7 + Throw Error + + + 8 + Throw Error + + + Message: + { + "errorInformation": { + "errorCode": <Error Code>, + "errorDescription": <Msg>, + } + } + + + 9 + Return + HTTP Status: + 502 + + diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.puml b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.puml new file mode 100644 index 000000000..083b0fac2 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.puml @@ -0,0 +1,112 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.2 Create Oracle Endpoints + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS Admin Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service Admin API" as ALSADM +control "POST Oracle Handler" as ORC_HANDLER +database "ALS Store" as DB + +box "Account Lookup Service" #LightYellow +participant ALSADM +participant ORC_HANDLER +participant DB +end box + +' start flow + +activate OPERATOR +group Get Oracle Endpoint + OPERATOR -> ALSADM: Request to Create Oracle Endpoint -\nPOST /oracles + note left of ALSADM #yellow + Message: + { + "oracleIdType": , + "endpoint": { + "value": , + "endpointType": + }, + "currency": , + "isDefault": + } + end note + activate ALSADM + + ALSADM -> ORC_HANDLER: Create Oracle Endpoint + + activate ORC_HANDLER + ORC_HANDLER -> ORC_HANDLER: Build Oracle Endpoint Data Object + ORC_HANDLER -> DB: Insert Oracle Endpoint Data Object + activate DB + + alt Create Oracle Entry (success) + DB --> ORC_HANDLER: Return success response + deactivate DB + + ORC_HANDLER -> ALSADM: Return success response + deactivate ORC_HANDLER + ALSADM --> OPERATOR: Return HTTP Status: 201 + + deactivate ALSADM + deactivate OPERATOR + end + + alt Create Oracle Entry (failure) + DB --> ORC_HANDLER: Throw Error + deactivate DB + ORC_HANDLER -> ALSADM: Throw Error + deactivate ORC_HANDLER + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + + ALSADM --> OPERATOR: Return HTTP Status: 502 + + deactivate ALSADM + deactivate OPERATOR + + + end +end + +@enduml diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.svg new file mode 100644 index 000000000..07b6a4441 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.svg @@ -0,0 +1,127 @@ + + 7.3.2 Create Oracle Endpoints + + + 7.3.2 Create Oracle Endpoints + + Account Lookup Service + + + + + + + + + + + + HUB OPERATOR + + + HUB OPERATOR + + + Account Lookup Service Admin API + + + Account Lookup Service Admin API + + + POST Oracle Handler + + + POST Oracle Handler + + + ALS Store + + + ALS Store + + + + + + + + + Get Oracle Endpoint + + + 1 + Request to Create Oracle Endpoint - + POST /oracles + + + Message: + { + "oracleIdType": <PartyIdType>, + "endpoint": { + "value": <string>, + "endpointType": <EndpointType> + }, + "currency": <Currency>, + "isDefault": <boolean> + } + + + 2 + Create Oracle Endpoint + + + + + 3 + Build Oracle Endpoint Data Object + + + 4 + Insert Oracle Endpoint Data Object + + + alt + [Create Oracle Entry (success)] + + + 5 + Return success response + + + 6 + Return success response + + + 7 + Return + HTTP Status: + 201 + + + alt + [Create Oracle Entry (failure)] + + + 8 + Throw Error + + + 9 + Throw Error + + + Message: + { + "errorInformation": { + "errorCode": <Error Code>, + "errorDescription": <Msg>, + } + } + + + 10 + Return + HTTP Status: + 502 + + diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.puml b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.puml new file mode 100644 index 000000000..142eae685 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.puml @@ -0,0 +1,131 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.3 Update Oracle Endpoint + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS Admin Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service Admin API" as ALSADM +control "PUT Oracle Handler" as ORC_HANDLER +database "ALS Store" as DB + +box "Account Lookup Service" #LightYellow +participant ALSADM +participant ORC_HANDLER +participant DB +end box + +' start flow + +activate OPERATOR +group Get Oracle Endpoint + OPERATOR -> ALSADM: Request to Update Oracle Endpoint -\nPUT /oracles/{ID} + note left of ALSADM #yellow + Message: + { + "oracleIdType": , + "endpoint": { + "value": , + "endpointType": + }, + "currency": , + "isDefault": + } + end note + activate ALSADM + + ALSADM -> ORC_HANDLER: Update Oracle Endpoint + + activate ORC_HANDLER + ORC_HANDLER -> DB: Find existing Oracle Endpoint + alt Find existing Oracle Endpoint (success) + activate DB + DB -> ORC_HANDLER: Return Oracle Endpoint Result + deactivate DB + ORC_HANDLER -> ORC_HANDLER: Update Returned Oracle Data Object + ORC_HANDLER -> DB: Update Oracle Data Object + activate DB + alt Update Oracle Entry (success) + DB --> ORC_HANDLER: Return success response + deactivate DB + + ORC_HANDLER -> ALSADM: Return success response + deactivate ORC_HANDLER + ALSADM --> OPERATOR: Return HTTP Status: 204 + + deactivate ALSADM + deactivate OPERATOR + end + + alt Update Oracle Entry (failure) + DB --> ORC_HANDLER: Throw Error + deactivate DB + ORC_HANDLER -> ALSADM: Throw Error + deactivate ORC_HANDLER + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + + ALSADM --> OPERATOR: Return HTTP Status: 502 + + deactivate ALSADM + deactivate OPERATOR + + + end + end + alt Find existing Oracle Endpoint (failure) + DB -> ORC_HANDLER: Returns Empty Object + ORC_HANDLER -> ALSADM: Throw Error + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + ALSADM --> OPERATOR: Return HTTP Status: 502 + end +end + +@enduml diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.svg new file mode 100644 index 000000000..449542355 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.svg @@ -0,0 +1,170 @@ + + 7.3.3 Update Oracle Endpoint + + + 7.3.3 Update Oracle Endpoint + + Account Lookup Service + + + + + + + + + + + + + + + HUB OPERATOR + + + HUB OPERATOR + + + Account Lookup Service Admin API + + + Account Lookup Service Admin API + + + PUT Oracle Handler + + + PUT Oracle Handler + + + ALS Store + + + ALS Store + + + + + + + + + + Get Oracle Endpoint + + + 1 + Request to Update Oracle Endpoint - + PUT /oracles/{ID} + + + Message: + { + "oracleIdType": <PartyIdType>, + "endpoint": { + "value": <string>, + "endpointType": <EndpointType> + }, + "currency": <Currency>, + "isDefault": <boolean> + } + + + 2 + Update Oracle Endpoint + + + 3 + Find existing Oracle Endpoint + + + alt + [Find existing Oracle Endpoint (success)] + + + 4 + Return Oracle Endpoint Result + + + + + 5 + Update Returned Oracle Data Object + + + 6 + Update Oracle Data Object + + + alt + [Update Oracle Entry (success)] + + + 7 + Return success response + + + 8 + Return success response + + + 9 + Return + HTTP Status: + 204 + + + alt + [Update Oracle Entry (failure)] + + + 10 + Throw Error + + + 11 + Throw Error + + + Message: + { + "errorInformation": { + "errorCode": <Error Code>, + "errorDescription": <Msg>, + } + } + + + 12 + Return + HTTP Status: + 502 + + + alt + [Find existing Oracle Endpoint (failure)] + + + 13 + Returns Empty Object + + + 14 + Throw Error + + + Message: + { + "errorInformation": { + "errorCode": <Error Code>, + "errorDescription": <Msg>, + } + } + + + 15 + Return + HTTP Status: + 502 + + diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.puml b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.puml new file mode 100644 index 000000000..3095e7bad --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.puml @@ -0,0 +1,104 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.0 Delete Endpoint Cache + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS API Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service API" as ALSAPI +control "Delete Endpoint Cache Handler" as DEL_HANDLER +database "Cache" as Cache + +box "Account Lookup Service" #LightYellow +participant ALSAPI +participant DEL_HANDLER +participant Cache +end box + +' start flow + +activate OPERATOR +group Delete Endpoint Cache + OPERATOR -> ALSAPI: Request to DELETE Endpoint Cache - DELETE /endpointcache + activate ALSAPI + activate ALSAPI + + ALSAPI -> DEL_HANDLER: Delete Cache + activate DEL_HANDLER + DEL_HANDLER -> Cache: Stop Cache + activate Cache + + + alt Stop Cache Status (success) + Cache --> DEL_HANDLER: Return status + deactivate Cache + + DEL_HANDLER -> Cache: Initialize Cache + activate Cache + Cache -> DEL_HANDLER: Return Status + deactivate Cache + DEL_HANDLER -> ALSAPI: Return Status + deactivate DEL_HANDLER + ALSAPI --> OPERATOR: Return HTTP Status: 202 + + deactivate ALSAPI + deactivate OPERATOR + end + + alt Validate Status (service failure) + Cache --> DEL_HANDLER: Throw Error + deactivate Cache + DEL_HANDLER -> ALSAPI: Throw Error + deactivate DEL_HANDLER + note left of ALSAPI #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + + ALSAPI --> OPERATOR: Return HTTP Status: 502 + + deactivate ALSAPI + deactivate OPERATOR + + + end +end + +@enduml diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.svg new file mode 100644 index 000000000..916884be8 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.svg @@ -0,0 +1,120 @@ + + 7.3.0 Delete Endpoint Cache + + + 7.3.0 Delete Endpoint Cache + + Account Lookup Service + + + + + + + + + + + + + + HUB OPERATOR + + + HUB OPERATOR + + + Account Lookup Service API + + + Account Lookup Service API + + + Delete Endpoint Cache Handler + + + Delete Endpoint Cache Handler + + + Cache + + + Cache + + + + + + + + + + + Delete Endpoint Cache + + + 1 + Request to DELETE Endpoint Cache - DELETE /endpointcache + + + 2 + Delete Cache + + + 3 + Stop Cache + + + alt + [Stop Cache Status (success)] + + + 4 + Return status + + + 5 + Initialize Cache + + + 6 + Return Status + + + 7 + Return Status + + + 8 + Return + HTTP Status: + 202 + + + alt + [Validate Status (service failure)] + + + 9 + Throw Error + + + 10 + Throw Error + + + Message: + { + "errorInformation": { + "errorCode": <Error Code>, + "errorDescription": <Msg>, + } + } + + + 11 + Return + HTTP Status: + 502 + + diff --git a/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.plantuml b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.plantuml similarity index 100% rename from mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.plantuml rename to docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.plantuml diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.svg new file mode 100644 index 000000000..47aa36464 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.svg @@ -0,0 +1,357 @@ + + 7.1.2. Delete Participant Details + + + 7.1.2. Delete Participant Details + + Financial Service Provider + + Account Lookup Service + + Central Services + + ALS Oracle Service/Adapter + + Financial Service Provider + + + + + + + + + + + + + + + + + + + + + + + + + + Payer FSP + + + Payer FSP + + + Account Lookup + Service (ALS) + + + Account Lookup + Service (ALS) + + + ALS Participant + Handler + + + ALS Participant + Handler + + + ALS Participant Endpoint + Oracle DAO + + + ALS Participant Endpoint + Oracle DAO + + + ALS Database + + + ALS Database + + + ALS CentralService + Endpoint DAO + + + ALS CentralService + Endpoint DAO + + + ALS CentralService + Participant DAO + + + ALS CentralService + Participant DAO + + + ALS Parties + FSP DAO + + + ALS Parties + FSP DAO + + + Central Service API + + + Central Service API + + + Oracle Service API + + + Oracle Service API + + + Payee FSP + + + Payee FSP + + + + + + + + + + + + + + + Get Party Details + + + + 1 + Request to delete Participant details + DEL - /participants/{TYPE}/{ID}?currency={CURRENCY} + Response code: + 202 + Error code: + 200x, 300x, 310x, 320x + + + Validate request against + Mojaloop Interface Specification. + Error code: + 300x, 310x + + + 2 + Request to delete Participant details + + + alt + [oracleEndpoint match found & parties information retrieved] + + + + 3 + Get Oracle Routing Config + Error code: + 200x, 310x, 320x + + + ref + GET Participants - + + Get Oracle Routing Config Sequence + + + + + + + Validate FSPIOP-Source Participant + + + 4 + Request FSPIOP-Source participant information + Error code: + 200x + + + 5 + GET - /participants/{FSPIOP-Source} + Error code: + 200x, 310x, 320x + + + 6 + Return FSPIOP-Source participant information + + + 7 + Return FSPIOP-Source participant information + + + + + 8 + Validate FSPIOP-Source participant + Error code: + 320x + + + + + 9 + Validate that PARTICIPANT.fspId == FSPIOP-Source + Error code: + 3100 + + + + 10 + Get Participant Information for PayerFSP + Error code: + 200x, 310x, 320x + + + ref + GET Participants - + + Request Participant Information from Oracle Sequence + + + + + + + Validate Participant Ownership + + + + + 11 + Validate that PARTICIPANT.fspId matches Participant Information retrieved from Oracle. + Error code: + 3100 + + + 12 + Request to delete Participant's FSP details DEL - /participants/{TYPE}/{ID}?currency={CURRENCY} + Error code: + 200x, 310x, 320x + + + 13 + Request to delete Participant's FSP details DEL - /participants/{TYPE}/{ID}?currency={CURRENCY} + Response code: + 200 +   + Error code: + 200x, 310x, 320x + + + 14 + Return result + + + 15 + Return result + + + 16 + Retrieve the PayerFSP Participant Callback Endpoint + Error code: + 200x + + + 17 + Retrieve the PayerFSP Participant Callback Endpoint + GET - /participants/{FSPIOP-Source}/endpoints + Error code: + 200x, 310x, 320x + + + 18 + List of PayerFSP Participant Callback Endpoints + + + 19 + List of PayerFSP Participant Callback Endpoints + + + + + 20 + Match PayerFSP Participant Callback Endpoints for + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + + 21 + Return delete request result + + + + 22 + Callback indiciating success: + PUT - /participants/{TYPE}/{ID}?currency={CURRENCY} + + [Validation failure or Oracle was unable process delete request] + + + 23 + Retrieve the PayerFSP Participant Callback Endpoint + Error code: + 200x, 310x, 320x + + + 24 + Retrieve the PayerFSP Participant Callback Endpoint + GET - /participants/{FSPIOP-Source}/endpoints + Response code: + 200 + Error code: + 200x, 310x, 320x + + + 25 + List of PayerFSP Participant Callback Endpoints + + + 26 + List of PayerFSP Participant Callback Endpoints + + + + + 27 + Match PayerFSP Participant Callback Endpoints for + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + + 28 + Handle error + Error code: + 200x, 310x, 320x + + + + 29 + Callback: PUT - /participants/{TYPE}/{ID}/error + + [Empty list of switchEndpoint results returned] + + + + + 30 + Handle error + Error code: + 200x + + Error Handling Framework + + diff --git a/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.plantuml b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.plantuml similarity index 100% rename from mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.plantuml rename to docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.plantuml diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.svg new file mode 100644 index 000000000..70592a767 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.svg @@ -0,0 +1,308 @@ + + 7.1.0. Get Participant Details + + + 7.1.0. Get Participant Details + + Financial Service Provider + + Account Lookup Service + + Central Services + + ALS Oracle Service/Adapter + + + + + + + + + + + + + + + + + + + + + + + + + Payer FSP + + + Payer FSP + + + Account Lookup + Service (ALS) + + + Account Lookup + Service (ALS) + + + ALS Participant + Handler + + + ALS Participant + Handler + + + ALS Endpoint Type + Config DAO + + + ALS Endpoint Type + Config DAO + + + ALS Participant + Oracle DAO + + + ALS Participant + Oracle DAO + + + ALS Database + + + ALS Database + + + ALS CentralService + Endpoint DAO + + + ALS CentralService + Endpoint DAO + + + Central Service API + + + Central Service API + + + Oracle Service API + + + Oracle Service API + + + + + + + + + + + + + + + Get Participant's FSP Details + + + + 1 + Request to get participant's FSP details + GET - /participants/{TYPE}/{ID}?currency={CURRENCY} + Response code: + 202 +   + Error code: + 200x, 300x, 310x, 320x + + + Validate request against + Mojaloop Interface Specification. + Error code: + 300x, 310x + + + 2 + Request to get participant's FSP details + + + alt + [oracleEndpoint match found] + + + IMPLEMENTATION: Get Oracle Routing Config Sequence + [CACHED] + + + 3 + Fetch Oracle Routing information based on + {TYPE} and {CURRENCY} if provided + Error code: + 200x + + + 4 + Retrieve oracleEndpoint + Error code: + 200x + + oracleEndpoint + endpointType + partyIdType + currency (optional) + + + 5 + Return oracleEndpoint result set + + + 6 + List of + oracleEndpoint + for the Participant + + + opt + [oracleEndpoint IS NULL] + + + + + 7 + Error code: + 3200 + + + IMPLEMENTATION: Request Participant Information from Oracle Sequence + + + 8 + Request to get participant's FSP details + GET - /participants/{TYPE}/{ID}?currency={CURRENCY} + Error code: + 200x, 310x, 320x + + + 9 + Request to get participant's FSP details + GET - /participants/{TYPE}/{ID}?currency={CURRENCY} + Response code: + 200 +   + Error code: + 200x, 310x, 320x + + + 10 + Return list of Participant information + + + 11 + Return list of Participant information + + + 12 + Retrieve the PayerFSP Participant Callback Endpoint + Error code: + 200x, 310x, 320x + + + 13 + Retrieve the PayerFSP Participant Callback Endpoint + GET - /participants/{FSPIOP-Source}/endpoints + Response code: + 200 +   + Error code: + 200x, 310x, 320x + + + 14 + List of PayerFSP Participant Callback Endpoints + + + 15 + List of PayerFSP Participant Callback Endpoints + + + + + 16 + Match PayerFSP Participant Callback Endpoints for + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + + 17 + Return list of Participant information + + + + 18 + Callback: PUT - /participants/{TYPE}/{ID}?currency={CURRENCY} + + [oracleEndpoint IS NULL OR error occurred] + + + 19 + Retrieve the Participant Callback Endpoint + Error code: + 200x, 310x, 320x + + + 20 + Retrieve the Participant Callback Endpoint + GET - /participants/{FSPIOP-Source}/endpoints. + Response code: + 200 +   + Error code: + 200x, 310x, 320x + + + 21 + List of Participant Callback Endpoints + + + 22 + List of Participant Callback Endpoints + + + + + 23 + Match Participant Callback Endpoints for + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + + 24 + Handle error + Error code: + 200x, 310x, 320x + + + + 25 + Callback: PUT - /participants/{TYPE}/{ID}/error + + [switchEndpoint IS NULL] + + + + + 26 + Handle error + Error code: + 200x + + Error Handling Framework + + diff --git a/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.plantuml b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.plantuml similarity index 100% rename from mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.plantuml rename to docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.plantuml diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.svg new file mode 100644 index 000000000..6c1cfad73 --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.svg @@ -0,0 +1,389 @@ + + 7.2.0. Get Party Details + + + 7.2.0. Get Party Details + + Financial Service Provider + + Account Lookup Service + + Central Services + + ALS Oracle Service/Adapter + + Financial Service Provider + + + + + + + + + + + + + + + + + + + + + + + + + + Payer FSP + + + Payer FSP + + + Account Lookup + Service (ALS) + + + Account Lookup + Service (ALS) + + + ALS Participant + Handler + + + ALS Participant + Handler + + + ALS Database + + + ALS Database + + + ALS CentralService + Endpoint DAO + + + ALS CentralService + Endpoint DAO + + + ALS CentralService + Participant DAO + + + ALS CentralService + Participant DAO + + + ALS Parties + FSP DAO + + + ALS Parties + FSP DAO + + + Central Service API + + + Central Service API + + + Oracle Service API + + + Oracle Service API + + + Payee FSP + + + Payee FSP + + + + + + + + + + + + + + + + + Get Party Details + + + + 1 + Request to get parties's FSP details + GET - /parties/{TYPE}/{ID}?currency={CURRENCY} + Response code: + 202 + Error code: + 200x, 300x, 310x, 320x + + + Validate request against + Mojaloop Interface Specification. + Error code: + 300x, 310x + + + 2 + Request to get parties's FSP details + + + alt + [oracleEndpoint match found & parties information retrieved] + + + + 3 + Get Oracle Routing Config + Error code: + 200x, 310x, 320x + + + ref + GET Participants - + + Get Oracle Routing Config Sequence + + + + + + + Validate FSPIOP-Source Participant + + + 4 + Request FSPIOP-Source participant information + Error code: + 200x + + + 5 + GET - /participants/{FSPIOP-Source} + Error code: + 200x, 310x, 320x + + + 6 + Return FSPIOP-Source participant information + + + 7 + Return FSPIOP-Source participant information + + + + + 8 + Validate FSPIOP-Source participant + Error code: + 320x + + + + 9 + Get Participant Information for PayeeFSP + Error code: + 200x, 310x, 320x + + + ref + GET Participants - + + Request Participant Information from Oracle Sequence + + + + + + + 10 + Request Parties information from FSP. + Error code: + 200x + + + + 11 + Parties Callback to Destination: + GET - /parties/{TYPE}/{ID}?currency={CURRENCY} + Response code: + 202 + Error code: + 200x, 310x, 320x + + + + 12 + Callback with Participant Information: + PUT - /parties/{TYPE}/{ID}?currency={CURRENCY} + Error code: + 200x, 300x, 310x, 320x + + + + + 13 + Validate request against + Mojaloop Interface Specification + Error code: + 300x, 310x + + + 14 + Process Participant Callback Information for PUT + + + 15 + Retrieve the PayerFSP Participant Callback Endpoint + Error code: + 200x + + + 16 + Retrieve the PayerFSP Participant Callback Endpoint + GET - /participants/{FSPIOP-Source}/endpoints + Error code: + 200x, 310x, 320x + + + 17 + List of PayerFSP Participant Callback Endpoints + + + 18 + List of PayerFSP Participant Callback Endpoints + + + + + 19 + Match PayerFSP Participant Callback Endpoints for + FSPIOP_CALLBACK_URL_PARTIES_PUT + + + 20 + Return Participant Information to PayerFSP + + + + 21 + Callback with Parties Information: + PUT - /parties/{TYPE}/{ID}?currency={CURRENCY} + + [Empty list of End-Points returned for either (PayeeFSP or Oracle) config information or Error occurred for PayerFSP] + + + 22 + Retrieve the PayerFSP Participant Callback Endpoint + Error code: + 200x, 310x, 320x + + + 23 + Retrieve the PayerFSP Participant Callback Endpoint + GET - /participants/{FSPIOP-Source}/endpoints + Response code: + 200 + Error code: + 200x, 310x, 320x + + + 24 + List of PayerFSP Participant Callback Endpoints + + + 25 + List of PayerFSP Participant Callback Endpoints + + + + + 26 + Match PayerFSP Participant Callback Endpoints for + FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR + + + 27 + Handle error + Error code: + 200x, 310x, 320x + + + + 28 + Callback: PUT - /participants/{TYPE}/{ID}/error + + [Empty list of End-Points returned for PayerFSP config information or Error occurred for PayeeFSP] + + + 29 + Retrieve the PayeeFSP Participant Callback Endpoint + Error code: + 200x, 310x, 320x + + + 30 + Retrieve the PayeeFSP Participant Callback Endpoint + GET - /participants/{FSPIOP-Source}/endpoints + Response code: + 200 + Error code: + 200x, 310x, 320x + + + 31 + List of PayeeFSP Participant Callback Endpoints + + + 32 + List of PayeeFSP Participant Callback Endpoints + + + + + 33 + Match PayeeFSP Participant Callback Endpoints for + FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR + + + 34 + Handle error + Error code: + 200x, 310x, 320x + + + + 35 + Callback: PUT - /participants/{TYPE}/{ID}/error + + [Empty list of switchEndpoint results returned] + + + + + 36 + Handle error + Error code: + 200x + + Error Handling Framework + + diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.plantuml b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.plantuml new file mode 100644 index 000000000..7769e3a8d --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.plantuml @@ -0,0 +1,213 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.1.3 Post Participant Details by Type and ID + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +actor "Payer FSP" as PAYER_FSP +boundary "Account Lookup\nService (ALS)" as ALS_API +control "ALS Participant\nHandler" as ALS_PARTICIPANT_HANDLER +entity "ALS CentralService\nEndpoint DAO" as ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +entity "ALS CentralService\nParticipant DAO" as ALS_CENTRALSERVICE_PARTICIPANT_DAO +entity "ALS Participant\nOracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +database "ALS Database" as ALS_DB +boundary "Oracle Service API" as ORACLE_API +boundary "Central Service API" as CENTRALSERVICE_API + +box "Financial Service Provider" #LightGrey +participant PAYER_FSP +end box + +box "Account Lookup Service" #LightYellow +participant ALS_API +participant ALS_PARTICIPANT_HANDLER +participant ALS_PARTICIPANT_ORACLE_DAO +participant ALS_DB +participant ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +participant ALS_CENTRALSERVICE_PARTICIPANT_DAO +end box + +box "Central Services" #LightGreen +participant CENTRALSERVICE_API +end box + +box "ALS Oracle Service/Adapter" #LightBlue +participant ORACLE_API +end box + +' START OF FLOW + +group Post Participant's FSP Details + note right of PAYER_FSP #yellow + Headers - postParticipantsByTypeIDHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - postParticipantsByTypeIDMessage: + { + "fspId": "string" + } + end note + PAYER_FSP ->> ALS_API: Request to add participant's FSP details\nPOST - /participants/{Type}/{ID}\nResponse code: 202 \nError code: 200x, 300x, 310x, 320x + + activate ALS_API + note left ALS_API #lightgray + Validate request against + Mojaloop Interface Specification. + Error code: 300x, 310x + end note + + ALS_API -> ALS_PARTICIPANT_HANDLER: Process create participant's FSP details + deactivate ALS_API + activate ALS_PARTICIPANT_HANDLER + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate that PARTICIPANT.fspId == FSPIOP-Source\nError code: 3100 + + '********************* Sort into Participant buckets based on {TYPE} - END ************************ + + alt Validation passed + + + '********************* Fetch Oracle Routing Information - START ************************ + + '********************* Retrieve Oracle Routing Information - START ************************ + + ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Oracle Routing Config based on Type (and optional Currency)\nError code: 300x, 310x + ref over ALS_PARTICIPANT_HANDLER, ALS_DB + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Oracle Routing Config Sequence]] + ||| + end ref + + '********************* Retrieve Oracle Routing Information - END ************************ + + ||| + +' '********************* Fetch Oracle Routing Information - END ************************ +' +' '********************* Retrieve Switch Routing Information - START ************************ +' +' ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Switch Routing Config\nError code: 300x, 310x +' ref over ALS_PARTICIPANT_HANDLER, ALS_DB +' ||| +' GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Switch Routing Config Sequence]] +' ||| +' end ref +' +' '********************* Retrieve Switch Routing Information - END ************************ +' ||| + + '********************* Validate Participant - START ************************ + group Validate Participant's FSP + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Request participant (PARTICIPANT.fspId) information for {Type}\nError code: 200x + activate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_CENTRALSERVICE_PARTICIPANT_DAO -> CENTRALSERVICE_API: GET - /participants/{PARTICIPANT.fspId}\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Return participant information + deactivate CENTRALSERVICE_API + + ALS_CENTRALSERVICE_PARTICIPANT_DAO --> ALS_PARTICIPANT_HANDLER: Return participant information + + deactivate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate participant\nError code: 320x + end group + '********************* Validate Participant - END ************************ + + '********************* Create Participant Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_ORACLE_DAO: Create participant's FSP details\nPOST - /participants\nError code: 200x, 310x, 320x + activate ALS_PARTICIPANT_ORACLE_DAO + ALS_PARTICIPANT_ORACLE_DAO -> ORACLE_API: Create participant's FSP details\nPOST - /participants\nResponse code: 204 \nError code: 200x, 310x, 320x + activate ORACLE_API + + ORACLE_API --> ALS_PARTICIPANT_ORACLE_DAO: Return result of Participant Create request + deactivate ORACLE_API + + ALS_PARTICIPANT_ORACLE_DAO --> ALS_PARTICIPANT_HANDLER: Return result of Participant Create request + deactivate ALS_PARTICIPANT_ORACLE_DAO + + '********************* Create Participant Information - END ************************ + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Return list of Participant information from ParticipantResult + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{Type}/{ID} + + else Validation failure + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{Type}/{ID}/error + end alt + + + deactivate ALS_PARTICIPANT_HANDLER +end +@enduml diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.svg new file mode 100644 index 000000000..b38dcc95a --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.svg @@ -0,0 +1,326 @@ + + 7.1.3 Post Participant Details by Type and ID + + + 7.1.3 Post Participant Details by Type and ID + + Financial Service Provider + + Account Lookup Service + + Central Services + + ALS Oracle Service/Adapter + + + + + + + + + + + + + + + + + + + + + + + Payer FSP + + + Payer FSP + + + Account Lookup + Service (ALS) + + + Account Lookup + Service (ALS) + + + ALS Participant + Handler + + + ALS Participant + Handler + + + ALS Participant + Oracle DAO + + + ALS Participant + Oracle DAO + + + ALS Database + + + ALS Database + + + ALS CentralService + Endpoint DAO + + + ALS CentralService + Endpoint DAO + + + ALS CentralService + Participant DAO + + + ALS CentralService + Participant DAO + + + Central Service API + + + Central Service API + + + Oracle Service API + + + Oracle Service API + + + + + + + + + + + + + + + Post Participant's FSP Details + + + Headers - postParticipantsByTypeIDHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } +   + Payload - postParticipantsByTypeIDMessage: + { + "fspId": "string" + } + + + + 1 + Request to add participant's FSP details + POST - /participants/{Type}/{ID} + Response code: + 202 +   + Error code: + 200x, 300x, 310x, 320x + + + Validate request against + Mojaloop Interface Specification. + Error code: + 300x, 310x + + + 2 + Process create participant's FSP details + + + + + 3 + Validate that PARTICIPANT.fspId == FSPIOP-Source + Error code: + 3100 + + + alt + [Validation passed] + + + + 4 + Get Oracle Routing Config based on Type (and optional Currency) + Error code: + 300x, 310x + + + ref + GET Participants - + + Get Oracle Routing Config Sequence + + + + + + + Validate Participant's FSP + + + 5 + Request participant (PARTICIPANT.fspId) information for {Type} + Error code: + 200x + + + 6 + GET - /participants/{PARTICIPANT.fspId} + Response code: + 200 +   + Error code: + 200x, 310x, 320x + + + 7 + Return participant information + + + 8 + Return participant information + + + + + 9 + Validate participant + Error code: + 320x + + + 10 + Create participant's FSP details + POST - /participants + Error code: + 200x, 310x, 320x + + + 11 + Create participant's FSP details + POST - /participants + Response code: + 204 +   + Error code: + 200x, 310x, 320x + + + 12 + Return result of Participant Create request + + + 13 + Return result of Participant Create request + + + 14 + Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint + Error code: + 200x, 310x, 320x + + + 15 + Retrieve the PayerFSP Participant Callback Endpoint + GET - /participants/{FSPIOP-Source}/endpoints + Response code: + 200 +   + Error code: + 200x, 310x, 320x + + + 16 + List of PayerFSP Participant Callback Endpoints + + + 17 + List of PayerFSP Participant Callback Endpoints + + + + + 18 + Match PayerFSP Participant Callback Endpoints for + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + + 19 + Return list of Participant information from ParticipantResult + + + + 20 + Callback: PUT - /participants/{Type}/{ID} + + [Validation failure] + + + 21 + Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint + Error code: + 200x, 310x, 320x + + + 22 + Retrieve the PayerFSP Participant Callback Endpoint + GET - /participants/{FSPIOP-Source}/endpoints + Response code: + 200 +   + Error code: + 200x, 310x, 320x + + + 23 + List of PayerFSP Participant Callback Endpoints + + + 24 + List of PayerFSP Participant Callback Endpoints + + + + + 25 + Match Participant Callback Endpoints for + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + + 26 + Handle error + Error code: + 200x, 310x, 320x + + + + 27 + Callback: PUT - /participants/{Type}/{ID}/error + + diff --git a/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.plantuml b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.plantuml similarity index 100% rename from mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.plantuml rename to docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.plantuml diff --git a/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.svg b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.svg new file mode 100644 index 000000000..aed0ef55f --- /dev/null +++ b/docs/technical/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.svg @@ -0,0 +1,368 @@ + + 7.1.1. Post Participant (Batch) Details + + + 7.1.1. Post Participant (Batch) Details + + Financial Service Provider + + Account Lookup Service + + Central Services + + ALS Oracle Service/Adapter + + + + + + + + + + + + + + + + + + + + + + + + + + Payer FSP + + + Payer FSP + + + Account Lookup + Service (ALS) + + + Account Lookup + Service (ALS) + + + ALS Participant + Handler + + + ALS Participant + Handler + + + ALS Participant + Oracle DAO + + + ALS Participant + Oracle DAO + + + ALS Database + + + ALS Database + + + ALS CentralService + Endpoint DAO + + + ALS CentralService + Endpoint DAO + + + ALS CentralService + Participant DAO + + + ALS CentralService + Participant DAO + + + Central Service API + + + Central Service API + + + Oracle Service API + + + Oracle Service API + + + + + + + + + + + + + + + Post Participant's FSP Details + + + Headers - postParticipantsHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } +   + Payload - postParticipantsMessage: + { + "requestId": "string", + "partyList": [ + { + "partyIdType": "string", + "partyIdentifier": "string", + "partySubIdOrType": "string", + "fspId": "string" + } + ], + "currency": "string" + } + + + + 1 + Request to add participant's FSP details + POST - /participants + Response code: + 202 +   + Error code: + 200x, 300x, 310x, 320x + + + Validate request against + Mojaloop Interface Specification. + Error code: + 300x, 310x + + + 2 + Process create participant's FSP details + + + loop + [for Participant in ParticipantList] + + + + + 3 + Validate that PARTICIPANT.fspId == FSPIOP-Source + Error code: + 3100 + + + + + 4 + Group Participant lists into a Map (ParticipantMap) based on {TYPE} + + + alt + [Validation passed and the ParticipantMap was created successfully] + + + loop + [for keys in ParticipantMap -> TypeKey] + + + + 5 + Get Oracle Routing Config based on TypeKey (and optional Currency) + Error code: + 300x, 310x + + + ref + GET Participants - + + Get Oracle Routing Config Sequence + + + + + + + Validate Participant's FSP + + + 6 + Request participant (PARTICIPANT.fspId) information for {TypeKey} + Error code: + 200x + + + 7 + GET - /participants/{PARTICIPANT.fspId} + Response code: + 200 +   + Error code: + 200x, 310x, 320x + + + 8 + Return participant information + + + 9 + Return participant information + + + + + 10 + Validate participant + Error code: + 320x + + + 11 + Create participant's FSP details + POST - /participants + Error code: + 200x, 310x, 320x + + + 12 + Create participant's FSP details + POST - /participants + Response code: + 204 +   + Error code: + 200x, 310x, 320x + + + 13 + Return result of Participant Create request + + + 14 + Return result of Participant Create request + + + + + 15 + Store results in ParticipantResultMap[TypeKey] + + + loop + [for keys in ParticipantResultMap -> TypeKey] + + + + + 16 + Combine ParticipantResultMap[TypeKey] results into ParticipantResult + + + 17 + Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint + Error code: + 200x, 310x, 320x + + + 18 + Retrieve the PayerFSP Participant Callback Endpoint + GET - /participants/{FSPIOP-Source}/endpoints + Response code: + 200 +   + Error code: + 200x, 310x, 320x + + + 19 + List of PayerFSP Participant Callback Endpoints + + + 20 + List of PayerFSP Participant Callback Endpoints + + + + + 21 + Match PayerFSP Participant Callback Endpoints for + FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT + + + 22 + Return list of Participant information from ParticipantResult + + + + 23 + Callback: PUT - /participants/{requestId} + + [Validation failure and/or the ParticipantMap was not created successfully] + + + 24 + Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint + Error code: + 200x, 310x, 320x + + + 25 + Retrieve the PayerFSP Participant Callback Endpoint + GET - /participants/{FSPIOP-Source}/endpoints + Response code: + 200 +   + Error code: + 200x, 310x, 320x + + + 26 + List of PayerFSP Participant Callback Endpoints + + + 27 + List of PayerFSP Participant Callback Endpoints + + + + + 28 + Match Participant Callback Endpoints for + FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR + + + 29 + Handle error + Error code: + 200x, 310x, 320x + + + + 30 + Callback: PUT - /participants/{requestId}/error + + diff --git a/mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookup-ddl-MySQLWorkbench.sql b/docs/technical/technical/account-lookup-service/assets/entities/AccountLookup-ddl-MySQLWorkbench.sql similarity index 100% rename from mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookup-ddl-MySQLWorkbench.sql rename to docs/technical/technical/account-lookup-service/assets/entities/AccountLookup-ddl-MySQLWorkbench.sql diff --git a/mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookupDB-schema-DBeaver.erd b/docs/technical/technical/account-lookup-service/assets/entities/AccountLookupDB-schema-DBeaver.erd similarity index 100% rename from mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookupDB-schema-DBeaver.erd rename to docs/technical/technical/account-lookup-service/assets/entities/AccountLookupDB-schema-DBeaver.erd diff --git a/mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookupService-schema.png b/docs/technical/technical/account-lookup-service/assets/entities/AccountLookupService-schema.png similarity index 100% rename from mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookupService-schema.png rename to docs/technical/technical/account-lookup-service/assets/entities/AccountLookupService-schema.png diff --git a/mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI5.svg b/docs/technical/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI5.svg similarity index 100% rename from mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI5.svg rename to docs/technical/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI5.svg diff --git a/mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg b/docs/technical/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg similarity index 100% rename from mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg rename to docs/technical/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg diff --git a/mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-simple.svg b/docs/technical/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-simple.svg similarity index 100% rename from mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-simple.svg rename to docs/technical/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-simple.svg diff --git a/mojaloop-technical-overview/assets/diagrams/architecture/central_ledger_block_diagram.png b/docs/technical/technical/assets/diagrams/architecture/central_ledger_block_diagram.png similarity index 100% rename from mojaloop-technical-overview/assets/diagrams/architecture/central_ledger_block_diagram.png rename to docs/technical/technical/assets/diagrams/architecture/central_ledger_block_diagram.png diff --git a/docs/technical/technical/central-bulk-transfers/README.md b/docs/technical/technical/central-bulk-transfers/README.md new file mode 100644 index 000000000..c1d0b3d54 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/README.md @@ -0,0 +1,298 @@ +# Bulk Transfers Design + +The Bulk Transfers scenario is described in the API Definition document regarding the resource /bulkTransfers. For details _(refer to section `6.10`)_ as per the [Mojaloop Specification](https://github.com/mojaloop/mojaloop-specification/blob/master/API%20Definition%20v1.0.pdf) + +1. [Introduction](introduction) +2. [Design Considerations](design-considerations) +3. [Steps involved in the high-level Architecture](steps-involved-in-the-high-level-architecture) +4. [Notes](notes) + 1. [Discussion items](discussion-items) + 2. [Proposed new tables](proposed-new-tables) + 3. [Bulk Transfers States](bulk-transfers-states) + 4. [Additional Notes](additional-notes) +5. [Roadmap Topics](roadmap-topics) + +## 1. Introduction + +The Bulk Transfers process is discussed in section 6.10 of the API Definition 1.0 document, depicted in Figure 60, of which a snapshot is posted below. +![Figure 60](./assets/diagrams/architecture/Figure60-Example-Bulk-Transfer-Process-Spec1.0.png) + +The key items implied in the specification in its current version 1.0 are that + +- Reservation of funds is done for each individual transfer from the Payer FSP to the Payee FSP +- Even if a single individual transfer fails during the prepare process, the whole bulk is to be rejected. + +## 2. Design Considerations + +According to the Figure-60 of the specification, below are a few key implications from the Specification. + +1. The Payer DFSP performs user look-ups for the individual parties involved in the bulk payment separately +2. The Payer DFSP performs bulk quoting per Payee DFSP +3. The onus is on the Payer DFSP to prepare bulk transfers based on Payee FSPs and send out a bulk transfer request to a single Payee FSP +4. This seems to be an all-or-nothing process where even if a single individual transfer fails to be reserved, then the whole bulk needs to be rejected because it cannot be sent to the Payee as it is if it has an individual transfer for which funds couldn't be reserved. +5. In light of the above, the proposal being made right now is to empower the Switch (needs updating the Specification) to send out the POST /bulkTransfers request with the list of individual transfers for which funds were able to be reserved on the Switch. +6. The implication is that the Switch aggregates commits/failures from the Payee FSP for the bulk and sends out a single PUT /bulkTransfers/{ID} call to the Payer FSP that includes the entire list of transfers that includes individual transfers that failed both at the Switch and the Payee FSP +7. For example: If there are 1000 individual transfers in a Bulk Transfer and if the Switch is able to reserve funds for 900 of the individual transfers, then a prepare bulk transfer request to the Payee DFSP is sent with the list of those 900 individual transfers. Once the Payee FSP sends the Bulk Fulfil request for those 900 transfers of which lets say, 800 can be committed and 100 are aborted, then the Switch processes those individual transfers accordingly and sends out the PUT callback (PUT /bulkTransfers/{ID}) notification to the Payer FSP with all the 1000 individual transfers, 800 of which are committed and 200 of which are aborted. +8. There will be implications to aspects such as Signature, Encryption, PKI and other security aspects that will need to be addressed. +9. The ordering of the individual transfers need to be considered as well by the Scheme. A Goal for implementation in emerging markets is to maximize the number of transactions involved and so a well designed Scheme may re-order individual transfers in the ascending order of the magnitude of amounts and then process them. But this can be a Scheme consideration. +10. However, a recommended Scheme Rule is that the Payee FSPs shouldn't be allowed to re-order the individual transfers in a bulk to avoid bias towards Payee parties. +11. For Settlements with bulk transfers where Government payments are involved with large sums of money needs to be discussed to allow for moving through transfers without strict liquidity rules needs to be discussed. + +## 3. Steps involved in the high-level Architecture + +Below are the steps involved at a high level for bulk transfers. + +![architecture diagram](./assets/diagrams/architecture/bulk-transfer-arch-flows.svg) + +1. [1.0, 1.1, 1.2] An Incoming bulk Transfer request (POST /bulkTransfers) on the bulk-api-adapter is placed in an object store and a notification with a reference to the actual message is sent via a kafka topic “bulk-prepare” and a 202 is sent to the Payer FSP +2. [1.3] Bulk Prepare handler consumes the request, records the status as RECEIVED + + a. Bulk Prepare handler then validates the Bulk and changes state to PENDING if the validation is successful + + b. One validation rule proposed in addition, here is to reject a bulk if there are duplicate transfer IDs used in the bulk itself. + + c. [1.4] If validation fails, Bulk Prepare handler changes the bulkTransferState to PENDING_INVALID (an internal state) and produces a message onto the bulk processing topic + i. Bulk processing Handler then updates the bulkTransferState to REJECTED and sends a notification to the Payer + +3. [1.4] [Continuing 2.a] Bulk Prepare handler breaks down the bulk into individual transfers and puts each of them on the prepare topic + + a. As part of this, each transfer is individually assigned the 'expiration time' of the bulk Transfer itself (and other fields necessary for individual transfers) + +4. [1.5, 1.6, 1.7] Prepare handler, Position handler are refactored to handle individual transfers in a bulk, using flags such as type, action, status, etc. + + a. Reservation of funds --> This is left to the individual handlers and the whole bulk is then aggregated in the Bulk Processing Handler. + +5. [1.8] Position Handler produces messages corresponding to individual transfers that are part of a bulk to bulk processing topic +6. [1.9] For every message consumed from the bulk processing topic a check is made on the Bulk processing Handler to see if that’s the last individual transfer in a bulk for that processing phase. +7. [1.10, 1.11, 1.12] If it is the last transfer, aggregate the state of all the individual transfers and + + a. If all of them are in reserved state --> Send POST /bulkTransfers to the Payee (by producing a message to the notifications topic which is then consumed by the notification handler) + + b. Once the bulkTransfer prepare request is sent to the Payee, then change status to ACCEPTED + +8. In a successful case of Prepare - when the PUT from the Payee FSP for bulkFulfil is received, a notification is put on the bulk fulfil topic with a reference to the actual Fulfil message that's stored in an Object store. +9. This is to be consumed by the bulkFulfilHandler, which then changes state to PROCESSING. +10. The bulk-fulfil-handler breaks down the bulk into individual transfers and sends each of them through the refactored Fulfil, Position Handlers to commit/abort each of them based on the PUT /bulkTransfers/{ID} message by the Payee and commit/release funds on the Switch +11. The bulk-processing-handler is to then aggregate all the individual transfer results and change the state of bulkTransfer to COMPLETED/REJECTED based on success/failure + + a. If the Payee sends COMMITTED for even one of the individual transfers the proposal is to change bulk state to COMPLETED. + + b. However, for step-8 or if the Payee sends REJECTED as bulkTransferState then final state on Switch should be REJECTED. + +12. Send notifications to both Payer and Payee (similar to Single transfers, though diverging from the Spec 1.0). The Payer-FSP receives the notification that includes an exhaustive list of individual transfers, same as the list present in the prepare request sent by the Payer. The Payee-FSP receives a notification only for sub-set of transfers, which were sent to it from the Switch as the Bulk prepare request (that were able to be reserved at the Switch). + +## 4. Implementation Details + +### 4.1 Bulk Transfer States + +Below are the states of a Bulk transfer as per the Mojaloop API Specification + +1. RECEIVED +2. PENDING +3. ACCEPTED +4. PROCESSING +5. COMPLETED +6. REJECTED +7. Internal state - PENDING_PREPARE (mapped to PENDING) +8. Internal state - PENDING_INVALID (mapped to PENDING) +9. Internal state - PENDING_FULFIL (mapped to PROCESSING) +10. Internal state - EXPIRING (mapped to PROCESSING) +11. Internal state - EXPIRED (mapped to COMPLETED) +12. Internal state - INVALID (mapped to REJECTED) +13. Additional micro-states may be added for internal use on the Switch + +### 4.2 Proposed New tables + +Below are the proposed tables as part of designing the Bulk transfers + +- bulkTransfer +- bulkTransferStateChange +- bulkTransferError +- bulkTransferDuplicateCheck +- bulkTransferFulfilment +- bulkTransferFulfilmentDuplicateCheck +- bulkTransferAssociation +- bulkTransferExtension +- bulkTransferState +- bulkProcessingState + +### 4.3 Internal Type-Action-Status combinations + +#### 1. Bulk transfer that passes schema validation [ml-api-adapter -> bulk-prepare-handler] + + 1. type: bulk-prepare + 2. action: bulk-prepare + 3. Status: success + 4. Result: bulkTransferState=RECEIVED, bulkProcessingState=RECEIVED + +#### 2. Duplicate [bulk-prepare-handler -> notification handler] + + 1. type: notification + 2. action: bulk-prepare-duplicate + 3. Status: success + 4. Result: bulkTransferState=N/A, bulkProcessingState=N/A + +#### 3. Validate Bulk Prepare transfer failure [bulk-prepare-handler -> notification-handler] + + 1. type: notification + 2. action: bulk-abort + 3. Status: error + +#### 4. For a Valid Bulk Prepare transfer (broken down and sent as individual transfers) [bulk-prepare-handler -> prepare-handler] + + 1. type: prepare + 2. action: bulk-prepare + 3. Status: success + +#### 5. Duplicate of individual transfer that is part of a bulk-transfer [prepare-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: prepare-duplicate + 3. Status: success + 4. Expected action: Add error message indicating it’s a duplicate + 5. Result: bulkTransferState=PENDING_PREPARE/ACCEPTED (depending on whether it’s the last one), bulkProcessingState=RECEIVED_DUPLICATE + +#### 6. For individual Prepare transfer that’s a valid duplicate in prepare handler [prepare-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: prepare-duplicate + 3. Status: error + 4. Result: bulkTransferState=PENDING_PREPARE/ACCEPTED (depending on whether it’s the last one), bulkProcessingState=RECEIVED_DUPLICATE + +#### 7. For a Valid individual Prepare transfer that’s part of a bulk [prepare-handler -> position-handler] + + 1. type: position + 2. action: bulk-prepare + 3. Status: success + +#### 8. For individual Prepare transfer that’s part of a bulk that failed validation in prepare handler [prepare-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-prepare + 3. Status: error + 4. Result: bulkTransferState=PENDING_PREPARE/ACCEPTED (depending on whether it’s the last one), bulkProcessingState=RECEIVED_INVALID + +#### 9. For a Valid individual Prepare transfer that’s part of a bulk [position-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-prepare + 3. Status: success + 4. Result: bulkTransferState=PENDING_PREPARE/ACCEPTED (depending on whether it’s the last one), bulkProcessingState=ACCEPTED + +#### 10. For individual Prepare transfer that’s part of a bulk that failed validation in position handler [position-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-prepare + 3. Status: error + 4. Result: bulkTransferState=PENDING_PREPARE/ACCEPTED (depending on whether it’s the last one), bulkProcessingState=RECEIVED_INVALID + +#### 11. For a Valid individual Fulfil transfer (for commit) that’s part of a bulk [position-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-commit + 3. Status: success + 4. Result: bulkTransferState=PENDING_FULFIL/COMPLETED (depending on whether it’s the last one), bulkProcessingState=COMPLETED + +#### 12. For Bulk transfer Fulfil message that passes validation [ml-api-adapter -> bulk-fulfil-handler] + + 1. type: bulk-fulfil + 2. action: bulk-commit + 3. Status: success + +#### 13. For a valid individual transfer part of a bulk that timed-out in position handler [position-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-timeout-reserved + 3. Status: error + 4. Result: bulkTransferState=PENDING_FULFIL/COMPLETED (depending on whether it’s the last one), bulkProcessingState=FULFIL_INVALID + +#### 14. For a Valid individual Fulfil transfer (for reject) that’s part of a bulk [position-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: reject + 3. Status: success + 4. Result: bulkTransferState=PENDING_FULFIL/COMPLETED (depending on whether it’s the last one), bulkProcessingState=REJECTED + +#### 15. Invalid Fulfil duplicate of an individual transfer in a bulk [fulfil-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: fulfil-duplicate + 3. Status: error + 4. Result: bulkTransferState=PENDING_FULFIL/COMPLETED (depending on whether it’s the last one), bulkProcessingState=FULFIL_DUPLICATE + +#### 16. Valid Fulfil duplicate of an individual transfer in a bulk [fulfil-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: fulfil-duplicate + 3. Status: success + 4. Result: bulkTransferState=PENDING_FULFIL/COMPLETED (depending on whether it’s the last one), bulkProcessingState=FULFIL_DUPLICATE + +#### 17. Valid Fulfil message of an individual transfer in a bulk [fulfil-handler -> position-handler] + + 1. type: position + 2. action: bulk-commit + 3. Status: success + +#### 18. For individual Fulfil transfer that’s part of a bulk that failed validation in fulfil handler [fulfil-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-commit + 3. Status: error + 4. Result: bulkTransferState=PENDING_FULFIL/COMPLETED (depending on whether it’s the last one), bulkProcessingState=FULFIL_INVALID + +#### 19. Fulfil transfer request that’s part of a bulk that passes validation [bulk-fulfil-handler -> fulfil-handler] + + 1. type: bulk-fulfil + 2. action: bulk-commit + 3. Status: success + +#### 20. For Bulk transfers failing validation at bulk-fulfil-handler level [bulk-fulfil-handler -> notification-handler] + + 1. type: notification + 2. action: bulk-abort + 3. Status: error + +#### 21. For Bulk transfer notifications to FSPs [bulk-processing-handler -> notification-handler] + + 1. type: notification + 2. action: bulk-prepare / bulk-commit + 3. Status: success + +#### 22. For timeout notification [timeout-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-timeout-received + 3. Status: error + 4. Result: bulkTransferState=COMPLETED (for the last one), bulkProcessingState=EXPIRED + +#### 23. For timeout notification [timeout-handler -> position-handler] + + 1. type: position + 2. action: bulk-timeout-reserved + 3. Status: error + +#### 24. For timeout notification after position adjust [position-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-timeout-reserved + 3. Status: error + 4. Result: bulkTransferState=COMPLETED (for the last one), bulkProcessingState=EXPIRED + +### 4.4 Additional Notes + +1. Document GET /bulkTransfers to indicate the difference in responses the Payer-FSP & Payee-FSP receive for Bulk Transfers +2. Used a separate service: bulk-api-adapter to support bulk transfers end-points (that includes persistence as discussed above) + +## 5. Roadmap Topics + +1. Re-assess the need to support multiple Payee FSPs as part of a Bulk and the changes to the Specification needed. +2. Issues, learnings from the PoC that are documented are addressed in order of priority +3. Find out a need to support something like a Bulk make resource (/bulkMake ?) in which the Switch accepts an entire Bulk as it is and then takes care of all three phases - lookup, quote and transfers. +4. Throttling of individual transfers in a bulk? +5. The aspect of ordering in a Bulk - the order of processing at the Switch and at the FSPs. Recommendation to Scheme to incorporate Rule to mandate all FSPs to process transactions a bulk in the existing order and not have preferential processing. On the Switch currently being neutral with ordering but best practice is to sort in ascending order of amounts and process. +6. For Settlements with bulk transfers where Government payments are involved with large sums of money needs to be discussed to allow for moving through transfers without strict liquidity rules needs to be discussed. +7. Implement GET /bulkTransfers +8. Implement notifications/logging for all bulk negative scenarios +9. Full unit tests code coverage +10. Integration testing of successful bulk transfer (golden path) +11. Regression testing, including negative scenarios diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-ddl-MySQLWorkbench.sql b/docs/technical/technical/central-bulk-transfers/assets/database/central-ledger-ddl-MySQLWorkbench.sql similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-ddl-MySQLWorkbench.sql rename to docs/technical/technical/central-bulk-transfers/assets/database/central-ledger-ddl-MySQLWorkbench.sql diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-schema-DBeaver.erd b/docs/technical/technical/central-bulk-transfers/assets/database/central-ledger-schema-DBeaver.erd similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-schema-DBeaver.erd rename to docs/technical/technical/central-bulk-transfers/assets/database/central-ledger-schema-DBeaver.erd diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-schema.png b/docs/technical/technical/central-bulk-transfers/assets/database/central-ledger-schema.png similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-schema.png rename to docs/technical/technical/central-bulk-transfers/assets/database/central-ledger-schema.png diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/architecture/Figure60-Example-Bulk-Transfer-Process-Spec1.0.png b/docs/technical/technical/central-bulk-transfers/assets/diagrams/architecture/Figure60-Example-Bulk-Transfer-Process-Spec1.0.png similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/architecture/Figure60-Example-Bulk-Transfer-Process-Spec1.0.png rename to docs/technical/technical/central-bulk-transfers/assets/diagrams/architecture/Figure60-Example-Bulk-Transfer-Process-Spec1.0.png diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/architecture/bulk-transfer-arch-flows.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/architecture/bulk-transfer-arch-flows.svg similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/architecture/bulk-transfer-arch-flows.svg rename to docs/technical/technical/central-bulk-transfers/assets/diagrams/architecture/bulk-transfer-arch-flows.svg diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml new file mode 100644 index 000000000..5bdd8119f --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml @@ -0,0 +1,217 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declare title +title 1.1.0. DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "Bulk API Adapter" as BULK_API +control "Bulk API Notification \nHandler" as NOTIFY_HANDLER +collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE +boundary "Central Service API" as CSAPI +collections "topic-\nbulk-prepare" as TOPIC_BULK_PREPARE +control "Bulk Prepare\nHandler" as BULK_PREP_HANDLER +collections "topic-\ntransfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Handler" as PREP_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +control "Bulk Processing\nHandler" as BULK_PROC_HANDLER +collections "topic-\nnotifications" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "Bulk API Adapter Service" #LightBlue + participant BULK_API + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant OBJECT_STORE + participant CSAPI + participant TOPIC_BULK_PREPARE + participant BULK_PREP_HANDLER + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_BULK_PROCESSING + participant BULK_PROC_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate BULK_PREP_HANDLER +activate PREP_HANDLER +activate POS_HANDLER +activate BULK_PROC_HANDLER +group DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + note right of DFSP1 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - bulkTransferMessage: + { + bulkTransferId: , + bulkQuoteId: , + payeeFsp: , + payerFsp: , + individualTransfers: [ + { + transferId: , + transferAmount: + { + currency: , + amount: + }, + ilpPacket: , + condition: , + extensionList: { extension: [ + { key: , value: } + ] } + } + ], + extensionList: { extension: [ + { key: , value: } + ] }, + expiration: + } + end note + DFSP1 ->> BULK_API: POST - /bulkTransfers + activate BULK_API + BULK_API -> BULK_API: Validate incoming message\nError codes: 3000-3002, 3100-3107 + loop + BULK_API -> OBJECT_STORE: Persist individual transfers in the bulk to\nobject store: **MLOS.individualTransfers** + activate OBJECT_STORE + OBJECT_STORE --> BULK_API: Return messageId reference to the stored object(s) + deactivate OBJECT_STORE + end + note right of BULK_API #yellow + Message: + { + id: + to: , + from: , + type: "application/json" + content: { + headers: , + payload: { + bulkTransferId: , + bulkQuoteId": , + payerFsp: , + payeeFsp: , + expiration: , + hash: + } + }, + metadata: { + event: { + id: , + type: "bulk-prepare", + action: "bulk-prepare", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + BULK_API -> TOPIC_BULK_PREPARE: Route & Publish Bulk Prepare event \nfor Payer\nError code: 2003 + activate TOPIC_BULK_PREPARE + TOPIC_BULK_PREPARE <-> TOPIC_BULK_PREPARE: Ensure event is replicated \nas configured (ACKS=all)\nError code: 2003 + TOPIC_BULK_PREPARE --> BULK_API: Respond replication acknowledgements \nhave been received + deactivate TOPIC_BULK_PREPARE + BULK_API -->> DFSP1: Respond HTTP - 202 (Accepted) + deactivate BULK_API + ||| + TOPIC_BULK_PREPARE <- BULK_PREP_HANDLER: Consume message + ref over TOPIC_BULK_PREPARE, BULK_PREP_HANDLER, TOPIC_TRANSFER_PREPARE: Bulk Prepare Handler Consume \n + alt Success + BULK_PREP_HANDLER -> TOPIC_TRANSFER_PREPARE: Produce (stream) single transfer message\nfor each individual transfer [loop] + else Failure + BULK_PREP_HANDLER --> TOPIC_NOTIFICATIONS: Produce single message for the entire bulk + end + ||| + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume message + ref over TOPIC_TRANSFER_PREPARE, PREP_HANDLER, TOPIC_TRANSFER_POSITION: Prepare Handler Consume\n + alt Success + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + else Failure + PREP_HANDLER --> TOPIC_BULK_PROCESSING: Produce message + end + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, POS_HANDLER, TOPIC_BULK_PROCESSING: Position Handler Consume\n + POS_HANDLER -> TOPIC_BULK_PROCESSING: Produce message + ||| + TOPIC_BULK_PROCESSING <- BULK_PROC_HANDLER: Consume message + ref over TOPIC_BULK_PROCESSING, BULK_PROC_HANDLER, TOPIC_NOTIFICATIONS: Bulk Processing Handler Consume\n + BULK_PROC_HANDLER -> OBJECT_STORE: Persist bulk message by destination to the\nobject store: **MLOS.bulkTransferResults** + activate OBJECT_STORE + OBJECT_STORE --> BULK_PROC_HANDLER: Return the reference to the stored \nnotification object(s): **messageId** + deactivate OBJECT_STORE + BULK_PROC_HANDLER -> TOPIC_NOTIFICATIONS: Send Bulk Prepare notification + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + NOTIFY_HANDLER -> OBJECT_STORE: Retrieve bulk notification(s) by reference & destination:\n**MLOS.bulkTransferResults.messageId + destination** + activate OBJECT_STORE + OBJECT_STORE --> NOTIFY_HANDLER: Return notification(s) payload + deactivate OBJECT_STORE + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send Bulk Prepare notification to Payee + ||| +end +deactivate POS_HANDLER +deactivate BULK_PREP_HANDLER +deactivate PREP_HANDLER +deactivate BULK_PROC_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.svg new file mode 100644 index 000000000..9c52a416a --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.svg @@ -0,0 +1,405 @@ + + 1.1.0. DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + + + 1.1.0. DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + + Financial Service Providers + + Bulk API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + DFSP2 + Payee + + + DFSP2 + Payee + + + Bulk API Adapter + + + Bulk API Adapter + + + Bulk API Notification + Handler + + + Bulk API Notification + Handler + + + + + mojaloop- + object-store + ( + MLOS + ) + + + mojaloop- + object-store + ( + MLOS + ) + Central Service API + + + Central Service API + + + + + topic- + bulk-prepare + + + topic- + bulk-prepare + Bulk Prepare + Handler + + + Bulk Prepare + Handler + + + + + topic- + transfer-prepare + + + topic- + transfer-prepare + Prepare Handler + + + Prepare Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + Position Handler + + + Position Handler + + + + + topic- + bulk-processing + + + topic- + bulk-processing + Bulk Processing + Handler + + + Bulk Processing + Handler + + + + + topic- + notifications + + + topic- + notifications + + + + + + + + + + + + + DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + + + Headers - transferHeaders: { + Content-Length: <int>, + Content-Type: <string>, + Date: <date>, + FSPIOP-Source: <string>, + FSPIOP-Destination: <string>, + FSPIOP-Encryption: <string>, + FSPIOP-Signature: <string>, + FSPIOP-URI: <uri>, + FSPIOP-HTTP-Method: <string> + } +   + Payload - bulkTransferMessage: + { + bulkTransferId: <uuid>, + bulkQuoteId: <uuid>, + payeeFsp: <string>, + payerFsp: <string>, + individualTransfers: [ + { + transferId: <uuid>, + transferAmount: + { + currency: <string>, + amount: <string> + }, + ilpPacket: <string>, + condition: <string>, + extensionList: { extension: [ + { key: <string>, value: <string> } + ] } + } + ], + extensionList: { extension: [ + { key: <string>, value: <string> } + ] }, + expiration: <string> + } + + + + 1 + POST - /bulkTransfers + + + + + 2 + Validate incoming message + Error codes: + 3000-3002, 3100-3107 + + + loop + + + 3 + Persist individual transfers in the bulk to + object store: + MLOS.individualTransfers + + + 4 + Return messageId reference to the stored object(s) + + + Message: + { + id: <messageId> + to: <payeeFspName>, + from: <payerFspName>, + type: "application/json" + content: { + headers: <bulkTransferHeaders>, + payload: { + bulkTransferId: <uuid>, + bulkQuoteId": <uuid>, + payerFsp: <string>, + payeeFsp: <string>, + expiration: <timestamp>, + hash: <string> + } + }, + metadata: { + event: { + id: <uuid>, + type: "bulk-prepare", + action: "bulk-prepare", + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 5 + Route & Publish Bulk Prepare event + for Payer + Error code: + 2003 + + + + + + 6 + Ensure event is replicated + as configured (ACKS=all) + Error code: + 2003 + + + 7 + Respond replication acknowledgements + have been received + + + + 8 + Respond HTTP - 202 (Accepted) + + + 9 + Consume message + + + ref + Bulk Prepare Handler Consume +   + + + alt + [Success] + + + 10 + Produce (stream) single transfer message + for each individual transfer [loop] + + [Failure] + + + 11 + Produce single message for the entire bulk + + + 12 + Consume message + + + ref + Prepare Handler Consume +   + + + alt + [Success] + + + 13 + Produce message + + [Failure] + + + 14 + Produce message + + + 15 + Consume message + + + ref + Position Handler Consume +   + + + 16 + Produce message + + + 17 + Consume message + + + ref + Bulk Processing Handler Consume +   + + + 18 + Persist bulk message by destination to the + object store: + MLOS.bulkTransferResults + + + 19 + Return the reference to the stored + notification object(s): + messageId + + + 20 + Send Bulk Prepare notification + + + 21 + Consume message + + + 22 + Retrieve bulk notification(s) by reference & destination: + MLOS.bulkTransferResults.messageId + destination + + + 23 + Return notification(s) payload + + + ref + Send notification to Participant (Payee) +   + + + 24 + Send Bulk Prepare notification to Payee + + diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml new file mode 100644 index 000000000..a9c53292f --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml @@ -0,0 +1,320 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declare title +title 1.1.1. Bulk Prepare Handler Consume + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-\nbulk-prepare" as TOPIC_BULK_PREPARE +collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE +control "Bulk Prepare \nHandler" as BULK_PREP_HANDLER +collections "topic-\ntransfer-prepare" as TOPIC_TRANSFER_PREPARE +collections "topic-event" as TOPIC_EVENTS +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-bulk-\nprocessing" as TOPIC_BULK_PROCESSING +entity "Bulk DAO" as BULK_DAO +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant OBJECT_STORE + participant TOPIC_BULK_PREPARE + participant BULK_PREP_HANDLER + participant TOPIC_TRANSFER_PREPARE + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant TOPIC_BULK_PROCESSING + participant BULK_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate BULK_PREP_HANDLER +group Bulk Prepare Handler Consume + TOPIC_BULK_PREPARE <- BULK_PREP_HANDLER: Consume Bulk Prepare message + activate TOPIC_BULK_PREPARE + deactivate TOPIC_BULK_PREPARE + group Validate Bulk Prepare Transfer + group Duplicate Check + note right of BULK_PREP_HANDLER #cyan + The Specification doesn't touch on the duplicate handling + of bulk transfers, so the current design mostly follows the + strategy used for individual transfers, except in two places: + + 1. For duplicate requests where hash matches, the current design + includes only the status of the bulk & timestamp (if completed), + but not the individual transfers (for which a GET should be used). + + 2. For duplicate requests where hash matches, but are not in a + finalized state, only the state of the bulkTransfer is sent. + end note + ||| + BULK_PREP_HANDLER -> DB: Request Duplicate Check + ref over BULK_PREP_HANDLER, DB: Request Duplicate Check (using message.content.payload)\n + DB --> BULK_PREP_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break Return TRUE & Log ('Not implemented') + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of BULK_PREP_HANDLER #yellow + { + id: , + from: , + to: , + type: "application/json", + content: { + headers: , + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request", + extensionList: { + extension: [ + { + key: "_cause", + value: + } + ] + } + }, + uriParams: { + id: + } + } + }, + metadata: { + correlationId: , + event: { + id: , + type: "notification", + action: "bulk-prepare", + createdAt: , + state: { + status: "error", + code: "3106", + description: "Modified request" + }, + responseTo: + } + } + } + end note + BULK_PREP_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError codes: 3106 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else hasDuplicateId == FALSE + group Validate Bulk Transfer Prepare Request + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: FSPIOP Source matches Payer + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Check expiration + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Payer and Payee FSP's are different + group Validate Payer + BULK_PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payer Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> BULK_PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Validate Payer\nError codes: 3202 + end + group Validate Payee + BULK_PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payee Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> BULK_PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Validate Payee\nError codes: 3203 + end + end + ||| + alt Validate Bulk Transfer Prepare Request (success) + group Persist Bulk Transfer State (with bulkTransferState='RECEIVED') + BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Persist bulkTransfer + hnote over DB #lightyellow + bulkTransfer + bulkTransferExtension + bulkTransferStateChange + end note + activate DB + deactivate DB + BULK_DAO --> BULK_PREP_HANDLER: Return state + deactivate BULK_DAO + end + else Validate Bulk Transfer Prepare Request (failure) + group Persist Bulk Transfer State (with bulkTransferState='INVALID') (Introducing a new status INVALID to mark these entries) + BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer\n(when Payee/Payer/crypto-condition validation fails)\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Persist transfer + hnote over DB #lightyellow + bulkTransfer + bulkTransferExtension + bulkTransferStateChange + bulkTransferError + end note + activate DB + deactivate DB + BULK_DAO --> BULK_PREP_HANDLER: Return state + deactivate BULK_DAO + end + end + end + end + alt Validate Bulk Prepare Transfer (success) + loop for each individual transfer in the bulk + BULK_PREP_HANDLER -> OBJECT_STORE: Retrieve individual transfers from the bulk using\nreference: **MLOS.individualTransfers.messageId** + activate OBJECT_STORE + note right of OBJECT_STORE #lightgrey + Add elements such as Expiry time, Payer FSP, Payee FSP, etc. to each + transfer to make their format similar to a single transfer + end note + OBJECT_STORE --> BULK_PREP_HANDLER: Stream bulk's individual transfers + deactivate OBJECT_STORE + + group Insert Bulk Transfer Association (with bulkProcessingState='RECEIVED') + BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer association\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Insert bulkTransferAssociation + hnote over DB #lightyellow + bulkTransferAssociation + bulkTransferStateChange + end note + activate DB + deactivate DB + BULK_DAO --> BULK_PREP_HANDLER: Return state + deactivate BULK_DAO + end + + note right of BULK_PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "prepare", + action: "bulk-prepare", + createdAt: , + state: { + status: "success", + code: 0, + description:"action successful" + } + } + } + } + end note + BULK_PREP_HANDLER -> TOPIC_TRANSFER_PREPARE: Route & Publish Prepare event to the Payee for the Individual Transfer\nError codes: 2003 + activate TOPIC_TRANSFER_PREPARE + deactivate TOPIC_TRANSFER_PREPARE + end + else Validate Bulk Prepare Transfer (failure) + note right of BULK_PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json", + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": + "errorDescription": "", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "bulk-processing", + action: "bulk-abort", + createdAt: , + state: { + status: "error", + code: + description: + } + } + } + } + end note + BULK_PREP_HANDLER -> TOPIC_BULK_PROCESSING: Publish Processing (failure) event for Payer\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + group Insert Bulk Transfer Association (with bulkProcessingState='INVALID') + BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer association\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Insert bulkTransferAssociation + hnote over DB #lightyellow + bulkTransferAssociation + bulkTransferStateChange + end note + activate DB + deactivate DB + BULK_DAO --> BULK_PREP_HANDLER: Return state + deactivate BULK_DAO + end + + end +end +deactivate BULK_PREP_HANDLER +@enduml + diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.svg new file mode 100644 index 000000000..ac272e017 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.svg @@ -0,0 +1,518 @@ + + 1.1.1. Bulk Prepare Handler Consume + + + 1.1.1. Bulk Prepare Handler Consume + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mojaloop- + object-store + ( + MLOS + ) + + + mojaloop- + object-store + ( + MLOS + ) + + + topic- + bulk-prepare + + + topic- + bulk-prepare + Bulk Prepare + Handler + + + Bulk Prepare + Handler + + + + + topic- + transfer-prepare + + + topic- + transfer-prepare + + + topic-event + + + topic-event + + + topic- + notification + + + topic- + notification + + + topic-bulk- + processing + + + topic-bulk- + processing + Bulk DAO + + + Bulk DAO + + + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + + + + Bulk Prepare Handler Consume + + + 1 + Consume Bulk Prepare message + + + Validate Bulk Prepare Transfer + + + Duplicate Check + + + The Specification doesn't touch on the duplicate handling + of bulk transfers, so the current design mostly follows the + strategy used for individual transfers, except in two places: +   + 1. For duplicate requests where hash matches, the current design + includes only the status of the bulk & timestamp (if completed), + but not the individual transfers (for which a GET should be used). +   + 2. For duplicate requests where hash matches, but are not in a + finalized state, only the state of the bulkTransfer is sent. + + + 2 + Request Duplicate Check + + + ref + Request Duplicate Check (using message.content.payload) +   + + + 3 + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + alt + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + break + [Return TRUE & Log ('Not implemented')] + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + { + id: <messageId>, + from: <ledgerName>, + to: <payerFspName>, + type: "application/json", + content: { + headers: <bulkTransferHeaders>, + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request", + extensionList: { + extension: [ + { + key: "_cause", + value: <FSPIOPError> + } + ] + } + }, + uriParams: { + id: <bulkTransferId> + } + } + }, + metadata: { + correlationId: <uuid>, + event: { + id: <uuid>, + type: "notification", + action: "bulk-prepare", + createdAt: <timestamp>, + state: { + status: "error", + code: "3106", + description: "Modified request" + }, + responseTo: <uuid> + } + } + } + + + 4 + Publish Notification (failure) event for Payer + Error codes: + 3106 + + [hasDuplicateId == FALSE] + + + Validate Bulk Transfer Prepare Request + + + + + + 5 + FSPIOP Source matches Payer + + + + + + 6 + Check expiration + + + + + + 7 + Payer and Payee FSP's are different + + + Validate Payer + + + 8 + Request to retrieve Payer Participant details (if it exists) + + + 9 + Request Participant details + + participant + participantCurrency + + + 10 + Return Participant details if it exists + + + 11 + Return Participant details if it exists + + + + + + 12 + Validate Payer + Error codes: + 3202 + + + Validate Payee + + + 13 + Request to retrieve Payee Participant details (if it exists) + + + 14 + Request Participant details + + participant + participantCurrency + + + 15 + Return Participant details if it exists + + + 16 + Return Participant details if it exists + + + + + + 17 + Validate Payee + Error codes: + 3203 + + + alt + [Validate Bulk Transfer Prepare Request (success)] + + + Persist Bulk Transfer State (with bulkTransferState='RECEIVED') + + + 18 + Request to persist bulk transfer + Error codes: + 2003 + + + 19 + Persist bulkTransfer + + bulkTransfer + bulkTransferExtension + bulkTransferStateChange + + + 20 + Return state + + [Validate Bulk Transfer Prepare Request (failure)] + + + Persist Bulk Transfer State (with bulkTransferState='INVALID') (Introducing a new status INVALID to mark these entries) + + + 21 + Request to persist bulk transfer + (when Payee/Payer/crypto-condition validation fails) + Error codes: + 2003 + + + 22 + Persist transfer + + bulkTransfer + bulkTransferExtension + bulkTransferStateChange + bulkTransferError + + + 23 + Return state + + + alt + [Validate Bulk Prepare Transfer (success)] + + + loop + [for each individual transfer in the bulk] + + + 24 + Retrieve individual transfers from the bulk using + reference: + MLOS.individualTransfers.messageId + + + Add elements such as Expiry time, Payer FSP, Payee FSP, etc. to each + transfer to make their format similar to a single transfer + + + 25 + Stream bulk's individual transfers + + + Insert Bulk Transfer Association (with bulkProcessingState='RECEIVED') + + + 26 + Request to persist bulk transfer association + Error codes: + 2003 + + + 27 + Insert bulkTransferAssociation + + bulkTransferAssociation + bulkTransferStateChange + + + 28 + Return state + + + Message: + { + id: <messageId> + from: <payerFspName>, + to: <payeeFspName>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "prepare", + action: "bulk-prepare", + createdAt: <timestamp>, + state: { + status: "success", + code: 0, + description:"action successful" + } + } + } + } + + + 29 + Route & Publish Prepare event to the Payee for the Individual Transfer + Error codes: + 2003 + + [Validate Bulk Prepare Transfer (failure)] + + + Message: + { + id: <messageId> + from: <ledgerName>, + to: <bulkTransferMessage.payerFsp>, + type: "application/json", + content: { + headers: <bulkTransferHeaders>, + payload: { + "errorInformation": { + "errorCode": <possible codes: [2003, 3100, 3105, 3106, 3202, 3203, 3300, 3301]> + "errorDescription": "<refer to section 7.6 for description>", + "extensionList": <transferMessage.extensionList> + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "bulk-processing", + action: "bulk-abort", + createdAt: <timestamp>, + state: { + status: "error", + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 30 + Publish Processing (failure) event for Payer + Error codes: + 2003 + + + Insert Bulk Transfer Association (with bulkProcessingState='INVALID') + + + 31 + Request to persist bulk transfer association + Error codes: + 2003 + + + 32 + Insert bulkTransferAssociation + + bulkTransferAssociation + bulkTransferStateChange + + + 33 + Return state + + diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.plantuml similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.plantuml rename to docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.plantuml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.svg new file mode 100644 index 000000000..210388650 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.svg @@ -0,0 +1,484 @@ + + 1.2.1. Prepare Handler Consume individual transfers from Bulk + + + 1.2.1. Prepare Handler Consume individual transfers from Bulk + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + topic- + transfer-prepare + + + topic- + transfer-prepare + Prepare Handler + + + Prepare Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + + + topic- + event + + + topic- + event + + + topic- + notification + + + topic- + notification + + + topic- + bulk-processing + + + topic- + bulk-processing + Position DAO + + + Position DAO + + + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + Prepare Handler Consume + + + 1 + Consume Prepare event message + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type == 'prepare' && action == 'bulk-prepare' + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + Validate Prepare Transfer + + + + + + 4 + Schema validation of the incoming message + + + + + + 5 + Verify the message's signature (to be confirmed in future requirement) + + + Validate Duplicate Check + + + 6 + Request Duplicate Check + + + ref + Request Duplicate Check +   + + + 7 + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + alt + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + In the context of a bulk (when compared to regular transfers), duplicate + individual transfers are now considered and reported with Modified Request, + because they could have already been handled for another bulk. + + + break + + + { + id: <messageId> + from: <ledgerName>, + to: <payerFspName>, + type: "application/json", + content: { + headers: <transferHeaders>, + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request - Individual transfer prepare duplicate", + extensionList: { extension: [ { key: "_cause", value: <FSPIOPError> } ] } + } + }, + uriParams: { id: <transferId> } + }, + metadata: { + correlationId: <uuid>, + event: { + type: "bulk-processing", + action: "prepare-duplicate", + createdAt: <timestamp>, + state: { + code: "3106", + status: "error", + description: "Modified request - Individual transfer prepare duplicate" + }, + id: <uuid>, + responseTo: <uuid> + } + } + + + 8 + Publish Processing (failure) event for Payer + Error codes: + 2003 + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + break + + + { + id: <messageId> + from: <ledgerName>, + to: <payerFspName>, + type: "application/json", + content: { + headers: <transferHeaders>, + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request", + extensionList: { extension: [ { key: "_cause", value: <FSPIOPError> } ] } + } + }, + uriParams: { id: <transferId> } + }, + metadata: { + correlationId: <uuid>, + event: { + type: "bulk-processing", + action: "prepare-duplicate", + createdAt: <timestamp>, + state: { + code: "3106", + status: "error", + description: "Modified request" + }, + id: <uuid>, + responseTo: <uuid> + } + } + + + 9 + Publish Processing (failure) event for Payer + Error codes: + 2003 + + [hasDuplicateId == FALSE] + + + The validation of Payer, Payee can be skipped for individual transfers in Bulk + as they should've/would've been validated already in the bulk prepare part. + However, leaving it here for now, as in the future, this can be leveraged + when bulk transfers to multiple Payees are supported by the Specification. + + + Validate Payer + + + 10 + Request to retrieve Payer Participant details (if it exists) + + + 11 + Request Participant details + + participant + participantCurrency + + + 12 + Return Participant details if it exists + + + 13 + Return Participant details if it exists + + + + + + 14 + Validate Payer + Error codes: + 3202 + + + Validate Payee + + + 15 + Request to retrieve Payee Participant details (if it exists) + + + 16 + Request Participant details + + participant + participantCurrency + + + 17 + Return Participant details if it exists + + + 18 + Return Participant details if it exists + + + + + + 19 + Validate Payee + Error codes: + 3203 + + + alt + [Validate Prepare Transfer (success)] + + + Persist Transfer State (with transferState='RECEIVED-PREPARE') + + + 20 + Request to persist transfer + Error codes: + 2003 + + + 21 + Persist transfer + + transfer + transferParticipant + transferStateChange + transferExtension + ilpPacket + + + 22 + Return success + + [Validate Prepare Transfer (failure)] + + + Persist Transfer State (with transferState='INVALID') (Introducing a new status INVALID to mark these entries) + + + 23 + Request to persist transfer + (when Payee/Payer/crypto-condition validation fails) + Error codes: + 2003 + + + 24 + Persist transfer + + transfer + transferParticipant + transferStateChange + transferExtension + transferError + ilpPacket + + + 25 + Return success + + + alt + [Validate Prepare Transfer (success)] + + + Message: + { + id: <messageId> + from: <payerFspName>, + to: <payeeFspName>, + type: "application/json", + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "position", + action: "bulk-prepare", + createdAt: <timestamp>, + state: { + status: "success", + code: 0, + description:"action successful" + } + } + } + } + + + 26 + Route & Publish Position event for Payer + Error codes: + 2003 + + [Validate Prepare Transfer (failure)] + + + Message: + { + id: <messageId> + from: <ledgerName>, + to: <payerFspName>, + type: "application/json" + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": <possible codes: [2003, 3100, 3105, 3106, 3202, 3203, 3300, 3301]> + "errorDescription": "<refer to section 35.1.3 for description>", + "extensionList": <transferMessage.extensionList> + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "bulk-processing", + action: "prepare", + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 27 + Publish Prepare failure event to Bulk Processing Topic (for Payer) + Error codes: + 2003 + + diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.plantuml similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.plantuml rename to docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.plantuml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.svg new file mode 100644 index 000000000..ee9d9ac7c --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.svg @@ -0,0 +1,187 @@ + + 1.3.0. Position Handler Consume individual transfers from Bulk + + + 1.3.0. Position Handler Consume individual transfers from Bulk + + Central Service + + + + + + + + + + + + + + + + + + + + + + topic-transfer-position + + + topic-transfer-position + Position Handler + + + Position Handler + + + + + Event-Topic + + + Event-Topic + + + Notification-Topic + + + Notification-Topic + + + + + + + Position Handler Consume + + + alt + [Consume Prepare message for Payer] + + + 1 + Consume Position event message for Payer + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type == 'position' && action == 'bulk-prepare' + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + ref + Prepare Position Handler Consume +   + + + 4 + Produce message + + [Consume Fulfil message for Payee] + + + 5 + Consume Position event message for Payee + + + break + + + Validate Event + + + + + + 6 + Validate event - Rule: type == 'position' && action == 'bulk-commit' + Error codes: + 2001 + + + Persist Event Information + + + 7 + Publish event information + + + ref + Event Handler Consume +   + + + ref + Fulfil Position Handler Consume +   + + + 8 + Produce message + + [Consume Abort message] + + + 9 + Consume Position event message + + + break + + + Validate Event + + + + + + 10 + Validate event - Rule: type == 'position' && action == 'timeout-reserved' + Error codes: + 2001 + + + Persist Event Information + + + 11 + Publish event information + + + ref + Event Handler Consume +   + + + ref + Abort Position Handler Consume +   + + + 12 + Produce message + + diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.plantuml similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.plantuml rename to docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.plantuml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.svg new file mode 100644 index 000000000..bbf658e1c --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.svg @@ -0,0 +1,522 @@ + + 1.3.1. Prepare Position Handler Consume (single message, includes individual transfers from Bulk) + + + 1.3.1. Prepare Position Handler Consume (single message, includes individual transfers from Bulk) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Position Handler + + + Position Handler + + + + + topic- + notification + + + topic- + notification + + + topic- + bulk-processing + + + topic- + bulk-processing + Position + Management + Facade + + + Position + Management + Facade + + + Position DAO + + + Position DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + Prepare Position Handler Consume + + + 1 + Request transfers to be processed + + + + + 2 + Check 1st transfer to select the Participant and Currency + + + DB TRANSACTION + + + + + 3 + Loop through batch and build list of transferIds and calculate sumTransfersInBatch, + checking all in Batch are for the correct Paricipant and Currency + Error code: + 2001, 3100 + + + 4 + Retrieve current state of all transfers in array from DB with select whereIn + (FYI: The two DB transaction model needs to add a mini-state step here (RECEIVED_PREPARE => RECEIVDED_PREPARE_PROCESSING) so that the transfers are left alone if processing has started) + + transferStateChange + transferParticipant + + + 5 + Return current state of all selected transfers from DB + + + + + + 6 + Validate current state (transferStateChange.transferStateId == 'RECEIVED_PREPARE') + Error code: + 2001 + against failing transfers + Batch is not rejected as a whole. + + + List of transfers used during processing + reservedTransfers + is list of transfers to be processed in the batch + abortedTransfers + is the list of transfers in the incorrect state going into the process. Currently the transferStateChange is set to ABORTED - this should only be done if not already in a final state (idempotency) + processedTransfers + is the list of transfers that have gone through the position management algorithm. Both successful and failed trasnfers appear here as the order and "running position" against each is necessary for reconciliation +   + Scalar intermidate values used in the algorithm + transferAmount + = payload.amount.amount + sumTransfersInBatch + = SUM amount against each Transfer in batch + currentPosition + = participantPosition.value + reservedPosition + = participantPosition.{original}reservedValue + effectivePosition + = currentPosition + reservedPosition + heldPosition + = effectivePosition + sumTransfersInBatch + availablePosition + = participantLimit(NetDebitCap) - effectivePosition + sumReserved + = SUM of transfers that have met rule criteria and processed + + + Going to reserve the sum of the valid transfers in the batch against the Participants Positon in the Currency of this batch + and calculate the available position for the Participant to use + + + 7 + Select effectivePosition FOR UPDATE from DB for Payer + + participantPosition + + + 8 + Return effectivePosition (currentPosition and reservedPosition) from DB for Payer + + + + + 9 + Increment reservedValue to heldPosition + (reservedValue = reservedPosition + sumTransfersInBatch) + + + 10 + Persist reservedValue + + UPDATE + participantPosition + SET reservedValue += sumTransfersInBatch + + + 11 + Request position limits for Payer Participant + + FROM + participantLimit + WHERE participantLimit.limitTypeId = 'NET-DEBIT-CAP' + AND participantLimit.participantId = payload.payerFsp + AND participantLimit.currencyId = payload.amount.currency + + + 12 + Return position limits + + + + + + 13 + availablePosition + = participantLimit(netDebitCap) - effectivePosition (same as = netDebitCap - currentPosition - reservedPosition) + + + For each transfer in the batch, validate the availablility of position to meet the transfer amount + this will be as per the position algorithm documented below + + + + + + 14 + Validate availablePosition for each tranfser (see algorithm below) + Error code: + 4001 + + + 01: sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED + 02: sumProcessed =0 // Record the sum of the transfers already processed in this batch + 03: processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position + 04: foreach transfer in reservedTransfers + 05: sumProcessed += transfer.amount // the total processed so far + (NEED TO UPDATE IN CODE) + 06: if availablePosition >= transfer.amount + 07: transfer.state = "RESERVED" + 08: availablePosition -= preparedTransfer.amount + 09: sumRESERVED += preparedTransfer.amount + 10: else + 11: preparedTransfer.state = "ABORTED" + 12: preparedTransfer.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + 13: end if + 14: runningPosition = currentPosition + sumReserved // the initial value of the Participants position plus the total value that has been accepted in the batch so far + 15: runningReservedValue = sumTransfersInBatch - sumProcessed + reservedPosition + (NEED TO UPDATE IN CODE) + // the running down of the total reserved value at the begining of the batch. + 16: Add transfer to the processedTransfer list recording the transfer state and running position and reserved values { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue } + 16: end foreach + + + Once the outcome for all transfers is known,update the Participant's position and remove the reserved amount associated with the batch + (If there are any alarm limits, process those returning limits in which the threshold has been breached) + Do a bulk insert of the trasnferStateChanges associated with processing, using the result to complete the participantPositionChange and bulk insert of these to persist the running position + + + + + 15 + Assess any limit thresholds on the final position + adding to alarm list if triggered + + + 16 + Persist latest position + value + and + reservedValue + to DB for Payer + + UPDATE + participantPosition + SET value += sumRESERVED, + reservedValue -= sumTransfersInBatch + + + 17 + Bulk persist transferStateChange for all processedTransfers + + batch INSERT + transferStateChange + select for update from transfer table where transferId in ([transferBatch.transferId,...]) + build list of transferStateChanges from transferBatch +   + + + + + 18 + Populate batchParticipantPositionChange from the resultant transferStateChange and the earlier processedTransfer list + + + Effectively: + SET transferStateChangeId = processedTransfer.transferStateChangeId, + participantPositionId = preparedTransfer.participantPositionId, + value = preparedTransfer.positionValue, + reservedValue = preparedTransfer.positionReservedValue + + + 19 + Bulk persist the participant position change for all processedTransfers + + batch INSERT + participantPositionChange +              + + + 20 + Return a map of transferIds and their transferStateChanges + + + alt + [Calculate & Validate Latest Position Prepare (success)] + + + + + 21 + Notifications for Position Validation Success + Reference: Position Validation Success case (Prepare) + + [Calculate & Validate Latest Position Prepare (failure)] + + + Validation failure! + + + Persist Transfer State (with transferState='ABORTED' on position check fail) + + + 22 + Request to persist transfer + Error code: + 2003 + + + transferStateChange.state = "ABORTED", + transferStateChange.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + + + 23 + Persist transfer state + + transferStateChange + + + 24 + Return success + + + + + 25 + Notifications for failures + Reference: Failure in Position Validation (Prepare) + + + Reference: Failure in Position Validation (Prepare) + + + alt + [If action == 'bulk-prepare'] + + + Message: + { + id: "<messageId>" + from: <ledgerName>, + to: <transferMessage.payerFsp>, + type: "application/json" + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": <transferMessage.extensionList> + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "bulk-processing", + action: "bulk-prepare", + createdAt: <timestamp>, + state: { + status: "error", + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 26 + Publish Position failure event (in Prepare) to Bulk Processing Topic (for Payer) + Error codes: + 2003 + + [If action == 'prepare'] + + + Message: + { + id: "<messageId>" + from: <ledgerName>, + to: <transferMessage.payerFsp>, + type: "application/json" + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": <transferMessage.extensionList> + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "notification", + action: "position", + createdAt: <timestamp>, + state: { + status: "error", + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 27 + Publish Notification (failure) event for Payer + Error code: + 2003 + + + Reference: Position Validation Success case (Prepare) + + + alt + [If action == 'bulk-prepare'] + + + Message: + { + id: "<messageId>" + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: "application/json" + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "bulk-processing", + action: "bulk-prepare", + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 28 + Publish Position Success event (in Prepare) to Bulk Processing Topic + Error codes: + 2003 + + [If action == 'prepare'] + + + Message: + { + id: "<messageId>" + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: "application/json" + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "notification", + action: "abort", + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 29 + Publish Notification event + Error code: + 2003 + + diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.plantuml new file mode 100644 index 000000000..19b2a9574 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.plantuml @@ -0,0 +1,347 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declare title +title 1.4.0. Bulk Processing Handler Consume + +autonumber + +/'***** + Diagram notes + -------------- + RECEIVED/RECEIVED + from: prepare-handler , action: prepare-duplicate/success, result: PENDING_PREPARE/ACCEPTED & RECEIVED_DUPLICATE + from: prepare-handler , action: prepare-duplicate/error , result: PENDING_PREPARE/ACCEPTED & RECEIVED_DUPLICATE + from: prepare-handler , action: prepare/error , result: PENDING_PREPARE/ACCEPTED & RECEIVED_INVALID + from: position-handler, action: prepare/error , result: PENDING_PREPARE/ACCEPTED & RECEIVED_INVALID + from: position-handler, action: prepare/success , result: PENDING_PREPARE/ACCEPTED & ACCEPTED + from: timeout-handler , action: timeout-received/error , result: unchanged/COMPLETED & EXPIRED + -------------- + ACCEPTED/ACCEPTED + from: position-handler, action: timeout-reserved/error , result: unchanged/COMPLETED & EXPIRED + -------------- + PROCESSING/ACCEPTED + from: fulfil-handler , action: fulfil-duplicate/success , result: PENDING_FULFIL/COMPLETED & FULFIL_DUPLICATE + from: fulfil-handler , action: fulfil-duplicate/error , result: PENDING_FULFIL/COMPLETED & FULFIL_DUPLICATE + from: position-handler, action: commit/success , result: PENDING_FULFIL/COMPLETED & COMPLETED + from: position-handler, action: reject/success , result: PENDING_FULFIL/COMPLETED & REJECTED + from: position-handler, action: abort/error , result: PENDING_FULFIL/COMPLETED & FULFIL_INVALID + from: fulfil-handler , action: commit/error , result: PENDING_FULFIL/COMPLETED & FULFIL_INVALID + from: position-handler, action: timeout-reserved/error , result: unchanged/COMPLETED & EXPIRED + -------------- + COMPLETED/EXPIRED + -------------- + ******'/ + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-bulk-\nprocessing" as TOPIC_BULK_PROCESSING +control "Bulk Processing\nHandler" as BULK_PROC_HANDLER +collections "topic-event" as TOPIC_EVENTS +collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE +collections "topic-notification" as TOPIC_NOTIFICATION +entity "Bulk DAO" as BULK_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_BULK_PROCESSING + participant BULK_PROC_HANDLER + participant TOPIC_EVENTS + participant OBJECT_STORE + participant TOPIC_NOTIFICATION + participant BULK_DAO + participant DB +end box + +' start flow +activate BULK_PROC_HANDLER +group Bulk Processing Handler Consume + TOPIC_BULK_PROCESSING <- BULK_PROC_HANDLER: Consume message + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + + break + group Validate Event + BULK_PROC_HANDLER <-> BULK_PROC_HANDLER: Validate event - Rule:\ntype == 'bulk-processing' && action IN\n['prepare-duplicate', 'bulk-prepare',\n'bulk-timeout-received', 'fulfil-duplicate',\n'bulk-commit', 'bulk-timeout-reserved']\nError codes: 2001 + end + end + + group Persist Event Information + ||| + BULK_PROC_HANDLER -> TOPIC_EVENTS: Publish event information + ref over BULK_PROC_HANDLER, TOPIC_EVENTS: Event Handler Consume\n + ||| + end + + group Process Message + BULK_PROC_HANDLER -> BULK_DAO: Retrieve current state of Bulk Transfer + activate BULK_DAO + BULK_DAO -> DB: Retrieve current state of Bulk Transfer + activate DB + hnote over DB #lightyellow + bulkTransfer + bulkTransferStateChange + end note + BULK_DAO <-- DB: Return **bulkTransferInfo** + deactivate DB + BULK_PROC_HANDLER <-- BULK_DAO: Return **bulkTransferInfo** + deactivate BULK_DAO + + group Validate Bulk Transfer State + note right of BULK_PROC_HANDLER #lightgrey + **Initialize variables**: + let criteriaState + let incompleteBulkState + let completedBulkState + let bulkTransferState + let processingState + let errorCode, errorMessage + let produceNotification = false + end note + alt bulkTransferInfo.bulkTransferState IN ['RECEIVED', 'PENDING_PREPARE'] + note right of BULK_PROC_HANDLER #lightgrey + criteriaState = 'RECEIVED' + incompleteBulkState = 'PENDING_PREPARE' + completedBulkState = 'ACCEPTED' + end note + alt action == 'prepare-duplicate' AND state.status == 'error' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'RECEIVED_DUPLICATE' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + end note + else action == 'bulk-prepare' AND state.status == 'error' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'RECEIVED_INVALID' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + end note + else action == 'bulk-prepare' AND state.status == 'success' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'ACCEPTED' + end note + else action IN ['bulk-timeout-received', 'bulk-timeout-reserved'] + note right of BULK_PROC_HANDLER #lightgrey + incompleteBulkState = 'EXPIRING' + completedBulkState = 'COMPLETED' + processingState = 'EXPIRED' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + end note + else all other actions + note right of BULK_PROC_HANDLER #lightgrey + throw ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + end note + end + else bulkTransferInfo.bulkTransferState IN ['ACCEPTED'] + alt action == 'bulk-timeout-reserved' + note right of BULK_PROC_HANDLER #lightgrey + criteriaState = 'ACCEPTED' + incompleteBulkState = 'EXPIRING' + completedBulkState = 'COMPLETED' + processingState = 'EXPIRED' + end note + else all other actions + note right of BULK_PROC_HANDLER #lightgrey + throw ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + end note + end + else bulkTransferInfo.bulkTransferState IN ['PROCESSING', 'PENDING_FULFIL', 'EXPIRING'] + note right of BULK_PROC_HANDLER #lightgrey + criteriaState = 'PROCESSING' + incompleteBulkState = 'PENDING_FULFIL' + completedBulkState = 'COMPLETED' + end note + alt action == 'fulfil-duplicate' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'FULFIL_DUPLICATE' + end note + else action == 'bulk-commit' AND state.status == 'success' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'COMPLETED' + end note + else action == 'reject' AND state.status == 'success' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'REJECTED' + end note + else action IN ['commit', 'abort'] AND state.status == 'error' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'FULFIL_INVALID' + end note + else action == 'bulk-timeout-reserved' + note right of BULK_PROC_HANDLER #lightgrey + incompleteBulkState = 'EXPIRING' + completedBulkState = 'COMPLETED' + processingState = 'EXPIRED' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + end note + else all other actions + note right of BULK_PROC_HANDLER #lightgrey + throw ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + end note + end + else bulkTransferInfo.bulkTransferState IN ['ABORTING'] + alt action == 'bulk-abort' + note right of BULK_PROC_HANDLER #lightgrey + criteriaState = 'ABORTING' + processingState = 'FULFIL_INVALID' + completedBulkState = 'REJECTED' + incompleteBulkState = 'ABORTING' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + end note + else all other actions + note right of BULK_PROC_HANDLER #lightgrey + throw ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + end note + end + else all other ['PENDING_INVALID', 'COMPLETED', 'REJECTED', 'INVALID'] + note right of BULK_PROC_HANDLER #lightgrey + throw ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + end note + end + end + + BULK_PROC_HANDLER -> BULK_DAO: Persist individual transfer processing state + activate BULK_DAO + BULK_DAO -> DB: Persist individual transfer processing state\n-- store errorCode/errorMessage when\nstate.status == 'error' + activate DB + hnote over DB #lightyellow + bulkTransferAssociation + end note + deactivate DB + BULK_PROC_HANDLER <-- BULK_DAO: Return success + deactivate BULK_DAO + + BULK_PROC_HANDLER -> BULK_DAO: Check previously defined completion criteria + activate BULK_DAO + BULK_DAO -> DB: Select EXISTS (LIMIT 1) in criteriaState + activate DB + hnote over DB #lightyellow + bulkTransferAssociation + end note + BULK_DAO <-- DB: Return **existingIndividualTransfer** + deactivate DB + BULK_PROC_HANDLER <-- BULK_DAO: Return **existingIndividualTransfer** + deactivate BULK_DAO + + alt individual transfer exists + note right of BULK_PROC_HANDLER #lightgrey + bulkTransferState = incompleteBulkState + end note + else no transfer in criteriaState exists + note right of BULK_PROC_HANDLER #lightgrey + bulkTransferState = completedBulkState + produceNotification = true + end note + end + + BULK_PROC_HANDLER -> BULK_DAO: Persist bulkTransferState from previous step + activate BULK_DAO + BULK_DAO -> DB: Persist bulkTransferState + activate DB + deactivate DB + hnote over DB #lightyellow + bulkTransferStateChange + end note + BULK_PROC_HANDLER <-- BULK_DAO: Return success + deactivate BULK_DAO + + + alt produceNotification == true + BULK_PROC_HANDLER -> BULK_DAO: Request to retrieve all bulk transfer and individual transfer results + activate BULK_DAO + BULK_DAO -> DB: Get bulkTransferResult + activate DB + hnote over DB #lightyellow + bulkTransfer + bulkTransferStateChange + bulkTransferAssociation + end note + BULK_DAO <-- DB: Return **bulkTransferResult** + deactivate DB + BULK_PROC_HANDLER <-- BULK_DAO: Return **bulkTransferResult** + deactivate BULK_DAO + + group Send Bulk Notification(s) + note right of BULK_PROC_HANDLER #lightgrey + Depending on the action decide where to + send notification: payer, payee OR both + end note + + BULK_PROC_HANDLER -> OBJECT_STORE: Generate & Persist bulk message to object store:\n**MLOS.bulkTransferResults** by destination + activate OBJECT_STORE + OBJECT_STORE --> BULK_PROC_HANDLER: Return reference to the stored object(s)\n**MLOS.bulkTransferResults.messageId** + deactivate OBJECT_STORE + note right of BULK_PROC_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json" + content: { + headers: , + payload: { + bulkTransferId: , + bulkTransferState: + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "notification", + action: "bulk-[prepare | commit | abort | processing]", + createdAt: , + state: { + status: state.status, + code: state.code + } + } + } + } + end note + + BULK_PROC_HANDLER -> TOPIC_NOTIFICATION: Publish Notification event for Payer/Payee\nError codes: 2003 + activate TOPIC_NOTIFICATION + deactivate TOPIC_NOTIFICATION + end + else produceNotification == false + note right of BULK_PROC_HANDLER #lightgrey + Do nothing (awaitAllTransfers) + end note + end + end +end +deactivate BULK_PROC_HANDLER +@enduml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.svg new file mode 100644 index 000000000..9d756ff45 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.svg @@ -0,0 +1,468 @@ + + 1.4.0. Bulk Processing Handler Consume + + + 1.4.0. Bulk Processing Handler Consume + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + topic-bulk- + processing + + + topic-bulk- + processing + Bulk Processing + Handler + + + Bulk Processing + Handler + + + + + topic-event + + + topic-event + + + mojaloop- + object-store + ( + MLOS + ) + + + mojaloop- + object-store + ( + MLOS + ) + + + topic-notification + + + topic-notification + Bulk DAO + + + Bulk DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + Bulk Processing Handler Consume + + + 1 + Consume message + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: + type == 'bulk-processing' && action IN + ['prepare-duplicate', 'bulk-prepare', + 'bulk-timeout-received', 'fulfil-duplicate', + 'bulk-commit', 'bulk-timeout-reserved'] + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + Process Message + + + 4 + Retrieve current state of Bulk Transfer + + + 5 + Retrieve current state of Bulk Transfer + + bulkTransfer + bulkTransferStateChange + + + 6 + Return + bulkTransferInfo + + + 7 + Return + bulkTransferInfo + + + Validate Bulk Transfer State + + + Initialize variables + : + let criteriaState + let incompleteBulkState + let completedBulkState + let bulkTransferState + let processingState + let errorCode, errorMessage + let produceNotification = false + + + alt + [bulkTransferInfo.bulkTransferState IN ['RECEIVED', 'PENDING_PREPARE']] + + + criteriaState = 'RECEIVED' + incompleteBulkState = 'PENDING_PREPARE' + completedBulkState = 'ACCEPTED' + + + alt + [action == 'prepare-duplicate' AND state.status == 'error'] + + + processingState = 'RECEIVED_DUPLICATE' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + + [action == 'bulk-prepare' AND state.status == 'error'] + + + processingState = 'RECEIVED_INVALID' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + + [action == 'bulk-prepare' AND state.status == 'success'] + + + processingState = 'ACCEPTED' + + [action IN ['bulk-timeout-received', 'bulk-timeout-reserved']] + + + incompleteBulkState = 'EXPIRING' + completedBulkState = 'COMPLETED' + processingState = 'EXPIRED' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + + [all other actions] + + + throw + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + [bulkTransferInfo.bulkTransferState IN ['ACCEPTED']] + + + alt + [action == 'bulk-timeout-reserved'] + + + criteriaState = 'ACCEPTED' + incompleteBulkState = 'EXPIRING' + completedBulkState = 'COMPLETED' + processingState = 'EXPIRED' + + [all other actions] + + + throw + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + [bulkTransferInfo.bulkTransferState IN ['PROCESSING', 'PENDING_FULFIL', 'EXPIRING']] + + + criteriaState = 'PROCESSING' + incompleteBulkState = 'PENDING_FULFIL' + completedBulkState = 'COMPLETED' + + + alt + [action == 'fulfil-duplicate'] + + + processingState = 'FULFIL_DUPLICATE' + + [action == 'bulk-commit' AND state.status == 'success'] + + + processingState = 'COMPLETED' + + [action == 'reject' AND state.status == 'success'] + + + processingState = 'REJECTED' + + [action IN ['commit', 'abort'] AND state.status == 'error'] + + + processingState = 'FULFIL_INVALID' + + [action == 'bulk-timeout-reserved'] + + + incompleteBulkState = 'EXPIRING' + completedBulkState = 'COMPLETED' + processingState = 'EXPIRED' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + + [all other actions] + + + throw + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + [bulkTransferInfo.bulkTransferState IN ['ABORTING']] + + + alt + [action == 'bulk-abort'] + + + criteriaState = 'ABORTING' + processingState = 'FULFIL_INVALID' + completedBulkState = 'REJECTED' + incompleteBulkState = 'ABORTING' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + + [all other actions] + + + throw + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + [all other ['PENDING_INVALID', 'COMPLETED', 'REJECTED', 'INVALID']] + + + throw + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + + 8 + Persist individual transfer processing state + + + 9 + Persist individual transfer processing state + -- store errorCode/errorMessage when + state.status == 'error' + + bulkTransferAssociation + + + 10 + Return success + + + 11 + Check previously defined completion criteria + + + 12 + Select EXISTS (LIMIT 1) in criteriaState + + bulkTransferAssociation + + + 13 + Return + existingIndividualTransfer + + + 14 + Return + existingIndividualTransfer + + + alt + [individual transfer exists] + + + bulkTransferState = incompleteBulkState + + [no transfer in criteriaState exists] + + + bulkTransferState = completedBulkState + produceNotification = true + + + 15 + Persist bulkTransferState from previous step + + + 16 + Persist bulkTransferState + + bulkTransferStateChange + + + 17 + Return success + + + alt + [produceNotification == true] + + + 18 + Request to retrieve all bulk transfer and individual transfer results + + + 19 + Get bulkTransferResult + + bulkTransfer + bulkTransferStateChange + bulkTransferAssociation + + + 20 + Return + bulkTransferResult + + + 21 + Return + bulkTransferResult + + + Send Bulk Notification(s) + + + Depending on the action decide where to + send notification: payer, payee OR both + + + 22 + Generate & Persist bulk message to object store: + MLOS.bulkTransferResults + by destination + + + 23 + Return reference to the stored object(s) + MLOS.bulkTransferResults.messageId + + + Message: + { + id: <messageId> + from: <source>, + to: <destination>, + type: "application/json" + content: { + headers: <bulkTransferHeaders>, + payload: { + bulkTransferId: <uuid>, + bulkTransferState: <string> + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "notification", + action: "bulk-[prepare | commit | abort | processing]", + createdAt: <timestamp>, + state: { + status: state.status, + code: state.code + } + } + } + } + + + 24 + Publish Notification event for Payer/Payee + Error codes: + 2003 + + [produceNotification == false] + + + Do nothing (awaitAllTransfers) + + diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.plantuml new file mode 100644 index 000000000..476d76354 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.plantuml @@ -0,0 +1,225 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.1.0. DFSP2 sends a Bulk Fulfil Success Transfer request + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API \nNotification Handler" as NOTIFY_HANDLER +collections "mongo-\nobject-store" as OBJECT_STORE +boundary "Central Service API" as CSAPI +collections "topic-\nbulk-fulfil" as TOPIC_BULK_FULFIL +control "Bulk Fulfil\nHandler" as BULK_FULFIL_HANDLER +collections "topic-\nfulfil" as TOPIC_FULFIL +control "Fulfil \nHandler" as FULF_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position \nHandler" as POS_HANDLER +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +control "Bulk Processing\nHandler" as BULK_PROC_HANDLER +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant OBJECT_STORE + participant CSAPI + participant TOPIC_BULK_FULFIL + participant BULK_FULFIL_HANDLER + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_BULK_PROCESSING + participant BULK_PROC_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate BULK_FULFIL_HANDLER +activate FULF_HANDLER +activate POS_HANDLER +activate BULK_PROC_HANDLER +group DFSP2 sends a Bulk Fulfil Success Transfer request to DFSP1 + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - bulkTransferMessage: + { + bulkTransferState: , + completedTimestamp: , + individualTransferResults: + [ + { + transferId: , + fulfilment: , + extensionList: { extension: [ + { key: , value: } + ] } + } + ], + extensionList: { extension: [ + { key: , value: } + ] } + } + end note + DFSP2 ->> MLAPI: PUT - /bulkTransfers/ + activate MLAPI + MLAPI -> OBJECT_STORE: Persist incoming bulk message to\nobject store: **MLOS.individualTransferFulfils** + activate OBJECT_STORE + OBJECT_STORE --> MLAPI: Return messageId reference to the stored object(s) + deactivate OBJECT_STORE + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: "application/json", + content: { + headers: , + payload: { + bulkTransferId: , + bulkTransferState: "COMPLETED", + completedTimestamp: , + extensionList: { extension: [ + { key: , value: } + ] }, + count: , + hash: + } + }, + metadata: { + event: { + id: , + type: "bulk-fulfil", + action: "bulk-commit", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_BULK_FULFIL: Route & Publish Bulk Fulfil event for Payee\nError code: 2003 + activate TOPIC_BULK_FULFIL + TOPIC_BULK_FULFIL <-> TOPIC_BULK_FULFIL: Ensure event is replicated \nas configured (ACKS=all)\nError code: 2003 + TOPIC_BULK_FULFIL --> MLAPI: Respond replication acknowledgements \nhave been received + deactivate TOPIC_BULK_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_BULK_FULFIL <- BULK_FULFIL_HANDLER: Consume message + BULK_FULFIL_HANDLER -> OBJECT_STORE: Retrieve individual transfers by key:\n**MLOS.individualTransferFulfils.messageId** + activate OBJECT_STORE + OBJECT_STORE --> BULK_FULFIL_HANDLER: Stream bulk's individual transfers + deactivate OBJECT_STORE + ref over TOPIC_BULK_FULFIL, TOPIC_FULFIL: Bulk Prepare Handler Consume \n + alt Success + BULK_FULFIL_HANDLER -> TOPIC_FULFIL: Produce (stream) single transfer message\nfor each individual transfer [loop] + else Failure + BULK_FULFIL_HANDLER --> TOPIC_NOTIFICATIONS: Produce single message for the entire bulk + end + ||| + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Success)\n + alt Success + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + else Failure + FULF_HANDLER --> TOPIC_BULK_PROCESSING: Produce message + end + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_BULK_PROCESSING: Position Handler Consume (Success)\n + POS_HANDLER -> TOPIC_BULK_PROCESSING: Produce message + ||| + TOPIC_BULK_PROCESSING <- BULK_PROC_HANDLER: Consume message + ref over TOPIC_BULK_PROCESSING, TOPIC_NOTIFICATIONS: Bulk Processing Handler Consume (Success)\n + BULK_PROC_HANDLER -> OBJECT_STORE: Persist bulk message by destination to the\nobject store: **MLOS.bulkTransferResults** + activate OBJECT_STORE + OBJECT_STORE --> BULK_PROC_HANDLER: Return the reference to the stored \nnotification object(s): **messageId** + deactivate OBJECT_STORE + BULK_PROC_HANDLER -> TOPIC_NOTIFICATIONS: Send Bulk Commit notification + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + NOTIFY_HANDLER -> OBJECT_STORE: Retrieve bulk notification(s) by reference & destination:\n**MLOS.bulkTransferResults.messageId + destination** + activate OBJECT_STORE + OBJECT_STORE --> NOTIFY_HANDLER: Return notification payload + deactivate OBJECT_STORE + opt action == 'bulk-commit' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + NOTIFY_HANDLER -> OBJECT_STORE: Retrieve bulk notification(s) by reference & destination:\n**MLOS.bulkTransferResults.messageId + destination** + activate OBJECT_STORE + OBJECT_STORE --> NOTIFY_HANDLER: Return notification payload + deactivate OBJECT_STORE + opt action == 'bulk-commit' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +deactivate POS_HANDLER +activate BULK_FULFIL_HANDLER +deactivate FULF_HANDLER +deactivate BULK_PROC_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.svg new file mode 100644 index 000000000..223109602 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.svg @@ -0,0 +1,429 @@ + + 2.1.0. DFSP2 sends a Bulk Fulfil Success Transfer request + + + 2.1.0. DFSP2 sends a Bulk Fulfil Success Transfer request + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + DFSP2 + Payee + + + DFSP2 + Payee + + + ML API Adapter + + + ML API Adapter + + + ML API + Notification Handler + + + ML API + Notification Handler + + + + + mongo- + object-store + + + mongo- + object-store + Central Service API + + + Central Service API + + + + + topic- + bulk-fulfil + + + topic- + bulk-fulfil + Bulk Fulfil + Handler + + + Bulk Fulfil + Handler + + + + + topic- + fulfil + + + topic- + fulfil + Fulfil + Handler + + + Fulfil + Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + Position + Handler + + + Position + Handler + + + + + topic- + bulk-processing + + + topic- + bulk-processing + Bulk Processing + Handler + + + Bulk Processing + Handler + + + + + topic- + notification + + + topic- + notification + + + + + + + + + + + + + + + DFSP2 sends a Bulk Fulfil Success Transfer request to DFSP1 + + + Headers - transferHeaders: { + Content-Length: <int>, + Content-Type: <string>, + Date: <date>, + FSPIOP-Source: <string>, + FSPIOP-Destination: <string>, + FSPIOP-Encryption: <string>, + FSPIOP-Signature: <string>, + FSPIOP-URI: <uri>, + FSPIOP-HTTP-Method: <string> + } +   + Payload - bulkTransferMessage: + { + bulkTransferState: <bulkTransferState>, + completedTimestamp: <completedTimeStamp>, + individualTransferResults: + [ + { + transferId: <uuid>, + fulfilment: <ilpCondition>, + extensionList: { extension: [ + { key: <string>, value: <string> } + ] } + } + ], + extensionList: { extension: [ + { key: <string>, value: <string> } + ] } + } + + + + 1 + PUT - /bulkTransfers/<ID> + + + 2 + Persist incoming bulk message to + object store: + MLOS.individualTransferFulfils + + + 3 + Return messageId reference to the stored object(s) + + + Message: + { + id: <messageId>, + from: <payeeFspName>, + to: <payerFspName>, + type: "application/json", + content: { + headers: <bulkTransferHeaders>, + payload: { + bulkTransferId: <uuid>, + bulkTransferState: "COMPLETED", + completedTimestamp: <timestamp>, + extensionList: { extension: [ + { key: <string>, value: <string> } + ] }, + count: <int>, + hash: <string> + } + }, + metadata: { + event: { + id: <uuid>, + type: "bulk-fulfil", + action: "bulk-commit", + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 4 + Route & Publish Bulk Fulfil event for Payee + Error code: + 2003 + + + + + + 5 + Ensure event is replicated + as configured (ACKS=all) + Error code: + 2003 + + + 6 + Respond replication acknowledgements + have been received + + + + 7 + Respond HTTP - 200 (OK) + + + 8 + Consume message + + + 9 + Retrieve individual transfers by key: + MLOS.individualTransferFulfils.messageId + + + 10 + Stream bulk's individual transfers + + + ref + Bulk Prepare Handler Consume +   + + + alt + [Success] + + + 11 + Produce (stream) single transfer message + for each individual transfer [loop] + + [Failure] + + + 12 + Produce single message for the entire bulk + + + 13 + Consume message + + + ref + Fulfil Handler Consume (Success) +   + + + alt + [Success] + + + 14 + Produce message + + [Failure] + + + 15 + Produce message + + + 16 + Consume message + + + ref + Position Handler Consume (Success) +   + + + 17 + Produce message + + + 18 + Consume message + + + ref + Bulk Processing Handler Consume (Success) +   + + + 19 + Persist bulk message by destination to the + object store: + MLOS.bulkTransferResults + + + 20 + Return the reference to the stored + notification object(s): + messageId + + + 21 + Send Bulk Commit notification + + + 22 + Consume message + + + 23 + Retrieve bulk notification(s) by reference & destination: + MLOS.bulkTransferResults.messageId + destination + + + 24 + Return notification payload + + + opt + [action == 'bulk-commit'] + + + ref + Send notification to Participant (Payer) +   + + + 25 + Send callback notification + + + 26 + Consume message + + + 27 + Retrieve bulk notification(s) by reference & destination: + MLOS.bulkTransferResults.messageId + destination + + + 28 + Return notification payload + + + opt + [action == 'bulk-commit'] + + + ref + Send notification to Participant (Payee) +   + + + 29 + Send callback notification + + diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.plantuml new file mode 100644 index 000000000..2da07f279 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.plantuml @@ -0,0 +1,324 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declare title +title 2.1.1. Bulk Fulfil Handler Consume + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "mongo-\nobject-store" as OBJECT_STORE +collections "topic-bulk-\nfulfil" as TOPIC_BULK_FULFIL +collections "topic-bulk-\nprocessing" as TOPIC_BULK_PROCESSING +control "Bulk Fulfil\nHandler" as BULK_FULF_HANDLER +collections "topic-transfer-\nfulfil" as TOPIC_TRANSFER_FULFIL +collections "topic-event" as TOPIC_EVENTS +collections "topic-notification" as TOPIC_NOTIFICATION +entity "Bulk DAO" as BULK_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant OBJECT_STORE + participant TOPIC_BULK_FULFIL + participant BULK_FULF_HANDLER + participant TOPIC_TRANSFER_FULFIL + participant TOPIC_BULK_PROCESSING + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATION + participant BULK_DAO + participant DB +end box + +' start flow +activate BULK_FULF_HANDLER +group Bulk Fulfil Handler Consume + TOPIC_BULK_FULFIL <- BULK_FULF_HANDLER: Consume message + activate TOPIC_BULK_FULFIL + deactivate TOPIC_BULK_FULFIL + + break + group Validate Event + BULK_FULF_HANDLER <-> BULK_FULF_HANDLER: Validate event - Rule:\ntype == 'bulk-fulfil' && action == 'bulk-commit'\nError codes: 2001 + end + end + + group Persist Event Information + ||| + BULK_FULF_HANDLER -> TOPIC_EVENTS: Publish event information + ref over BULK_FULF_HANDLER, TOPIC_EVENTS: Event Handler Consume \n + ||| + end + + group Validate FSPIOP-Signature + ||| + ref over BULK_FULF_HANDLER, TOPIC_NOTIFICATION: Validate message.content.headers.**FSPIOP-Signature**\nError codes: 3105/3106\n + ||| + end + + group Validate Bulk Fulfil Transfer + BULK_FULF_HANDLER <-> BULK_FULF_HANDLER: Schema validation of the incoming message + BULK_FULF_HANDLER <-> BULK_FULF_HANDLER: Verify the message's signature\n(to be confirmed in future requirement) + note right of BULK_FULF_HANDLER #lightgrey + The above validation steps are already handled by the + Bulk-API-Adapter for the open source implementation. + It may need to be added in future for custom adapters. + end note + + group Validate Duplicate Check + ||| + BULK_FULF_HANDLER -> DB: Request Duplicate Check + ref over BULK_FULF_HANDLER, DB: Request Duplicate Check\n + DB --> BULK_FULF_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break + BULK_FULF_HANDLER -> BULK_DAO: Request to retrieve Bulk Transfer state & completedTimestamp\nError code: 2003 + activate BULK_DAO + BULK_DAO -> DB: Query database + hnote over DB #lightyellow + bulkTransfer + bulkTransferFulfilment + bulkTransferStateChange + end note + activate DB + BULK_DAO <-- DB: Return resultset + deactivate DB + BULK_DAO --> BULK_FULF_HANDLER: Return **bulkTransferStateId** & **completedTimestamp** (not null when completed) + deactivate BULK_DAO + + note right of BULK_FULF_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + bulkTransferState: , + completedTimestamp: + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "notification", + action: "bulk-fulfil-duplicate", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + BULK_FULF_HANDLER -> TOPIC_NOTIFICATION: Publish Notification event for Payee + activate TOPIC_NOTIFICATION + deactivate TOPIC_NOTIFICATION + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of BULK_FULF_HANDLER #yellow + { + id: , + from: , + type: "application/json", + content: { + headers: , + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request", + extensionList: { + extension: [ + { + key: "_cause", + value: + } + ] + } + }, + uriParams: { + id: + } + } + }, + metadata: { + correlationId: , + event: { + id: , + type: "notification", + action: "bulk-commit", + createdAt: , + state: { + status: "error", + code: "3106", + description: "Modified request" + }, + responseTo: + } + } + } + end note + BULK_FULF_HANDLER -> TOPIC_NOTIFICATION: Publish Notification (failure) event for Payer\nError codes: 3106 + activate TOPIC_NOTIFICATION + deactivate TOPIC_NOTIFICATION + else hasDuplicateId == FALSE + alt Validate Bulk Transfer Fulfil (success) + group Persist Bulk Transfer State (with bulktransferState='PROCESSING') + BULK_FULF_HANDLER -> BULK_DAO: Request to persist bulk transfer fulfil\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Persist bulkTransferFulfilment + hnote over DB #lightyellow + bulkTransferFulfilment + bulkTransferStateChange + bulkTransferExtension + end note + activate DB + deactivate DB + BULK_DAO --> BULK_FULF_HANDLER: Return success + deactivate BULK_DAO + end + else Validate Bulk Transfer Fulfil (failure) + group Persist Bulk Transfer State (with bulkTransferState='ABORTING') + BULK_FULF_HANDLER -> BULK_DAO: Request to persist bulk\ntransfer fulfil failure\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Persist transfer + hnote over DB #lightyellow + bulkTransferFulfilment + bulkTransferStateChange + bulkTransferExtension + bulkTransferError + end note + activate DB + deactivate DB + BULK_DAO --> BULK_FULF_HANDLER: Return success + deactivate BULK_DAO + end + end + end + end + alt Validate Bulk Transfer Fulfil (success) + loop for every individual transfer in the bulk fulfil list + BULK_FULF_HANDLER -> OBJECT_STORE: Retrieve individual transfers from the bulk using\nreference: **MLOS.individualTransferFulfils.messageId** + activate OBJECT_STORE + OBJECT_STORE --> BULK_FULF_HANDLER: Return stored bulk transfer containing individual transfers + deactivate OBJECT_STORE + + BULK_FULF_HANDLER --> OBJECT_STORE: Update bulk transfer association record to bulk transfer processing state 'PROCESSING' + activate OBJECT_STORE + OBJECT_STORE --> BULK_FULF_HANDLER: Bulk transfer association record commited + deactivate OBJECT_STORE + + note right of BULK_FULF_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json" + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "fulfil", + action: "bulk-commit", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + BULK_FULF_HANDLER -> TOPIC_TRANSFER_FULFIL: Route & Publish fulfil bulk commit events to the Payer for the Individual Transfer\nError codes: 2003 + activate TOPIC_TRANSFER_FULFIL + deactivate TOPIC_TRANSFER_FULFIL + end + else Validate Bulk Transfer Fulfil (failure) + loop for every individual transfer in the bulk fulfil list + BULK_FULF_HANDLER -> OBJECT_STORE: Retrieve individual transfers from the bulk using\nreference: **MLOS.individualTransferFulfils.messageId** + activate OBJECT_STORE + OBJECT_STORE --> BULK_FULF_HANDLER: Stream bulk's individual transfer fulfils + deactivate OBJECT_STORE + + BULK_FULF_HANDLER --> OBJECT_STORE: Update bulk transfer association record to bulk transfer processing state 'ABORTING' + activate OBJECT_STORE + OBJECT_STORE --> BULK_FULF_HANDLER: Bulk transfer association record commited + deactivate OBJECT_STORE + + note right of BULK_FULF_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json" + content: { + headers: , + payload: "errorInformation": { + "errorCode": + "errorDescription": "", + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "fulfil", + action: "bulk-abort", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + BULK_FULF_HANDLER -> TOPIC_TRANSFER_FULFIL: Route & Publish fulfil bulk abort events to the Payer for the Individual Transfer\nError codes: 2003 + activate TOPIC_TRANSFER_FULFIL + deactivate TOPIC_TRANSFER_FULFIL + end +end +deactivate BULK_FULF_HANDLER +@enduml + diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.svg new file mode 100644 index 000000000..7ab28f05f --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.svg @@ -0,0 +1,496 @@ + + 2.1.1. Bulk Fulfil Handler Consume + + + 2.1.1. Bulk Fulfil Handler Consume + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mongo- + object-store + + + mongo- + object-store + + + topic-bulk- + fulfil + + + topic-bulk- + fulfil + Bulk Fulfil + Handler + + + Bulk Fulfil + Handler + + + + + topic-transfer- + fulfil + + + topic-transfer- + fulfil + + + topic-bulk- + processing + + + topic-bulk- + processing + + + topic-event + + + topic-event + + + topic-notification + + + topic-notification + Bulk DAO + + + Bulk DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + + 1 + Consume message + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: + type == 'bulk-fulfil' && action == 'bulk-commit' + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + Validate FSPIOP-Signature + + + ref + Validate message.content.headers. + FSPIOP-Signature + Error codes: + 3105/3106 +   + + + Validate Bulk Fulfil Transfer + + + + + + 4 + Schema validation of the incoming message + + + + + + 5 + Verify the message's signature + (to be confirmed in future requirement) + + + The above validation steps are already handled by the + Bulk-API-Adapter for the open source implementation. + It may need to be added in future for custom adapters. + + + Validate Duplicate Check + + + 6 + Request Duplicate Check + + + ref + Request Duplicate Check +   + + + 7 + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + alt + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + break + + + 8 + Request to retrieve Bulk Transfer state & completedTimestamp + Error code: + 2003 + + + 9 + Query database + + bulkTransfer + bulkTransferFulfilment + bulkTransferStateChange + + + 10 + Return resultset + + + 11 + Return + bulkTransferStateId + & + completedTimestamp + (not null when completed) + + + Message: + { + id: <messageId> + from: <ledgerName>, + to: <payeeFspName>, + type: application/json + content: { + headers: <bulkTransferHeaders>, + payload: { + bulkTransferState: <string>, + completedTimestamp: <optional> + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "notification", + action: "bulk-fulfil-duplicate", + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 12 + Publish Notification event for Payee + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + { + id: <messageId>, + from: <ledgerName", + to: <payeeFspName>, + type: "application/json", + content: { + headers: <bulkTransferHeaders>, + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request", + extensionList: { + extension: [ + { + key: "_cause", + value: <FSPIOPError> + } + ] + } + }, + uriParams: { + id: <bulkTransferId> + } + } + }, + metadata: { + correlationId: <uuid>, + event: { + id: <uuid>, + type: "notification", + action: "bulk-commit", + createdAt: <timestamp>, + state: { + status: "error", + code: "3106", + description: "Modified request" + }, + responseTo: <uuid> + } + } + } + + + 13 + Publish Notification (failure) event for Payer + Error codes: + 3106 + + [hasDuplicateId == FALSE] + + + alt + [Validate Bulk Transfer Fulfil (success)] + + + Persist Bulk Transfer State (with bulktransferState='PROCESSING') + + + 14 + Request to persist bulk transfer fulfil + Error codes: + 2003 + + + 15 + Persist bulkTransferFulfilment + + bulkTransferFulfilment + bulkTransferStateChange + bulkTransferExtension + + + 16 + Return success + + [Validate Bulk Transfer Fulfil (failure)] + + + Persist Bulk Transfer State (with bulkTransferState='ABORTING') + + + 17 + Request to persist bulk + transfer fulfil failure + Error codes: + 2003 + + + 18 + Persist transfer + + bulkTransferFulfilment + bulkTransferStateChange + bulkTransferExtension + bulkTransferError + + + 19 + Return success + + + alt + [Validate Bulk Transfer Fulfil (success)] + + + loop + [for every individual transfer in the bulk fulfil list] + + + 20 + Retrieve individual transfers from the bulk using + reference: + MLOS.individualTransferFulfils.messageId + + + 21 + Return stored bulk transfer containing individual transfers + + + 22 + Update bulk transfer association record to bulk transfer processing state 'PROCESSING' + + + 23 + Bulk transfer association record commited + + + Message: + { + id: <messageId> + from: <payeeFspName>, + to: <payerFspName>, + type: "application/json" + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "fulfil", + action: "bulk-commit", + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 24 + Route & Publish fulfil bulk commit events to the Payer for the Individual Transfer + Error codes: + 2003 + + [Validate Bulk Transfer Fulfil (failure)] + + + loop + [for every individual transfer in the bulk fulfil list] + + + 25 + Retrieve individual transfers from the bulk using + reference: + MLOS.individualTransferFulfils.messageId + + + 26 + Stream bulk's individual transfer fulfils + + + 27 + Update bulk transfer association record to bulk transfer processing state 'ABORTING' + + + 28 + Bulk transfer association record commited + + + Message: + { + id: <messageId> + from: <payeeFspName>, + to: <payerFspName>, + type: "application/json" + content: { + headers: <transferHeaders>, + payload: "errorInformation": { + "errorCode": <possible codes: [3100]> + "errorDescription": "<description>", + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "fulfil", + action: "bulk-abort", + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 29 + Route & Publish fulfil bulk abort events to the Payer for the Individual Transfer + Error codes: + 2003 + + diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.plantuml similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.plantuml rename to docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.plantuml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.svg new file mode 100644 index 000000000..6dccfb80f --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.svg @@ -0,0 +1,401 @@ + + 2.2.1. Fulfil Handler Consume (Success) individual transfers from Bulk + + + 2.2.1. Fulfil Handler Consume (Success) individual transfers from Bulk + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fulfil-Topic + + + Fulfil-Topic + Fulfil Handler + + + Fulfil Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + + + topic- + event + + + topic- + event + + + topic- + bulk-processing + + + topic- + bulk-processing + + + topic- + notification + + + topic- + notification + Position DAO + + + Position DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + Fulfil Handler Consume (Success) + + + 1 + Consume Fulfil event message for Payer + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type == 'fulfil' && action == 'bulk-commit' + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + Validate FSPIOP-Signature + + + ref + Validate message.content.headers. + FSPIOP-Signature + Error codes: + 3105/3106 +   + + + Validate Duplicate Check + + + 4 + Request Duplicate Check + + + ref + Request Duplicate Check +   + + + 5 + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + alt + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + break + + + + + 6 + stateRecord = await getTransferState(transferId) + + + alt + [endStateList.includes(stateRecord.transferStateId)] + + + ref + getTransfer callback +   + + + 7 + Produce message + + + + Ignore - resend in progress + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + Validate Prepare Transfer (failure) - Modified Request + + [hasDuplicateId == FALSE] + + + Validate and persist Transfer Fulfilment + + + 8 + Request information for the validate checks + Error code: + 2003 + + + 9 + Fetch from database + + transfer + + + 10 +   + + + 11 + Return transfer + + + + + 12 + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + Error code: + 2001 + + + + + 13 + Validate expirationDate + Error code: + 3303 + + + opt + [Transfer.ilpCondition validate successful] + + + Request current Settlement Window + + + 14 + Request to retrieve current/latest transfer settlement window + Error code: + 2003 + + + 15 + Fetch settlementWindowId + + settlementWindow + + + 16 +   + + + 17 + Return settlementWindowId to be appended during transferFulfilment insert + TODO + : During settlement design make sure transfers in 'RECEIVED-FULFIL' + state are updated to the next settlement window + + + Persist fulfilment + + + 18 + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + Error code: + 2003 + + + 19 + Persist to database + + transferFulfilment + transferExtension + + + 20 + Return success + + + alt + [Transfer.ilpCondition validate successful] + + + Persist Transfer State (with transferState='RECEIVED-FULFIL') + + + 21 + Request to persist transfer state + Error code: + 2003 + + + 22 + Persist transfer state + + transferStateChange + + + 23 + Return success + + + Message: + { + id: <messageId>, + from: <payeeFspName>, + to: <payerFspName>, + type: "application/json", + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "position", + action: "bulk-commit", + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 24 + Route & Publish Position event for Payee + + [Validate Fulfil Transfer not successful] + + + break + + + + + 25 + Route & Publish Notification event for Payee + Reference: Failure in validation + + + Reference: Failure in validation + + + Message: + { + id: <messageId>, + from: <ledgerName>, + to: <payeeFspName>, + type: "application/json", + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: "bulk-processing", + action: "bulk-commit", + createdAt: <timestamp>, + state: { + status: "error", + code: 1 + } + } + } + } + + + 26 + Publish Notification event for Payee to Bulk Processing Topic + Error codes: + 2003 + + diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.plantuml similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.plantuml rename to docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.plantuml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.svg new file mode 100644 index 000000000..6cb06df4e --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.svg @@ -0,0 +1,949 @@ + + 2.2.2. Fulfil Handler Consume (Reject/Abort) (single message, includes individual transfers from Bulk) + + + 2.2.2. Fulfil Handler Consume (Reject/Abort) (single message, includes individual transfers from Bulk) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + topic- + fulfil + + + topic- + fulfil + Fulfil Handler + + + Fulfil Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + + + topic- + event + + + topic- + event + + + topic- + bulk-processing + + + topic- + bulk-processing + + + topic- + notification + + + topic- + notification + Transfer DAO + + + Transfer DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fulfil Handler Consume (Failure) + + + alt + [Consume Single Message] + + + 1 + Consume Fulfil event message for Payer + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type IN ['fulfil','bulk-fulfil'] && ( action IN ['reject','abort'] ) + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + Validate FSPIOP-Signature + + + ref + Validate message.content.headers. + FSPIOP-Signature + Error codes: + 2001 + + + Validate Transfer Fulfil Duplicate Check + + + + + 4 + Generate transferFulfilmentId uuid + + + 5 + Request to retrieve transfer fulfilment hashes by transferId + Error code: + 2003 + + + 6 + Request Transfer fulfilment + duplicate message hashes + + SELET transferId, hash + FROM + transferFulfilmentDuplicateCheck + WHERE transferId = request.params.id + + + 7 + Return existing hashes + + + 8 + Return (list of) transfer fulfil messages hash(es) + + + + + 9 + Loop the list of returned hashes & compare + each entry with the calculated message hash + + + alt + [Hash matched] + + + 10 + Request to retrieve Transfer Fulfilment & Transfer state + Error code: + 2003 + + + 11 + Request to retrieve + transferFulfilment & transferState + + transferFulfilment + transferStateChange + + + 12 + Return transferFulfilment & + transferState + + + 13 + Return Transfer Fulfilment & Transfer state + + + alt + [transferFulfilment.isValid == 0] + + + break + + + alt + [If type == 'fulfil'] + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: fulfil-duplicate, + createdAt: <timestamp>, + state: { + status: "error", + code: 1 + } + } + } + } + + + 14 + Publish Notification event for Payee - Modified Request + Error codes: + 3106 + + [If type == 'bulk-fulfil'] + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: bulk-processing, + action: fulfil-duplicate, + createdAt: <timestamp>, + state: { + status: "error", + code: 1 + } + } + } + } + + + 15 + Publish Notification event for Payee - Modified Request + 3106 to Bulk Processing Topic + Error codes: + 3106 + + [transferState IN ['COMMITTED', 'ABORTED']] + + + break + + + alt + [If type == 'fulfil'] + + + ref + Send notification to Participant (Payee) +   + + [If type == 'bulk-fulfil'] + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: bulk-processing, + action: fulfil-duplicate, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 16 + Publish Notification event for Payee to Bulk Processing Topic + Error codes: + 2003 + + [transferState NOT 'RESERVED'] + + + break + + + + + + 17 + Reference: Failure in validation + Error code: + 2001 + + + + break + + + alt + [If type == 'fulfil'] + + + + + + 18 + Allow previous request to complete + + [If type == 'bulk-fulfil'] + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: bulk-processing, + action: fulfil-duplicate, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 19 + Publish Notification event for Payee to Bulk Processing Topic + Error codes: + 2003 + + [Hash not matched] + + + 20 + Request to persist transfer hash + Error codes: + 2003 + + + 21 + Persist hash + + transferFulfilmentDuplicateCheck + + + 22 + Return success + + + alt + [action=='reject' call made on PUT /transfers/{ID}] + + + 23 + Request information for the validate checks + Error code: + 2003 + + + 24 + Fetch from database + + transfer + + + 25 +   + + + 26 + Return transfer + + + alt + [Fulfilment present in the PUT /transfers/{ID} message] + + + + + 27 + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + Error code: + 2001 + + + Persist fulfilment + + + 28 + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + Error code: + 2003 + + + 29 + Persist to database + + transferFulfilment + transferExtension + + + 30 + Return success + + [Fulfilment NOT present in the PUT /transfers/{ID} message] + + + + + 31 + Validate that transfer fulfilment message to Abort is valid + Error code: + 2001 + + + Persist extensions + + + 32 + Persist extensionList elements + Error code: + 2003 + + + 33 + Persist to database + + transferExtension + + + 34 + Return success + + + alt + [Transfer.ilpCondition validate successful OR generic validation successful] + + + Persist Transfer State (with transferState='RECEIVED_REJECT') + + + 35 + Request to persist transfer state + Error code: + 2003 + + + 36 + Persist transfer state + + transferStateChange + + + 37 + Return success + + + + + 38 + Route & Publish Position event for Payer + Reference: Publish Position Reject event for Payer + + [Validate Fulfil Transfer not successful or Generic validation failed] + + + break + + + + + 39 + Publish event for Payee + Reference: Failure in validation + + [action=='abort' Error callback] + + + alt + [Validation successful] + + + Persist Transfer State (with transferState='RECEIVED_ERROR') + + + 40 + Request to persist transfer state & Error + Error code: + 2003 + + + 41 + Persist transfer state & Error + + transferStateChange + transferError + transferExtension + + + 42 + Return success + + + + + 43 + Error callback validated + Reference: Produce message for validated error callback + + [Validate Transfer Error Message not successful] + + + break + + + + + 44 + Notifications for failures + Reference: Validate Transfer Error Message not successful + + [Consume Batch Messages] + + + To be delivered by future story + + + Reference: Validate Transfer Error Message not successful + + + alt + [If type == 'bulk-fulfil'] + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: bulk-processing, + action: abort, + createdAt: <timestamp>, + state: { + status: "error", + code: 1 + } + } + } + } + + + 45 + Publish Processing event for Payee to Bulk Processing Topic + Error codes: + 2003 + + [If type == 'fulfil'] + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: fulfil, + action: abort, + createdAt: <timestamp>, + state: { + status: "error", + code: 1 + } + } + } + } + + + 46 + Route & Publish Notification event for Payee + + + Reference: Produce message for validated error callback + + + alt + [If type == 'bulk-fulfil'] + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: bulk-position, + action: abort, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 47 + Route & Publish Position event for Payer + + [If type == 'fulfil'] + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: abort, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 48 + Route & Publish Position event for Payer + + + Reference: Failure in validation + + + alt + [If type == 'bulk-fulfil'] + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: bulk-processing, + action: reject, + createdAt: <timestamp>, + state: { + status: "error", + code: 1 + } + } + } + } + + + 49 + Publish processing event to the Bulk Processing Topic + Error codes: + 2003 + + [If type == 'fulfil'] + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: fulfil, + action: reject, + createdAt: <timestamp>, + state: { + status: "error", + code: 1 + } + } + } + } + + + 50 + Route & Publish Notification event for Payee + + + Reference: Publish Position Reject event for Payer + + + alt + [If type == 'bulk-fulfil'] + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: bulk-position, + action: reject, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 51 + Route & Publish Position event for Payer + + [If type == 'fulfil'] + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: reject, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 52 + Route & Publish Position event for Payer + + diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.plantuml similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.plantuml rename to docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.plantuml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.svg new file mode 100644 index 000000000..750ea14e1 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.svg @@ -0,0 +1,238 @@ + + 2.3.1. Fulfil Position Handler Consume (single message, includes individual transfers from Bulk) + + + 2.3.1. Fulfil Position Handler Consume (single message, includes individual transfers from Bulk) + + Central Service + + + + + + + + + + + + + + + + + + + + Position Handler + + + Position Handler + + + + + topic- + notifications + + + topic- + notifications + + + topic- + bulk-processing + + + topic- + bulk-processing + Position DAO + + + Position DAO + + + Position Facade + + + Position Facade + + + Central Store + + + Central Store + + + + + + + + + + + + + + Fulfil Position Handler Consume + + + 1 + Request current state of transfer from DB + Error code: + 2003 + + + 2 + Retrieve current state of transfer from DB + + transferStateChange + transferParticipant + + + 3 + Return current state of transfer from DB + + + 4 + Return current state of transfer from DB + + + + + + 5 + Validate current state (transferState is 'RECEIVED-FULFIL') + Error code: + 2001 + + + Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + + + 6 + Request to persist latest position and state to DB + Error code: + 2003 + + + DB TRANSACTION + + + 7 + Select participantPosition.value FOR UPDATE from DB for Payee + + participantPosition + + + 8 + Return participantPosition.value from DB for Payee + + + + + + 9 + latestPosition + = participantPosition.value - payload.amount.amount + + + 10 + Persist latestPosition to DB for Payee + + UPDATE + participantPosition + SET value = latestPosition + + + 11 + Persist transfer state and participant position change + + INSERT + transferStateChange + transferStateId = 'COMMITTED' +   + INSERT + participantPositionChange + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + + + 12 + Return success + + + alt + [If type == 'bulk-position'] + + + Message: + { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: bulk-processing, + action: bulk-commit, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 13 + Publish Transfer event to Bulk Processing Topic + Error codes: + 2003 + + [If type == 'position'] + + + Message: + { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: commit, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 14 + Publish Transfer event + Error code: + 2003 + + diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.plantuml similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.plantuml rename to docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.plantuml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.svg new file mode 100644 index 000000000..038eaff5f --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.svg @@ -0,0 +1,613 @@ + + 2.3.2. Abort Position Handler Consume (single message, includes individual transfers from Bulk) + + + 2.3.2. Abort Position Handler Consume (single message, includes individual transfers from Bulk) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Position Handler + + + Position Handler + + + + + topic- + notification + + + topic- + notification + + + topic- + bulk-processing + + + topic- + bulk-processing + Position DAO + + + Position DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + + + + + + + + Abort Position Handler Consume + + + opt + [type IN ['position','bulk-position'] && action == 'timeout-reserved'] + + + 1 + Request current state of transfer from DB + Error code: + 2003 + + + 2 + Retrieve current state of transfer from DB + + transferStateChange + transferParticipant + + + 3 + Return current state of transfer from DB + + + 4 + Return current state of transfer from DB + + + + + + 5 + Validate current state + (transferStateChange.transferStateId == 'RESERVED_TIMEOUT') + Error code: + 2001 + + + Persist Position change and Transfer state + + + + + 6 + transferStateId + = 'EXPIRED_RESERVED' + + + 7 + Request to persist latest position and state to DB + Error code: + 2003 + + + DB TRANSACTION IMPLEMENTATION + + + 8 + Select participantPosition.value FOR UPDATE for payerCurrencyId + + participantPosition + + + 9 + Return participantPosition + + + + + + 10 + latestPosition + = participantPosition - payload.amount.amount + + + 11 + Persist latestPosition to DB for Payer + + UPDATE + participantPosition + SET value = latestPosition + + + 12 + Persist participant position change and state change + + INSERT + transferStateChange +   + VALUES (transferStateId) +   + INSERT + participantPositionChange + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + + + 13 + Return success + + + alt + [If type == 'bulk-position'] + + + Message: { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: bulk-processing, + action: abort, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 14 + Publish Transfer event to Bulk Processing Topic (for Payer) + Error codes: + 2003 + + [If type == 'position'] + + + Message: { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: abort, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 15 + Publish Notification event + Error code: + 2003 + + + opt + [type IN ['position','bulk-position'] && (action IN ['reject', 'abort'])] + + + 16 + Request current state of transfer from DB + Error code: + 2003 + + + 17 + Retrieve current state of transfer from DB + + transferStateChange + + + 18 + Return current state of transfer from DB + + + 19 + Return current state of transfer from DB + + + + + + 20 + Validate current state + (transferStateChange.transferStateId IN ['RECEIVED_REJECT', 'RECEIVED_ERROR']) + Error code: + 2001 + + + Persist Position change and Transfer state + + + + + 21 + transferStateId + = (action == 'reject' ? 'ABORTED_REJECTED' : 'ABORTED_ERROR' ) + + + 22 + Request to persist latest position and state to DB + Error code: + 2003 + + + Refer to + DB TRANSACTION IMPLEMENTATION + above + + + 23 + Persist to database + + participantPosition + transferStateChange + participantPositionChange + + + 24 + Return success + + + alt + [If action == 'reject'] + + + alt + [If type == 'position'] + + + Message: { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: reject, + createdAt: <timestamp>, + state: { + status: "success", + code: 0, + description: "action successful" + } + } + } + } + + + 25 + Publish Notification event + Error code: + 2003 + + [If type == 'bulk-position'] + + + Message: { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: bulk-processing, + action: reject, + createdAt: <timestamp>, + state: { + status: "success", + code: 0, + description: "action successful" + } + } + } + } + + + 26 + Publish Notification event + Error code: + 2003 + + [action == 'abort'] + + + Message: { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: abort, + createdAt: <timestamp>, + state: { + status: 'error', + code: <payload.errorInformation.errorCode || 5000> + description: <payload.errorInformation.errorDescription> + } + } + } + } + + + 27 + Publish Notification event + Error code: + 2003 + + + opt + [type IN ['position','bulk-position'] && action == 'fail' (Unable to currently trigger this scenario)] + + + 28 + Request current state of transfer from DB + Error code: + 2003 + + + 29 + Retrieve current state of transfer from DB + + transferStateChange + + + 30 + Return current state of transfer from DB + + + 31 + Return current state of transfer from DB + + + + + + 32 + Validate current state (transferStateChange.transferStateId == 'FAILED') + + + Persist Position change and Transfer state + + + + + 33 + transferStateId + = 'FAILED' + + + 34 + Request to persist latest position and state to DB + Error code: + 2003 + + + Refer to + DB TRANSACTION IMPLEMENTATION + above + + + 35 + Persist to database + + participantPosition + transferStateChange + participantPositionChange + + + 36 + Return success + + + alt + [If type =='position'] + + + Message: { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": 3100, + "errorDescription": "Transfer failed", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: abort, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 37 + Publish Notification event + Error code: + 2003 + + [If type =='bulk-position'] + + + Message: { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": 3100, + "errorDescription": "Transfer failed", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: bulk-processing, + action: abort, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 38 + Publish Notification event + Error code: + 2003 + + diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.plantuml new file mode 100644 index 000000000..3f29d4657 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.plantuml @@ -0,0 +1,230 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 3.1.0. Transfer Timeout (incl. Bulk Transfer) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API\nAdapter" as MLAPI +control "ML API Notification\nEvent Handler" as NOTIFY_HANDLER +control "Transfer Timeout\nHandler" as EXP_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event\nHandler" as POS_HANDLER +control "Bulk Processing\nHandler" as BULK_PROCESSING_HANDLER +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-event" as TOPIC_EVENT +collections "topic-\nbulk-processing" as BULK_PROCESSING_TOPIC + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant EXP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant BULK_PROCESSING_HANDLER + participant BULK_PROCESSING_TOPIC +end box + +' start flow +activate NOTIFY_HANDLER +activate EXP_HANDLER +activate POS_HANDLER +activate BULK_PROCESSING_HANDLER +group Transfer Expiry + ||| + ref over EXP_HANDLER, TOPIC_EVENT : Timeout Handler Consume\n + alt transferStateId == 'RECEIVED_PREPARE' + alt Regular Transfer + EXP_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Individual Transfer from a Bulk + EXP_HANDLER -> BULK_PROCESSING_TOPIC: Produce message + end + else transferStateId == 'RESERVED' + EXP_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS : Position Hander Consume (Timeout)\n + alt Regular Transfer + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Individual Transfer from a Bulk + POS_HANDLER -> BULK_PROCESSING_TOPIC: Produce message + end + end + opt action IN ['bulk-timeout-received', 'bulk-timeout-reserved'] + ||| + BULK_PROCESSING_TOPIC <- BULK_PROCESSING_HANDLER: Consume message + ref over TOPIC_NOTIFICATIONS, BULK_PROCESSING_TOPIC : Bulk Processing Consume\n + BULK_PROCESSING_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + end + ||| + opt action IN ['timeout-received', 'timeout-reserved', 'bulk-timeout-received', 'bulk-timeout-reserved'] + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + ref over DFSP1, TOPIC_NOTIFICATIONS : Send notification to Participant (Payer)\n + alt Timeout before any processing + note left of NOTIFY_HANDLER #yellow + PUT /bulkTransfers/ + { + headers: , + body: { + "bulkTransferState": "COMPLETED", + "completedTimestamp": "2022-08-18T01:00:24.407Z", + "individualTransferResults": [ + { + "errorInformation": { + "errorCode": "3303", + "errorDescription": "Transfer expired", + "extensionList": + } + "transferId": + }, + { + "errorInformation": { + "errorCode": "3303", + "errorDescription": "Transfer expired", + "extensionList": + } + "transferId": + }, + ] + } + } + end note + else Timeout in middle of processing + note left of NOTIFY_HANDLER #yellow + PUT /bulkTransfers/ + { + headers: , + body: { + "bulkTransferState": "COMPLETED", + "completedTimestamp": "2022-08-18T01:00:24.407Z", + "individualTransferResults": [ + { + "transferId": , + "fulfilment": + }, + { + "errorInformation": { + "errorCode": "3303", + "errorDescription": "Transfer expired", + "extensionList": + } + "transferId": + }, + ] + } + } + end note + end + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + opt action IN ['timeout-reserved', 'bulk-timeout-reserved'] + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + ref over DFSP2, TOPIC_NOTIFICATIONS : Send notification to Participant (Payee)\n + alt Timeout before any processing + note left of NOTIFY_HANDLER #yellow + PUT /bulkTransfers/ + { + headers: , + body: { + "bulkTransferState": "COMPLETED", + "completedTimestamp": "2022-08-18T01:00:24.407Z", + "individualTransferResults": [ + { + "errorInformation": { + "errorCode": "3303", + "errorDescription": "Transfer expired", + "extensionList": + } + "transferId": + }, + { + "errorInformation": { + "errorCode": "3303", + "errorDescription": "Transfer expired", + "extensionList": + } + "transferId": + }, + ] + } + } + end note + else Timeout in middle of processing + note left of NOTIFY_HANDLER #yellow + PUT /bulkTransfers/ + { + headers: , + body: { + "bulkTransferState": "COMPLETED", + "completedTimestamp": "2022-08-18T01:00:24.407Z", + "individualTransferResults": [ + { + "transferId": , + "fulfilment": + }, + { + "errorInformation": { + "errorCode": "3303", + "errorDescription": "Transfer expired", + "extensionList": + } + "transferId": + }, + ] + } + } + end note + end + NOTIFY_HANDLER -> DFSP2: Send callback notification + end +end +deactivate BULK_PROCESSING_HANDLER +deactivate POS_HANDLER +deactivate EXP_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.svg new file mode 100644 index 000000000..e9424fc66 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.svg @@ -0,0 +1,349 @@ + + 3.1.0. Transfer Timeout (incl. Bulk Transfer) + + + 3.1.0. Transfer Timeout (incl. Bulk Transfer) + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + DFSP2 + Payee + + + DFSP2 + Payee + + + ML API + Adapter + + + ML API + Adapter + + + ML API Notification + Event Handler + + + ML API Notification + Event Handler + + + Transfer Timeout + Handler + + + Transfer Timeout + Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + + + topic-event + + + topic-event + Position Event + Handler + + + Position Event + Handler + + + + + topic- + notification + + + topic- + notification + Bulk Processing + Handler + + + Bulk Processing + Handler + + + + + topic- + bulk-processing + + + topic- + bulk-processing + + + + + + + Transfer Expiry + + + ref + Timeout Handler Consume +   + + + alt + [transferStateId == 'RECEIVED_PREPARE'] + + + alt + [Regular Transfer] + + + 1 + Produce message + + [Individual Transfer from a Bulk] + + + 2 + Produce message + + [transferStateId == 'RESERVED'] + + + 3 + Produce message + + + 4 + Consume message + + + ref + Position Hander Consume (Timeout) +   + + + alt + [Regular Transfer] + + + 5 + Produce message + + [Individual Transfer from a Bulk] + + + 6 + Produce message + + + opt + [action IN ['bulk-timeout-received', 'bulk-timeout-reserved']] + + + 7 + Consume message + + + ref + Bulk Processing Consume +   + + + 8 + Produce message + + + opt + [action IN ['timeout-received', 'timeout-reserved', 'bulk-timeout-received', 'bulk-timeout-reserved']] + + + 9 + Consume message + + + ref + Send notification to Participant (Payer) +   + + + alt + [Timeout before any processing] + + + PUT /bulkTransfers/<ID> + { + headers: <bulkTransferHeaders>, + body: { + "bulkTransferState": "COMPLETED", + "completedTimestamp": "2022-08-18T01:00:24.407Z", + "individualTransferResults": [ + { + "errorInformation": { + "errorCode": "3303", + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + "transferId": <ID> + }, + { + "errorInformation": { + "errorCode": "3303", + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + "transferId": <ID> + }, + ] + } + } + + [Timeout in middle of processing] + + + PUT /bulkTransfers/<ID> + { + headers: <bulkTransferHeaders>, + body: { + "bulkTransferState": "COMPLETED", + "completedTimestamp": "2022-08-18T01:00:24.407Z", + "individualTransferResults": [ + { + "transferId": <ID>, + "fulfilment": <fulfilment> + }, + { + "errorInformation": { + "errorCode": "3303", + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + "transferId": <ID> + }, + ] + } + } + + + 10 + Send callback notification + + + opt + [action IN ['timeout-reserved', 'bulk-timeout-reserved']] + + + 11 + Consume message + + + ref + Send notification to Participant (Payee) +   + + + alt + [Timeout before any processing] + + + PUT /bulkTransfers/<ID> + { + headers: <bulkTransferHeaders>, + body: { + "bulkTransferState": "COMPLETED", + "completedTimestamp": "2022-08-18T01:00:24.407Z", + "individualTransferResults": [ + { + "errorInformation": { + "errorCode": "3303", + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + "transferId": <ID> + }, + { + "errorInformation": { + "errorCode": "3303", + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + "transferId": <ID> + }, + ] + } + } + + [Timeout in middle of processing] + + + PUT /bulkTransfers/<ID> + { + headers: <bulkTransferHeaders>, + body: { + "bulkTransferState": "COMPLETED", + "completedTimestamp": "2022-08-18T01:00:24.407Z", + "individualTransferResults": [ + { + "transferId": <ID>, + "fulfilment": <fulfilment> + }, + { + "errorInformation": { + "errorCode": "3303", + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + "transferId": <ID> + }, + ] + } + } + + + 12 + Send callback notification + + diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.plantuml new file mode 100644 index 000000000..1c9343431 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.plantuml @@ -0,0 +1,420 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + -------------- + ******'/ + +@startuml +' declare title +title 3.1.1. Timeout Handler Consume (incl. Bulk Transfer) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +control "Transfer Timeout\nHandler" as TIMEOUT_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nnotification" as NOTIFICATIONS_TOPIC +collections "topic-event" as EVENT_TOPIC +collections "topic-\nbulk-processing" as BULK_PROCESSING_TOPIC +entity "Segment DAO" as SEGMENT_DAO +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TIMEOUT_HANDLER + participant TOPIC_TRANSFER_POSITION + participant NOTIFICATIONS_TOPIC + participant EVENT_TOPIC + participant BULK_PROCESSING_TOPIC + participant POS_DAO + participant SEGMENT_DAO + participant DB +end box + +' start flow + +group Timeout Handler Consume + activate TIMEOUT_HANDLER + group Persist Event Information + TIMEOUT_HANDLER -> EVENT_TOPIC: Publish event information + ref over TIMEOUT_HANDLER, EVENT_TOPIC : Event Handler Consume\n + end + + group Get previous checkpoint of last record processed (Lower limit for inclusion) + TIMEOUT_HANDLER -> SEGMENT_DAO: Get last segment as @intervalMin + activate SEGMENT_DAO + SEGMENT_DAO -> DB: Get last segment as @intervalMin + hnote over DB #lightyellow + SELECT value INTO @intervalMin + FROM **segment** + WHERE segmentType = 'timeout' + AND enumeration = 0 + AND tableName = 'transferStateChange' + end note + activate DB + DB --> SEGMENT_DAO: Return @intervalMin + deactivate DB + SEGMENT_DAO --> TIMEOUT_HANDLER: Return @intervalMin + deactivate SEGMENT_DAO + opt @intervalMin IS NULL => segment record NOT FOUND + TIMEOUT_HANDLER->TIMEOUT_HANDLER: Set @intervalMin = 0 + end + end + + group Do Cleanup + TIMEOUT_HANDLER -> POS_DAO: Clean up transferTimeout from finalised transfers + activate POS_DAO + POS_DAO -> DB: Clean up transferTimeout from finalised transfers + hnote over DB #lightyellow + DELETE tt + FROM **transferTimeout** AS tt + JOIN (SELECT tsc.transferId, MAX(tsc.transferStateChangeId) maxTransferStateChangeId + FROM **transferTimeout** tt1 + JOIN **transferStateChange** tsc + ON tsc.transferId = tt1.transferId + GROUP BY transferId) ts + ON ts.transferId = tt.transferId + JOIN **transferStateChange** tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + WHERE tsc.transferStateId IN ('RECEIVED_FULFIL', 'COMMITTED', 'FAILED' + , 'EXPIRED', 'REJECTED', 'EXPIRED_PREPARED', 'EXPIRED_RESERVED', 'ABORTED') + end note + activate DB + deactivate DB + POS_DAO --> TIMEOUT_HANDLER: Return success + deactivate POS_DAO + end + + group Determine IntervalMax (Upper limit for inclusion) + TIMEOUT_HANDLER -> POS_DAO: Get last transferStateChangeId as @intervalMax + activate POS_DAO + POS_DAO -> DB: Get last transferStateChangeId as @intervalMax + hnote over DB #lightyellow + SELECT MAX(transferStateChangeId) INTO @intervalMax + FROM **transferStateChange** + end note + activate DB + DB --> POS_DAO: Return @intervalMax + deactivate DB + POS_DAO --> TIMEOUT_HANDLER: Return @intervalMax + deactivate POS_DAO + end + + + group Prepare data and return the list for expiration + TIMEOUT_HANDLER -> POS_DAO: Prepare data and get transfers to be expired + activate POS_DAO + group DB TRANSACTION + POS_DAO <-> POS_DAO: **transactionTimestamp** = now() + POS_DAO -> DB: Insert all new transfers still in processing state + hnote over DB #lightyellow + INSERT INTO **transferTimeout**(transferId, expirationDate) + SELECT t.transferId, t.expirationDate + FROM **transfer** t + JOIN (SELECT transferId, MAX(transferStateChangeId) maxTransferStateChangeId + FROM **transferStateChange** + WHERE transferStateChangeId > @intervalMin + AND transferStateChangeId <= @intervalMax + GROUP BY transferId) ts + ON ts.transferId = t.transferId + JOIN **transferStateChange** tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + WHERE tsc.transferStateId IN ('RECEIVED_PREPARE', 'RESERVED') + end note + activate DB + deactivate DB + + POS_DAO -> DB: Insert transfer state ABORTED for\nexpired RECEIVED_PREPARE transfers + hnote over DB #lightyellow + INSERT INTO **transferStateChange** + SELECT tt.transferId, 'EXPIRED_PREPARED' AS transferStateId, 'Aborted by Timeout Handler' AS reason + FROM **transferTimeout** tt + JOIN ( -- Following subquery is reused 3 times and may be optimized if needed + SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + FROM **transferStateChange** tsc1 + JOIN **transferTimeout** tt1 + ON tt1.transferId = tsc1.transferId + GROUP BY tsc1.transferId) ts + ON ts.transferId = tt.transferId + JOIN **transferStateChange** tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + WHERE tt.expirationDate < {transactionTimestamp} + AND tsc.transferStateId = 'RECEIVED_PREPARE' + end note + activate DB + deactivate DB + + POS_DAO -> DB: Insert transfer state EXPIRED for\nexpired RESERVED transfers + hnote over DB #lightyellow + INSERT INTO **transferStateChange** + SELECT tt.transferId, 'RESERVED_TIMEOUT' AS transferStateId, 'Expired by Timeout Handler' AS reason + FROM **transferTimeout** tt + JOIN (SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + FROM **transferStateChange** tsc1 + JOIN **transferTimeout** tt1 + ON tt1.transferId = tsc1.transferId + GROUP BY tsc1.transferId) ts + ON ts.transferId = tt.transferId + JOIN **transferStateChange** tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + WHERE tt.expirationDate < {transactionTimestamp} + AND tsc.transferStateId = 'RESERVED' + end note + activate DB + deactivate DB + + POS_DAO -> DB: Update segment table to be used for the next run + hnote over DB #lightyellow + IF @intervalMin = 0 + INSERT + INTO **segment**(segmentType, enumeration, tableName, value) + VALUES ('timeout', 0, 'transferStateChange', @intervalMax) + ELSE + UPDATE **segment** + SET value = @intervalMax + WHERE segmentType = 'timeout' + AND enumeration = 0 + AND tableName = 'transferStateChange' + end note + activate DB + deactivate DB + end + + POS_DAO -> DB: Get list of transfers to be expired with current state + hnote over DB #lightyellow + SELECT tt.*, tsc.transferStateId, tp1.participantCurrencyId payerParticipantId, + tp2.participantCurrencyId payeeParticipantId, bta.bulkTransferId + FROM **transferTimeout** tt + JOIN (SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + FROM **transferStateChange** tsc1 + JOIN **transferTimeout** tt1 + ON tt1.transferId = tsc1.transferId + GROUP BY tsc1.transferId) ts + ON ts.transferId = tt.transferId + JOIN **transferStateChange** tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + JOIN **transferParticipant** tp1 + ON tp1.transferId = tt.transferId + AND tp1.transferParticipantRoleTypeId = {PAYER_DFSP} + AND tp1.ledgerEntryTypeId = {PRINCIPLE_VALUE} + JOIN **transferParticipant** tp2 + ON tp2.transferId = tt.transferId + AND tp2.transferParticipantRoleTypeId = {PAYEE_DFSP} + AND tp2.ledgerEntryTypeId = {PRINCIPLE_VALUE} + LEFT JOIN **bulkTransferAssociation** bta + ON bta.transferId = tt.transferId + WHERE tt.expirationDate < {transactionTimestamp} + end note + activate DB + POS_DAO <-- DB: Return **transferTimeoutList** + deactivate DB + POS_DAO --> TIMEOUT_HANDLER: Return **transferTimeoutList** + deactivate POS_DAO + end + + loop for each transfer in the list + ||| + alt transferTimeoutList.bulkTransferId == NULL (Regular Transfer) + alt transferStateId == 'RECEIVED_PREPARE' + note right of TIMEOUT_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + }, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + type: notification, + action: timeout-received, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + TIMEOUT_HANDLER -> NOTIFICATIONS_TOPIC: Publish Notification event + activate NOTIFICATIONS_TOPIC + deactivate NOTIFICATIONS_TOPIC + else transferStateId == 'RESERVED' + note right of TIMEOUT_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + }, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + type: position, + action: timeout-reserved, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + TIMEOUT_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end + else Individual Transfer from a Bulk + alt transferStateId == 'RECEIVED_PREPARE' + note right of TIMEOUT_HANDLER #yellow + Message: + { + id: , + transferId: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + type: bulk-processing, + action: bulk-timeout-received, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + TIMEOUT_HANDLER -> BULK_PROCESSING_TOPIC: Publish to Bulk Processing topic + activate BULK_PROCESSING_TOPIC + deactivate BULK_PROCESSING_TOPIC + else transferStateId == 'RESERVED' + note right of TIMEOUT_HANDLER #yellow + Message: + { + id: , + transferId: , + from: , + to: , + type: application/json, + content: { + headers: ,, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + type: position, + action: bulk-timeout-reserved, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + TIMEOUT_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end + end + end + + deactivate TIMEOUT_HANDLER +end +@enduml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.svg new file mode 100644 index 000000000..5d241117d --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.svg @@ -0,0 +1,596 @@ + + 3.1.1. Timeout Handler Consume (incl. Bulk Transfer) + + + 3.1.1. Timeout Handler Consume (incl. Bulk Transfer) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Transfer Timeout + Handler + + + Transfer Timeout + Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + + + topic- + notification + + + topic- + notification + + + topic-event + + + topic-event + + + topic- + bulk-processing + + + topic- + bulk-processing + Position DAO + + + Position DAO + + + Segment DAO + + + Segment DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + + + Timeout Handler Consume + + + Persist Event Information + + + 1 + Publish event information + + + ref + Event Handler Consume +   + + + Get previous checkpoint of last record processed (Lower limit for inclusion) + + + 2 + Get last segment as @intervalMin + + + 3 + Get last segment as @intervalMin + + SELECT value INTO @intervalMin + FROM + segment + WHERE segmentType = 'timeout' + AND enumeration = 0 + AND tableName = 'transferStateChange' + + + 4 + Return @intervalMin + + + 5 + Return @intervalMin + + + opt + [@intervalMin IS NULL => segment record NOT FOUND] + + + + + 6 + Set @intervalMin = 0 + + + Do Cleanup + + + 7 + Clean up transferTimeout from finalised transfers + + + 8 + Clean up transferTimeout from finalised transfers + + DELETE tt + FROM + transferTimeout + AS tt + JOIN (SELECT tsc.transferId, MAX(tsc.transferStateChangeId) maxTransferStateChangeId + FROM + transferTimeout + tt1 + JOIN + transferStateChange + tsc + ON tsc.transferId = tt1.transferId + GROUP BY transferId) ts + ON ts.transferId = tt.transferId + JOIN + transferStateChange + tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + WHERE tsc.transferStateId IN ('RECEIVED_FULFIL', 'COMMITTED', 'FAILED' + , 'EXPIRED', 'REJECTED', 'EXPIRED_PREPARED', 'EXPIRED_RESERVED', 'ABORTED') + + + 9 + Return success + + + Determine IntervalMax (Upper limit for inclusion) + + + 10 + Get last transferStateChangeId as @intervalMax + + + 11 + Get last transferStateChangeId as @intervalMax + + SELECT MAX(transferStateChangeId) INTO @intervalMax + FROM + transferStateChange + + + 12 + Return @intervalMax + + + 13 + Return @intervalMax + + + Prepare data and return the list for expiration + + + 14 + Prepare data and get transfers to be expired + + + DB TRANSACTION + + + + + + 15 + transactionTimestamp + = now() + + + 16 + Insert all new transfers still in processing state + + INSERT INTO + transferTimeout + (transferId, expirationDate) + SELECT t.transferId, t.expirationDate + FROM + transfer + t + JOIN (SELECT transferId, MAX(transferStateChangeId) maxTransferStateChangeId + FROM + transferStateChange + WHERE transferStateChangeId > @intervalMin + AND transferStateChangeId <= @intervalMax + GROUP BY transferId) ts + ON ts.transferId = t.transferId + JOIN + transferStateChange + tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + WHERE tsc.transferStateId IN ('RECEIVED_PREPARE', 'RESERVED') + + + 17 + Insert transfer state ABORTED for + expired RECEIVED_PREPARE transfers + + INSERT INTO + transferStateChange + SELECT tt.transferId, 'EXPIRED_PREPARED' AS transferStateId, 'Aborted by Timeout Handler' AS reason + FROM + transferTimeout + tt + JOIN ( + -- Following subquery is reused 3 times and may be optimized if needed + SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + FROM + transferStateChange + tsc1 + JOIN + transferTimeout + tt1 + ON tt1.transferId = tsc1.transferId + GROUP BY tsc1.transferId) ts + ON ts.transferId = tt.transferId + JOIN + transferStateChange + tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + WHERE tt.expirationDate < {transactionTimestamp} + AND tsc.transferStateId = 'RECEIVED_PREPARE' + + + 18 + Insert transfer state EXPIRED for + expired RESERVED transfers + + INSERT INTO + transferStateChange + SELECT tt.transferId, 'RESERVED_TIMEOUT' AS transferStateId, 'Expired by Timeout Handler' AS reason + FROM + transferTimeout + tt + JOIN (SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + FROM + transferStateChange + tsc1 + JOIN + transferTimeout + tt1 + ON tt1.transferId = tsc1.transferId + GROUP BY tsc1.transferId) ts + ON ts.transferId = tt.transferId + JOIN + transferStateChange + tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + WHERE tt.expirationDate < {transactionTimestamp} + AND tsc.transferStateId = 'RESERVED' + + + 19 + Update segment table to be used for the next run + + IF @intervalMin = 0 + INSERT + INTO + segment + (segmentType, enumeration, tableName, value) + VALUES ('timeout', 0, 'transferStateChange', @intervalMax) + ELSE + UPDATE + segment + SET value = @intervalMax + WHERE segmentType = 'timeout' + AND enumeration = 0 + AND tableName = 'transferStateChange' + + + 20 + Get list of transfers to be expired with current state + + SELECT tt.*, tsc.transferStateId, tp1.participantCurrencyId payerParticipantId, + tp2.participantCurrencyId payeeParticipantId, bta.bulkTransferId + FROM + transferTimeout + tt + JOIN (SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + FROM + transferStateChange + tsc1 + JOIN + transferTimeout + tt1 + ON tt1.transferId = tsc1.transferId + GROUP BY tsc1.transferId) ts + ON ts.transferId = tt.transferId + JOIN + transferStateChange + tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + JOIN + transferParticipant + tp1 + ON tp1.transferId = tt.transferId + AND tp1.transferParticipantRoleTypeId = {PAYER_DFSP} + AND tp1.ledgerEntryTypeId = {PRINCIPLE_VALUE} + JOIN + transferParticipant + tp2 + ON tp2.transferId = tt.transferId + AND tp2.transferParticipantRoleTypeId = {PAYEE_DFSP} + AND tp2.ledgerEntryTypeId = {PRINCIPLE_VALUE} + LEFT JOIN + bulkTransferAssociation + bta + ON bta.transferId = tt.transferId + WHERE tt.expirationDate < {transactionTimestamp} + + + 21 + Return + transferTimeoutList + + + 22 + Return + transferTimeoutList + + + loop + [for each transfer in the list] + + + alt + [transferTimeoutList.bulkTransferId == NULL (Regular Transfer)] + + + alt + [transferStateId == 'RECEIVED_PREPARE'] + + + Message: + { + id: <transferId>, + from: <payerParticipantId>, + to: <payeeParticipantId>, + type: application/json, + content: { + headers: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + }, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + type: notification, + action: timeout-received, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 23 + Publish Notification event + + [transferStateId == 'RESERVED'] + + + Message: + { + id: <transferId>, + from: <payerParticipantId>, + to: <payeeParticipantId>, + type: application/json, + content: { + headers: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + }, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + type: position, + action: timeout-reserved, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 24 + Route & Publish Position event + + [Individual Transfer from a Bulk] + + + alt + [transferStateId == 'RECEIVED_PREPARE'] + + + Message: + { +      + id + : <transferTimeoutList.bulkTransferId>, +      + transferId + : <transferTimeoutList.transferId>, + from: <payerParticipantId>, + to: <payeeParticipantId>, + type: application/json, + content: { + headers: <bulkTransferHeaders>, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + type: bulk-processing, + action: bulk-timeout-received, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 25 + Publish to Bulk Processing topic + + [transferStateId == 'RESERVED'] + + + Message: + { +      + id + : <transferTimeoutList.bulkTransferId>, +      + transferId + : <transferTimeoutList.transferId>, + from: <payerParticipantId>, + to: <payeeParticipantId>, + type: application/json, + content: { + headers: <bulkTransferHeaders>,, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + type: position, + action: bulk-timeout-reserved, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 26 + Route & Publish Position event + + diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.plantuml new file mode 100644 index 000000000..e02a15142 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.plantuml @@ -0,0 +1,233 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- + ******'/ + +@startuml +' declare title +title 4.1.0. Bulk Transfer Abort + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "Bulk API Adapter" as BULKAPI +control "Bulk API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Bulk-Fulfil-Topic" as TOPIC_BULK_FULFIL +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Bulk Fulfil Event Handler" as BULK_FULFIL_HANDLER +control "Fulfil Event Handler" as FULFIL_HANDLER +collections "topic-transfer-position" as TOPIC_POSITION +control "Position Event Handler" as POS_HANDLER +collections "topic-bulk-processing" as TOPIC_BULK_PROCESSING +control "Bulk Processing Event Handler" as BULK_PROCESSING_HANDLER +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE +database "Central Services DB" as DB + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "Bulk API Adapter Service" #LightBlue + participant BULKAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_BULK_FULFIL + participant TOPIC_FULFIL + participant BULK_FULFIL_HANDLER + participant FULFIL_HANDLER + participant TOPIC_POSITION + participant TOPIC_EVENTS + participant POS_HANDLER + participant TOPIC_BULK_PROCESSING + participant BULK_PROCESSING_HANDLER + participant TOPIC_NOTIFICATIONS + participant OBJECT_STORE + participant DB +end box + +' start flow +activate NOTIFY_HANDLER +activate BULK_FULFIL_HANDLER +activate FULFIL_HANDLER +activate FULFIL_HANDLER +activate BULK_PROCESSING_HANDLER +activate POS_HANDLER + +group DFSP2 sends a Fulfil Abort Transfer request + note right of DFSP2 #lightblue + **Note**: In the payload for PUT /bulkTransfers//error + only the **errorInformation** field is **required** + end note + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + Payload - errorMessage: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + } + end note + DFSP2 ->> BULKAPI: **PUT - /bulkTransfers//error** + activate BULKAPI + + BULKAPI -> OBJECT_STORE: Persist request payload with messageId in cache + activate OBJECT_STORE + note right of BULKAPI #yellow + Message: { + messageId: , + bulkTransferId: , + payload: + } + end note + hnote over OBJECT_STORE #lightyellow + individualTransferFulfils + end hnote + BULKAPI <- OBJECT_STORE: Response of save operation + deactivate OBJECT_STORE + note right of BULKAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + BULKAPI -> TOPIC_BULK_FULFIL: Produce bulk-fulfil message + BULKAPI -->> DFSP2: Respond HTTP - 200 (OK) + TOPIC_BULK_FULFIL <- BULK_FULFIL_HANDLER: Consume bulk-fulfil message + BULK_FULFIL_HANDLER -> BULK_FULFIL_HANDLER: Perform duplicate check + BULK_FULFIL_HANDLER -> BULK_FULFIL_HANDLER: Validate request + loop n times, n = number of individual transfers + note right of BULK_FULFIL_HANDLER + Message: { + transferId: , + bulkTransferId< , + bulkTransferAssociationRecord: { + transferId: , + bulkTransferId: , + bulkProcessingStateId: , + errorCode: , + errorDescription: + } + } + end note + BULK_FULFIL_HANDLER -> DB: Update bulkTransferAssociation table + activate DB + hnote over DB #lightyellow + bulkTransferAssociation + end hnote + deactivate DB + BULK_FULFIL_HANDLER -> TOPIC_FULFIL: Produce fulfil message with action bulk-abort for each individual transfer + end + ||| + loop n times, n = number of individual transfers + TOPIC_FULFIL <- FULFIL_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_EVENTS: Fulfil Handler Consume (bulk-abort)\n + FULFIL_HANDLER -> TOPIC_POSITION: Produce message + end + ||| + loop n times, n = number of individual transfers + TOPIC_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_POSITION, BULK_PROCESSING_HANDLER: Position Handler Consume (bulk-abort)\n + POS_HANDLER -> TOPIC_BULK_PROCESSING: Produce message + end + ||| + loop n times, n = number of individual transfers + TOPIC_BULK_PROCESSING <- BULK_PROCESSING_HANDLER: Consume individual transfer message + ref over TOPIC_BULK_PROCESSING, TOPIC_NOTIFICATIONS: Bulk Processing Handler Consume (bulk-abort)\n + end + BULK_PROCESSING_HANDLER -> TOPIC_NOTIFICATIONS: Produce message (Payer) + BULK_PROCESSING_HANDLER -> TOPIC_NOTIFICATIONS: Produce message (Payee) + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message (Payer) + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message (Payee) + opt action == 'bulk-abort' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Notification Handler (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + opt action == 'bulk-abort' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Notification Handler (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +activate POS_HANDLER +activate FULFIL_HANDLER +activate FULFIL_HANDLER +activate NOTIFY_HANDLER +@enduml + diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.svg new file mode 100644 index 000000000..51eae9583 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.svg @@ -0,0 +1,397 @@ + + 4.1.0. Bulk Transfer Abort + + + 4.1.0. Bulk Transfer Abort + + Financial Service Providers + + Bulk API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + DFSP2 + Payee + + + DFSP2 + Payee + + + Bulk API Adapter + + + Bulk API Adapter + + + Bulk API Notification Event Handler + + + Bulk API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + Bulk-Fulfil-Topic + + + Bulk-Fulfil-Topic + + + Fulfil-Topic + + + Fulfil-Topic + Bulk Fulfil Event Handler + + + Bulk Fulfil Event Handler + + + Fulfil Event Handler + + + Fulfil Event Handler + + + + + topic-transfer-position + + + topic-transfer-position + + + Event-Topic + + + Event-Topic + Position Event Handler + + + Position Event Handler + + + + + topic-bulk-processing + + + topic-bulk-processing + Bulk Processing Event Handler + + + Bulk Processing Event Handler + + + + + Notification-Topic + + + Notification-Topic + + + mojaloop- + object-store + ( + MLOS + ) + + + mojaloop- + object-store + ( + MLOS + ) + Central Services DB + + + Central Services DB + + + + + + + + + + + + + + DFSP2 sends a Fulfil Abort Transfer request + + + Note + : In the payload for PUT /bulkTransfers/<ID>/error + only the + errorInformation + field is + required + + + Headers - transferHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } + Payload - errorMessage: + { + "errorInformation": { + "errorCode": <string>, + "errorDescription": <string>, + "extensionList": { + "extension": [ + { + "key": <string>, + "value": <string> + } + ] + } + } + } + + + + 1 + PUT - /bulkTransfers/<ID>/error + + + 2 + Persist request payload with messageId in cache + + + Message: { + messageId: <string>, + bulkTransferId: <string>, + payload: <object> + } + + individualTransferFulfils + + + 3 + Response of save operation + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + type: fulfil, + action: reject, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 4 + Produce bulk-fulfil message + + + + 5 + Respond HTTP - 200 (OK) + + + 6 + Consume bulk-fulfil message + + + + + 7 + Perform duplicate check + + + + + 8 + Validate request + + + loop + [n times, n = number of individual transfers] + + + Message: { + transferId: <string>, + bulkTransferId< <string>, + bulkTransferAssociationRecord: { + transferId: <string>, + bulkTransferId: <string>, + bulkProcessingStateId: <string>, + errorCode: <string>, + errorDescription: <string> + } + } + + + 9 + Update bulkTransferAssociation table + + bulkTransferAssociation + + + 10 + Produce fulfil message with action bulk-abort for each individual transfer + + + loop + [n times, n = number of individual transfers] + + + 11 + Consume message + + + ref + Fulfil Handler Consume (bulk-abort) +   + + + 12 + Produce message + + + loop + [n times, n = number of individual transfers] + + + 13 + Consume message + + + ref + Position Handler Consume (bulk-abort) +   + + + 14 + Produce message + + + loop + [n times, n = number of individual transfers] + + + 15 + Consume individual transfer message + + + ref + Bulk Processing Handler Consume (bulk-abort) +   + + + 16 + Produce message (Payer) + + + 17 + Produce message (Payee) + + + 18 + Consume message (Payer) + + + 19 + Consume message (Payee) + + + opt + [action == 'bulk-abort'] + + + ref + Notification Handler (Payer) +   + + + 20 + Send callback notification + + + opt + [action == 'bulk-abort'] + + + ref + Notification Handler (Payee) +   + + + 21 + Send callback notification + + diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.plantuml b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.plantuml new file mode 100644 index 000000000..e219f2465 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.plantuml @@ -0,0 +1,209 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- + ******'/ + +@startuml +' declate title +title 5.1.0. Request Bulk Transfer Status + +autonumber + +' declare actors +actor "DFSP(n)\nParticipant" as DFSP +control "Bulk API Notification Event Handler" as NOTIFY_HANDLER +boundary "Bulk API Adapter" as BULKAPI +collections "Topic-Transfer-Get" as TOPIC_GET +control "GET Event Handler" as GET_HANDLER +entity "Bulk Transfer DAO" as BULK_TRANSFER_DAO +database "Central Store" as DB + +box "Financial Service Provider" #lightGray + participant DFSP +end box +box "Bulk API Adapter Service" #LightBlue + participant BULKAPI + participant NOTIFY_HANDLER +end box +box "Central Ledger" #LightYellow + participant TOPIC_GET + participant GET_HANDLER + participant BULK_TRANSFER_DAO + participant DB +end box + +' start flow +group Request Bulk transfer status + activate DFSP + DFSP -> BULKAPI: Request bulk transfer status - GET - /bulkTransfers/{ID} + activate BULKAPI + ||| + BULKAPI -> TOPIC_GET: Publish event information + deactivate BULKAPI + activate TOPIC_GET + ||| + deactivate GET_HANDLER + + DFSP <-- BULKAPI: Respond HTTP - 200 (OK) + deactivate DFSP + deactivate BULKAPI + GET_HANDLER -> TOPIC_GET: Consume message + ||| + ref over TOPIC_GET, GET_HANDLER : GET Handler Consume\n + ||| + deactivate TOPIC_GET + + GET_HANDLER -> BULK_TRANSFER_DAO: Request bulk transfer participants + activate GET_HANDLER + activate BULK_TRANSFER_DAO + BULK_TRANSFER_DAO -> DB: Fetch bulk transfer participants + activate DB + hnote over DB #lightYellow + bulkTransfer + participant + end hnote + BULK_TRANSFER_DAO <-- DB: Return query result + deactivate DB + GET_HANDLER <-- BULK_TRANSFER_DAO: Return bulk transfer participants + deactivate BULK_TRANSFER_DAO + alt Is request not from bulk transfer Payer or Payee FSP? + note left of NOTIFY_HANDLER #yellow + { + "errorInformation": { + "errorCode": 3210, + "errorDescription": "Bulk transfer ID not found" + } + } + end note + GET_HANDLER -> NOTIFY_HANDLER: Publish notification event (404) + deactivate GET_HANDLER + activate NOTIFY_HANDLER + DFSP <- NOTIFY_HANDLER: callback PUT on /bulkTransfers/{ID}/error + deactivate NOTIFY_HANDLER + end + GET_HANDLER -> BULK_TRANSFER_DAO: Request bulk transfer status + activate GET_HANDLER + activate BULK_TRANSFER_DAO + BULK_TRANSFER_DAO -> DB: Fetch bulk transfer status + + activate DB + hnote over DB #lightyellow + bulkTransferStateChange + bulkTransferState + bulkTransferError + bulkTransferExtension + transferStateChange + transferState + transferFulfilment + transferError + transferExtension + ilpPacket + end hnote + BULK_TRANSFER_DAO <-- DB: Return query result + deactivate DB + + GET_HANDLER <-- BULK_TRANSFER_DAO: Return bulk transfer status + deactivate BULK_TRANSFER_DAO + + alt Is there a bulk transfer with the given ID recorded in the system? + alt Bulk Transfer state is **"PROCESSING"** + note left of GET_HANDLER #yellow + { + "bulkTransferState": "PROCESSING" + } + end note + NOTIFY_HANDLER <- GET_HANDLER: Publish notification event + deactivate GET_HANDLER + activate NOTIFY_HANDLER + NOTIFY_HANDLER -> DFSP: Send callback - PUT /bulkTransfers/{ID} + deactivate NOTIFY_HANDLER + end + ||| + alt Request is from Payee FSP? + GET_HANDLER <-> GET_HANDLER: Exclude transfers with **transferStateId** not in \n [ **COMMITTED**, **ABORTED_REJECTED**, **EXPIRED_RESERVED** ] + activate GET_HANDLER + end + + note left of GET_HANDLER #yellow + { + "bulkTransferState": "", + "individualTransferResults": [ + { + "transferId": "", + "fulfilment": "WLctttbu2HvTsa1XWvUoGRcQozHsqeu9Ahl2JW9Bsu8", + "errorInformation": , + "extensionList": { + "extension": + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + ], + "completedTimestamp": "2018-09-24T08:38:08.699-04:00", + "extensionList": + { + "extension": + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + end note + note left of GET_HANDLER #lightGray + NOTE: If transfer is REJECTED, error information may be provided. + Either fulfilment or errorInformation should be set, not both. + end note + NOTIFY_HANDLER <- GET_HANDLER: Publish notification event + deactivate GET_HANDLER + activate NOTIFY_HANDLER + DFSP <- NOTIFY_HANDLER: callback PUT on /bulkTransfers/{ID} + deactivate NOTIFY_HANDLER + note right of NOTIFY_HANDLER #lightgray + Log ERROR event + end note + else A bulk transfer with the given ID is not present in the System or this is an invalid request + note left of NOTIFY_HANDLER #yellow + { + "errorInformation": { + "errorCode": 3210, + "errorDescription": "Bulk transfer ID not found" + } + } + end note + GET_HANDLER -> NOTIFY_HANDLER: Publish notification event (404) + activate NOTIFY_HANDLER + DFSP <- NOTIFY_HANDLER: callback PUT on /bulkTransfers/{ID}/error + deactivate NOTIFY_HANDLER + end + + deactivate GET_HANDLER + deactivate NOTIFY_HANDLER +deactivate DFSP +end +@enduml diff --git a/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.svg b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.svg new file mode 100644 index 000000000..9b520a21c --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.svg @@ -0,0 +1,295 @@ + + 5.1.0. Request Bulk Transfer Status + + + 5.1.0. Request Bulk Transfer Status + + Financial Service Provider + + Bulk API Adapter Service + + Central Ledger + + + + + + + + + + + + + + + + + + + + + + + + + + + DFSP(n) + Participant + + + DFSP(n) + Participant + + + Bulk API Adapter + + + Bulk API Adapter + + + Bulk API Notification Event Handler + + + Bulk API Notification Event Handler + + + + + Topic-Transfer-Get + + + Topic-Transfer-Get + GET Event Handler + + + GET Event Handler + + + Bulk Transfer DAO + + + Bulk Transfer DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + Request Bulk transfer status + + + 1 + Request bulk transfer status - GET - /bulkTransfers/{ID} + + + 2 + Publish event information + + + 3 + Respond HTTP - 200 (OK) + + + 4 + Consume message + + + ref + GET Handler Consume +   + + + 5 + Request bulk transfer participants + + + 6 + Fetch bulk transfer participants + + bulkTransfer + participant + + + 7 + Return query result + + + 8 + Return bulk transfer participants + + + alt + [Is request not from bulk transfer Payer or Payee FSP?] + + + { + "errorInformation": { + "errorCode": 3210, + "errorDescription": "Bulk transfer ID not found" + } + } + + + 9 + Publish notification event (404) + + + 10 + callback PUT on /bulkTransfers/{ID}/error + + + 11 + Request bulk transfer status + + + 12 + Fetch bulk transfer status + + bulkTransferStateChange + bulkTransferState + bulkTransferError + bulkTransferExtension + transferStateChange + transferState + transferFulfilment + transferError + transferExtension + ilpPacket + + + 13 + Return query result + + + 14 + Return bulk transfer status + + + alt + [Is there a bulk transfer with the given ID recorded in the system?] + + + alt + [Bulk Transfer state is + "PROCESSING" + ] + + + { + "bulkTransferState": "PROCESSING" + } + + + 15 + Publish notification event + + + 16 + Send callback - PUT /bulkTransfers/{ID} + + + alt + [Request is from Payee FSP?] + + + + + + 17 + Exclude transfers with + transferStateId + not in + [ + COMMITTED + , + ABORTED_REJECTED + , + EXPIRED_RESERVED + ] + + + { + "bulkTransferState": "<BulkTransferState>", + "individualTransferResults": [ + { + "transferId": "<TransferId>", + "fulfilment": "WLctttbu2HvTsa1XWvUoGRcQozHsqeu9Ahl2JW9Bsu8", + "errorInformation": <ErrorInformationObject>, + "extensionList": { + "extension": + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + ], + "completedTimestamp": "2018-09-24T08:38:08.699-04:00", + "extensionList": + { + "extension": + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + + + NOTE: If transfer is REJECTED, error information may be provided. + Either fulfilment or errorInformation should be set, not both. + + + 18 + Publish notification event + + + 19 + callback PUT on /bulkTransfers/{ID} + + + Log ERROR event + + [A bulk transfer with the given ID is not present in the System or this is an invalid request] + + + { + "errorInformation": { + "errorCode": 3210, + "errorDescription": "Bulk transfer ID not found" + } + } + + + 20 + Publish notification event (404) + + + 21 + callback PUT on /bulkTransfers/{ID}/error + + diff --git a/docs/technical/technical/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md b/docs/technical/technical/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md new file mode 100644 index 000000000..8ad8c6ce7 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md @@ -0,0 +1,15 @@ +# Bulk Prepare Transfer Request [Overview] [includes individual transfers in a bulk] + +Sequence design diagram for Prepare Transfer Request process. + +## References within Sequence Diagram + +* [Bulk Prepare Handler Consume (1.1.1)](1.1.1-bulk-prepare-handler-consume.md) +* [Prepare Handler Consume (1.2.1)](1.2.1-prepare-handler-consume-for-bulk.md) +* [Position Handler Consume (1.3.0)](1.3.0-position-handler-consume-overview.md) +* [Bulk Processing Handler Consume (1.4.1)](1.4.1-bulk-processing-handler.md) +* [Send notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-bulk-1.1.0-bulk-prepare-overview.svg](../assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md b/docs/technical/technical/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md new file mode 100644 index 000000000..495a0fdaf --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md @@ -0,0 +1,11 @@ +# Bulk Prepare handler consume + +Sequence design diagram for Bulk Prepare Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-bulk-1.1.1-bulk-prepare-handler.svg](../assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md b/docs/technical/technical/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md new file mode 100644 index 000000000..aabde9fb1 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md @@ -0,0 +1,11 @@ +# Prepare handler consume [that includes individual transfers in a bulk] + +Sequence design diagram for Prepare Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-bulk-1.2.1-prepare-handler.svg](../assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md b/docs/technical/technical/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md new file mode 100644 index 000000000..aae066006 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md @@ -0,0 +1,14 @@ +# Position Handler Consume [that includes individual transfers in a bulk] + +Sequence design diagram for Position Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [Prepare Position Handler Consume (1.3.1)](1.3.1-prepare-position-handler-consume.md) +* [Fufil Position Handler Consume (2.2.1)](2.2.1-fulfil-commit-for-bulk.md) +* [Abort Position Handler Consume (2.2.2)](2.2.2-fulfil-abort-for-bulk.md) + +## Sequence Diagram + +![seq-bulk-1.3.0-position-overview.svg](../assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md b/docs/technical/technical/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md new file mode 100644 index 000000000..460ab7350 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md @@ -0,0 +1,7 @@ +# Prepare Position Handler Consume [that includes individual transfers in a bulk] + +Sequence design diagram for Prepare Position Handler Consume process + +## Sequence Diagram + +![seq-bulk-1.3.1-position-prepare.svg](../assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md b/docs/technical/technical/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md new file mode 100644 index 000000000..53fe3c2b8 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md @@ -0,0 +1,7 @@ +# Bulk Processing Handler Consume + +Sequence design diagram for Bulk Processing Handler Consume process + +## Sequence Diagram + +![seq-bulk-1.4.1-bulk-processing-handler.svg](../assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md b/docs/technical/technical/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md new file mode 100644 index 000000000..f08b37d9e --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md @@ -0,0 +1,15 @@ +# Bulk Fulfil Transfer Request Overview + +Sequence design diagram for the Bulk Fulfil Transfer request + +## References within Sequence Diagram + +* [Bulk Fulfil Handler Consume (Success) (2.1.1)](2.1.1-bulk-fulfil-handler-consume.md) +* [Fulfil Handler Consume (Success) (2.2.1)](2.2.1-fulfil-commit-for-bulk.md) +* [Position Handler Consume (Success) (2.3.1)](2.3.1-fulfil-position-handler-consume.md) +* [Bulk Processing Handler Consume (1.4.1)](1.4.1-bulk-processing-handler.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-bulk-2.1.0-bulk-fulfil-overview.svg](../assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md b/docs/technical/technical/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md new file mode 100644 index 000000000..ea730d0b8 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md @@ -0,0 +1,13 @@ +# Bulk Fulfil Handler Consume + +Sequence design diagram for the Bulk Fulfil Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-bulk-2.1.1-bulk-fulfil-handler.svg](../assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md b/docs/technical/technical/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md new file mode 100644 index 000000000..7a2102201 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md @@ -0,0 +1,11 @@ +# Payee sends a Bulk Fulfil Transfer request - Bulk is broken down into individual transfers + +Sequence design diagram for the Bulk Fulfil Transfer for the Commit option + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-bulk-2.2.1-fulfil-handler-commit.svg](../assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md b/docs/technical/technical/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md new file mode 100644 index 000000000..6b32a71bc --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md @@ -0,0 +1,13 @@ +# Payee sends a Bulk Fulfil Transfer request - Bulk is broken down into individual transfers + +Sequence design diagram for the Fulfil Handler Consume Reject/Abort process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-bulk-2.2.2-fulfil-handler-abort.svg](../assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md b/docs/technical/technical/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md new file mode 100644 index 000000000..3b4d2877a --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md @@ -0,0 +1,11 @@ +# Fulfil Position Handler Consume [that includes individual transfers in a bulk] + +Sequence design diagram for the Fulfil Position Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-bulk-2.3.1-position-fulfil.svg](../assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md b/docs/technical/technical/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md new file mode 100644 index 000000000..ed4d3f9f8 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md @@ -0,0 +1,7 @@ +# Position Handler Consume for Fulfil aborts at individual transfer level + +Sequence design diagram for Fulfil Position Handler Consume process + +## Sequence Diagram + +![seq-bulk-2.3.2-position-abort.svg](../assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md b/docs/technical/technical/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md new file mode 100644 index 000000000..030f29281 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md @@ -0,0 +1,7 @@ +# Transfer Timeout [includes individual transfers in a Bulk] + +Sequence design diagram for the Transfer Timeout process. + +## Sequence Diagram + +![seq-bulk-3.1.0-timeout-overview.svg](../assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md b/docs/technical/technical/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md new file mode 100644 index 000000000..d8fcefc23 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md @@ -0,0 +1,7 @@ +# TimeOut Handler + +Sequence design diagram for Timeout Handler process + +## Sequence Diagram + +![seq-bulk-3.1.1-timeout-handler.svg](../assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.md b/docs/technical/technical/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.md new file mode 100644 index 000000000..25c4873e4 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.md @@ -0,0 +1,7 @@ +# Bulk Transfer Abort Overview [includes individual transfers in a Bulk] + +Sequence design diagram for the Bulk Transfer Abort process. + +## Sequence Diagram + +![seq-bulk-4.1.0-abort-overview.svg](../assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.md b/docs/technical/technical/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.md new file mode 100644 index 000000000..d4d05674a --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.md @@ -0,0 +1,7 @@ +# Get Bulk Transfer Overview + +Sequence design diagram for the Get Bulk Transfer process. + +## Sequence Diagram + +![seq-bulk-5.1.0-get-overview.svg](../assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.svg) diff --git a/docs/technical/technical/central-bulk-transfers/transfers/README.md b/docs/technical/technical/central-bulk-transfers/transfers/README.md new file mode 100644 index 000000000..36adeecc5 --- /dev/null +++ b/docs/technical/technical/central-bulk-transfers/transfers/README.md @@ -0,0 +1,11 @@ +# Mojaloop Bulk Transfer operations + +Operational processes that is the core of the transfer operational process; + +- Bulk Prepare Process at Bulk Transfer level +- Prepare process at a single transfer level +- Bulk Fulfil process at Bulk Transfer level +- Fulfil process at a single transfer level +- Notifications process at Bulk Transfer level +- Reject/Abort process +- Bulk Processing at a single transfer level to aggregate Bulks diff --git a/mojaloop-technical-overview/central-event-processor/README.md b/docs/technical/technical/central-event-processor/README.md similarity index 100% rename from mojaloop-technical-overview/central-event-processor/README.md rename to docs/technical/technical/central-event-processor/README.md diff --git a/mojaloop-technical-overview/central-event-processor/assets/diagrams/architecture/CEPArchTechOverview.svg b/docs/technical/technical/central-event-processor/assets/diagrams/architecture/CEPArchTechOverview.svg similarity index 100% rename from mojaloop-technical-overview/central-event-processor/assets/diagrams/architecture/CEPArchTechOverview.svg rename to docs/technical/technical/central-event-processor/assets/diagrams/architecture/CEPArchTechOverview.svg diff --git a/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.plantuml b/docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.plantuml rename to docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.plantuml diff --git a/docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.svg b/docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.svg new file mode 100644 index 000000000..37ea1f2bd --- /dev/null +++ b/docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.svg @@ -0,0 +1,83 @@ + + 9.1.0. Event Handler Placeholder + + + 9.1.0. Event Handler Placeholder + + Event Handler Placeholder + + + + + + Event Handler Placeholder + + + Event Handler Placeholder + + + + + Event-Topic + + + Event-Topic + + + + + Event Handler Placeholder + + + 1 + Consume Event message +   + Error code: + 2001 + + + Message: + { + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + type: INFO, + action: AUDIT, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + The type would be an ENUM with values: + [INFO, DEBUG, ERROR, WARN, FATAL, TRACE] + Possible values for "action" would be + [AUDIT, EXCEPTION] + The event messages can be handled based on the values of these two variables + (when the placeholder is extended). + + + + + 2 + Auto-commit +   + Error code: + 2001 + + + Currently events to only be published as part of the placeholder. + This can be evolved to add relevant functionality. + + diff --git a/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.plantuml b/docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.plantuml similarity index 100% rename from mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.plantuml rename to docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.plantuml diff --git a/docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.svg b/docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.svg new file mode 100644 index 000000000..3dfc4a19f --- /dev/null +++ b/docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.svg @@ -0,0 +1,160 @@ + + 5.1.1. Notification Handler for Rejections + + + 5.1.1. Notification Handler for Rejections + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + Event-Topic + + + Event-Topic + + + Notification-Topic + + + Notification-Topic + + + + + + + DFSP Notified of Rejection + + + 1 + Consume Notification event message +   + Error code: + 2001 + + + Persist Event Information + + + 2 + Publish event information +   + Error code: + 3201 + + + ref + Event Handler + + + alt + [consume a single messages] + + + Validate Event + + + + + + 3 + Validate event - Rule: type == 'notification' && [action IN ['reject', 'timeout-received', 'timeout-reserved']] + + + 4 + Request Participant Callback details +   + Error code: + 3201 + + + ref + Get Participant Callback Details + + + 5 + Return Participant Callback details + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + payload: <transferMessage> + }, + } + + + 6 + Send Callback Notification +   + Error code: + 1000, 1001, 3002 + + [Validate rule type != 'notification' / Error] + + + Message: + { + "errorInformation": { + "errorCode": <errorCode>, + "errorDescription": <ErrorMessage>, + } + } + + + 7 + Invalid messages retrieved from the Notification Topic +   + Error code: + 3201 + + + ref + Event Handler + + + Log ERROR Messages + Update Event log upon ERROR notification + + diff --git a/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-signature-validation.plantuml b/docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-signature-validation.plantuml similarity index 100% rename from mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-signature-validation.plantuml rename to docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-signature-validation.plantuml diff --git a/docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-signature-validation.svg b/docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-signature-validation.svg new file mode 100644 index 000000000..86939d30d --- /dev/null +++ b/docs/technical/technical/central-event-processor/assets/diagrams/sequence/seq-signature-validation.svg @@ -0,0 +1,29 @@ + + Signature Validation + + + Signature Validation + + + + Alice + + Alice + + Bob + + Bob + + + Authentication Request + + + Authentication Response + + + Another authentication Request + + + another authentication Response + + diff --git a/docs/technical/technical/central-event-processor/event-handler-placeholder.md b/docs/technical/technical/central-event-processor/event-handler-placeholder.md new file mode 100644 index 000000000..e0b8a605b --- /dev/null +++ b/docs/technical/technical/central-event-processor/event-handler-placeholder.md @@ -0,0 +1,7 @@ +# Event Handler Placeholder + +Sequence design diagram for the Event Handler process. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-event-9.1.0.svg) diff --git a/docs/technical/technical/central-event-processor/notification-handler-for-rejections.md b/docs/technical/technical/central-event-processor/notification-handler-for-rejections.md new file mode 100644 index 000000000..e41bd68ea --- /dev/null +++ b/docs/technical/technical/central-event-processor/notification-handler-for-rejections.md @@ -0,0 +1,12 @@ +# Notification Handler for Rejections + +Sequence design diagram for the Notification Handler for Rejections process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](9.1.0-event-handler-placeholder.md) +* [Get Participant Callback Details (3.1.0)](../central-ledger/admin-operations/3.1.0-post-participant-callback-details.md) + +## Sequence Diagram + +![](;./assets/diagrams/sequence/seq-notification-reject-5.1.1.svg) diff --git a/docs/technical/technical/central-event-processor/signature-validation.md b/docs/technical/technical/central-event-processor/signature-validation.md new file mode 100644 index 000000000..8ead8f91b --- /dev/null +++ b/docs/technical/technical/central-event-processor/signature-validation.md @@ -0,0 +1,7 @@ +# Signature Validation + +Sequence design diagram for the Signature Validation process. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-signature-validation.svg) diff --git a/assets/images/uml/.gitkeep b/docs/technical/technical/central-ledger/.gitkeep similarity index 100% rename from assets/images/uml/.gitkeep rename to docs/technical/technical/central-ledger/.gitkeep diff --git a/docs/technical/technical/central-ledger/README.md b/docs/technical/technical/central-ledger/README.md new file mode 100644 index 000000000..69df63f59 --- /dev/null +++ b/docs/technical/technical/central-ledger/README.md @@ -0,0 +1,52 @@ +# Central-Ledger Services + +The central ledger is a series of services that facilitate clearing and settlement of transfers between DFSPs, including the following functions: + +* Brokering real-time messaging for funds clearing +* Maintaining net positions for a deferred net settlement +* Propagating scheme-level and off-transfer fees + +## 1. Central Ledger Process Design + +### 1.1 Architecture overview + +![Central-Ledger Architecture](./assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg) + +## 2. Transfers End-to-End Architecture + + +### 2.1 Transfers End-to-End Architecture for v1.1 +![Transfers Architecture for Mojaloop FSP Interoperability API v1.1](./assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.1.svg) + +### 2.2 Transfers End-to-End Architecture for v1.0 +![Transfers Architecture for Mojaloop FSP Interoperability API v1.0](./assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0.svg) + +## 3. Database Design + +### Note + +The tables *Grey* colored tables are specific to the transfer process. The *Blue* and *Green* color tables are used for reference purposes during the Transfer process. + +Summary of the tables specific to the transfer process; + +- `transfer` - stores data related to the transfer; +- `transferDuplicateCheck` - used to identify duplication during the transfer requests process; +- `transferError` - stores information on transfer errors encountered during the transfer process; +- `transferErrorDuplicateCheck` - used to identify duplication error transfer processes; +- `transferExtensions` - stores information on the transfer extension data; +- `transferFulfilment` - stores data for transfers that have completed the prepare transfer process; +- `transferFulfilmentDuplicateCheck` - used the identify duplicate transfer fulfil requests; +- `transferParticipant` - participant information related to the transfer process; +- `transferStateChange` - use to track state changes of each individual transfer, creating and audit trail for a specific transfer request; +- `transferTimeout` - stores information of transfers that encountered a timeout exception during the process; +- `ilpPacket` - stores the ilp package for the transfer; + +The remaining tables in the below ERD are either lookup (blue) or settlement-specific (red) and are included as direct or indirect dependencies to depict the relation between the transfer specific entities and the transfer tables. + +The **Central Ledger** database schema definition [Central-Ledger Database Schema Definition](./assets/database/central-ledger-ddl-MySQLWorkbench.sql). + +![Central-Ledger Database Diagram](./assets/database/central-ledger-schema.png) + +## 4. API Specification + +Refer to **Central Ledger API** in the [API Specifications](../../api/README.md#central-ledger-api) section. diff --git a/docs/technical/technical/central-ledger/admin-operations/1.0.0-get-health-check.md b/docs/technical/technical/central-ledger/admin-operations/1.0.0-get-health-check.md new file mode 100644 index 000000000..021204219 --- /dev/null +++ b/docs/technical/technical/central-ledger/admin-operations/1.0.0-get-health-check.md @@ -0,0 +1,265 @@ +# GET Health Check + +Design discussion for new Health Check implementation. + + +## Objectives + +The goal for this design is to implement a new Health check for mojaloop switch services that allows for a greater level of detail. + +It Features: +- Clear HTTP Statuses (no need to inspect the response to know there are no issues) +- ~Backwards compatibility with existing health checks~ - No longer a requirement. See [this discussion](https://github.com/mojaloop/project/issues/796#issuecomment-498350828). +- Information about the version of the API, and how long it has been running for +- Information about sub-service (kafka, logging sidecar and mysql) connections + +## Request Format +`/health` + +Uses the newly implemented health check. As discussed [here](https://github.com/mojaloop/project/issues/796#issuecomment-498350828) since there will be no added connection overhead (e.g. pinging a database) as part of implementing the health check, there is no need to complicate things with a simple and detailed version. + +Responses Codes: +- `200` - Success. The API is up and running, and is sucessfully connected to necessary services. +- `502` - Bad Gateway. The API is up and running, but the API cannot connect to necessary service (eg. `kafka`). +- `503` - Service Unavailable. This response is not implemented in this design, but will be the default if the api is not and running + +## Response Format + +| Name | Type | Description | Example | +| --- | --- | --- | --- | +| `status` | `statusEnum` | The status of the service. Options are `OK` and `DOWN`. _See `statusEnum` below_. | `"OK"` | +| `uptime` | `number` | How long (in seconds) the service has been alive for. | `123456` | +| `started` | `string` (ISO formatted date-time) | When the service was started (UTC) | `"2019-05-31T05:09:25.409Z"` | +| `versionNumber` | `string` (semver) | The current version of the service. | `"5.2.5"` | +| `services` | `Array` | A list of services this service depends on, and their connection status | _see below_ | + +### serviceHealth + +| Name | Type | Description | Example | +| --- | --- | --- | --- | +| `name` | `subServiceEnum` | The sub-service name. _See `subServiceEnum` below_. | `"broker"` | +| `status` | `enum` | The status of the service. Options are `OK` and `DOWN` | `"OK"` | + +### subServiceEnum + +The subServiceEnum enum describes a name of the subservice: + +Options: +- `datastore` -> The database for this service (typically a MySQL Database). +- `broker` -> The message broker for this service (typically Kafka). +- `sidecar` -> The logging sidecar sub-service this service attaches to. +- `cache` -> The caching sub-service this services attaches to. + + +### statusEnum + +The status enum represents status of the system or sub-service. + +It has two options: +- `OK` -> The service or sub-service is healthy. +- `DOWN` -> The service or sub-service is unhealthy. + +When a service is `OK`: the API is considered healthy, and all sub-services are also considered healthy. + +If __any__ sub-service is `DOWN`, then the entire health check will fail, and the API will be considered `DOWN`. + +## Defining Sub-Service health + +It is not enough to simply ping a sub-service to know if it is healthy, we want to go one step further. These criteria will change with each sub-service. + +### `datastore` + +For `datastore`, a status of `OK` means: +- An existing connection to the database +- The database is not empty (contains more than 1 table) + + +### `broker` + +For `broker`, a status of `OK` means: +- An existing connection to the kafka broker +- The necessary topics exist. This will change depending on which service the health check is running for. + +For example, for the `central-ledger` service to be considered healthy, the following topics need to be found: +``` +topic-admin-transfer +topic-transfer-prepare +topic-transfer-position +topic-transfer-fulfil +``` + +### `sidecar` + +For `sidecar`, a status of `OK` means: +- An existing connection to the sidecar + + +### `cache` + +For `cache`, a status of `OK` means: +- An existing connection to the cache + + +## Swagger Definition + +>_Note: These will be added to the existing swagger definitions for the following services:_ +> - `ml-api-adapter` +> - `central-ledger` +> - `central-settlement` +> - `central-event-processor` +> - `email-notifier` + +```json +{ + /// . . . + "/health": { + "get": { + "operationId": "getHealth", + "tags": [ + "health" + ], + "responses": { + "default": { + "schema": { + "$ref": "#/definitions/health" + }, + "description": "Successful" + } + } + } + }, + // . . . + "definitions": { + "health": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "OK", + "DOWN" + ] + }, + "uptime": { + "description": "How long (in seconds) the service has been alive for.", + "type": "number", + }, + "started": { + "description": "When the service was started (UTC)", + "type": "string", + "format": "date-time" + }, + "versionNumber": { + "description": "The current version of the service.", + "type": "string", + "example": "5.2.3", + }, + "services": { + "description": "A list of services this service depends on, and their connection status", + "type": "array", + "items": { + "$ref": "#/definitions/serviceHealth" + } + }, + }, + }, + "serviceHealth": { + "type": "object", + "properties": { + "name": { + "description": "The sub-service name.", + "type": "string", + "enum": [ + "datastore", + "broker", + "sidecar", + "cache" + ] + }, + "status": { + "description": "The connection status with the service.", + "type": "string", + "enum": [ + "OK", + "DOWN" + ] + } + } + } + } +} +``` + + +### Example Requests and Responses: + +__Successful Legacy Health Check:__ + +```bash +GET /health HTTP/1.1 +Content-Type: application/json + +200 SUCCESS +{ + "status": "OK" +} +``` + + +__Successful New Health Check:__ + +``` +GET /health?detailed=true HTTP/1.1 +Content-Type: application/json + +200 SUCCESS +{ + "status": "OK", + "uptime": 0, + "started": "2019-05-31T05:09:25.409Z", + "versionNumber": "5.2.3", + "services": [ + { + "name": "broker", + "status": "OK", + } + ] +} +``` + +__Failed Health Check, but API is up:__ + +``` +GET /health?detailed=true HTTP/1.1 +Content-Type: application/json + +502 BAD GATEWAY +{ + "status": "DOWN", + "uptime": 0, + "started": "2019-05-31T05:09:25.409Z", + "versionNumber": "5.2.3", + "services": [ + { + "name": "broker", + "status": "DOWN", + } + ] +} +``` + +__Failed Health Check:__ + +``` +GET /health?detailed=true HTTP/1.1 +Content-Type: application/json + +503 SERVICE UNAVAILABLE +``` + + +## Sequence Diagram + +Sequence design diagram for the GET Health + +![seq-get-health-1.0.0.svg](../assets/diagrams/sequence/seq-get-health-1.0.0.svg) diff --git a/docs/technical/technical/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md b/docs/technical/technical/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md new file mode 100644 index 000000000..7a1c5e933 --- /dev/null +++ b/docs/technical/technical/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md @@ -0,0 +1,7 @@ +# GET Participant Limit Details For All Participants + +Sequence design diagram for the GET Participant Limit Details For All Participants process. + +## Sequence Diagram + +![seq-get-all-participant-limit-1.0.0.svg](../assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.svg) diff --git a/docs/technical/technical/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md b/docs/technical/technical/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md new file mode 100644 index 000000000..6fda674e3 --- /dev/null +++ b/docs/technical/technical/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md @@ -0,0 +1,7 @@ +# Create initial position and limits for Participant + +Sequence design diagram for the POST (create) Participant Initial Position and Limit process. + +## Sequence Diagram + +![seq-participant-position-limits-1.0.0.svg](../assets/diagrams/sequence/seq-participant-position-limits-1.0.0.svg) diff --git a/docs/technical/technical/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md b/docs/technical/technical/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md new file mode 100644 index 000000000..2419df6fe --- /dev/null +++ b/docs/technical/technical/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md @@ -0,0 +1,7 @@ +# Request Participant Position and Limit Details + +Sequence design diagram for the Request Participant Position and Limit Details process. + +## Sequence Diagram + +![seq-get-participant-position-limit-1.1.0.svg](../assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.svg) diff --git a/docs/technical/technical/central-ledger/admin-operations/1.1.0-post-participant-limits.md b/docs/technical/technical/central-ledger/admin-operations/1.1.0-post-participant-limits.md new file mode 100644 index 000000000..99fb44d05 --- /dev/null +++ b/docs/technical/technical/central-ledger/admin-operations/1.1.0-post-participant-limits.md @@ -0,0 +1,7 @@ +# Adjust Participant Limit for a certain Currency + +Sequence design diagram for the POST (manage) Participant Limit Details process. + +## Sequence Diagram + +![seq-manage-participant-limit-1.1.0.svg](../assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.svg) diff --git a/docs/technical/technical/central-ledger/admin-operations/1.1.5-get-transfer-status.md b/docs/technical/technical/central-ledger/admin-operations/1.1.5-get-transfer-status.md new file mode 100644 index 000000000..b5c1f6734 --- /dev/null +++ b/docs/technical/technical/central-ledger/admin-operations/1.1.5-get-transfer-status.md @@ -0,0 +1,7 @@ +# Request transfer status + +Sequence design diagram for the GET Transfer Status process. + +## Sequence Diagram + +![seq-get-transfer-1.1.5-phase2.svg](../assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.svg) diff --git a/docs/technical/technical/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md b/docs/technical/technical/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md new file mode 100644 index 000000000..72020a489 --- /dev/null +++ b/docs/technical/technical/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md @@ -0,0 +1,7 @@ +# 3.1.0 Get Participant Callback Details + +Sequence design diagram for the GET Participant Callback Details process. + +## Sequence Diagram + +![seq-callback-3.1.0.svg](../assets/diagrams/sequence/seq-callback-3.1.0.svg) diff --git a/docs/technical/technical/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md b/docs/technical/technical/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md new file mode 100644 index 000000000..2b9afae31 --- /dev/null +++ b/docs/technical/technical/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md @@ -0,0 +1,7 @@ +# 3.1.0 Add Participant Callback Details + +Sequence design diagram for the POST (Add) Participant Callback Details process. + +## Sequence Diagram + +![seq-callback-add-3.1.0.svg](../assets/diagrams/sequence/seq-callback-add-3.1.0.svg) diff --git a/docs/technical/technical/central-ledger/admin-operations/4.1.0-get-participant-position-details.md b/docs/technical/technical/central-ledger/admin-operations/4.1.0-get-participant-position-details.md new file mode 100644 index 000000000..1153ef409 --- /dev/null +++ b/docs/technical/technical/central-ledger/admin-operations/4.1.0-get-participant-position-details.md @@ -0,0 +1,7 @@ +# Get Participant Position Details + +Sequence design diagram for the GET Participant Position Details process. + +## Sequence Diagram + +![seq-participants-positions-query-4.1.0.svg](../assets/diagrams/sequence/seq-participants-positions-query-4.1.0.svg) diff --git a/docs/technical/technical/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md b/docs/technical/technical/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md new file mode 100644 index 000000000..176494d61 --- /dev/null +++ b/docs/technical/technical/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md @@ -0,0 +1,7 @@ +# Get Position Details for all Participants + +Sequence design diagram for the Get Positions of all Participants process. + +## Sequence Diagram + +![seq-participants-positions-query-all-4.2.0.svg](../assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.svg) diff --git a/docs/technical/technical/central-ledger/admin-operations/README.md b/docs/technical/technical/central-ledger/admin-operations/README.md new file mode 100644 index 000000000..ebdb6ac1d --- /dev/null +++ b/docs/technical/technical/central-ledger/admin-operations/README.md @@ -0,0 +1,3 @@ +# Mojaloop HUB/Switch operations + +Operational processes normally initiated by a HUB/Switch operator. diff --git a/docs/technical/technical/central-ledger/assets/database/README.md b/docs/technical/technical/central-ledger/assets/database/README.md new file mode 100644 index 000000000..77d71d79d --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/database/README.md @@ -0,0 +1,17 @@ +# How to EDIT the central-ledger-schema-DBeaver.erd file + +This is a basic guide on how to successfully view/update the central-ledger-schema-DBeaver.erd file. + +## Prerequisites +* Download and install the DBeaver Community DB Manager +* The Mojaloop Central-Ledger MySQL Database needs to be up and running, and connectable by the DBeaver +* You'll also need a text editor +## Steps to follow +* Create a new db connection in DBeaver under Database Navigator tab for the MySQL instance running. +* Under the Projects tab right click and create a New ER Diagram. +* Give the diagram a name and select central-ledger db in the wizard. + +* Copy the `central-ledger-schema-DBeaver.erd` file from the documentation module to `DBeaverData/workspace/General/Diagrams` in your DBeaver storage location +* Navigate to the newly created erd file using a text editor, search for `data-source id` and copy its value which looks like `mysql5-171ea991174-1218b6e1bf273693`. +* Navigate with a text editor to the `central-ledger-schema-DBeaver.erd` file in the ER Diagrams directory and replace its `data-source id` value with the one copied from the newly created erd file. +* The `central-ledger-schema-DBeaver.erd` should now show the tables as per the `central-ledger-schema.png` \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-ddl-MySQLWorkbench.sql b/docs/technical/technical/central-ledger/assets/database/central-ledger-ddl-MySQLWorkbench.sql similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/database/central-ledger-ddl-MySQLWorkbench.sql rename to docs/technical/technical/central-ledger/assets/database/central-ledger-ddl-MySQLWorkbench.sql diff --git a/docs/technical/technical/central-ledger/assets/database/central-ledger-schema-DBeaver.erd b/docs/technical/technical/central-ledger/assets/database/central-ledger-schema-DBeaver.erd new file mode 100644 index 000000000..303fa1534 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/database/central-ledger-schema-DBeaver.erd @@ -0,0 +1,612 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/technical/technical/central-ledger/assets/database/central-ledger-schema.png b/docs/technical/technical/central-ledger/assets/database/central-ledger-schema.png new file mode 100644 index 000000000..62b4a1a1e Binary files /dev/null and b/docs/technical/technical/central-ledger/assets/database/central-ledger-schema.png differ diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg b/docs/technical/technical/central-ledger/assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg rename to docs/technical/technical/central-ledger/assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End.svg b/docs/technical/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0-old.svg similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End.svg rename to docs/technical/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0-old.svg diff --git a/docs/technical/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0.svg new file mode 100644 index 000000000..02658b83d --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0.svg @@ -0,0 +1,3 @@ + + +
    1.5 Increment Position (fsp1)
    1.5 Increment Position (fsp1)
    1.4 Increment
    Position (fsp1)

    1.4 Increment...
    PrepareHandler
    PrepareHandler
    PositionHandler
    PositionHandler
    Fulfil
    Sucess
    Fulfil...
    2.4 Fulfil
    Success
    2.4 Fulfil...
    <alt> 2.4 
    Fulfil Reject

    <alt> 2.4...
    Fulfil
    Reject
    Fulfil...
    <alt> 2.5 Decrement
    Position (fsp1)

    <alt> 2.5 Decrement...
    <alt>1.6 Reject Notification
    (Not enough position)

    <alt>1.6...
    Central - Services
    Central - Services
    3.0 Reject
    3.0 Reject
    2.6 Fulfil Notification /
     <alt> 2.6 Reject Notification (Fulfil) /
    3.2 Reject Notification (Timeout)

    2.6 Fulfil Notification /...
    1.0 Transfer 
    Request

    1.0 Transfer...
    3.1 Decrement
    Position (fsp1)

    3.1 Decrement...
    1.6 Prepare Notification
    1.6 Prepare Notification
    ML-Adapter
    ML-Adapter
    Transfer
    API
    Transfer...
    Notification
    Event Handler
    Notification...
    fsp prepare
    fsp prep...
    1.3 Prepare Consume
    1.3 Prepare Consume
    notifications
    notificati...
    FSP1
    (Payer)

    FSP1...
    FSP2
    (Payee)
    FSP2...
    1.1
    Prepare Request
    1.1...
    1.2 Accpeted
    (202)
    1.2 Accpeted...
    Transfer
    API
    Transfer...
    2.0 Fulfil 
    Success / 
    Reject

    2...
    fulfils
    fulfils
    FulfilHandler
    FulfilHandler
    Success/
    Reject
    Success/...
    2.5 Decrement
    Position (fsp2)

    2.5 Decrement...
    2.1 Fulfil 
    Success / Reject

    2.1 Fulfil...
    2.2 OK
    (200)
    2.2 OK...
    2.3 Fulfil
    Success /
    Reject
    Consume
    2.3 Fulfil...
    OK (200)
    OK (200)
    OK (200)
    OK (200)
    Transfer Timeout
    Handler
    Transfer Timeout...
    <alt> 1.4 Prepare Failure
    <alt> 1.4 Prepare Failure
    <alt> 2.4 Fulfil Failure
    <alt>...
    2.7 Fulfil Notify Callback /
    <alt> 2.7 Reject Response (Fulfil reject) /
    3.1, 3.3 Reject Response (Timeout) /
    <alt> 1.7 Reject Response (Not enough position)
    <alt> 1.5 Prepare Failure 

    2.7 Fulfil Notify Callback /...
    1.7 Prepare Notify /
    2.8 Commit Notify (optional) /
    <alt> 2.7 Reject Response (Fulfil reject)
    3.3 Reject Response (Timeout)
    <alt> 2.5 Fulfil Failure

    1.7 Prepare Notify /...
    position
    position
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/technical/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.1.svg new file mode 100644 index 000000000..e9a1460c8 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.1.svg @@ -0,0 +1,3 @@ + + +
    1.5 Increment Position (fsp1)
    1.5 Increment Position (fsp1)
    1.4 Increment
    Position (fsp1)

    1.4 Increment...
    PrepareHandler
    PrepareHandler
    PositionHandler
    PositionHandler
    Fulfil
    Sucess
    Fulfil...
    2.4 Fulfil
    Success
    2.4 Fulfil...
    <alt> 2.4 
    Fulfil Reject

    <alt> 2.4...
    Fulfil
    Reject
    Fulfil...
    <alt> 2.5 Decrement
    Position (fsp1)

    <alt> 2.5 Decrement...
    <alt>1.6 Reject Notification
    (Not enough position)

    <alt>1.6...
    Central - Services
    Central - Services
    3.0 Reject
    3.0 Reject
    2.6 Fulfil Notification /
     <alt> 2.6 Reject Notification (Fulfil) /
    3.2 Reject Notification (Timeout)

    2.6 Fulfil Notification /...
    1.0 Transfer 
    Request

    1.0 Transfer...
    3.1 Decrement
    Position (fsp1)

    3.1 Decrement...
    1.6 Prepare Notification
    1.6 Prepare Notification
    ML-Adapter
    ML-Adapter
    Transfer
    API
    Transfer...
    Notification
    Event Handler
    Notification...
    fsp prepare
    fsp prep...
    1.3 Prepare Consume
    1.3 Prepare Consume
    notifications
    notificati...
    FSP1
    (Payer)

    FSP1...
    FSP2
    (Payee)
    FSP2...
    1.1
    Prepare Request
    1.1...
    1.2 Accpeted
    (202)
    1.2 Accpeted...
    Transfer
    API
    Transfer...
    2.0 Fulfil 
    Success / 
    Reject

    2...
    fulfils
    fulfils
    FulfilHandler
    FulfilHandler
    Success/
    Reject
    Success/...
    2.5 Decrement
    Position (fsp2)

    2.5 Decrement...
    2.1 Fulfil 
    Success / Reject

    2.1 Fulfil...
    2.2 OK
    (200)
    2.2 OK...
    2.3 Fulfil
    Success /
    Reject
    Consume
    2.3 Fulfil...
    OK (200)
    OK (200)
    OK (200)
    OK (200)
    Transfer Timeout
    Handler
    Transfer Timeout...
    <alt> 1.4 Prepare Failure
    <alt> 1.4 Prepare Failure
    <alt> 2.4 Fulfil Failure
    <alt>...
    2.7 Fulfil Notify Callback /
    <alt> 2.7 Reject Response (Fulfil reject) /
    3.1, 3.3 Reject Response (Timeout) /
    <alt> 1.7 Reject Response (Not enough position)
    <alt> 1.5 Prepare Failure 

    2.7 Fulfil Notify Callback /...
    1.7 Prepare Notify /
    2.8 Commit Notify (if transfer reserved) /
    <alt> 2.7 Reject Response (Fulfil reject)
    3.3 Reject Response (Timeout)
    <alt> 2.5 Fulfil Failure

    1.7 Prepare Notify /...
    position
    position
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.svg new file mode 100644 index 000000000..108afd9d1 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.svg @@ -0,0 +1,228 @@ + + 3.1.0 Get Participant Callback Details + + + 3.1.0 Get Participant Callback Details + + ML API Adapter Service + + Central Services + + + + + + + + + + + + + + + + + + + ML-API-ADAPTER + + + ML-API-ADAPTER + + + Central Service API + + + Central Service API + + + Participant Handler + + + Participant Handler + + + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + Get Callback Details + + + 1 + Request to get callback details - GET - /participants/{name}/endpoints?type={typeValue} + + + 2 + Fetch Callback details for Participant + + + 3 + Fetch Participant + Error code: + 3200 + + + 4 + Fetch Participant + + participant + + + 5 + Retrieved Participant + + + 6 + Return Participant + + + + + 7 + Validate DFSP + + + alt + [Validate participant (success)] + + + + + 8 + check if "type" parameter is sent + + + alt + [Check if "type" parameter is sent (Sent)] + + + 9 + Fetch Callback details for Participant and type + Error code: + 3000 + + + 10 + Fetch Callback details for Participant and type + + + Condition: + isActive = 1 + [endpointTypeId = <type>] + + participantEndpoint + + + 11 + Retrieved Callback details for Participant and type + + + 12 + Return Callback details for Participant and type + + + Message: + { + endpoints: {type: <type>, value: <value>} + } + + + 13 + Return Callback details for Participant + + + 14 + Return Callback details for Participant + + [Check if "type" parameter is sent (Not Sent)] + + + 15 + Fetch Callback details for Participant + Error code: + 3000 + + + 16 + Fetch Callback details for Participant + + + Condition: + isActive = 1 + + participantEndpoint + + + 17 + Retrieved Callback details for Participant + + + 18 + Return Callback details for Participant + + + Message: + { + endpoints: [ + {type: <type>, value: <value>}, + {type: <type>, value: <value>} + ] + } + + + 19 + Return Callback details for Participant + + + 20 + Return Callback details for Participant + + [Validate participant (failure)/ Error] + + + Validation failure/ Error! + + + Message: + { + "errorInformation": { + "errorCode": <errorCode>, + "errorDescription": <ErrorMessage>, + } + } + + + 21 + Return + Error code: + 3000, 3200 + + + 22 + Return + Error code: + 3000, 3200 + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.svg new file mode 100644 index 000000000..e214ffafe --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.svg @@ -0,0 +1,215 @@ + + 3.1.0 Add Participant Callback Details + + + 3.1.0 Add Participant Callback Details + + Central Services + + + + + + + + + + + + + + + + + HUB OPERATOR + + + HUB OPERATOR + + + Central Service API + + + Central Service API + + + Participant Handler + + + Participant Handler + + + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + Add Callback Details + + + 1 + Request to add callback details - POST - /paticipants/{name}/endpoints + + + Message: + { + payload: { + endpoint: { + type: <typeValue>, + value: <endpointValue> + } + } + } + + + 2 + Add Callback details for Participant + + + 3 + Fetch Participant + Error code: + 3200 + + + 4 + Fetch Participant + + participant + + + 5 + Retrieved Participant + + + 6 + Return Participant + + + + + 7 + Validate DFSP + + + alt + [Validate participant (success)] + + + 8 + Add Callback details for Participant + Error code: + 2003/ + Msg: + Service unavailable +   + Error code: + 2001/ + Msg: + Internal Server Error + + + 9 + Persist Participant Endpoint + + participantEndpoint + + + If (endpoint exists && isActive = 1) + oldEndpoint.isActive = 0 + insert endpoint + Else + insert endpoint + End +      + + + 10 + Return status + + + + + 11 + Validate status + + + alt + [Validate status (success)] + + + 12 + Return Status Code 201 + + + 13 + Return Status Code 201 + + [Validate status (failure) / Error] + + + Error! + + + Message: + { + "errorInformation": { + "errorCode": <Error Code>, + "errorDescription": <Msg>, + } + } + + + 14 + Return + Error code + + + 15 + Return + Error code + + [Validate participant (failure)] + + + Validation failure! + + + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "FSP id Not Found", + } + } + + + 16 + Return + Error code: + 3200 + + + 17 + Return + Error code: + 3200 + + diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.plantuml new file mode 100644 index 000000000..c24ae484b --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.plantuml @@ -0,0 +1,207 @@ +/' + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Valentin Genev + -------------- + '/ + + +@startuml +' declate title +title 2.1.0. DFSP2 sends a Fulfil Success Transfer request v1.1 + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "topic-fulfil" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +control "Settlement Model\nHandler" as SETMODEL_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_SETMODEL + participant SETMODEL_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate SETMODEL_HANDLER +activate POS_HANDLER +group DFSP2 sends a request for notification after tranfer is being committed in the Switch + DFSP2 <-> DFSP2: Retrieve fulfilment string generated during\nthe quoting process or regenerate it using\n**Local secret** and **ILP Packet** as inputs + alt Send back notification reserve request + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "fulfilment": , + "transferState": "RESERVED" + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + end note + else Send back commit request + + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "fulfilment": , + "completedTimestamp": , + "transferState": "COMMITTED" + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + end note + end + DFSP2 ->> MLAPI: PUT - /transfers/ + activate MLAPI + MLAPI -> MLAPI: Validate incoming token and originator matching Payee\nError codes: 3000-3002, 3100-3107 + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: reserve || commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Fulfil event for Payee\nError code: 2003 + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Success) {[[https://github.com/mojaloop/documentation/tree/master/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg 2.1.1-v1.1]]} \n + FULF_HANDLER -> TOPIC_SETMODEL: Produce message + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_SETMODEL <- SETMODEL_HANDLER: Consume message + ref over TOPIC_SETMODEL, SETMODEL_HANDLER: Settlement Model Handler Consume (Success)\n + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Success)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'commit' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'reserve' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +deactivate POS_HANDLER +deactivate FULF_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.svg new file mode 100644 index 000000000..63ae6110e --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.svg @@ -0,0 +1,342 @@ + + 2.1.0. DFSP2 sends a Fulfil Success Transfer request v1.1 + + + 2.1.0. DFSP2 sends a Fulfil Success Transfer request v1.1 + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + DFSP2 + Payee + + + DFSP2 + Payee + + + ML API Adapter + + + ML API Adapter + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + topic-fulfil + + + topic-fulfil + Fulfil Event Handler + + + Fulfil Event Handler + + + + + topic- + settlement-model + + + topic- + settlement-model + Settlement Model + Handler + + + Settlement Model + Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + Position Handler + + + Position Handler + + + + + topic- + notification + + + topic- + notification + + + + + + + + + DFSP2 sends a request for notification after tranfer is being committed in the Switch + + + + + + 1 + Retrieve fulfilment string generated during + the quoting process or regenerate it using + Local secret + and + ILP Packet + as inputs + + + alt + [Send back notification reserve request] + + + Headers - transferHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } +   + Payload - transferMessage: + { + "fulfilment": <IlpFulfilment>, + "transferState": "RESERVED" + "extensionList": { + "extension": [ + { + "key": <string>, + "value": <string> + } + ] + } + } + + [Send back commit request] + + + Headers - transferHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } +   + Payload - transferMessage: + { + "fulfilment": <IlpFulfilment>, + "completedTimestamp": <DateTime>, + "transferState": "COMMITTED" + "extensionList": { + "extension": [ + { + "key": <string>, + "value": <string> + } + ] + } + } + + + + 2 + PUT - /transfers/<ID> + + + + + 3 + Validate incoming token and originator matching Payee + Error codes: + 3000-3002, 3100-3107 + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + type: fulfil, + action: reserve || commit, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 4 + Route & Publish Fulfil event for Payee + Error code: + 2003 + + + + + + 5 + Ensure event is replicated as configured (ACKS=all) + Error code: + 2003 + + + 6 + Respond replication acknowledgements have been received + + + + 7 + Respond HTTP - 200 (OK) + + + 8 + Consume message + + + ref + Fulfil Handler Consume (Success) { + + 2.1.1-v1.1 + + } +   + + + 9 + Produce message + + + 10 + Produce message + + + 11 + Consume message + + + ref + Settlement Model Handler Consume (Success) +   + + + 12 + Consume message + + + ref + Position Handler Consume (Success) +   + + + 13 + Produce message + + + 14 + Consume message + + + opt + [action == 'commit'] + + + ref + Send notification to Participant (Payer) +   + + + 15 + Send callback notification + + + 16 + Consume message + + + opt + [action == 'reserve'] + + + ref + Send notification to Participant (Payee) +   + + + 17 + Send callback notification + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.svg new file mode 100644 index 000000000..abe0d547b --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.svg @@ -0,0 +1,307 @@ + + 2.1.0. DFSP2 sends a Fulfil Success Transfer request + + + 2.1.0. DFSP2 sends a Fulfil Success Transfer request + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + DFSP2 + Payee + + + DFSP2 + Payee + + + ML API Adapter + + + ML API Adapter + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + topic-fulfil + + + topic-fulfil + Fulfil Event Handler + + + Fulfil Event Handler + + + + + topic- + settlement-model + + + topic- + settlement-model + Settlement Model + Handler + + + Settlement Model + Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + Position Handler + + + Position Handler + + + + + topic- + notification + + + topic- + notification + + + + + + + + + DFSP2 sends a Fulfil Success Transfer request + + + + + + 1 + Retrieve fulfilment string generated during + the quoting process or regenerate it using + Local secret + and + ILP Packet + as inputs + + + Headers - transferHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } +   + Payload - transferMessage: + { + "fulfilment": <IlpFulfilment>, + "completedTimestamp": <DateTime>, + "transferState": "COMMITTED", + "extensionList": { + "extension": [ + { + "key": <string>, + "value": <string> + } + ] + } + } + + + + 2 + PUT - /transfers/<ID> + + + + + 3 + Validate incoming token and originator matching Payee + Error codes: + 3000-3002, 3100-3107 + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + type: fulfil, + action: commit, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 4 + Route & Publish Fulfil event for Payee + Error code: + 2003 + + + + + + 5 + Ensure event is replicated as configured (ACKS=all) + Error code: + 2003 + + + 6 + Respond replication acknowledgements have been received + + + + 7 + Respond HTTP - 200 (OK) + + + 8 + Consume message + + + ref + Fulfil Handler Consume (Success) { + + 2.1.1 + + } +   + + + 9 + Produce message + + + 10 + Produce message + + + 11 + Consume message + + + ref + Settlement Model Handler Consume (Success) +   + + + 12 + Consume message + + + ref + Position Handler Consume (Success) +   + + + 13 + Produce message + + + 14 + Consume message + + + opt + [action == 'commit'] + + + ref + Send notification to Participant (Payer) +   + + + 15 + Send callback notification + + + 16 + Consume message + + + opt + [action == 'commit'] + + + ref + Send notification to Participant (Payee) +   + + + 17 + Send callback notification + + diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.plantuml new file mode 100644 index 000000000..9f2523d6d --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.plantuml @@ -0,0 +1,273 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title 2.1.1. Fulfil Handler Consume (Success) v1.1 +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "topic-fulfil" as TOPIC_FULFIL +control "Fulfil Event\nHandler" as FULF_HANDLER +collections "topic-event" as TOPIC_EVENT +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +entity "Position DAO" as POS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_SETMODEL + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Success) + alt Consume Single Message + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type == 'fulfil' && action IN ['commit', 'reserve']\nError codes: 2001 + end + end + group Persist Event Information + ||| + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume\n + ||| + end + + group Validate Duplicate Check + ||| + FULF_HANDLER -> DB: Request Duplicate Check + ref over FULF_HANDLER, DB: Request Duplicate Check\n + DB --> FULF_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break + FULF_HANDLER -> FULF_HANDLER: stateRecord = await getTransferState(transferId) + alt endStateList.includes(stateRecord.transferStateId) + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: getTransfer callback\n + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else + note right of FULF_HANDLER #lightgrey + Ignore - resend in progress + end note + end + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of FULF_HANDLER #lightgrey + Validate Prepare Transfer (failure) - Modified Request + end note + else hasDuplicateId == FALSE + group Validate and persist Transfer Fulfilment + FULF_HANDLER -> POS_DAO: Request information for the validate checks\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch from database + activate DB + hnote over DB #lightyellow + transfer + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return transfer + deactivate POS_DAO + FULF_HANDLER ->FULF_HANDLER: Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment)\nError code: 2001 + FULF_HANDLER -> FULF_HANDLER: Validate expirationDate\nError code: 3303 + + opt Transfer.ilpCondition validate successful + group Request current Settlement Window + FULF_HANDLER -> POS_DAO: Request to retrieve current/latest transfer settlement window\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch settlementWindowId + activate DB + hnote over DB #lightyellow + settlementWindow + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return settlementWindowId to be appended during transferFulfilment insert\n**TODO**: During settlement design make sure transfers in 'RECEIVED-FULFIL'\nstate are updated to the next settlement window + deactivate POS_DAO + end + end + + group Persist fulfilment + FULF_HANDLER -> POS_DAO: Persist fulfilment with the result of the above check (transferFulfilment.isValid)\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferFulfilment + transferExtension + end note + FULF_HANDLER <-- POS_DAO: Return success + deactivate POS_DAO + end + + alt Transfer.ilpCondition validate successful + group Persist Transfer State (with transferState='RECEIVED-FULFIL') + FULF_HANDLER -> POS_DAO: Request to persist transfer state\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + POS_DAO --> FULF_HANDLER: Return success + deactivate POS_DAO + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: switch, + to: switch, + type: application/json + content: { + payload: { + transferId: {id} + } + }, + metadata: { + event: { + id: , + responseTo: , + type: setmodel, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_SETMODEL: Route & Publish settlement model event + activate TOPIC_SETMODEL + deactivate TOPIC_SETMODEL + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: commit || reserve, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Fulfil Transfer not successful + group Persist Transfer State (with transferState='ABORTED') + FULF_HANDLER -> POS_DAO: Request to persist transfer state\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + POS_DAO --> FULF_HANDLER: Return success + deactivate POS_DAO + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end + end + end + else Consume Batch Messages + note left of FULF_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate FULF_HANDLER +@enduml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg new file mode 100644 index 000000000..ad91cb1e3 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg @@ -0,0 +1,439 @@ + + 2.1.1. Fulfil Handler Consume (Success) v1.1 + + + 2.1.1. Fulfil Handler Consume (Success) v1.1 + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + topic-fulfil + + + topic-fulfil + Fulfil Event + Handler + + + Fulfil Event + Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + + + topic-event + + + topic-event + + + topic- + settlement-model + + + topic- + settlement-model + + + topic- + notification + + + topic- + notification + Position DAO + + + Position DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + Fulfil Handler Consume (Success) + + + alt + [Consume Single Message] + + + 1 + Consume Fulfil event message for Payer + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type == 'fulfil' && action IN ['commit', 'reserve'] + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + Validate Duplicate Check + + + 4 + Request Duplicate Check + + + ref + Request Duplicate Check +   + + + 5 + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + alt + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + break + + + + + 6 + stateRecord = await getTransferState(transferId) + + + alt + [endStateList.includes(stateRecord.transferStateId)] + + + ref + getTransfer callback +   + + + 7 + Produce message + + + + Ignore - resend in progress + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + Validate Prepare Transfer (failure) - Modified Request + + [hasDuplicateId == FALSE] + + + Validate and persist Transfer Fulfilment + + + 8 + Request information for the validate checks + Error code: + 2003 + + + 9 + Fetch from database + + transfer + + + 10 +   + + + 11 + Return transfer + + + + + 12 + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + Error code: + 2001 + + + + + 13 + Validate expirationDate + Error code: + 3303 + + + opt + [Transfer.ilpCondition validate successful] + + + Request current Settlement Window + + + 14 + Request to retrieve current/latest transfer settlement window + Error code: + 2003 + + + 15 + Fetch settlementWindowId + + settlementWindow + + + 16 +   + + + 17 + Return settlementWindowId to be appended during transferFulfilment insert + TODO + : During settlement design make sure transfers in 'RECEIVED-FULFIL' + state are updated to the next settlement window + + + Persist fulfilment + + + 18 + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + Error code: + 2003 + + + 19 + Persist to database + + transferFulfilment + transferExtension + + + 20 + Return success + + + alt + [Transfer.ilpCondition validate successful] + + + Persist Transfer State (with transferState='RECEIVED-FULFIL') + + + 21 + Request to persist transfer state + Error code: + 2003 + + + 22 + Persist transfer state + + transferStateChange + + + 23 + Return success + + + Message: + { + id: <id>, + from: switch, + to: switch, + type: application/json + content: { + payload: { + transferId: {id} + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: setmodel, + action: commit, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 24 + Route & Publish settlement model event + + + Message: + { + id: <id>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: commit || reserve, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 25 + Route & Publish Position event for Payee + + [Validate Fulfil Transfer not successful] + + + Persist Transfer State (with transferState='ABORTED') + + + 26 + Request to persist transfer state + Error code: + 2003 + + + 27 + Persist transfer state + + transferStateChange + + + 28 + Return success + + + Message: + { + id: <id>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: abort, + createdAt: <timestamp>, + state: { + status: "error", + code: 1 + } + } + } + } + + + 29 + Route & Publish Position event for Payer + + [Consume Batch Messages] + + + To be delivered by future story + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.svg new file mode 100644 index 000000000..aa745728d --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.svg @@ -0,0 +1,439 @@ + + 2.1.1. Fulfil Handler Consume (Success) + + + 2.1.1. Fulfil Handler Consume (Success) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + topic-fulfil + + + topic-fulfil + Fulfil Event + Handler + + + Fulfil Event + Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + + + topic-event + + + topic-event + + + topic- + settlement-model + + + topic- + settlement-model + + + topic- + notification + + + topic- + notification + Position DAO + + + Position DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + Fulfil Handler Consume (Success) + + + alt + [Consume Single Message] + + + 1 + Consume Fulfil event message for Payer + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type == 'fulfil' && action == 'commit' + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + Validate Duplicate Check + + + 4 + Request Duplicate Check + + + ref + Request Duplicate Check +   + + + 5 + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + alt + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + break + + + + + 6 + stateRecord = await getTransferState(transferId) + + + alt + [endStateList.includes(stateRecord.transferStateId)] + + + ref + getTransfer callback +   + + + 7 + Produce message + + + + Ignore - resend in progress + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + Validate Prepare Transfer (failure) - Modified Request + + [hasDuplicateId == FALSE] + + + Validate and persist Transfer Fulfilment + + + 8 + Request information for the validate checks + Error code: + 2003 + + + 9 + Fetch from database + + transfer + + + 10 +   + + + 11 + Return transfer + + + + + 12 + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + Error code: + 2001 + + + + + 13 + Validate expirationDate + Error code: + 3303 + + + opt + [Transfer.ilpCondition validate successful] + + + Request current Settlement Window + + + 14 + Request to retrieve current/latest transfer settlement window + Error code: + 2003 + + + 15 + Fetch settlementWindowId + + settlementWindow + + + 16 +   + + + 17 + Return settlementWindowId to be appended during transferFulfilment insert + TODO + : During settlement design make sure transfers in 'RECEIVED-FULFIL' + state are updated to the next settlement window + + + Persist fulfilment + + + 18 + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + Error code: + 2003 + + + 19 + Persist to database + + transferFulfilment + transferExtension + + + 20 + Return success + + + alt + [Transfer.ilpCondition validate successful] + + + Persist Transfer State (with transferState='RECEIVED-FULFIL') + + + 21 + Request to persist transfer state + Error code: + 2003 + + + 22 + Persist transfer state + + transferStateChange + + + 23 + Return success + + + Message: + { + id: <id>, + from: switch, + to: switch, + type: application/json + content: { + payload: { + transferId: {id} + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: setmodel, + action: commit, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 24 + Route & Publish settlement model event + + + Message: + { + id: <id>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: commit, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 25 + Route & Publish Position event for Payee + + [Validate Fulfil Transfer not successful] + + + Persist Transfer State (with transferState='ABORTED') + + + 26 + Request to persist transfer state + Error code: + 2003 + + + 27 + Persist transfer state + + transferStateChange + + + 28 + Return success + + + Message: + { + id: <id>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: abort, + createdAt: <timestamp>, + state: { + status: "error", + code: 1 + } + } + } + } + + + 29 + Route & Publish Position event for Payer + + [Consume Batch Messages] + + + To be delivered by future story + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.svg new file mode 100644 index 000000000..1e1d53096 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.svg @@ -0,0 +1,127 @@ + + 1.0.0 Get Participant Limit Details For All Participants + + + 1.0.0 Get Participant Limit Details For All Participants + + Central Services + + + + + + + + + + + + HUB OPERATOR + + + HUB OPERATOR + + + Central Service API + + + Central Service API + + + Participant Handler + + + Participant Handler + + + Participant Facade + + + Participant Facade + + + Central Store + + + Central Store + + + + + + + + + + Get Limits for all Participants + + + 1 + Request to get Limits - GET - /participants/limits?type={typeValue}&currency={currencyType} + + + 2 + Fetch Limits for all Participants + + + 3 + Fetch Limits for all participants with currency and type + Error code: + 3000 + + + 4 + Fetch Limits for currencyId and type(if passed) + + + Condition: + participantCurrency.participantCurrencyId = participant.participantCurrencyId + participantLimit.isActive = 1 + participantLimit.participantCurrencyId = participantCurrency.participantCurrencyId + [ + participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + participantLimit.participantCurrencyId = <currencyId> + participantLimitType.name = <type> + ] + + participant + participantCurrency + participantLimit + participantLimitType + + + 5 + Retrieved Participant Limits for currencyId and type + + + 6 + Return Limits for all participants + + + Message: + [ + { + name: <fsp> + currency: <currencyId>, + limit: {type: <type>, value: <value>} + }, + { + name: <fsp> + currency: <currencyId>, + limit: {type: <type>, value: <value>} + } + ] + + + 7 + Return Limits for all participants + Error code: + 3000 + + + 8 + Return Limits for all participants + Error code: + 3000 + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.svg new file mode 100644 index 000000000..053316d82 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.svg @@ -0,0 +1,174 @@ + + 1.0.0 Get Health Check + + + 1.0.0 Get Health Check + + Central Services + + + + + + + + + + + + + + + + HUB OPERATOR + + + HUB OPERATOR + + + Central Service API + + + Central Service API + + + Metadata Handler + + + Metadata Handler + + + Central Store + + + Central Store + + + + + Kafka Store + + + Kafka Store + + + Logging Sidecar + + + Logging Sidecar + + + + + + + + + Get Detailed Health Check + + + 1 + Request to getHealth - GET /health?detailed=true + + + 2 + Fetch health status for all sub services + + + + + 3 + Fetch Service Metadata + + + - versionNumber + - uptime + - time service started + + + 4 + Check connection status + + + 5 + Report connection status + + + 6 + Check connection status + + + 7 + Report connection status + + + 8 + Check connection status + + + 9 + Report connection status + + + alt + [Validate Status (success)] + + + 10 + Return status response + + + Example Message: + 200 Success + { + "status": "UP", + "uptime": 1234, + "started": "2019-05-31T05:09:25.409Z", + "versionNumber": "5.2.3", + "services": [ + { + "name": "kafka", + "status": "UP", + "latency": 10 + } + ] + } + + + 11 + Return + HTTP Status: + 200 + + + alt + [Validate Status (service failure)] + + + 12 + Return status response + + + Example Message: + 502 Bad Gateway + { + "status": "DOWN", + "uptime": 1234, + "started": "2019-05-31T05:09:25.409Z", + "versionNumber": "5.2.3", + "services": [ + { + "name": "kafka", + "status": "DOWN", + "latency": 1111111 + } + ] + } + + + 13 + Return + HTTP Status: + 502 + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.svg new file mode 100644 index 000000000..acbd9b098 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.svg @@ -0,0 +1,306 @@ + + 1.1.0 Request Participant Position and Limit Details + + + 1.1.0 Request Participant Position and Limit Details + + Central Services + + + + + + + + + + + + + + + + + + + + + + + + + HUB OPERATOR + + + HUB OPERATOR + + + Central Service API + + + Central Service API + + + Participant Handler + + + Participant Handler + + + Participant Facade + + + Participant Facade + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + Get Callback Details + + + 1 + Request to get Limits - GET - /participants/{name}/limits?type={typeValue}&currency={currencyValue} + + + 2 + Fetch Limits for Participant + + + + + 3 + check if "currency" parameter is sent + + + alt + [Check if "currency" parameter is sent (Sent)] + + + 4 + Fetch Participant/currency id + Error code: + 3200 + + + 5 + Fetch Participant/currency id + + participant + participantCurrency + + + 6 + Retrieved Participant + + + 7 + Return Participant/currency id + + + + + 8 + Validate DFSP + + + alt + [Validate participant (success)] + + + 9 + Fetch Participant Limits for currency and type + Error code: + 3000 + + + 10 + Fetch Participant Limit for currencyId and type(if passed) + + + Condition: + participantLimit.isActive = 1 + participantLimit.participantCurrencyId = <currencyId> + [ participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + participantLimitType.name = <type> + ] + + participantLimit + participantLimitType + + + 11 + Retrieved Participant Limits for currencyId and type + + + 12 + Return Participant Limits for currencyId and type + + + Message: + [ + { currency: <currencyId>, + limit: {type: <type>, value: <value>} + } + ] + + + 13 + Return Participant Limits + + + 14 + Return Participant Limits + + [Validate participant (failure)/ Error] + + + Validation failure/ Error! + + + Message: + { + "errorInformation": { + "errorCode": <errorCode>, + "errorDescription": <ErrorMessage>, + } + } + + + 15 + Return + Error code: + 3000, 3200 + + + 16 + Return + Error code: + 3000, 3200 + + [Check if "currency" parameter is sent (Not Sent)] + + + 17 + Fetch Participant + Error code: + 3200 + + + 18 + Fetch Participant + + participant + + + 19 + Retrieved Participant + + + 20 + Return Participant + + + + + 21 + Validate DFSP + + + alt + [Validate participant (success)] + + + 22 + Fetch Participant Limits for all currencies and type + Error code: + 3000 + + + 23 + Fetch Participant Limit for all currencies and type(if passed) + + + Condition: + participantCurrency.participantId = <participantId> + participantLimit.participantCurrencyId = participantCurrency.participantCurrencyId + participantLimit.isActive = 1 + [ participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + participantLimitType.name = <type> + ] + + participantCurrency + participantLimit + participantLimitType + + + 24 + Retrieved Participant Limits for all currencies and type + + + 25 + Return Participant Limits for all currencies and type + + + Message: + [ + { currency: <currencyId>, + limit: {type: <type>, value: <value>} + } + ] + + + 26 + Return Participant Limits + + + 27 + Return Participant Limits + + [Validate participant (failure)/ Error] + + + Validation failure/ Error! + + + Message: + { + "errorInformation": { + "errorCode": <errorCode>, + "errorDescription": <ErrorMessage>, + } + } + + + 28 + Return + Error code: + 3000, 3200 + + + 29 + Return + Error code: + 3000, 3200 + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.svg new file mode 100644 index 000000000..801226ab8 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.svg @@ -0,0 +1,208 @@ + + 1.1.5. Request transfer status (getTransferStatusById) - Phase2 version + + + 1.1.5. Request transfer status (getTransferStatusById) - Phase2 version + + Financial Service Provider + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + DFSP(n) + Participant + + + DFSP(n) + Participant + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + Event-Topic + + + Event-Topic + Transfer-DAO + + + Transfer-DAO + + + Central Store + + + Central Store + + + + + + + + + + + Request transfer status + + + 1 + Callback transfer status request URL - GET - /transfers/{ID} + + + Persist Event Information + + + 2 + Request transfer information - GET - /transfers/{ID} + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + 4 + Return success + + + 5 + Return success + + + 6 + Respond HTTP - 200 (OK) + + + 7 + Request details for Transfer - GET - /transfers/{ID} + Error code: + 2003 + + + 8 + Request transfer status + Error code: + 2003 + + + 9 + Fetch transfer status + + SELECT transferId, transferStateId + FROM + transferStateChange + WHERE transferId = {ID} + ORDER BY transferStateChangeId desc limit 1 + + + 10 + Return transfer status + + + 11 + Return transfer status + Error codes: + 3202, 3203 + + + alt + [Is there a transfer with the given ID recorded in the system?] + + + alt + [Yes AND transferState is COMMITTED + This implies that a succesful transfer with the given ID is recorded in the system] + + + { + "fulfilment": "WLctttbu2HvTsa1XWvUoGRcQozHsqeu9Ahl2JW9Bsu8", + "completedTimestamp": "2018-09-24T08:38:08.699-04:00", + "transferState": "COMMITTED", + extensionList: + { + extension: + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + + + 12 + callback PUT on /transfers/{ID} + + [transferState in [RECEIVED, RESERVED, ABORTED]] + + + { + "transferState": "RECEIVED", + extensionList: + { + extension: + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + + + 13 + callback PUT on /transfers/{ID} + + + Log ERROR event + + [A transfer with the given ID is not present in the System or this is an invalid request] + + + { + "errorInformation": { + "errorCode": <integer>, + "errorDescription": "Client error description" + } + } + + + 14 + callback PUT on /transfers/{ID}/error + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.svg new file mode 100644 index 000000000..7ed0d712a --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.svg @@ -0,0 +1,243 @@ + + 1.1.0 Manage Participant Limits + + + 1.1.0 Manage Participant Limits + + Central Services + + + + + + + + + + + + + + + + + + + HUB OPERATOR + + + HUB OPERATOR + + + Central Service API + + + Central Service API + + + Participant Handler + + + Participant Handler + + + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + Manage Net Debit Cap + + + 1 + Request to adjust Participant Limit for a certain Currency - POST - /participants/{name}/limits + + + Message: + { + payload: { + currency: <string>, + limit: { + type: <string>, + value: <Id> + } + } + } + + + 2 + Adjust Limit for Participant + + + 3 + Fetch Participant/currency + Error code: + 3200 + + + 4 + Fetch Participant/currency + + participant + participantCurrency + + + 5 + Retrieved Participant/currency + + + 6 + Return Participant/currency + + + + + 7 + Validate DFSP + + + alt + [Validate participant (success)] + + + 8 + (for ParticipantCurrency) Fetch ParticipantLimit + Error code: + 3200 + + + 9 + Fetch ParticipantLimit + + participantLimit + + + 10 + Retrieved ParticipantLimit + + + 11 + Return ParticipantLimit + + + + + 12 + Validate ParticipantLimit + + + alt + [Validate participantLimit (success)] + + + DB TRANSACTION IMPLEMENTATION - Lock on ParticipantLimit table with UPDATE + + + If (record exists && isActive = 1) + oldIsActive.isActive = 0 + insert Record + Else + insert Record + End +   + + + 13 + (for ParticipantLimit) Insert new ParticipantLimit + Error code: + 3200 + + + 14 + Insert ParticipantLimit + + participantLimit + + + 15 + Inserted ParticipantLimit + + + 16 + Return ParticipantLimit + + [Validate participantLimit (failure)] + + + Validation failure! + + + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "ParticipantLimit Not Found", + } + } + + + 17 + Return new Limit values and status 200 + + + Message: + { + "currency": "EUR", + "limit": { + "participantLimitId": <number>, + "participantLimitTypeId": <number>, + "type": <string>, + "value": <string>, + "isActive": 1 + } + } + + + 18 + Return new Limit values and status 200 + + [Validate participant (failure)] + + + Validation failure! + + + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "FSP id Not Found", + } + } + + + 19 + Return + Error code: + 3200 + + + 20 + Return + Error code: + 3200 + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.svg new file mode 100644 index 000000000..2b4da73f4 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.svg @@ -0,0 +1,283 @@ + + 1.0.0 Create initial position and limits for Participant + + + 1.0.0 Create initial position and limits for Participant + + Central Services + + + + + + + + + + + + + + + + + + + + + + HUB OPERATOR + + + HUB OPERATOR + + + Central Service API + + + Central Service API + + + Participant Handler + + + Participant Handler + + + Participant FACADE + + + Participant FACADE + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + Create initial position and limits + + + 1 + Request to Create initial position and limits - POST - /paticipants/{name}/initialPositionAndLimits + + + Message: + { + currency: <currencyId>, + limit: { + type: <limitType>, + value: <limitValue> + }, + initialPosition: <positionValue> + } + + + 2 + Create initial position and limits for Participant + + + 3 + Fetch Participant/ Currency Id + Error code: + 3200 + + + 4 + Fetch Participant/Currency Id + + participant + participantCurrency + + + 5 + Retrieved Participant/Currency Id + + + 6 + Return Participant/Currency Id + + + + + 7 + Validate DFSP + + + alt + [Validate participant (success)] + + + 8 + Fetch limit for participantCurrencyId + + + 9 + Fetch limit for participantCurrencyId + + participantLimit + + + 10 + Retrieved participant limit + + + 11 + Return participant limit + + + 12 + Fetch position for participantCurrencyId + + + 13 + Fetch position for participantCurrencyId + + participantPosition + + + 14 + Retrieved participant position + + + 15 + Return participant position + + + + + 16 + Participant position or limit exists check + + + alt + [position or limit does not exist (success)] + + + 17 + create initial position and limits for Participantt + Error code: + 2003/ + Msg: + Service unavailable +   + Error code: + 2001/ + Msg: + Internal Server Error + + + 18 + Persist Participant limits/position + + participantPosition + participantLimit + + + 19 + Return status + + + alt + [Details persisted successfully] + + + 20 + Return Status Code 201 + + + 21 + Return Status Code 201 + + [Details not persisted/Error] + + + Error! + + + Message: + { + "errorInformation": { + "errorCode": <Error Code>, + "errorDescription": <Msg>, + } + } + + + 22 + Return + Error code + + + 23 + Return + Error code + + [position or limit exists (failure)] + + + Error! + + + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "Participant Limit or Initial Position already set", + } + } + + + 24 + Return + Error code: + 3200 + + + 25 + Return + Error code: + 3200 + + [Validate participant (failure)] + + + Validation failure! + + + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "FSP id Not Found", + } + } + + + 26 + Return + Error code: + 3200 + + + 27 + Return + Error code: + 3200 + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.svg new file mode 100644 index 000000000..effa45552 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.svg @@ -0,0 +1,240 @@ + + 4.1.0 Get Participant Position Details + + + 4.1.0 Get Participant Position Details + + HUB Operator + + Central Service + + + + + + + + + + + + + + + + + + + HUB OPERATOR + + + HUB OPERATOR + + + Central Service API + + + Central Service API + + + Participant Handler + + + Participant Handler + + + Participant DAO + + + Participant DAO + + + Position Facade + + + Position Facade + + + Central Store + + + Central Store + + + + + + + + + + + + + + Get Position Details + + + 1 + Request to get positions - GET - /participants/{name}/positions?currency={currencyId} + + + 2 + Fetch Positions for Participant + + + 3 + Fetch Participant + Error code: + 2003,3201 + + + 4 + Fetch Participant + + participant + + + 5 + Retrieved Participant + + + 6 + Return Participant + + + + + 7 + Validate DFSP + Error code: + 3201 + + + alt + [Validate participant (success)] + + + + + 8 + currency parameter passed ? + + + alt + [currency parameter passed] + + + 9 + Fetch Participant position for a currency id + Error code: + 2003 + + + 10 + Fetch Participant position for a currency id + + participantCurrency + participantPosition + + + 11 + Retrieved Participant position for a currency id + + + 12 + Return Positions for Participant + + + Message: + { + { + currency: <currencyId>, + value: <positionValue>, + updatedTime: <timeStamp1> + } + } + + + 13 + Return Participant position for a currency id + + + 14 + Return Participant position for a currency id + + [currency parameter not passed] + + + 15 + Fetch Participant Positions for all currencies + Error code: + 2003 + + + 16 + Fetch Participant Positions for all currencies + + participantCurrency + participantPosition + + + 17 + Retrieved Participant Positions for all currencies + + + 18 + Return Participant Positions for all currencies + + + Message: + { + [ + { + currency: <currencyId1>, + value: <positionValue1>, + updatedTime: <timeStamp1> + }, + { + currency: <currencyId2>, + value: <positionValue2>, + updatedTime: <timeStamp2> + } + ] + } + + + 19 + Return Participant Positions for all currencies + + + 20 + Return Participant Positions for all currencies + + [Validate participant (failure)] + + + Validation failure! + + + Message: + { + "errorInformation": { + "errorCode": 3201, + "errorDescription": "FSP id does not exist or not found", + } + } + + + 21 + Return + Error code: + 3201 + + + 22 + Return + Error code: + 3201 + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.svg new file mode 100644 index 000000000..fc37d05c6 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.svg @@ -0,0 +1,153 @@ + + 4.2.0 Get Positions of all Participants + + + 4.2.0 Get Positions of all Participants + + ML API Adapter Service + + Central Service + + + + + + + + + + + + ML-API-ADAPTER + + + ML-API-ADAPTER + + + Central Service API + + + Central Service API + + + Participant Handler + + + Participant Handler + + + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + + + + + + + + Get Position Details + + + 1 + Request to get positions - GET - /participants/positions + + + 2 + Fetch Positions for all Participants + + + 3 + Fetch Positions for all active Participants + Error code: + 2003,3200 + + + 4 + Fetch Positions for: + all active Participants + with all active Currencies for each Participant + + participant + participantPosition + participantCurrency + + + 5 + Retrieved Positions for Participants + + + 6 + Return Positions for Participants + + + Message: + { + snapshotAt: <timestamp0>, + positions: + [ + { + participantId: <dfsp1>, + participantPositions: + [ + { + currentPosition: { + currency: <currency1>, + value: <amount1>, + reservedValue: <amount2>, + lastUpdated: <timeStamp1> + } + }, + { + currentPosition: { + currency: <currency2>, + value: <amount3>, + reservedValue: <amount4>, + lastUpdated: <timeStamp2> + } + } + ] + }, + { + participantId: <dfsp2>, + participantPositions: + [ + { + currentPosition: { + currency: <currency1>, + value: <amount1>, + reservedValue: <amount2>, + lastUpdated: <timeStamp1> + } + }, + { + currentPosition: { + currency: <currency2>, + value: <amount3>, + reservedValue: <amount4>, + lastUpdated: <timeStamp2> + } + } + ] + } + ] + } + + + 7 + Return Positions for Participants + + + 8 + Return Positions for Participants + + diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.plantuml new file mode 100644 index 000000000..04d4356c9 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.plantuml @@ -0,0 +1,116 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title 1.3.0. Position Handler Consume (single message) v1.1 + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + alt Consume Prepare message for Payer + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'prepare'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Prepare Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Fulfil message for Payee + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action IN ['commit', 'reserve']\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Fulfil Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Abort message + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' &&\naction IN ['timeout-reserved', 'reject', 'fail']\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Abort Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + end + +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.svg new file mode 100644 index 000000000..d1915c8b0 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.svg @@ -0,0 +1,188 @@ + + 1.3.0. Position Handler Consume (single message) v1.1 + + + 1.3.0. Position Handler Consume (single message) v1.1 + + Central Service + + + + + + + + + + + + + + + + + + + + + + topic-transfer-position + + + topic-transfer-position + Position Handler + + + Position Handler + + + + + Event-Topic + + + Event-Topic + + + Notification-Topic + + + Notification-Topic + + + + + + + Position Handler Consume + + + alt + [Consume Prepare message for Payer] + + + 1 + Consume Position event message for Payer + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type == 'position' && action == 'prepare' + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + ref + Prepare Position Handler Consume +   + + + 4 + Produce message + + [Consume Fulfil message for Payee] + + + 5 + Consume Position event message for Payee + + + break + + + Validate Event + + + + + + 6 + Validate event - Rule: type == 'position' && action IN ['commit', 'reserve'] + Error codes: + 2001 + + + Persist Event Information + + + 7 + Publish event information + + + ref + Event Handler Consume +   + + + ref + Fulfil Position Handler Consume +   + + + 8 + Produce message + + [Consume Abort message] + + + 9 + Consume Position event message + + + break + + + Validate Event + + + + + + 10 + Validate event - Rule: type == 'position' && + action IN ['timeout-reserved', 'reject', 'fail'] + Error codes: + 2001 + + + Persist Event Information + + + 11 + Publish event information + + + ref + Event Handler Consume +   + + + ref + Abort Position Handler Consume +   + + + 12 + Produce message + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.svg new file mode 100644 index 000000000..295295eda --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.svg @@ -0,0 +1,188 @@ + + 1.3.0. Position Handler Consume (single message) + + + 1.3.0. Position Handler Consume (single message) + + Central Service + + + + + + + + + + + + + + + + + + + + + + topic-transfer-position + + + topic-transfer-position + Position Handler + + + Position Handler + + + + + Event-Topic + + + Event-Topic + + + Notification-Topic + + + Notification-Topic + + + + + + + Position Handler Consume + + + alt + [Consume Prepare message for Payer] + + + 1 + Consume Position event message for Payer + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type == 'position' && action == 'prepare' + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + ref + Prepare Position Handler Consume +   + + + 4 + Produce message + + [Consume Fulfil message for Payee] + + + 5 + Consume Position event message for Payee + + + break + + + Validate Event + + + + + + 6 + Validate event - Rule: type == 'position' && action == 'commit' + Error codes: + 2001 + + + Persist Event Information + + + 7 + Publish event information + + + ref + Event Handler Consume +   + + + ref + Fulfil Position Handler Consume +   + + + 8 + Produce message + + [Consume Abort message] + + + 9 + Consume Position event message + + + break + + + Validate Event + + + + + + 10 + Validate event - Rule: type == 'position' && + action IN ['timeout-reserved', 'reject', 'fail'] + Error codes: + 2001 + + + Persist Event Information + + + 11 + Publish event information + + + ref + Event Handler Consume +   + + + ref + Abort Position Handler Consume +   + + + 12 + Produce message + + diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml new file mode 100644 index 000000000..2e420c3b3 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml @@ -0,0 +1,283 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.3.1. Prepare Position Handler Consume + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER + +entity "Position\nManagement\nFacade" as POS_MGMT +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant POS_MGMT + participant POS_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Prepare Position Handler Consume + POS_HANDLER -> POS_MGMT: Request transfers to be processed + activate POS_MGMT + POS_MGMT -> POS_MGMT: Check 1st transfer to select the Participant and Currency + group DB TRANSACTION + ' DB Trans: This is where 1st DB Transaction would start in 2 DB transacation future model for horizontal scaling + POS_MGMT -> POS_MGMT: Loop through batch and build list of transferIds and calculate sumTransfersInBatch,\nchecking all in Batch are for the correct Paricipant and Currency\nError code: 2001, 3100 + POS_MGMT -> DB: Retrieve current state of all transfers in array from DB with select whereIn\n(FYI: The two DB transaction model needs to add a mini-state step here (RECEIVED_PREPARE => RECEIVDED_PREPARE_PROCESSING) so that the transfers are left alone if processing has started) + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_MGMT: Return current state of all selected transfers from DB + deactivate DB + POS_MGMT <-> POS_MGMT: Validate current state (transferStateChange.transferStateId == 'RECEIVED_PREPARE')\nError code: 2001 against failing transfers\nBatch is not rejected as a whole. + + note right of POS_MGMT #lightgray + List of transfers used during processing + **reservedTransfers** is list of transfers to be processed in the batch + **abortedTransfers** is the list of transfers in the incorrect state going into the process. Currently the transferStateChange is set to ABORTED - this should only be done if not already in a final state (idempotency) + **processedTransfers** is the list of transfers that have gone through the position management algorithm. Both successful and failed trasnfers appear here as the order and "running position" against each is necessary for reconciliation + + Scalar intermidate values used in the algorithm + **transferAmount** = payload.amount.amount + **sumTransfersInBatch** = SUM amount against each Transfer in batch + **currentPosition** = participantPosition.value + **reservedPosition** = participantPosition.{original}reservedValue + **effectivePosition** = currentPosition + reservedPosition + **heldPosition** = effectivePosition + sumTransfersInBatch + **availablePosition** = //if settlement model delay is IMMEDIATE then:// settlementBalance + participantLimit(NetDebitCap) - effectivePosition, //otherwise:// participantLimit(NetDebitCap) - effectivePosition + **sumReserved** = SUM of transfers that have met rule criteria and processed + end note + note over POS_MGMT,DB + Going to reserve the sum of the valid transfers in the batch against the Participants Positon in the Currency of this batch + and calculate the available position for the Participant to use + end note + POS_MGMT -> DB: Select effectivePosition FOR UPDATE from DB for Payer + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_MGMT: Return effectivePosition (currentPosition and reservedPosition) from DB for Payer + deactivate DB + POS_MGMT -> POS_MGMT: Increment reservedValue to heldPosition\n(reservedValue = reservedPosition + sumTransfersInBatch) + POS_MGMT -> DB: Persist reservedValue + activate DB + hnote over DB #lightyellow + UPDATE **participantPosition** + SET reservedValue += sumTransfersInBatch + end note + deactivate DB + ' DB Trans: This is where 1st DB Transaction would end in 2 DB transacation future model for horizontal scaling + + + POS_MGMT -> DB: Request position limits for Payer Participant + activate DB + hnote over DB #lightyellow + FROM **participantLimit** + WHERE participantLimit.limitTypeId = 'NET-DEBIT-CAP' + AND participantLimit.participantId = payload.payerFsp + AND participantLimit.currencyId = payload.amount.currency + end note + DB --> POS_MGMT: Return position limits + deactivate DB + POS_MGMT <-> POS_MGMT: **availablePosition** = //if settlement model delay is IMMEDIATE then://\n settlementBalance + participantLimit(NetDebitCap) - effectivePosition\n //otherwise://\n participantLimit(NetDebitCap) - effectivePosition\n(same as = (settlementBalance?) + netDebitCap - currentPosition - reservedPosition) + note over POS_MGMT,DB + For each transfer in the batch, validate the availablility of position to meet the transfer amount + this will be as per the position algorithm documented below + end note + POS_MGMT <-> POS_MGMT: Validate availablePosition for each tranfser (see algorithm below)\nError code: 4001 + note right of POS_MGMT #lightgray + 01: sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED + 02: sumProcessed =0 // Record the sum of the transfers already processed in this batch + 03: processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position + 04: foreach transfer in reservedTransfers + 05: sumProcessed += transfer.amount // the total processed so far **(NEED TO UPDATE IN CODE)** + 06: if availablePosition >= transfer.amount + 07: transfer.state = "RESERVED" + 08: availablePosition -= preparedTransfer.amount + 09: sumRESERVED += preparedTransfer.amount + 10: else + 11: preparedTransfer.state = "ABORTED" + 12: preparedTransfer.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + 13: end if + 14: runningPosition = currentPosition + sumReserved // the initial value of the Participants position plus the total value that has been accepted in the batch so far + 15: runningReservedValue = sumTransfersInBatch - sumProcessed + reservedPosition **(NEED TO UPDATE IN CODE)** // the running down of the total reserved value at the begining of the batch. + 16: Add transfer to the processedTransfer list recording the transfer state and running position and reserved values { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue } + 16: end foreach + end note + note over POS_MGMT,DB + Once the outcome for all transfers is known,update the Participant's position and remove the reserved amount associated with the batch + (If there are any alarm limits, process those returning limits in which the threshold has been breached) + Do a bulk insert of the trasnferStateChanges associated with processing, using the result to complete the participantPositionChange and bulk insert of these to persist the running position + end note + POS_MGMT->POS_MGMT: Assess any limit thresholds on the final position\nadding to alarm list if triggered + + ' DB Trans: This is where 2nd DB Transaction would start in 2 DB transacation future model for horizontal scaling + POS_MGMT->DB: Persist latest position **value** and **reservedValue** to DB for Payer + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value += sumRESERVED, + reservedValue -= sumTransfersInBatch + end note + activate DB + deactivate DB + + POS_MGMT -> DB: Bulk persist transferStateChange for all processedTransfers + hnote over DB #lightyellow + batch INSERT **transferStateChange** + select for update from transfer table where transferId in ([transferBatch.transferId,...]) + build list of transferStateChanges from transferBatch + + end note + activate DB + deactivate DB + + POS_MGMT->POS_MGMT: Populate batchParticipantPositionChange from the resultant transferStateChange and the earlier processedTransfer list + + note right of POS_MGMT #lightgray + Effectively: + SET transferStateChangeId = processedTransfer.transferStateChangeId, + participantPositionId = preparedTransfer.participantPositionId, + value = preparedTransfer.positionValue, + reservedValue = preparedTransfer.positionReservedValue + end note + POS_MGMT -> DB: Bulk persist the participant position change for all processedTransfers + hnote over DB #lightyellow + batch INSERT **participantPositionChange** + end note + activate DB + deactivate DB + ' DB Trans: This is where 2nd DB Transaction would end in 2 DB transacation future model for horizontal scaling + end + POS_MGMT --> POS_HANDLER: Return a map of transferIds and their transferStateChanges + deactivate POS_MGMT + alt Calculate & Validate Latest Position Prepare (success) + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else Calculate & Validate Latest Position Prepare (failure) + note right of POS_HANDLER #red: Validation failure! + + group Persist Transfer State (with transferState='ABORTED' on position check fail) + POS_HANDLER -> POS_DAO: Request to persist transfer\nError code: 2003 + activate POS_DAO + note right of POS_HANDLER #lightgray + transferStateChange.state = "ABORTED", + transferStateChange.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + end note + POS_DAO -> DB: Persist transfer state + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: prepare, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + deactivate POS_HANDLER + end +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.svg new file mode 100644 index 000000000..83f1209b8 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.svg @@ -0,0 +1,410 @@ + + 1.3.1. Prepare Position Handler Consume + + + 1.3.1. Prepare Position Handler Consume + + Central Service + + + + + + + + + + + + + + + + + + + + + + + Position Handler + + + Position Handler + + + + + Notification-Topic + + + Notification-Topic + Position + Management + Facade + + + Position + Management + Facade + + + Position DAO + + + Position DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + Prepare Position Handler Consume + + + 1 + Request transfers to be processed + + + + + 2 + Check 1st transfer to select the Participant and Currency + + + DB TRANSACTION + + + + + 3 + Loop through batch and build list of transferIds and calculate sumTransfersInBatch, + checking all in Batch are for the correct Paricipant and Currency + Error code: + 2001, 3100 + + + 4 + Retrieve current state of all transfers in array from DB with select whereIn + (FYI: The two DB transaction model needs to add a mini-state step here (RECEIVED_PREPARE => RECEIVDED_PREPARE_PROCESSING) so that the transfers are left alone if processing has started) + + transferStateChange + transferParticipant + + + 5 + Return current state of all selected transfers from DB + + + + + + 6 + Validate current state (transferStateChange.transferStateId == 'RECEIVED_PREPARE') + Error code: + 2001 + against failing transfers + Batch is not rejected as a whole. + + + List of transfers used during processing + reservedTransfers + is list of transfers to be processed in the batch + abortedTransfers + is the list of transfers in the incorrect state going into the process. Currently the transferStateChange is set to ABORTED - this should only be done if not already in a final state (idempotency) + processedTransfers + is the list of transfers that have gone through the position management algorithm. Both successful and failed trasnfers appear here as the order and "running position" against each is necessary for reconciliation +   + Scalar intermidate values used in the algorithm + transferAmount + = payload.amount.amount + sumTransfersInBatch + = SUM amount against each Transfer in batch + currentPosition + = participantPosition.value + reservedPosition + = participantPosition.{original}reservedValue + effectivePosition + = currentPosition + reservedPosition + heldPosition + = effectivePosition + sumTransfersInBatch + availablePosition + = + if settlement model delay is IMMEDIATE then: + settlementBalance + participantLimit(NetDebitCap) - effectivePosition, + otherwise: + participantLimit(NetDebitCap) - effectivePosition + sumReserved + = SUM of transfers that have met rule criteria and processed + + + Going to reserve the sum of the valid transfers in the batch against the Participants Positon in the Currency of this batch + and calculate the available position for the Participant to use + + + 7 + Select effectivePosition FOR UPDATE from DB for Payer + + participantPosition + + + 8 + Return effectivePosition (currentPosition and reservedPosition) from DB for Payer + + + + + 9 + Increment reservedValue to heldPosition + (reservedValue = reservedPosition + sumTransfersInBatch) + + + 10 + Persist reservedValue + + UPDATE + participantPosition + SET reservedValue += sumTransfersInBatch + + + 11 + Request position limits for Payer Participant + + FROM + participantLimit + WHERE participantLimit.limitTypeId = 'NET-DEBIT-CAP' + AND participantLimit.participantId = payload.payerFsp + AND participantLimit.currencyId = payload.amount.currency + + + 12 + Return position limits + + + + + + 13 + availablePosition + = + if settlement model delay is IMMEDIATE then: + settlementBalance + participantLimit(NetDebitCap) - effectivePosition +   + otherwise: + participantLimit(NetDebitCap) - effectivePosition + (same as = (settlementBalance?) + netDebitCap - currentPosition - reservedPosition) + + + For each transfer in the batch, validate the availablility of position to meet the transfer amount + this will be as per the position algorithm documented below + + + + + + 14 + Validate availablePosition for each tranfser (see algorithm below) + Error code: + 4001 + + + 01: sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED + 02: sumProcessed =0 // Record the sum of the transfers already processed in this batch + 03: processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position + 04: foreach transfer in reservedTransfers + 05: sumProcessed += transfer.amount // the total processed so far + (NEED TO UPDATE IN CODE) + 06: if availablePosition >= transfer.amount + 07: transfer.state = "RESERVED" + 08: availablePosition -= preparedTransfer.amount + 09: sumRESERVED += preparedTransfer.amount + 10: else + 11: preparedTransfer.state = "ABORTED" + 12: preparedTransfer.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + 13: end if + 14: runningPosition = currentPosition + sumReserved // the initial value of the Participants position plus the total value that has been accepted in the batch so far + 15: runningReservedValue = sumTransfersInBatch - sumProcessed + reservedPosition + (NEED TO UPDATE IN CODE) + // the running down of the total reserved value at the begining of the batch. + 16: Add transfer to the processedTransfer list recording the transfer state and running position and reserved values { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue } + 16: end foreach + + + Once the outcome for all transfers is known,update the Participant's position and remove the reserved amount associated with the batch + (If there are any alarm limits, process those returning limits in which the threshold has been breached) + Do a bulk insert of the trasnferStateChanges associated with processing, using the result to complete the participantPositionChange and bulk insert of these to persist the running position + + + + + 15 + Assess any limit thresholds on the final position + adding to alarm list if triggered + + + 16 + Persist latest position + value + and + reservedValue + to DB for Payer + + UPDATE + participantPosition + SET value += sumRESERVED, + reservedValue -= sumTransfersInBatch + + + 17 + Bulk persist transferStateChange for all processedTransfers + + batch INSERT + transferStateChange + select for update from transfer table where transferId in ([transferBatch.transferId,...]) + build list of transferStateChanges from transferBatch +   + + + + + 18 + Populate batchParticipantPositionChange from the resultant transferStateChange and the earlier processedTransfer list + + + Effectively: + SET transferStateChangeId = processedTransfer.transferStateChangeId, + participantPositionId = preparedTransfer.participantPositionId, + value = preparedTransfer.positionValue, + reservedValue = preparedTransfer.positionReservedValue + + + 19 + Bulk persist the participant position change for all processedTransfers + + batch INSERT + participantPositionChange + + + 20 + Return a map of transferIds and their transferStateChanges + + + alt + [Calculate & Validate Latest Position Prepare (success)] + + + Message: + { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: transfer, + action: prepare, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 21 + Publish Notification event + Error code: + 2003 + + [Calculate & Validate Latest Position Prepare (failure)] + + + Validation failure! + + + Persist Transfer State (with transferState='ABORTED' on position check fail) + + + 22 + Request to persist transfer + Error code: + 2003 + + + transferStateChange.state = "ABORTED", + transferStateChange.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + + + 23 + Persist transfer state + + transferStateChange + + + 24 + Return success + + + Message: + { + id: <transferMessage.transferId> + from: <ledgerName>, + to: <transferMessage.payerFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": <transferMessage.extensionList> + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: prepare, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 25 + Publish Notification (failure) event for Payer + Error code: + 2003 + + diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.plantuml new file mode 100644 index 000000000..fab0fbf38 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.plantuml @@ -0,0 +1,141 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title 1.3.2. Fulfil Position Handler Consume v1.1 + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER +collections "Notifications-Topic" as TOPIC_NOTIFICATIONS +entity "Position Facade" as POS_FACADE +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant POS_FACADE + participant DB +end box + +' start flow +activate POS_HANDLER +group Fulfil Position Handler Consume + POS_HANDLER -> POS_DAO: Request current state of transfer from DB \nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferState is 'RECEIVED-FULFIL')\nError code: 2001 + group Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + POS_HANDLER -> POS_FACADE: Request to persist latest position and state to DB\nError code: 2003 + group DB TRANSACTION + activate POS_FACADE + POS_FACADE -> DB: Select participantPosition.value FOR UPDATE from DB for Payee + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_FACADE: Return participantPosition.value from DB for Payee + deactivate DB + POS_FACADE <-> POS_FACADE: **latestPosition** = participantPosition.value - payload.amount.amount + POS_FACADE->DB: Persist latestPosition to DB for Payee + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value = latestPosition + end note + activate DB + deactivate DB + POS_FACADE -> DB: Persist transfer state and participant position change + hnote over DB #lightyellow + INSERT **transferStateChange** transferStateId = 'COMMITTED' + + INSERT **participantPositionChange** + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + end note + activate DB + deactivate DB + deactivate POS_DAO + end + POS_FACADE --> POS_HANDLER: Return success + deactivate POS_FACADE + end + + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: commit || reserve, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Transfer event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.svg new file mode 100644 index 000000000..f7fc9c3cf --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.svg @@ -0,0 +1,186 @@ + + 1.3.2. Fulfil Position Handler Consume v1.1 + + + 1.3.2. Fulfil Position Handler Consume v1.1 + + Central Service + + + + + + + + + + + + + + + + + Position Handler + + + Position Handler + + + + + Notifications-Topic + + + Notifications-Topic + Position DAO + + + Position DAO + + + Position Facade + + + Position Facade + + + Central Store + + + Central Store + + + + + + + + + + + + + Fulfil Position Handler Consume + + + 1 + Request current state of transfer from DB + Error code: + 2003 + + + 2 + Retrieve current state of transfer from DB + + transferStateChange + transferParticipant + + + 3 + Return current state of transfer from DB + + + 4 + Return current state of transfer from DB + + + + + + 5 + Validate current state (transferState is 'RECEIVED-FULFIL') + Error code: + 2001 + + + Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + + + 6 + Request to persist latest position and state to DB + Error code: + 2003 + + + DB TRANSACTION + + + 7 + Select participantPosition.value FOR UPDATE from DB for Payee + + participantPosition + + + 8 + Return participantPosition.value from DB for Payee + + + + + + 9 + latestPosition + = participantPosition.value - payload.amount.amount + + + 10 + Persist latestPosition to DB for Payee + + UPDATE + participantPosition + SET value = latestPosition + + + 11 + Persist transfer state and participant position change + + INSERT + transferStateChange + transferStateId = 'COMMITTED' +   + INSERT + participantPositionChange + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + + + 12 + Return success + + + Message: + { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: transfer, + action: commit || reserve, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 13 + Publish Transfer event + Error code: + 2003 + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.svg new file mode 100644 index 000000000..d95894bd6 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.svg @@ -0,0 +1,186 @@ + + 1.3.2. Fulfil Position Handler Consume + + + 1.3.2. Fulfil Position Handler Consume + + Central Service + + + + + + + + + + + + + + + + + Position Handler + + + Position Handler + + + + + Notifications-Topic + + + Notifications-Topic + Position DAO + + + Position DAO + + + Position Facade + + + Position Facade + + + Central Store + + + Central Store + + + + + + + + + + + + + Fulfil Position Handler Consume + + + 1 + Request current state of transfer from DB + Error code: + 2003 + + + 2 + Retrieve current state of transfer from DB + + transferStateChange + transferParticipant + + + 3 + Return current state of transfer from DB + + + 4 + Return current state of transfer from DB + + + + + + 5 + Validate current state (transferState is 'RECEIVED-FULFIL') + Error code: + 2001 + + + Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + + + 6 + Request to persist latest position and state to DB + Error code: + 2003 + + + DB TRANSACTION + + + 7 + Select participantPosition.value FOR UPDATE from DB for Payee + + participantPosition + + + 8 + Return participantPosition.value from DB for Payee + + + + + + 9 + latestPosition + = participantPosition.value - payload.amount.amount + + + 10 + Persist latestPosition to DB for Payee + + UPDATE + participantPosition + SET value = latestPosition + + + 11 + Persist transfer state and participant position change + + INSERT + transferStateChange + transferStateId = 'COMMITTED' +   + INSERT + participantPositionChange + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + + + 12 + Return success + + + Message: + { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: transfer, + action: commit, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 13 + Publish Transfer event + Error code: + 2003 + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.svg new file mode 100644 index 000000000..82d02319c --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.svg @@ -0,0 +1,457 @@ + + 1.3.3. Abort Position Handler Consume + + + 1.3.3. Abort Position Handler Consume + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Position Handler + + + Position Handler + + + + + Notification-Topic + + + Notification-Topic + Position DAO + + + Position DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + + + + Abort Position Handler Consume + + + opt + [type == 'position' && action == 'timeout-reserved'] + + + 1 + Request current state of transfer from DB + Error code: + 2003 + + + 2 + Retrieve current state of transfer from DB + + transferStateChange + transferParticipant + + + 3 + Return current state of transfer from DB + + + 4 + Return current state of transfer from DB + + + + + + 5 + Validate current state (transferStateChange.transferStateId == 'RESERVED_TIMEOUT') + Error code: + 2001 + + + Persist Position change and Transfer state + + + + + 6 + transferStateId + = 'EXPIRED_RESERVED' + + + 7 + Request to persist latest position and state to DB + Error code: + 2003 + + + DB TRANSACTION IMPLEMENTATION + + + 8 + Select participantPosition.value FOR UPDATE for payerCurrencyId + + participantPosition + + + 9 + Return participantPosition + + + + + + 10 + latestPosition + = participantPosition - payload.amount.amount + + + 11 + Persist latestPosition to DB for Payer + + UPDATE + participantPosition + SET value = latestPosition + + + 12 + Persist participant position change and state change + + INSERT + transferStateChange +   + VALUES (transferStateId) +   + INSERT + participantPositionChange + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + + + 13 + Return success + + + Message: { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: abort, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 14 + Publish Notification event + Error code: + 2003 + + + opt + [type == 'position' && (action IN ['reject', 'abort'])] + + + 15 + Request current state of transfer from DB + Error code: + 2003 + + + 16 + Retrieve current state of transfer from DB + + transferStateChange + + + 17 + Return current state of transfer from DB + + + 18 + Return current state of transfer from DB + + + + + + 19 + Validate current state (transferStateChange.transferStateId IN ['RECEIVED_REJECT', 'RECEIVED_ERROR']) + Error code: + 2001 + + + Persist Position change and Transfer state + + + + + 20 + transferStateId + = (action == 'reject' ? 'ABORTED_REJECTED' : 'ABORTED_ERROR' ) + + + 21 + Request to persist latest position and state to DB + Error code: + 2003 + + + Refer to + DB TRANSACTION IMPLEMENTATION + above + + + 22 + Persist to database + + participantPosition + transferStateChange + participantPositionChange + + + 23 + Return success + + + alt + [action == 'reject'] + + + Message: { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: reject, + createdAt: <timestamp>, + state: { + status: "success", + code: 0, + description: "action successful" + } + } + } + } + + [action == 'abort'] + + + Message: { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: abort, + createdAt: <timestamp>, + state: { + status: 'error', + code: <payload.errorInformation.errorCode || 5000> + description: <payload.errorInformation.errorDescription> + } + } + } + } + + + 24 + Publish Notification event + Error code: + 2003 + + + opt + [type == 'position' && action == 'fail' (Unable to currently trigger this scenario)] + + + 25 + Request current state of transfer from DB + Error code: + 2003 + + + 26 + Retrieve current state of transfer from DB + + transferStateChange + + + 27 + Return current state of transfer from DB + + + 28 + Return current state of transfer from DB + + + + + + 29 + Validate current state (transferStateChange.transferStateId == 'FAILED') + + + Persist Position change and Transfer state + + + + + 30 + transferStateId + = 'FAILED' + + + 31 + Request to persist latest position and state to DB + Error code: + 2003 + + + Refer to + DB TRANSACTION IMPLEMENTATION + above + + + 32 + Persist to database + + participantPosition + transferStateChange + participantPositionChange + + + 33 + Return success + + + Message: { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": 3100, + "errorDescription": "Transfer failed", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: abort, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 34 + Publish Notification event + Error code: + 2003 + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.svg new file mode 100644 index 000000000..fb6c0955f --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.svg @@ -0,0 +1,238 @@ + + 1.1.0. DFSP1 sends a Prepare Transfer request to DFSP2 + + + 1.1.0. DFSP1 sends a Prepare Transfer request to DFSP2 + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + DFSP2 + Payee + + + DFSP2 + Payee + + + ML API Adapter + + + ML API Adapter + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + topic-transfer-prepare + + + topic-transfer-prepare + Prepare Event Handler + + + Prepare Event Handler + + + + + topic-transfer-position + + + topic-transfer-position + Position Event Handler + + + Position Event Handler + + + + + Notification-Topic + + + Notification-Topic + + + + + + + + DFSP1 sends a Prepare Transfer request to DFSP2 + + + Headers - transferHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } +   + Payload - transferMessage: + { + "transferId": <uuid>, + "payeeFsp": dfsp2, + "payerFsp": dfsp1, + "amount": { + "currency": "AED", + "amount": "string" + }, + "ilpPacket": "string", + "condition": "string", + "expiration": "string", + "extensionList": { + "extension": [ + { + "key": "string", + "value": "string" + } + ] + } + } + + + + 1 + POST - /transfers + + + + + 2 + Validate incoming token and originator matching Payer + Error codes: + 3000-3002, 3100-3107 + + + Message: + { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + type: prepare, + action: prepare, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 3 + Route & Publish Prepare event for Payer + Error code: + 2003 + + + + + + 4 + Ensure event is replicated as configured (ACKS=all) + Error code: + 2003 + + + 5 + Respond replication acknowledgements have been received + + + + 6 + Respond HTTP - 202 (Accepted) + + + 7 + Consume message + + + ref + Prepare Handler Consume +   + + + 8 + Produce message + + + 9 + Consume message + + + ref + Position Handler Consume +   + + + 10 + Produce message + + + 11 + Consume message + + + ref + Send notification to Participant (Payee) +   + + + 12 + Send callback notification + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.svg new file mode 100644 index 000000000..a5e14b378 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.svg @@ -0,0 +1,405 @@ + + 1.1.1.a. Prepare Handler Consume (single message) + + + 1.1.1.a. Prepare Handler Consume (single message) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + topic-transfer-prepare + + + topic-transfer-prepare + Prepare Event Handler + + + Prepare Event Handler + + + + + topic-transfer-position + + + topic-transfer-position + + + Event-Topic + + + Event-Topic + + + Notification-Topic + + + Notification-Topic + Position DAO + + + Position DAO + + + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + Prepare Handler Consume + + + 1 + Consume Prepare event message + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type == 'prepare' && action == 'prepare' + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + Validate Prepare Transfer + + + + + + 4 + Schema validation of the incoming message + + + + + + 5 + Verify the message's signature (to be confirmed in future requirement) + + + The above validation steps are already handled by + the ML-Adapter for the open source implementation. + It may need to be added in future for custom adapters. + + + Validate Duplicate Check + + + 6 + Request Duplicate Check + + + ref + Request Duplicate Check +   + + + 7 + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + alt + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + break + + + + + 8 + stateRecord = await getTransferState(transferId) + + + alt + [endStateList.includes(stateRecord.transferStateId)] + + + ref + getTransfer callback +   + + + 9 + Produce message + + + + Ignore - resend in progress + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + Validate Prepare Transfer (failure) - Modified Request + + [hasDuplicateId == FALSE] + + + Validate Payer + + + 10 + Request to retrieve Payer Participant details (if it exists) + + + 11 + Request Participant details + + participant + participantCurrency + + + 12 + Return Participant details if it exists + + + 13 + Return Participant details if it exists + + + + + + 14 + Validate Payer + Error codes: + 3202 + + + Validate Payee + + + 15 + Request to retrieve Payee Participant details (if it exists) + + + 16 + Request Participant details + + participant + participantCurrency + + + 17 + Return Participant details if it exists + + + 18 + Return Participant details if it exists + + + + + + 19 + Validate Payee + Error codes: + 3203 + + + alt + [Validate Prepare Transfer (success)] + + + Persist Transfer State (with transferState='RECEIVED-PREPARE') + + + 20 + Request to persist transfer + Error codes: + 2003 + + + 21 + Persist transfer + + transfer + transferParticipant + transferStateChange + transferExtension + ilpPacket + + + 22 + Return success + + [Validate Prepare Transfer (failure)] + + + Persist Transfer State (with transferState='INVALID') (Introducing a new status INVALID to mark these entries) + + + 23 + Request to persist transfer + (when Payee/Payer/crypto-condition validation fails) + Error codes: + 2003 + + + 24 + Persist transfer + + transfer + transferParticipant + transferStateChange + transferExtension + transferError + ilpPacket + + + 25 + Return success + + + alt + [Validate Prepare Transfer (success)] + + + Message: + { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: prepare, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 26 + Route & Publish Position event for Payer + Error codes: + 2003 + + [Validate Prepare Transfer (failure)] + + + Message: + { + id: <transferMessage.transferId> + from: <ledgerName>, + to: <transferMessage.payerFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": <possible codes: [2003, 3100, 3105, 3106, 3202, 3203, 3300, 3301]> + "errorDescription": "<refer to section 35.1.3 for description>", + "extensionList": <transferMessage.extensionList> + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: prepare, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 27 + Publish Notification (failure) event for Payer + Error codes: + 2003 + + diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml new file mode 100644 index 000000000..1b01ef9c5 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml @@ -0,0 +1,186 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.1.b. Prepare Handler Consume (batch messages) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Event Handler" as PREP_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Position DAO" as POS_DAO +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate PREP_HANDLER +group Prepare Handler Consume + note over TOPIC_TRANSFER_PREPARE #LightSalmon + This flow has not been implemented + end note + + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume Prepare event batch of messages for Payer + activate TOPIC_TRANSFER_PREPARE + deactivate TOPIC_TRANSFER_PREPARE + group Persist Event Information + ||| + PREP_HANDLER -> TOPIC_EVENTS: Publish event information + ref over PREP_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + + group Fetch batch Payer information + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve batch of Payer Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payer + PREP_HANDLER -> PREP_HANDLER: store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYER + end + + group Fetch batch Payee information + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve batch of Payee Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payee + PREP_HANDLER -> PREP_HANDLER: store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYEE + end + + group Fetch batch of transfers + PREP_HANDLER -> POS_DAO: Request to retrieve batch of Transfers (if it exists) + activate POS_DAO + POS_DAO -> DB: Request batch of Transfers + hnote over DB #lightyellow + transfer + end note + activate DB + POS_DAO <-- DB: Return batch of Transfers (if it exists) + deactivate DB + POS_DAO --> PREP_HANDLER: Return batch of Transfer (if it exists) + deactivate POS_DAO + PREP_HANDLER -> PREP_HANDLER: store result set in var: $LIST_TRANSFERS + end + + loop for each message in batch + + group Validate Prepare Transfer + group Validate Payer + PREP_HANDLER <-> PREP_HANDLER: Validate Payer against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYER + end + group Validate Payee + PREP_HANDLER <-> PREP_HANDLER: Validate Payee against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYEE + end + group Duplicate check + PREP_HANDLER <-> PREP_HANDLER: Validate duplicate Check against in-memory var $LIST_TRANSFERS + end + PREP_HANDLER <-> PREP_HANDLER: Validate amount + PREP_HANDLER <-> PREP_HANDLER: Validate crypto-condition + PREP_HANDLER <-> PREP_HANDLER: Validate message signature (to be confirmed in future requirement) + end + + group Persist Transfer State (with transferState='RECEIVED' on validation pass) + PREP_HANDLER -> POS_DAO: Request to persist transfer + activate POS_DAO + POS_DAO -> DB: Persist transfer + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + POS_DAO --> PREP_HANDLER: Return success + deactivate POS_DAO + end + + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end +end +deactivate PREP_HANDLER +@enduml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.svg new file mode 100644 index 000000000..548fbff89 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.svg @@ -0,0 +1,320 @@ + + 1.1.1.b. Prepare Handler Consume (batch messages) + + + 1.1.1.b. Prepare Handler Consume (batch messages) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + topic-transfer-prepare + + + topic-transfer-prepare + Prepare Event Handler + + + Prepare Event Handler + + + + + topic-transfer-position + + + topic-transfer-position + + + Event-Topic + + + Event-Topic + + + Notification-Topic + + + Notification-Topic + Position DAO + + + Position DAO + + + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + Prepare Handler Consume + + + This flow has not been implemented + + + 1 + Consume Prepare event batch of messages for Payer + + + Persist Event Information + + + 2 + Publish event information + + + ref + Event Handler Consume +   + + + Fetch batch Payer information + + + 3 + Request to retrieve batch of Payer Participant details (if it exists) + + + 4 + Request Participant details + + participant + + + 5 + Return Participant details if it exists + + + 6 + Return Participant details if it exists + + + + + + 7 + Validate Payer + + + + + 8 + store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYER + + + Fetch batch Payee information + + + 9 + Request to retrieve batch of Payee Participant details (if it exists) + + + 10 + Request Participant details + + participant + + + 11 + Return Participant details if it exists + + + 12 + Return Participant details if it exists + + + + + + 13 + Validate Payee + + + + + 14 + store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYEE + + + Fetch batch of transfers + + + 15 + Request to retrieve batch of Transfers (if it exists) + + + 16 + Request batch of Transfers + + transfer + + + 17 + Return batch of Transfers (if it exists) + + + 18 + Return batch of Transfer (if it exists) + + + + + 19 + store result set in var: $LIST_TRANSFERS + + + loop + [for each message in batch] + + + Validate Prepare Transfer + + + Validate Payer + + + + + + 20 + Validate Payer against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYER + + + Validate Payee + + + + + + 21 + Validate Payee against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYEE + + + Duplicate check + + + + + + 22 + Validate duplicate Check against in-memory var $LIST_TRANSFERS + + + + + + 23 + Validate amount + + + + + + 24 + Validate crypto-condition + + + + + + 25 + Validate message signature (to be confirmed in future requirement) + + + Persist Transfer State (with transferState='RECEIVED' on validation pass) + + + 26 + Request to persist transfer + + + 27 + Persist transfer + + transferStateChange + + + 28 + Return success + + + Message: + { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: prepare, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 29 + Route & Publish Position event for Payer + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.svg new file mode 100644 index 000000000..f6eae8d3e --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.svg @@ -0,0 +1,366 @@ + + 1.1.2.a. Position Handler Consume (single message) + + + 1.1.2.a. Position Handler Consume (single message) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + topic-transfer-position + + + topic-transfer-position + Position Event Handler + + + Position Event Handler + + + + + Event-Topic + + + Event-Topic + + + Notification-Topic + + + Notification-Topic + Position DAO + + + Position DAO + + + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + + + + Position Handler Consume + + + 1 + Consume Position event message for Payer + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type == 'position' && action == 'prepare' + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + alt + [Calulate & Validate Latest Position (success)] + + + Calculate position and persist change + + + 4 + Request latest position from DB for Payer + + + 5 + Retrieve latest position from DB for Payer + + transferPosition + + + 6 + Retrieve latest position from DB for Payer + + + 7 + Return latest position + + + 8 + Request position limits for Payer Participant + + + 9 + Request position limits for Payer Participant + + participant + participantLimit + + + 10 + Return position limits + + + 11 + Return position limits + + + + + + 12 + Calculate latest position (lpos) for prepare + + + + + + 13 + Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + + 14 + Request to persist latest position for Payer + + + 15 + Persist latest position to DB for Payer + + transferPosition + + + 16 + Return success + + + Persist Transfer State (with transferState='RESERVED' on position check pass) + + + 17 + Request to persist transfer + + + 18 + Persist transfer state + + transferStateChange + + + 19 + Return success + + + Message: + { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: transfer, + action: prepare, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 20 + Publish Notification event to Payee + + [Calculate & Validate Latest Position (failure)] + + + Calculate position and persist change + + + 21 + Request latest position from DB for Payer + + + 22 + Retrieve latest position from DB for Payer + + transferPosition + + + 23 + Retrieve latest position from DB for Payer + + + 24 + Return latest position + + + 25 + Request position limits for Payer Participant + + + 26 + Request position limits for Payer Participant + + participant + participantLimit + + + 27 + Return position limits + + + 28 + Return position limits + + + + + + 29 + Calculate latest position (lpos) for prepare + + + + + + 30 + Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + + Validation failure! + + + Persist Transfer State (with transferState='ABORTED' on position check pass) + + + 31 + Request to persist transfer + + + 32 + Persist transfer state + + transferStateChange + + + 33 + Return success + + + Message: + { + id: <transferMessage.transferId> + from: <ledgerName>, + to: <transferMessage.payerFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": <transferMessage.extensionList> + } + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: notification, + action: prepare, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 34 + Publish Notification (failure) event for Payer + + diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml new file mode 100644 index 000000000..9e9bc1ff9 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml @@ -0,0 +1,148 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.2.b. Position Handler Consume (batch messages) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Transfer-Topic" as TOPIC_TRANSFERS +entity "Position DAO" as POS_DAO +entity "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Transfer DAO" as TRANS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_TRANSFERS + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant TRANS_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + note over TOPIC_TRANSFER_POSITION #LightSalmon + This flow has not been implemented + end note + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event batch of messages for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + + loop for each message in batch + group Calculate position and persist change + POS_HANDLER -> POS_DAO: Request latest position from DB for Payer + activate POS_DAO + POS_DAO -> DB: Retrieve latest position from DB for Payer + hnote over DB #lightyellow + transferPosition + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return latest position + deactivate POS_DAO + + POS_HANDLER <-> POS_HANDLER: Calculate latest position (lpos) by incrementing transfer for prepare + POS_HANDLER <-> POS_HANDLER: Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + POS_HANDLER -> POS_DAO: Request to persist latest position for Payer + activate POS_DAO + POS_DAO -> DB: Persist latest position to DB for Payer + hnote over DB #lightyellow + transferPosition + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + group Persist Transfer State (with transferState='RESERVED' on position check pass) + POS_HANDLER -> TRANS_DAO: Request to persist batch transfer + activate TRANS_DAO + TRANS_DAO -> DB: Persist batch transfer + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + TRANS_DAO --> POS_HANDLER: Return success + deactivate TRANS_DAO + end + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_TRANSFERS: Publish Transfer event + activate TOPIC_TRANSFERS + deactivate TOPIC_TRANSFERS + end +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.svg new file mode 100644 index 000000000..bba2e599a --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.svg @@ -0,0 +1,206 @@ + + 1.1.2.b. Position Handler Consume (batch messages) + + + 1.1.2.b. Position Handler Consume (batch messages) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + topic-transfer-position + + + topic-transfer-position + Position Event Handler + + + Position Event Handler + + + + + Transfer-Topic + + + Transfer-Topic + Event-Topic + + + Event-Topic + + + + + Notification-Topic + + + Notification-Topic + Position DAO + + + Position DAO + + + Transfer DAO + + + Transfer DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + Position Handler Consume + + + This flow has not been implemented + + + 1 + Consume Position event batch of messages for Payer + + + Persist Event Information + + + 2 + Publish event information + + + ref + Event Handler Consume +   + + + loop + [for each message in batch] + + + Calculate position and persist change + + + 3 + Request latest position from DB for Payer + + + 4 + Retrieve latest position from DB for Payer + + transferPosition + + + 5 + Return latest position + + + + + + 6 + Calculate latest position (lpos) by incrementing transfer for prepare + + + + + + 7 + Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + + 8 + Request to persist latest position for Payer + + + 9 + Persist latest position to DB for Payer + + transferPosition + + + 10 + Return success + + + Persist Transfer State (with transferState='RESERVED' on position check pass) + + + 11 + Request to persist batch transfer + + + 12 + Persist batch transfer + + transferStateChange + + + 13 + Return success + + + Message: + { + id: <transferMessage.transferId> + from: <transferMessage.payerFsp>, + to: <transferMessage.payeeFsp>, + type: application/json + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: transfer, + action: prepare, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 14 + Publish Transfer event + + diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.plantuml new file mode 100644 index 000000000..fc35e5b8b --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.plantuml @@ -0,0 +1,123 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Shashikant Hirugade + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) v1.1 + +autonumber + +' Actor Keys: +' actor - Payer DFSP, Payee DFSP +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "Payer DFSP\nParticipant" as PAYER_DFSP +actor "Payee DFSP\nParticipant" as PAYEE_DFSP +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +collections "Event-Topic" as TOPIC_EVENTS +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Financial Service Provider (Payer)" #lightGray + participant PAYER_DFSP +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant TOPIC_NOTIFICATIONS + participant CSAPI + participant TOPIC_EVENTS + participant PARTICIPANT_DAO + participant DB +end box + +box "Financial Service Provider (Payee)" #lightGray + participant PAYEE_DFSP +end box + +' start flow +activate NOTIFY_HANDLER +group Send notification to Participants + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume Notification event + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + + group Persist Event Information + NOTIFY_HANDLER -> CSAPI: Request to persist event information - POST - /events + activate CSAPI + CSAPI -> TOPIC_EVENTS: Publish event information + activate TOPIC_EVENTS + ||| + ref over TOPIC_EVENTS : Event Handler Consume\n + ||| + TOPIC_EVENTS --> CSAPI: Return success + deactivate TOPIC_EVENTS + CSAPI --> NOTIFY_HANDLER: Return success + deactivate CSAPI + end + note right of NOTIFY_HANDLER #lightgray + The endpoint details are cached, when the cache + expires, the details are fetched again + end note + NOTIFY_HANDLER -> CSAPI: Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints\nError code: 2003 + + activate CSAPI + CSAPI -> PARTICIPANT_DAO: Fetch Endpoint details for Participant\nError code: 2003 + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch Endpoint details for Participant + activate DB + hnote over DB #lightyellow + participantEndpoint + end note + DB -> PARTICIPANT_DAO: Retrieved Endpoint details for Participant + deactivate DB + PARTICIPANT_DAO --> CSAPI: Return Endpoint details for Participant + deactivate PARTICIPANT_DAO + CSAPI --> NOTIFY_HANDLER: Return Endpoint details for Participant\nError codes: 3202, 3203 + deactivate CSAPI + NOTIFY_HANDLER -> PAYER_DFSP: Notification with Prepare/fulfil result/error to \nPayer DFSP to specified Endpoint - PUT \nError code: 1001 + NOTIFY_HANDLER <-- PAYER_DFSP: HTTP 200 OK + alt event.action === 'reserve' + alt event.status === 'success' + NOTIFY_HANDLER -> PAYEE_DFSP: Notification to with succesful fulfil result (committed) to Payee DFSP to specified Endpoint - PATCH \nError code: 1001 + ||| + NOTIFY_HANDLER <-- PAYEE_DFSP: HTTP 200 OK + end + end +end +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.svg new file mode 100644 index 000000000..a6f26da77 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.svg @@ -0,0 +1,189 @@ + + 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) v1.1 + + + 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) v1.1 + + Financial Service Provider (Payer) + + ML API Adapter Service + + Central Service + + Financial Service Provider (Payee) + + + + + + + + + + + + + + + + + + + + Payer DFSP + Participant + + + Payer DFSP + Participant + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + + + Notification-Topic + + + Notification-Topic + Central Service API + + + Central Service API + + + + + Event-Topic + + + Event-Topic + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + Payee DFSP + Participant + + + Payee DFSP + Participant + + + + + + + + + + + + Send notification to Participants + + + 1 + Consume Notification event + + + Persist Event Information + + + 2 + Request to persist event information - POST - /events + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + 4 + Return success + + + 5 + Return success + + + The endpoint details are cached, when the cache + expires, the details are fetched again + + + 6 + Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints + Error code: + 2003 + + + 7 + Fetch Endpoint details for Participant + Error code: + 2003 + + + 8 + Fetch Endpoint details for Participant + + participantEndpoint + + + 9 + Retrieved Endpoint details for Participant + + + 10 + Return Endpoint details for Participant + + + 11 + Return Endpoint details for Participant + Error codes: + 3202, 3203 + + + 12 + Notification with Prepare/fulfil result/error to + Payer DFSP to specified Endpoint - PUT + Error code: + 1001 + + + 13 + HTTP 200 OK + + + alt + [event.action === 'reserve'] + + + alt + [event.status === 'success'] + + + 14 + Notification to with succesful fulfil result (committed) to Payee DFSP to specified Endpoint - PATCH + Error code: + 1001 + + + 15 + HTTP 200 OK + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.svg new file mode 100644 index 000000000..7f31b7361 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.svg @@ -0,0 +1,184 @@ + + 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) + + + 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) + + Financial Service Provider (Payer) + + ML API Adapter Service + + Central Service + + Financial Service Provider (Payee) + + + + + + + + + + + + + + + + + + + Payer DFSP + Participant + + + Payer DFSP + Participant + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + + + Notification-Topic + + + Notification-Topic + Central Service API + + + Central Service API + + + + + Event-Topic + + + Event-Topic + Participant DAO + + + Participant DAO + + + Central Store + + + Central Store + + + Payee DFSP + Participant + + + Payee DFSP + Participant + + + + + + + + + + + + Send notification to Participants + + + 1 + Consume Notification event + + + Persist Event Information + + + 2 + Request to persist event information - POST - /events + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + 4 + Return success + + + 5 + Return success + + + The endpoint details are cached, when the cache + expires, the details are fetched again + + + 6 + Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints + Error code: + 2003 + + + 7 + Fetch Endpoint details for Participant + Error code: + 2003 + + + 8 + Fetch Endpoint details for Participant + + participantEndpoint + + + 9 + Retrieved Endpoint details for Participant + + + 10 + Return Endpoint details for Participant + + + 11 + Return Endpoint details for Participant + Error codes: + 3202, 3203 + + + 12 + Notification with Prepare/fulfil result/error to + Payer DFSP to specified Endpoint - PUT + Error code: + 1001 + + + 13 + HTTP 200 OK + + + alt + [Config.SEND_TRANSFER_CONFIRMATION_TO_PAYEE === true] + + + 14 + Notification to with fulfil result (committed/aborted/rejected) to Payee DFSP to specified Endpoint - PUT + Error code: + 1001 + + + 15 + HTTP 200 OK + + diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml new file mode 100644 index 000000000..0c5c5fb5d --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml @@ -0,0 +1,108 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.4.b. Send notification to Participant (Payer/Payee) (batch messages) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP(n)\nParticipant" as DFSP +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +collections "Event-Topic" as TOPIC_EVENTS +entity "Notification DAO" as NOTIFY_DAO +database "Central Store" as DB + +box "Financial Service Provider" #lightGray + participant DFSP +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow +participant TOPIC_NOTIFICATIONS + participant CSAPI + participant TOPIC_EVENTS + participant EVENT_DAO + participant NOTIFY_DAO + participant DB +end box + +' start flow +activate NOTIFY_HANDLER +group Send notification to Participant + note over DFSP #LightSalmon + This flow has not been implemented + end note + + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: **Consume Notifications event batch of messages for Participant** + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + loop for each message in batch + group Persist Event Information + NOTIFY_HANDLER -> CSAPI: Request to persist event information - POST - /events + activate CSAPI + CSAPI -> TOPIC_EVENTS: Publish event information + activate TOPIC_EVENTS + ||| + ref over TOPIC_EVENTS : Event Handler Consume\n + ||| + TOPIC_EVENTS --> CSAPI: Return success + deactivate TOPIC_EVENTS + CSAPI --> NOTIFY_HANDLER: Return success + deactivate CSAPI + end + NOTIFY_HANDLER -> CSAPI: Request Notifications details for Participant - GET - /notifications/DFPS(n) + activate CSAPI + CSAPI -> NOTIFY_DAO: Fetch Notifications details for Participant + activate NOTIFY_DAO + NOTIFY_DAO -> DB: Fetch Notifications details for Participant + activate DB + hnote over DB #lightyellow + transferPosition + end note + DB --> NOTIFY_DAO: Retrieved Notification details for Participant + 'deactivate DB + NOTIFY_DAO --> CSAPI: Return Notifications details for Participant + deactivate NOTIFY_DAO + CSAPI --> NOTIFY_HANDLER: Return Notifications details for Participant + deactivate CSAPI + NOTIFY_HANDLER --> DFSP: Callback with Prepare result to Participant to specified URL - PUT - />/transfers + end +end +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.svg new file mode 100644 index 000000000..b7adfc723 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.svg @@ -0,0 +1,154 @@ + + 1.1.4.b. Send notification to Participant (Payer/Payee) (batch messages) + + + 1.1.4.b. Send notification to Participant (Payer/Payee) (batch messages) + + Financial Service Provider + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + DFSP(n) + Participant + + + DFSP(n) + Participant + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + + + Notification-Topic + + + Notification-Topic + Central Service API + + + Central Service API + + + + + Event-Topic + + + Event-Topic + + EVENT_DAO + + EVENT_DAO + Notification DAO + + + Notification DAO + + + Central Store + + + Central Store + + + + + + + + + + + + Send notification to Participant + + + This flow has not been implemented + + + 1 + Consume Notifications event batch of messages for Participant + + + loop + [for each message in batch] + + + Persist Event Information + + + 2 + Request to persist event information - POST - /events + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + 4 + Return success + + + 5 + Return success + + + 6 + Request Notifications details for Participant - GET - /notifications/DFPS(n) + + + 7 + Fetch Notifications details for Participant + + + 8 + Fetch Notifications details for Participant + + transferPosition + + + 9 + Retrieved Notification details for Participant + + + 10 + Return Notifications details for Participant + + + 11 + Return Notifications details for Participant + + + 12 + Callback with Prepare result to Participant to specified URL - PUT - /<dfsp-host>>/transfers + + diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.plantuml new file mode 100644 index 000000000..45f7fd524 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.plantuml @@ -0,0 +1,143 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER + +' collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +' control "Position Event Handler" as POS_HANDLER +' collections "Event-Topic" as TOPIC_EVENTS +' collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +group DFSP2 sends an error callback to reject a transfer with an errorCode and description + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + } + end note + DFSP2 ->> MLAPI: **PUT - /transfers//error** + + activate MLAPI + MLAPI -> MLAPI: Validate incoming token and originator matching Payee + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Fulfil event for Payee + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all) + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + FULF_HANDLER -> FULF_HANDLER: Log error message + note right of FULF_HANDLER: (corresponding to a Fulfil message with transferState='ABORTED')\naction REJECT is not allowed into fulfil handler +end +@enduml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.svg new file mode 100644 index 000000000..5cbfe019e --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.svg @@ -0,0 +1,178 @@ + + 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + + + 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + DFSP2 + Payee + + + DFSP2 + Payee + + + ML API Adapter + + + ML API Adapter + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + Fulfil-Topic + + + Fulfil-Topic + Fulfil Event Handler + + + Fulfil Event Handler + + + + + + + + + DFSP2 sends an error callback to reject a transfer with an errorCode and description + + + Headers - transferHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } +   + Payload - transferMessage: + { + "errorInformation": { + "errorCode": <errorCode>, + "errorDescription": <errorDescription>, + "extensionList": { + "extension": [ + { + "key": <string>, + "value": <string> + } + ] + } + } + } + + + + 1 + PUT - /transfers/<ID>/error + + + + + 2 + Validate incoming token and originator matching Payee + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + type: fulfil, + action: reject, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 3 + Route & Publish Fulfil event for Payee + + + + + + 4 + Ensure event is replicated as configured (ACKS=all) + + + 5 + Respond replication acknowledgements have been received + + + + 6 + Respond HTTP - 200 (OK) + + + 7 + Consume message + + + + + 8 + Log error message + + + (corresponding to a Fulfil message with transferState='ABORTED') + action REJECT is not allowed into fulfil handler + + diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.plantuml new file mode 100644 index 000000000..ec02b5318 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.plantuml @@ -0,0 +1,166 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- +******'/ + +@startuml +' declate title +title 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate POS_HANDLER +group DFSP2 sends a Fulfil Success Transfer request + DFSP2 <-> DFSP2: During processing of an incoming\nPOST /transfers request, some processing\nerror occurred and an Error callback is made + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - errorMessage: + { + errorInformation + { + "errorCode": , + "errorDescription": + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + } + end note + DFSP2 ->> MLAPI: PUT - /transfers//error + activate MLAPI + MLAPI -> MLAPI: Validate incoming originator matching Payee\nError codes: 3000-3002, 3100-3107 + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Abort event for Payee\nError code: 2003 + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Abort)\n + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Abort)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'abort' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'abort' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +deactivate POS_HANDLER +deactivate FULF_HANDLER +deactivate NOTIFY_HANDLER +@enduml \ No newline at end of file diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.svg new file mode 100644 index 000000000..fb382991c --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.svg @@ -0,0 +1,265 @@ + + 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + + + 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + DFSP2 + Payee + + + DFSP2 + Payee + + + ML API Adapter + + + ML API Adapter + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + Fulfil-Topic + + + Fulfil-Topic + Fulfil Event Handler + + + Fulfil Event Handler + + + + + topic-transfer-position + + + topic-transfer-position + Position Event Handler + + + Position Event Handler + + + + + Notification-Topic + + + Notification-Topic + + + + + + + + DFSP2 sends a Fulfil Success Transfer request + + + + + + 1 + During processing of an incoming + POST /transfers request, some processing + error occurred and an Error callback is made + + + Headers - transferHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } +   + Payload - errorMessage: + { + errorInformation + { + "errorCode": <errorCode>, + "errorDescription": <errorDescription> + "extensionList": { + "extension": [ + { + "key": <string>, + "value": <string> + } + ] + } + } + } + + + + 2 + PUT - /transfers/<ID>/error + + + + + 3 + Validate incoming originator matching Payee + Error codes: + 3000-3002, 3100-3107 + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <errorMessage> + }, + metadata: { + event: { + id: <uuid>, + type: fulfil, + action: abort, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 4 + Route & Publish Abort event for Payee + Error code: + 2003 + + + + + + 5 + Ensure event is replicated as configured (ACKS=all) + Error code: + 2003 + + + 6 + Respond replication acknowledgements have been received + + + + 7 + Respond HTTP - 200 (OK) + + + 8 + Consume message + + + ref + Fulfil Handler Consume (Abort) +   + + + 9 + Produce message + + + 10 + Consume message + + + ref + Position Handler Consume (Abort) +   + + + 11 + Produce message + + + 12 + Consume message + + + opt + [action == 'abort'] + + + ref + Send notification to Participant (Payer) +   + + + 13 + Send callback notification + + + 14 + Consume message + + + opt + [action == 'abort'] + + + ref + Send notification to Participant (Payee) +   + + + 15 + Send callback notification + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.svg new file mode 100644 index 000000000..07a2af94f --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.svg @@ -0,0 +1,265 @@ + + 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + + + 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + DFSP2 + Payee + + + DFSP2 + Payee + + + ML API Adapter + + + ML API Adapter + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + Fulfil-Topic + + + Fulfil-Topic + Fulfil Event Handler + + + Fulfil Event Handler + + + + + topic-transfer-position + + + topic-transfer-position + Position Event Handler + + + Position Event Handler + + + + + Notification-Topic + + + Notification-Topic + + + + + + + + DFSP2 sends a Fulfil Success Transfer request + + + + + + 1 + During processing of an incoming + POST /transfers request, some processing + error occurred and an Error callback is made + + + Headers - transferHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } +   + Payload - errorMessage: + { + errorInformation + { + "errorCode": <errorCode>, + "errorDescription": <errorDescription> + "extensionList": { + "extension": [ + { + "key": <string>, + "value": <string> + } + ] + } + } + } + + + + 2 + PUT - /transfers/<ID>/error + + + + + 3 + Validate incoming originator matching Payee + Error codes: + 3000-3002, 3100-3107 + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <errorMessage> + }, + metadata: { + event: { + id: <uuid>, + type: fulfil, + action: abort, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 4 + Route & Publish Abort/Reject event for Payee + Error code: + 2003 + + + + + + 5 + Ensure event is replicated as configured (ACKS=all) + Error code: + 2003 + + + 6 + Respond replication acknowledgements have been received + + + + 7 + Respond HTTP - 200 (OK) + + + 8 + Consume message + + + ref + Fulfil Handler Consume (Reject/Abort) +   + + + 9 + Produce message + + + 10 + Consume message + + + ref + Position Handler Consume (Abort) +   + + + 11 + Produce message + + + 12 + Consume message + + + opt + [action == 'abort'] + + + ref + Send notification to Participant (Payer) +   + + + 13 + Send callback notification + + + 14 + Consume message + + + opt + [action == 'abort'] + + + ref + Send notification to Participant (Payee) +   + + + 15 + Send callback notification + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.svg new file mode 100644 index 000000000..10a77439b --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.svg @@ -0,0 +1,262 @@ + + 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + + + 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + DFSP2 + Payee + + + DFSP2 + Payee + + + ML API Adapter + + + ML API Adapter + + + ML API Notification Event Handler + + + ML API Notification Event Handler + + + Central Service API + + + Central Service API + + + + + Fulfil-Topic + + + Fulfil-Topic + Fulfil Event Handler + + + Fulfil Event Handler + + + + + topic-transfer-position + + + topic-transfer-position + + + Event-Topic + + + Event-Topic + Position Event Handler + + + Position Event Handler + + + + + Notification-Topic + + + Notification-Topic + + + + + + + + DFSP2 sends a Fulfil Reject Transfer request + + + + + + 1 + Retrieve fulfilment string generated during + the quoting process or regenerate it using + Local secret + and + ILP Packet + as inputs + + + Note + : In the payload for PUT /transfers/<ID> + only the + transferState + field is + required + + + Headers - transferHeaders: { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + } +   + Payload - transferMessage: + { + "fulfilment": <IlpFulfilment>, + "completedTimestamp": <DateTime>, + "transferState": "ABORTED", + "extensionList": { + "extension": [ + { + "key": <string>, + "value": <string> + } + ] + } + } + + + Note + : Payee rejection reason should be captured + in the extensionList within the payload. + + + + 2 + PUT - /transfers/<ID> + + + + + 3 + Validate incoming token and originator matching Payee + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + type: fulfil, + action: reject, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 4 + Route & Publish Fulfil event for Payee + + + + + + 5 + Ensure event is replicated as configured (ACKS=all) + + + 6 + Respond replication acknowledgements have been received + + + + 7 + Respond HTTP - 200 (OK) + + + 8 + Consume message + + + ref + Fulfil Handler Consume (Reject/Abort) +   + + + 9 + Produce message + + + 10 + Consume message + + + ref + Position Handler Consume (Reject) +   + + + 11 + Produce message + + + 12 + Consume message + + + opt + [action == 'reject'] + + + ref + Send notification to Participant (Payer) +   + + + 13 + Send callback notification + + diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.plantuml new file mode 100644 index 000000000..3c390db71 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.plantuml @@ -0,0 +1,225 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + * Sam Kummary + -------------- + ******'/ + +@startuml +' declate title +title 2.2.1. Fulfil Handler Consume (Abort/Reject) +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "Event-Topic" as TOPIC_EVENT +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +'entity "Transfer Duplicate Facade" as DUP_FACADE +entity "Transfer DAO" as TRANS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_NOTIFICATIONS + participant TRANS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Failure) + alt Consume Single Message + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type == 'fulfil' && ( action IN ['reject','abort'] )\nError codes: 2001 + end + end + group Persist Event Information + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume + end + group Validate FSPIOP-Signature + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Validate message.content.headers.**FSPIOP-Signature**\nError codes: 2001 + end + group Validate Transfer Fulfil Duplicate Check + FULF_HANDLER -> FULF_HANDLER: Generate transferFulfilmentId uuid + FULF_HANDLER -> TRANS_DAO: Request to retrieve transfer fulfilment hashes by transferId\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request Transfer fulfilment duplicate message hashes + hnote over DB #lightyellow + SELET transferId, hash + FROM **transferFulfilmentDuplicateCheck** + WHERE transferId = request.params.id + end note + activate DB + TRANS_DAO <-- DB: Return existing hashes + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return (list of) transfer fulfil messages hash(es) + deactivate TRANS_DAO + FULF_HANDLER -> FULF_HANDLER: Loop the list of returned hashes and compare each entry with the calculated message hash + alt Hash matched + ' Need to check what respond with same results if finalised then resend, else ignore and wait for response + FULF_HANDLER -> TRANS_DAO: Request to retrieve Transfer Fulfilment and Transfer state\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request to retrieve Transfer Fulfilment and Transfer state + hnote over DB #lightyellow + transferFulfilment + transferStateChange + end note + activate DB + TRANS_DAO <-- DB: Return Transfer Fulfilment and Transfer state + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return Transfer Fulfilment and Transfer state + deactivate TRANS_DAO + alt transferFulfilment.isValid == 0 + break + FULF_HANDLER <-> FULF_HANDLER: Error handling: 3105 + end + else transferState IN ['COMMITTED', 'ABORTED'] + break + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + end + else transferState NOT 'RESERVED' + break + FULF_HANDLER <-> FULF_HANDLER: Error code: 2001 + end + else + break + FULF_HANDLER <-> FULF_HANDLER: Allow previous request to complete + end + end + else Hash not matched + FULF_HANDLER -> TRANS_DAO: Request to persist transfer hash\nError codes: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist hash + hnote over DB #lightyellow + transferFulfilmentDuplicateCheck + end note + activate DB + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + deactivate TRANS_DAO + end + end + alt action=='reject' call made on PUT /transfers/{ID} + FULF_HANDLER -> FULF_HANDLER: Log error message + note right of FULF_HANDLER: action REJECT is not allowed into fulfil handler + else action=='abort' Error callback + alt Validation successful + group Persist Transfer State (with transferState='RECEIVED_ERROR') + FULF_HANDLER -> TRANS_DAO: Request to persist transfer state and Error\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist transfer state and error information + activate DB + hnote over DB #lightyellow + transferStateChange + transferError + transferExtension + end note + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Transfer Error Message not successful + break + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Route & Publish Notification event for Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + end + end + else Consume Batch Messages + note left of FULF_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate FULF_HANDLER +@enduml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.svg new file mode 100644 index 000000000..517355e0c --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.svg @@ -0,0 +1,386 @@ + + 2.2.1. Fulfil Handler Consume (Abort/Reject) + + + 2.2.1. Fulfil Handler Consume (Abort/Reject) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fulfil-Topic + + + Fulfil-Topic + Fulfil Event Handler + + + Fulfil Event Handler + + + + + topic-transfer-position + + + topic-transfer-position + + + Event-Topic + + + Event-Topic + + + Notification-Topic + + + Notification-Topic + Transfer DAO + + + Transfer DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + Fulfil Handler Consume (Failure) + + + alt + [Consume Single Message] + + + 1 + Consume Fulfil event message for Payer + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type == 'fulfil' && ( action IN ['reject','abort'] ) + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume + + + Validate FSPIOP-Signature + + + ref + Validate message.content.headers. + FSPIOP-Signature + Error codes: + 2001 + + + Validate Transfer Fulfil Duplicate Check + + + + + 4 + Generate transferFulfilmentId uuid + + + 5 + Request to retrieve transfer fulfilment hashes by transferId + Error code: + 2003 + + + 6 + Request Transfer fulfilment duplicate message hashes + + SELET transferId, hash + FROM + transferFulfilmentDuplicateCheck + WHERE transferId = request.params.id + + + 7 + Return existing hashes + + + 8 + Return (list of) transfer fulfil messages hash(es) + + + + + 9 + Loop the list of returned hashes and compare each entry with the calculated message hash + + + alt + [Hash matched] + + + 10 + Request to retrieve Transfer Fulfilment and Transfer state + Error code: + 2003 + + + 11 + Request to retrieve Transfer Fulfilment and Transfer state + + transferFulfilment + transferStateChange + + + 12 + Return Transfer Fulfilment and Transfer state + + + 13 + Return Transfer Fulfilment and Transfer state + + + alt + [transferFulfilment.isValid == 0] + + + break + + + + + + 14 + Error handling: + 3105 + + [transferState IN ['COMMITTED', 'ABORTED']] + + + break + + + ref + Send notification to Participant (Payee) +   + + [transferState NOT 'RESERVED'] + + + break + + + + + + 15 + Error code: + 2001 + + + + break + + + + + + 16 + Allow previous request to complete + + [Hash not matched] + + + 17 + Request to persist transfer hash + Error codes: + 2003 + + + 18 + Persist hash + + transferFulfilmentDuplicateCheck + + + 19 + Return success + + + alt + [action=='reject' call made on PUT /transfers/{ID}] + + + + + 20 + Log error message + + + action REJECT is not allowed into fulfil handler + + [action=='abort' Error callback] + + + alt + [Validation successful] + + + Persist Transfer State (with transferState='RECEIVED_ERROR') + + + 21 + Request to persist transfer state and Error + Error code: + 2003 + + + 22 + Persist transfer state and error information + + transferStateChange + transferError + transferExtension + + + 23 + Return success + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: abort, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 24 + Route & Publish Position event for Payer + + [Validate Transfer Error Message not successful] + + + break + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: abort, + createdAt: <timestamp>, + state: { + status: "error", + code: 1 + } + } + } + } + + + 25 + Route & Publish Notification event for Payee + + [Consume Batch Messages] + + + To be delivered by future story + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.svg new file mode 100644 index 000000000..97665dece --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.svg @@ -0,0 +1,572 @@ + + 2.2.1. Fulfil Handler Consume (Reject/Abort) + + + 2.2.1. Fulfil Handler Consume (Reject/Abort) + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fulfil-Topic + + + Fulfil-Topic + Fulfil Event Handler + + + Fulfil Event Handler + + + + + topic-transfer-position + + + topic-transfer-position + + + Event-Topic + + + Event-Topic + + + Notification-Topic + + + Notification-Topic + Transfer DAO + + + Transfer DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + + + + + + + + + + + Fulfil Handler Consume (Failure) + + + alt + [Consume Single Message] + + + 1 + Consume Fulfil event message for Payer + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type == 'fulfil' && ( action IN ['reject','abort'] ) + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume + + + Validate FSPIOP-Signature + + + ref + Validate message.content.headers. + FSPIOP-Signature + Error codes: + 2001 + + + Validate Transfer Fulfil Duplicate Check + + + + + 4 + Generate transferFulfilmentId uuid + + + 5 + Request to retrieve transfer fulfilment hashes by transferId + Error code: + 2003 + + + 6 + Request Transfer fulfilment duplicate message hashes + + SELET transferId, hash + FROM + transferFulfilmentDuplicateCheck + WHERE transferId = request.params.id + + + 7 + Return existing hashes + + + 8 + Return (list of) transfer fulfil messages hash(es) + + + + + 9 + Loop the list of returned hashes and compare each entry with the calculated message hash + + + alt + [Hash matched] + + + 10 + Request to retrieve Transfer Fulfilment and Transfer state + Error code: + 2003 + + + 11 + Request to retrieve Transfer Fulfilment and Transfer state + + transferFulfilment + transferStateChange + + + 12 + Return Transfer Fulfilment and Transfer state + + + 13 + Return Transfer Fulfilment and Transfer state + + + alt + [transferFulfilment.isValid == 0] + + + break + + + + + + 14 + Error handling: + 3105 + + [transferState IN ['COMMITTED', 'ABORTED']] + + + break + + + ref + Send notification to Participant (Payee) +   + + [transferState NOT 'RESERVED'] + + + break + + + + + + 15 + Error code: + 2001 + + + + break + + + + + + 16 + Allow previous request to complete + + [Hash not matched] + + + 17 + Request to persist transfer hash + Error codes: + 2003 + + + 18 + Persist hash + + transferFulfilmentDuplicateCheck + + + 19 + Return success + + + alt + [action=='reject' call made on PUT /transfers/{ID}] + + + 20 + Request information for the validate checks + Error code: + 2003 + + + 21 + Fetch from database + + transfer + + + 22 +   + + + 23 + Return transfer + + + alt + [Fulfilment present in the PUT /transfers/{ID} message] + + + + + 24 + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + Error code: + 2001 + + + Persist fulfilment + + + 25 + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + Error code: + 2003 + + + 26 + Persist to database + + transferFulfilment + transferExtension + + + 27 + Return success + + [Fulfilment NOT present in the PUT /transfers/{ID} message] + + + + + 28 + Validate that transfer fulfilment message to Abort is valid + Error code: + 2001 + + + Persist extensions + + + 29 + Persist extensionList elements + Error code: + 2003 + + + 30 + Persist to database + + transferExtension + + + 31 + Return success + + + alt + [Transfer.ilpCondition validate successful OR generic validation successful] + + + Persist Transfer State (with transferState='RECEIVED_REJECT') + + + 32 + Request to persist transfer state + Error code: + 2003 + + + 33 + Persist transfer state + + transferStateChange + + + 34 + Return success + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: reject, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 35 + Route & Publish Position event for Payer + + [Validate Fulfil Transfer not successful or Generic validation failed] + + + break + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: reject, + createdAt: <timestamp>, + state: { + status: "error", + code: 1 + } + } + } + } + + + 36 + Route & Publish Notification event for Payee + + [action=='abort' Error callback] + + + alt + [Validation successful] + + + Persist Transfer State (with transferState='RECEIVED_ERROR') + + + 37 + Request to persist transfer state and Error + Error code: + 2003 + + + 38 + Persist transfer state and error information + + transferStateChange + transferError + transferExtension + + + 39 + Return success + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: abort, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 40 + Route & Publish Position event for Payer + + [Validate Transfer Error Message not successful] + + + break + + + Message: + { + id: <ID>, + from: <transferHeaders.FSPIOP-Source>, + to: <transferHeaders.FSPIOP-Destination>, + type: application/json, + content: { + headers: <transferHeaders>, + payload: <transferMessage> + }, + metadata: { + event: { + id: <uuid>, + responseTo: <previous.uuid>, + type: position, + action: abort, + createdAt: <timestamp>, + state: { + status: "error", + code: 1 + } + } + } + } + + + 41 + Route & Publish Notification event for Payee + + [Consume Batch Messages] + + + To be delivered by future story + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.svg new file mode 100644 index 000000000..9799da8cd --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.svg @@ -0,0 +1,167 @@ + + 9.1.1. Request Duplicate Check (incl. Transfers, Quotes, Bulk Transfers, Bulk Quotes) + + + 9.1.1. Request Duplicate Check (incl. Transfers, Quotes, Bulk Transfers, Bulk Quotes) + + Central Service + + + + + + + + + + + + + + + + + + + + topic-source + + + topic-source + Processing + Handler + + + Processing + Handler + + + + + topic-event + + + topic-event + + + topic-notifcation + + + topic-notifcation + Request DAO + + + Request DAO + + + Central Store + + + Central Store + + + + + + + + + + + Request Duplicate Check + + + 1 + Consume message + + + + + 2 + Generate hash: + generatedHash + + + UUID Check (compareById) + + + 3 + Query hash using getDuplicateDataFuncOverride(id) + Error code: + 2003 + + + request + keyword to be replaced by + transfer + , + transferFulfilment + , + bulkTransfer + or other depending + on the override + + + 4 + getDuplicateDataFuncOverride + + request + DuplicateCheck + + + 5 + Return + duplicateHashRecord + + + 6 + Return + hasDuplicateId + + + alt + [hasDuplicateId == TRUE] + + + Hash Check (compareByHash) + + + generatedHash == duplicateHashRecord.hash + + + + + 7 + Return + hasDuplicateHash + + [hasDuplicateId == FALSE] + + + Store Message Hash + + + 8 + Persist hash using saveHashFuncOverride(id, generatedHash) + Error code: + 2003 + + + 9 + Persist + generatedHash + + request + DuplicateCheck + + + 10 + Return success + + + return { + hasDuplicateId: Boolean, + hasDuplicateHash: Boolean + } + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.svg new file mode 100644 index 000000000..a3e2de88c --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.svg @@ -0,0 +1,175 @@ + + 2.1.2. Settlement Model Handler Consume + + + 2.1.2. Settlement Model Handler Consume + + Central Service + + + + + + + + + + + + + + + + + + + + + + + topic- + settlement-model + + + topic- + settlement-model + Settlement Model + Handler + + + Settlement Model + Handler + + + + + topic-event + + + topic-event + Settlement DAO + + + Settlement DAO + + + Central Store + + + Central Store + + + + + + + + + + + + Settlement Model Handler Consume + + + alt + [Consume Single Message] + + + 1 + Consume settlement model + event message + + + break + + + Validate Event + + + + + + 2 + Validate event - Rule: type == 'setmodel' && action == 'commit' + Error codes: + 2001 + + + Persist Event Information + + + 3 + Publish event information + + + ref + Event Handler Consume +   + + + 4 + Assign transferParicipant state(s) + Error code: + 2003 + + + DB TRANSACTION + + + 5 + Fetch transfer participant entries + + transferParticipant + + + 6 + Return + transferParticipantRecords + + + loop + [for each transferParticipant] + + + Settlement models caching to be considered + + + 7 + Get settlement model by currency and ledger entry + + settlementModel + + + 8 + Return + settlementModel + + + opt + [settlementModel.delay == 'IMMEDIATE' && settlementModel.granularity == 'GROSS'] + + + 9 + Set states: CLOSED->PENDING_SETTLEMENT->SETTLED + + transferParticipantStateChange + transferParticipant + + + + 10 + Set state: OPEN + + transferParticipantStateChange + transferParticipant + + + 11 + Return success + + [Consume Batch Messages] + + + To be delivered by future story + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.svg new file mode 100644 index 000000000..e4440f48f --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.svg @@ -0,0 +1,195 @@ + + 2.3.0. Transfer Timeout + + + 2.3.0. Transfer Timeout + + Financial Service Providers + + ML API Adapter Service + + Central Service + + + + + + + + + + + + + + + + + + + DFSP1 + Payer + + + DFSP1 + Payer + + + DFSP2 + Payee + + + DFSP2 + Payee + + + ML API + Adapter + + + ML API + Adapter + + + Notification + Handler + + + Notification + Handler + + + Timeout Prepare + Handler + + + Timeout Prepare + Handler + + + + + topic- + transfer-timeout + + + topic- + transfer-timeout + Timeout + Handler + + + Timeout + Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + Position + Handler + + + Position + Handler + + + + + topic-notification + + + topic-notification + + + + + + + Transfer Expiry + + + ref + Timeout Processing Handler Consume +   + + + 1 + Produce message + + + 2 + Consume message + + + ref + Timeout Processing Handler Consume +   + + + alt + [transferStateId == 'RECEIVED_PREPARE'] + + + 3 + Produce message + + [transferStateId == 'RESERVED'] + + + 4 + Produce message + + + 5 + Consume message + + + ref + Position Hander Consume (Timeout) +   + + + 6 + Produce message + + + opt + [action IN ['timeout-received', 'timeout-reserved']] + + + 7 + Consume message + + + ref + Send notification to Participant (Payer) +   + + + 8 + Send callback notification + + + 9 + Consume message + + + opt + [action == 'timeout-reserved'] + + + ref + Send notification to Participant (Payee) +   + + + 10 + Send callback notification + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.svg new file mode 100644 index 000000000..7a554e868 --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.svg @@ -0,0 +1,169 @@ + + 2.3.1. Timeout Prepare Handler + + + 2.3.1. Timeout Prepare Handler + + Central Service + + + + + + + + + + + + + + + + + Timeout Prepare + Handler + + + Timeout Prepare + Handler + + + + + topic- + transfer-timeout + + + topic- + transfer-timeout + + + topic-event + + + topic-event + Timeout DAO + + + Timeout DAO + + + Central Store + + + Central Store + + + + + + + + + + + Timeout Prepare Handler + + + Persist Event Information + + + 1 + Publish event information + + + ref + Event Handler Consume +   + + + Cleanup + + + 2 + Cleanup Fulfilled Transfers + Error code: + 2003 + + + 3 + Delete fuflfilled transfers records + + DELETE et + FROM + expiringTransfer + et + JOIN + transferFulfilment + tf + ON tf.transferId = et.transferId + + + 4 + Return success + + + List Expired + + + 5 + Retrieve Expired Transfers + Error code: + 2003 + + + 6 + Select using index + + SELECT * + FROM + expiringTransfer + WHERE expirationDate < currentTimestamp + + + 7 + Return expired transfers + + + 8 + Return + expiredTransfersList + + + loop + [for each transfer in the list] + + + Message: + { + id: <uuid> + from: <switch>, + to: <payerFsp>, + type: application/json + content: { + headers: null, + payload: <transfer> + }, + metadata: { + event: { + id: <uuid>, + responseTo: null, + type: transfer, + action: timeout, + createdAt: <timestamp>, + state: { + status: "success", + code: 0 + } + } + } + } + + + 9 + Publish Timeout event + Error code: + 2003 + + diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.plantuml b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.plantuml similarity index 100% rename from mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.plantuml rename to docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.plantuml diff --git a/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.svg b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.svg new file mode 100644 index 000000000..8c79f9dfd --- /dev/null +++ b/docs/technical/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.svg @@ -0,0 +1,302 @@ + + 2.3.2. Timeout Handler + + + 2.3.2. Timeout Handler + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + topic- + transfer-timeout + + + topic- + transfer-timeout + Transfer Timeout Handler + + + Transfer Timeout Handler + + + + + topic- + transfer-position + + + topic- + transfer-position + + + topic- + notification + + + topic- + notification + + + topic-event + + + topic-event + Timeout DAO + + + Timeout DAO + + + Central Store + + + Central Store + + + + + + + + + + + + + + + + + Timeout Handler Consume + + + 1 + Consume message + + + Persist Event Information + + + 2 + Publish event information + + + ref + Event Handler Consume +   + + + Get transfer info + + + 3 + Acquire transfer information + Error code: + 2003 + + + 4 + Get transfer data and state + + transfer + transferParticipant + participantCurrency + participant + transferStateChange + + + 5 + Return + transferInfo + + + 6 + Return + transferInfo + + + alt + [transferInfo.transferStateId == 'RECEIVED_PREPARE'] + + + 7 + Set EXPIRED_PREPARED state + Error code: + 2003 + + + 8 + Insert state change + + transferStateChange + + + 9 + Return success + + + Message: + { + id: <transferId>, + from: <payerParticipantId>, + to: <payeeParticipantId>, + type: application/json, + content: { +          + headers: + { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + }, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + type: notification, + action: timeout-received, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 10 + Publish Notification event + + [transferInfo.transferStateId == 'RESERVED'] + + + 11 + Set RESERVED_TIMEOUT state + Error code: + 2003 + + + 12 + Insert state change + + transferStateChange + + + 13 + Return success + + + Message: + { + id: <transferId>, + from: <payerParticipantId>, + to: <payeeParticipantId>, + type: application/json, + content: { +          + headers: + { + Content-Length: <Content-Length>, + Content-Type: <Content-Type>, + Date: <Date>, + X-Forwarded-For: <X-Forwarded-For>, + FSPIOP-Source: <FSPIOP-Source>, + FSPIOP-Destination: <FSPIOP-Destination>, + FSPIOP-Encryption: <FSPIOP-Encryption>, + FSPIOP-Signature: <FSPIOP-Signature>, + FSPIOP-URI: <FSPIOP-URI>, + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + }, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": <transferMessage.extensionList> + } + } + }, + metadata: { + event: { + id: <uuid>, + type: position, + action: timeout-reserved, + createdAt: <timestamp>, + state: { + status: 'error', + code: <errorInformation.errorCode> + description: <errorInformation.errorDescription> + } + } + } + } + + + 14 + Route & Publish Position event + Error code: + 2003 + + + + Any other state is ignored + + + Cleanup + + + 15 + Cleanup handled expiring transfer + Error code: + 2003 + + + 16 + Delete record + + expiringTransfer + + + 17 + Return success + + diff --git a/docs/technical/technical/central-ledger/transfers/1.1.0-prepare-transfer-request.md b/docs/technical/technical/central-ledger/transfers/1.1.0-prepare-transfer-request.md new file mode 100644 index 000000000..e98c606e8 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.1.0-prepare-transfer-request.md @@ -0,0 +1,16 @@ +# Prepare Transfer Request + +Sequence design diagram for Prepare Transfer Request process. + +## References within Sequence Diagram + +* [Prepare Handler Consume (1.1.1.a)](1.1.1.a-prepare-handler-consume.md) +* **Not Implemented** [Prepare Handler Consume (1.1.1.b)](1.1.1.b-prepare-handler-consume.md) +* [Position Handler Consume (1.1.2.a)](1.1.2.a-position-handler-consume.md) +* **Not Implemented** [Position Handler Consume (1.1.2.b)](1.1.2.b-position-handler-consume.md) +* [Send notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) +* **Not Implemented** [Send notification to Participant (1.1.4.b)](1.1.4.b-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-prepare-1.1.0.svg](../assets/diagrams/sequence/seq-prepare-1.1.0.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md b/docs/technical/technical/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md new file mode 100644 index 000000000..b0a401b5f --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md @@ -0,0 +1,11 @@ +# Prepare handler consume + +Sequence design diagram for Prepare Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.1.a.svg](../assets/diagrams/sequence/seq-prepare-1.1.1.a.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md b/docs/technical/technical/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md new file mode 100644 index 000000000..72e6784d5 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md @@ -0,0 +1,11 @@ +# Prepare handler consume + +Sequence design diagram for Prepare Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.1.b.svg](../assets/diagrams/sequence/seq-prepare-1.1.1.b.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.1.2.a-position-handler-consume.md b/docs/technical/technical/central-ledger/transfers/1.1.2.a-position-handler-consume.md new file mode 100644 index 000000000..8904fe97f --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.1.2.a-position-handler-consume.md @@ -0,0 +1,11 @@ +# Position handler consume + +Sequence design diagram for Position Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.2.a.svg](../assets/diagrams/sequence/seq-prepare-1.1.2.a.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.1.2.b-position-handler-consume.md b/docs/technical/technical/central-ledger/transfers/1.1.2.b-position-handler-consume.md new file mode 100644 index 000000000..161bea8d9 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.1.2.b-position-handler-consume.md @@ -0,0 +1,11 @@ +# Position handler consume + +Sequence design diagram for Position Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.2.b.svg](../assets/diagrams/sequence/seq-prepare-1.1.2.b.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.md b/docs/technical/technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.md new file mode 100644 index 000000000..9fd4fb1c5 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.md @@ -0,0 +1,11 @@ +# Send Notification to Participant v1.1 + +Sequence design diagram for the Send Notification to Participant request. + +## References within Sequence Diagram + +* [9.1.0-event-handler-consume](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.4.a-v1.1.svg](../assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md b/docs/technical/technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md new file mode 100644 index 000000000..12b1972d6 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md @@ -0,0 +1,11 @@ +# Send Notification to Participant + +Sequence design diagram for the Send Notification to Participant request. + +## References within Sequence Diagram + +* [9.1.0-event-handler-consume](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.4.a.svg](../assets/diagrams/sequence/seq-prepare-1.1.4.a.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md b/docs/technical/technical/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md new file mode 100644 index 000000000..c22b6c94f --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md @@ -0,0 +1,11 @@ +# Send Notification to Participant + +Sequence design diagram for the Send Notification to Participant request. + +## References within Sequence Diagram + +* [9.1.0-event-handler-consume](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.4.b.svg](../assets/diagrams/sequence/seq-prepare-1.1.4.b.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.md b/docs/technical/technical/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.md new file mode 100644 index 000000000..3f12ab0b1 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.md @@ -0,0 +1,14 @@ +# Position Handler Consume v1.1 + +Sequence design diagram for Position Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [Prepare Position Handler Consume (1.3.1)](1.3.1-prepare-position-handler-consume.md) +* [Fufil Position Handler Consume (1.3.2)](1.3.2-fulfil-position-handler-consume-v1.1.md) +* [Abort Position Handler Consume (1.3.3)](1.3.3-abort-position-handler-consume.md) + +## Sequence Diagram + +![seq-position-1.3.0-v1.1.svg](../assets/diagrams/sequence/seq-position-1.3.0-v1.1.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.3.0-position-handler-consume.md b/docs/technical/technical/central-ledger/transfers/1.3.0-position-handler-consume.md new file mode 100644 index 000000000..a3942172f --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.3.0-position-handler-consume.md @@ -0,0 +1,14 @@ +# Position Handler Consume + +Sequence design diagram for Position Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [Prepare Position Handler Consume (1.3.1)](1.3.1-prepare-position-handler-consume.md) +* [Fufil Position Handler Consume (1.3.2)](1.3.2-fulfil-position-handler-consume.md) +* [Abort Position Handler Consume (1.3.3)](1.3.3-abort-position-handler-consume.md) + +## Sequence Diagram + +![seq-position-1.3.0.svg](../assets/diagrams/sequence/seq-position-1.3.0.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md b/docs/technical/technical/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md new file mode 100644 index 000000000..2ab39456e --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md @@ -0,0 +1,7 @@ +# Prepare Position Handler Consume + +Sequence design diagram for Prepare Position Handler Consume process. + +## Sequence Diagram + +![seq-position-1.3.1-prepare.svg](../assets/diagrams/sequence/seq-position-1.3.1-prepare.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.md b/docs/technical/technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.md new file mode 100644 index 000000000..71799b0ea --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.md @@ -0,0 +1,7 @@ +# Fulfil Position Handler Consume v1.1 + +Sequence design diagram for Fulfil Position Handler Consume process. + +## Sequence Diagram + +![seq-position-1.3.2-fulfil-v1.1.svg](../assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md b/docs/technical/technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md new file mode 100644 index 000000000..25e5b2774 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md @@ -0,0 +1,7 @@ +# Fulfil Position Handler Consume + +Sequence design diagram for Fulfil Position Handler Consume process. + +## Sequence Diagram + +![seq-position-1.3.2-fulfil.svg](../assets/diagrams/sequence/seq-position-1.3.2-fulfil.svg) diff --git a/docs/technical/technical/central-ledger/transfers/1.3.3-abort-position-handler-consume.md b/docs/technical/technical/central-ledger/transfers/1.3.3-abort-position-handler-consume.md new file mode 100644 index 000000000..9ab80dc75 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/1.3.3-abort-position-handler-consume.md @@ -0,0 +1,7 @@ +# Abort Position Handler Consume + +Sequence design diagram for Abort Position Handler Consume process. + +## Sequence Diagram + +![seq-position-1.3.3-abort.svg](../assets/diagrams/sequence/seq-position-1.3.3-abort.svg) diff --git a/docs/technical/technical/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.md b/docs/technical/technical/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.md new file mode 100644 index 000000000..d7a71954f --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.md @@ -0,0 +1,13 @@ +# Fulfil Transfer Request success v1.1 + +Sequence design diagram for the Fulfil Success Transfer request. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Success) (2.1.1)](2.1.1-fulfil-handler-consume-v1.1.md) +* [Position Handler Consume (Success) (1.3.2)](1.3.2-fulfil-position-handler-consume-v1.1.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v1.1-v1.1.md) + +## Sequence Diagram + +![seq-fulfil-2.1.0-v1.1.svg](../assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.svg) diff --git a/docs/technical/technical/central-ledger/transfers/2.1.0-fulfil-transfer-request.md b/docs/technical/technical/central-ledger/transfers/2.1.0-fulfil-transfer-request.md new file mode 100644 index 000000000..c552a057a --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/2.1.0-fulfil-transfer-request.md @@ -0,0 +1,13 @@ +# Fulfil Transfer Request success + +Sequence design diagram for the Fulfil Success Transfer request. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Success) (2.1.1)](2.1.1-fulfil-handler-consume.md) +* [Position Handler Consume (Success) (1.3.2)](1.3.2-fulfil-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-fulfil-2.1.0.svg](../assets/diagrams/sequence/seq-fulfil-2.1.0.svg) diff --git a/docs/technical/technical/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.md b/docs/technical/technical/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.md new file mode 100644 index 000000000..69f2afa87 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.md @@ -0,0 +1,13 @@ +# Fulfil Handler Consume (Success) v1.1 + +Sequence design diagram for the Fulfil Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v1.1.md) + +## Sequence Diagram + +![seq-fulfil-2.1.1-v1.1.svg](../assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg) diff --git a/docs/technical/technical/central-ledger/transfers/2.1.1-fulfil-handler-consume.md b/docs/technical/technical/central-ledger/transfers/2.1.1-fulfil-handler-consume.md new file mode 100644 index 000000000..05f7e38f0 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/2.1.1-fulfil-handler-consume.md @@ -0,0 +1,13 @@ +# Fulfil Handler Consume (Success) + +Sequence design diagram for the Fulfil Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-fulfil-2.1.1.svg](../assets/diagrams/sequence/seq-fulfil-2.1.1.svg) diff --git a/docs/technical/technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.md b/docs/technical/technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.md new file mode 100644 index 000000000..ede9acee1 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.md @@ -0,0 +1,7 @@ +# Payee sends a Fulfil Abort Transfer request v1.1 + +Sequence design diagram for the Fulfil Reject Transfer process for version 1.1. of the API. + +## Sequence Diagram + +![seq-reject-2.2.0-v1.1.svg](../assets/diagrams/sequence/seq-reject-2.2.0-v1.1.svg) diff --git a/docs/technical/technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md b/docs/technical/technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md new file mode 100644 index 000000000..fc193a59d --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md @@ -0,0 +1,13 @@ +# [Outdated] Payee sends a Fulfil Reject Transfer request + +Sequence design diagram for the Fulfil Reject Transfer process. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Reject/Abort)(2.2.1)](2.2.1-fulfil-reject-handler.md) +* [Position Handler Consume (Reject)(1.3.3)](1.3.3-abort-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v1.1.md) + +## Sequence Diagram + +![seq-reject-2.2.0.svg](../assets/diagrams/sequence/seq-reject-2.2.0.svg) diff --git a/docs/technical/technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.md b/docs/technical/technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.md new file mode 100644 index 000000000..c50c356a0 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.md @@ -0,0 +1,13 @@ +# Payee sends a PUT call on /error end-point for a Transfer request v1.1 + +Sequence design diagram for the Fulfil Reject Transfer process for version 1.1. of the API. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Abort)(2.2.1)](2.2.1-fulfil-reject-handler-v1.1.md) +* [Position Handler Consume (Reject)(1.3.3)](1.3.3-abort-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v1.1.md) + +## Sequence Diagram + +![seq-reject-2.2.0.a-v1.1.svg](../assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.svg) diff --git a/docs/technical/technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md b/docs/technical/technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md new file mode 100644 index 000000000..0a1639855 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md @@ -0,0 +1,13 @@ +# Payee sends a PUT call on /error end-point for a Transfer request + +Sequence design diagram for the Fulfil Reject Transfer process. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Reject/Abort)(2.2.1)](2.2.1-fulfil-reject-handler.md) +* [Position Handler Consume (Reject)(1.3.3)](1.3.3-abort-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-reject-2.2.0.a.svg](../assets/diagrams/sequence/seq-reject-2.2.0.a.svg) diff --git a/docs/technical/technical/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.md b/docs/technical/technical/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.md new file mode 100644 index 000000000..1098c1c2f --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.md @@ -0,0 +1,7 @@ +# Fulfil Handler Consume (Reject/Abort) + +Sequence design diagram for the Fulfil Handler Consume Reject/Abort process for version 1.1. of the API. + +## Sequence Diagram + +![seq-reject-2.2.1-v1.1.svg](../assets/diagrams/sequence/seq-reject-2.2.1-v1.1.svg) diff --git a/docs/technical/technical/central-ledger/transfers/2.2.1-fulfil-reject-handler.md b/docs/technical/technical/central-ledger/transfers/2.2.1-fulfil-reject-handler.md new file mode 100644 index 000000000..b4512e034 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/2.2.1-fulfil-reject-handler.md @@ -0,0 +1,13 @@ +# Fulfil Handler Consume (Reject/Abort) + +Sequence design diagram for the Fulfil Handler Consume Reject/Abort process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-reject-2.2.1.svg](../assets/diagrams/sequence/seq-reject-2.2.1.svg) diff --git a/docs/technical/technical/central-ledger/transfers/2.3.0-transfer-timeout.md b/docs/technical/technical/central-ledger/transfers/2.3.0-transfer-timeout.md new file mode 100644 index 000000000..03d9f36c1 --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/2.3.0-transfer-timeout.md @@ -0,0 +1,13 @@ +# Transfer Timeout + +Sequence design diagram for the Transfer Timeout process. + +## References within Sequence Diagram + +* [Timeout Handler Consume (2.3.1)](2.3.1-timeout-handler-consume.md) +* [Position Handler Consume (Timeout)(1.3.3)](1.3.3-abort-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-timeout-2.3.0.svg](../assets/diagrams/sequence/seq-timeout-2.3.0.svg) diff --git a/docs/technical/technical/central-ledger/transfers/2.3.1-timeout-handler-consume.md b/docs/technical/technical/central-ledger/transfers/2.3.1-timeout-handler-consume.md new file mode 100644 index 000000000..dd1415f1f --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/2.3.1-timeout-handler-consume.md @@ -0,0 +1,11 @@ +# Timeout Handler Consume + +Sequence design diagram for the Timeout Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-timeout-2.3.1.svg](../assets/diagrams/sequence/seq-timeout-2.3.1.svg) diff --git a/docs/technical/technical/central-ledger/transfers/README.md b/docs/technical/technical/central-ledger/transfers/README.md new file mode 100644 index 000000000..ba8fc02cf --- /dev/null +++ b/docs/technical/technical/central-ledger/transfers/README.md @@ -0,0 +1,8 @@ +# Mojaloop Transfer operations + +Operational processes that is the core of the transfer operational process; + +- Prepare process +- Fulfil process +- Notifications process +- Reject/Abort process diff --git a/docs/technical/technical/deployment-guide/README.md b/docs/technical/technical/deployment-guide/README.md new file mode 100644 index 000000000..66ee65ccd --- /dev/null +++ b/docs/technical/technical/deployment-guide/README.md @@ -0,0 +1,487 @@ +# Mojaloop Deployment + +The document is intended for an audience with a stable technical knowledge that would like to setup an environment for development, testing and contributing to the Mojaloop project. + +## Deployment and Setup + +- [Mojaloop Deployment](#mojaloop-deployment) + - [Deployment and Setup](#deployment-and-setup) + - [1. Pre-requisites](#_1-pre-requisites) + - [2. Deployment Recommendations](#_2-deployment-recommendations) + - [3. Kubernetes](#_3-kubernetes) + - [3.1. Kubernetes Ingress Controller](#_3-1-kubernetes-ingress-controller) + - [3.2. Kubernetes Admin Interfaces](#_3-2-kubernetes-admin-interfaces) + - [4. Helm](#_4-helm) + - [4.1. Helm configuration](#_4-1-helm-configuration) + - [5. Mojaloop](#_5-mojaloop) + - [5.1. Backend Helm Deployment](#_5-1-prerequisite-backend-helm-deployment) + - [5.2. Mojaloop Helm Deployment](#_5-2-mojaloop-helm-deployment) + - [5.3. Verifying Ingress Rules](#_5-3-verifying-ingress-rules) + - [5.4. Testing Mojaloop](#_5-4-testing-mojaloop) + - [5.5. Testing Mojaloop with Postman](#_5-5-testing-mojaloop-with-postman) + - [6. Overlay Services/3PPI](#_6-overlay-services-3ppi) + - [6.1 Configuring a deployment for Third Party API support](#_6-1-configuring-a-deployment-for-third-party-api-support) + - [6.2 Validating and Testing the Third Party API](#_6-2-validating-and-testing-the-third-party-api) + - [6.2.1 Deploying the Simulators](#_6-2-1-deploying-the-simulators) + - [6.2.2 Provisioning the Environment](#_6-2-2-provisioning-the-environment) + - [6.2.3 Run the Third Party API Test Collection](#_6-2-3-run-the-third-party-api-test-collection) + +### 1. Pre-requisites + +Take particular care when choosing the software versions, as a miss-match may cause issues or incompatibilities. + +A list of the pre-requisite tool set required for the deployment of Mojaloop: + +- **Kubernetes** An open-source system for automating deployment, scaling, and management of containerized applications. Find out more about [Kubernetes](https://kubernetes.io). + + - **Recommended Versions** + + | Mojaloop Helm Chart Release Version | Recommended Kubernetes Version | + | ---------------------------------------------------------------- | -------------------------- | + | [v16.0.0](https://github.com/mojaloop/helm/releases/tag/v16.0.0) | v1.29 | + | [v15.0.0](https://github.com/mojaloop/helm/releases/tag/v15.0.0) | v1.24 - v1.25 | + | [v14.1.1](https://github.com/mojaloop/helm/releases/tag/v14.1.1) | v1.20 - v1.24 | + | [v14.0.0](https://github.com/mojaloop/helm/releases/tag/v14.0.0) | v1.20 - v1.21 | + | [v13.x](https://github.com/mojaloop/helm/releases/tag/v13.1.1) | v1.13 - v1.21 | + | [v12.x](https://github.com/mojaloop/helm/releases/tag/v12.0.0) | v1.13 - v1.20 | + | [v11.x](https://github.com/mojaloop/helm/releases/tag/v11.0.0) | v1.13 - v1.17 | + | [v10.x](https://github.com/mojaloop/helm/releases/tag/v10.4.0) | v1.13 - v1.15 | + + > NOTES: + > + > - Links above are to the latest major version (E.g. v13.x --> v13.1.1). + > - Refer to [https://github.com/mojaloop/helm/releases](https://github.com/mojaloop/helm/releases) for details on interim version. + > - `Recommend Kubernetes Version` column is the Kubernetes versions that have been tested and verified to work as expected against the matching `Mojaloop Helm Chart Release Version` column. + + - **kubectl** - Kubernetes CLI for Kubernetes Management is required. Find out more about [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/): + - [Install-kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) + +- **Helm** A package manager for Kubernetes. Find out more about [Helm](https://helm.sh) + + **Recommended Versions** + + - [Helm v3](https://helm.sh/docs/intro/install) + + > NOTES: + > + > - Refer to [Migration from Helm v2 to v3](https://docs.mojaloop.io/legacy/deployment-guide/helm-legacy-migration.html) guide to migrate from Helm v2.x to v3.x. + +### 2. Deployment Recommendations + +This provides environment resource recommendations with a view of the infrastructure architecture. + +**Resources Requirements:** + +- Control Plane (i.e. Master Node) + + [https://kubernetes.io/docs/setup/cluster-large/#size-of-master-and-master-components](https://kubernetes.io/docs/setup/cluster-large/#size-of-master-and-master-components) + + - 3x Master Nodes for future node scaling and HA (High Availability) + +- ETCd Plane: + + [https://etcd.io/docs/latest/op-guide/hardware/](https://etcd.io/docs/latest/op-guide/hardware/) + + - 3x ETCd nodes for HA (High Availability) + +- Compute Plane (i.e. Worker Node): + + To be confirmed once load testing has been concluded. However the current general recommended size: + + - 3x Worker nodes, each being: + - 4x vCPUs, 16GB of RAM, and 40gb storage + + **Note** that this would also depend on your underlying infrastructure, and it does NOT include requirements for persistent volumes/storage. + +![Mojaloop Deployment Recommendations - Infrastructure Architecture](./assets/diagrams/deployment/KubeInfrastructureArch.svg) + +### 3. Kubernetes + +If you are installing Kubernetes yourself, then we recommend using one of the following Kubernetes flavours ensuring you install the desired matching version as specified in section [1. Pre-requisites](#1-pre-requisites): + +- [k3s](https://docs.k3s.io/installation) - Flexible lightweight Kubernetes distribution that can be used for almost anything, spanning from local to Production grade environments. +- [Minikube](https://minikube.sigs.k8s.io/docs/start) - Simple platform agnostic single-node Kubernetes distribution that is useful for local or development environments. +- [Microk8s](https://microk8s.io/docs/install-alternatives) - Simple platform Kubernetes distribution that is useful for local or development environments. +- [Docker Desktop](https://docs.docker.com/desktop/kubernetes/) - Simple platform Kubernetes distribution that is useful for local or development environments (ensure you install applicable version that includes your target Kubernetes version by examining the [Docker Desktop release-notes](https://docs.docker.com/desktop/release-notes)). + +We do not specify a specific distribution of Kubernetes to be used, but rather any distribution of Kubernetes running on a [Cloud Native Computing Foundation (CNCF)](https://www.cncf.io/certification/software-conformance) certified distribution or managed solution (e.g. Azure, AWS, GCP) should be selected when testing new Mojaloop Releases. + +If you are new to Kubernetes it is strongly recommended to familiarize yourself with Kubernetes. [Kubernetes Concepts](https://kubernetes.io/docs/concepts/overview/) is a good place to start and will provide an overview. + +Insure **kubectl** is installed. A complete set of installation instruction are available [here](https://kubernetes.io/docs/tasks/tools/install-kubectl/). + +#### 3.1. Kubernetes Ingress Controller + +Install your preferred Ingress Controller for load-balancing and external access. + +Refer to the following documentation to install the Nginx-Ingress Controller used for this guide: . + +List of alternative Ingress Controllers: . + +Insure you install a supported `Ingress Controller` version that matches your target `Kubernetes` version. + +> **DEPLOYMENT TROUBLESHOOTING - Updated March 2023** +> +> - If you are using Mojaloop `v13.x` - `v14.0.x`, see [Deployment Troubleshooting - 1.1. Nginx-Ingress Controller support for Mojaloop Helm release v13.x - v14.0x.x support for Kubernetes v1.20 - v1.21](./depoyment/../deployment-troubleshooting.md#11-nginx-ingress-controller-support-for-mojaloop-helm-release-v13x---v140xx-support-for-kubernetes-v120---v121). +> +> - If you are using Mojaloop `v12.x`, see [Deployment Troubleshooting - 1.2. Nginx-Ingress Controller support for Mojaloop Helm release v12.x](./depoyment/../deployment-troubleshooting.md#12-nginx-ingress-controller-support-for-mojaloop-helm-release-v12x). +> +> - If you are using Mojaloop `v10.x`, see [Deployment Troubleshooting - 1.4.Mojaloop Helm release v10.x or less does not support Kubernetes v1.16 or greater](./depoyment/../deployment-troubleshooting.md#14-mojaloop-helm-release-v10x-or-less-does-not-support-kubernetes-v116-or-greater). +> + +#### 3.2. Kubernetes Admin Interfaces (Optional) + +1. Kubernetes Dashboards + + The official Kubernetes Web UI Admin interface. + + Visit the following link for installation instructions (not needed if **MicroK8s** is installed): [Web UI (Dashboard) Installation Instructions](https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/). + + **IMPORTANT:** Ensure (not needed if **MicroK8s** is installed) you configure RBAC roles and create an associated service account, refer to the following example on how to create a sample user for testing purposes only: [Creating sample user](https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md). + + If you have installed MicroK8s, **enable the MicroK8s** dashboard: + + ```bash + microk8s.enable dashboard + ``` + + Refer to the following link for more information: [Add-on: dashboard](https://microk8s.io/docs/addon-dashboard). + + **Remember** to prefix all **kubectl** commands with **MicroK8s** if you opted not to create an alias. + +2. k8sLens + + A local desktop GUI based kubectl alternative which is easy to install and setup. + + Visit the following link for more information: . + +### 4. Helm + +Please review [Mojaloop Helm Chart](../repositories/helm.md) to understand the relationships between the deployed Mojaloop helm charts. + +Refer to the official documentation on how to install the latest version of Helm: . + +Refer to the following document if are using Helm v2: [Deployment with (Deprecated) Helm v2](https://docs.mojaloop.io/legacy/deployment-guide/helm-legacy-deployment.html). + +Refer to the [Helm v2 to v3 Migration Guide](https://docs.mojaloop.io/legacy/deployment-guide/helm-legacy-migration.html) if you wish to migrate an existing Helm v2 deployment to v3. + +#### 4.1. Helm configuration + +1. Add mojaloop repo to your Helm config: + + ```bash + helm repo add mojaloop https://mojaloop.io/helm/repo/ + ``` + + If the repo already exists, substitute 'add' with 'apply' in the above command. + +2. Update helm repositories: + + ```bash + helm repo update + ``` + +### 5. Mojaloop + +#### 5.1. Prerequisite Backend Helm Deployment + +Mojaloop has several external backend dependencies. + +We recommend deploying these dependencies in a separate named deployment. + +This example backend chart is provided purely as an example and should only be used for PoC, development and testing purposes. + +Further reading can be found [here](https://github.com/mojaloop/helm/blob/master/README.md#deploying-backend-dependencies). + +1. Deploy backend + + ```bash + helm ---namespace demo install backend mojaloop/example-mojaloop-backend --create-namespace + ``` + +#### 5.2. Mojaloop Helm Deployment + +1. Install Mojaloop: + + 1.1. Installing latest version: + + ```bash + helm --namespace demo install moja mojaloop/mojaloop --create-namespace + ``` + + Or if you require a customized configuration: + + ```bash + helm --namespace demo install moja mojaloop/mojaloop --create-namespace -f {custom-values.yaml} + ``` + + Further reading can be found [here](https://github.com/mojaloop/helm/blob/master/README.md#deploying-mojaloop-helm-charts). + + _Note: Download and customize the [values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml). Also ensure that you are using the value.yaml (i.e. `https://github.com/mojaloop/helm/blob/v/mojaloop/values.yaml`) from the correct version which can be found via [Helm Releases](https://github.com/mojaloop/helm/releases). You can confirm the installed version by using the following command: `helm --namespace demo list`. Under the **CHART** column, you should see something similar to 'mojaloop-**{version}**' with **{version}** being the deployed version._ + + ```bash + $ helm -n demo list + NAME NAMESPACE REVISION UPDATED STATUS CHART + moja demo 1 2021-06-11 15:06:04.533094 +0200 SAST deployed mojaloop-{version} + ``` + + _Note: The `--create-namespace` flag is only necessary if the `demo` namespace does not exist. You can alternatively create it using the following command: `kubectl create namespace demo`._ + + 1.2. Version specific installation: + + ```bash + helm --namespace demo install moja mojaloop/mojaloop --create-namespace --version {version} + ``` + + 1.3. List of Mojaloop releases: + + ```bash + $ helm search repo mojaloop/mojaloop -l + NAME CHART VERSION APP VERSION DESCRIPTION + mojaloop/mojaloop {version} {list of app-versions} Mojaloop Helm chart for Kubernetes + ... ... ... ... + ``` + +#### 5.3. Verifying Ingress Rules + +1. Update your /etc/hosts for local deployment: + + _Note: This is only applicable for local deployments, and is not needed if custom DNS or ingress rules are configured in a customized [values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml)_. + + ```bash + vi /etc/hosts + ``` + + _Windows the file can be updated in notepad - need to open with Administrative privileges. File location `C:\Windows\System32\drivers\etc\hosts`_. + + Include the following lines (_or alternatively combine them_) to the host config. + + The below required config is applicable to Helm release >= versions 6.2.2 for Mojaloop API Services; + + ```bash + # Mojaloop Demo + 127.0.0.1 ml-api-adapter.local central-ledger.local account-lookup-service.local account-lookup-service-admin.local quoting-service.local central-settlement-service.local transaction-request-service.local central-settlement.local bulk-api-adapter.local moja-simulator.local sim-payerfsp.local sim-payeefsp.local sim-testfsp1.local sim-testfsp2.local sim-testfsp3.local sim-testfsp4.local mojaloop-simulators.local finance-portal.local operator-settlement.local settlement-management.local testing-toolkit.local testing-toolkit-specapi.local + ``` + +2. Test system health in your browser after installation. This will only work if you have an active helm chart deployment running. + + _Note: The examples below are only applicable to a local deployment. The entries should match the DNS values or ingress rules as configured in the [values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml) or otherwise matching any custom ingress rules configured_. + + **ml-api-adapter** health test: + + **central-ledger** health test: + +#### 5.4. Testing Mojaloop + +The [Mojaloop Testing Toolkit](../../documentation/mojaloop-technical-overview/ml-testing-toolkit/README.md) (**TTK**) is used for testing deployments, and has been integrated into Helm utilizing its CLI to easily test any Mojaloop deployment. + +1. Validating Mojaloop using Helm + + ```bash + helm -n demo test moja + ``` + + Or with logs printed to console + + ```bash + helm -n demo test moja --logs + ``` + + This will automatically execute the following [test cases](https://github.com/mojaloop/testing-toolkit-test-cases) using the [Mojaloop Testing Toolkit](../../documentation/mojaloop-technical-overview/ml-testing-toolkit/README.md) (**TTK**) CLI: + + - [TTK Hub setup and Simulator Provisioning Collection](https://github.com/mojaloop/testing-toolkit-test-cases/tree/master/collections/hub/provisioning). + + Use the following command to view the provisioning Collection logs: + + ```bash + kubectl -n demo logs pod/moja-ml-ttk-test-setup + ``` + + - [TTK Golden Path Test Collection](https://github.com/mojaloop/testing-toolkit-test-cases/tree/master/collections/hub/golden_path). + + Use the following command to view the Golden Path Collection logs: + + ```bash + kubectl -n demo logs pod/moja-ml-ttk-test-validation + ``` + + Example of the finally summary being displayed from the Golden Path test collection log output: + + ```bash + Test Suite:GP Tests + Environment:Development + ┌───────────────────────────────────────────────────┐ + │ SUMMARY │ + ├───────────────────┬───────────────────────────────┤ + │ Total assertions │ 1557 │ + ├───────────────────┼───────────────────────────────┤ + │ Passed assertions │ 1557 │ + ├───────────────────┼───────────────────────────────┤ + │ Failed assertions │ 0 │ + ├───────────────────┼───────────────────────────────┤ + │ Total requests │ 297 │ + ├───────────────────┼───────────────────────────────┤ + │ Total test cases │ 61 │ + ├───────────────────┼───────────────────────────────┤ + │ Passed percentage │ 100.00% │ + ├───────────────────┼───────────────────────────────┤ + │ Started time │ Fri, 11 Jun 2021 15:45:53 GMT │ + ├───────────────────┼───────────────────────────────┤ + │ Completed time │ Fri, 11 Jun 2021 15:47:25 GMT │ + ├───────────────────┼───────────────────────────────┤ + │ Runtime duration │ 91934 ms │ + └───────────────────┴───────────────────────────────┘ + TTK-Assertion-Report-multi-2021-06-11T15:47:25.656Z.html was generated + ``` + +2. Accessing the Mojaloop Testing Toolkit UI + + Open the following link in a browser: . + + One is able to manually load and execute the Testing Toolkit Collections using the UI which allows one to visually inspect the requests, responses and assertions in more detail. This is a great way to learn more about Mojaloop. + + Refer to the [Mojaloop Testing Toolkit Documentation](../../documentation/mojaloop-technical-overview/ml-testing-toolkit/README.md) for more information and guides. + +#### 5.5. Testing Mojaloop with Postman + +[Postman](https://www.postman.com/downloads) can be used as an alternative to the [Mojaloop Testing Toolkit](../../documentation/mojaloop-technical-overview/ml-testing-toolkit/README.md). Refer to the [Automated Testing Guide](../contributors-guide/tools-and-technologies/automated-testing.md) for more information. + +The available [Mojaloop Postman Collections](https://github.com/mojaloop/postman) are similar to the [Mojaloop Testing Toolkit's Test Cases](https://github.com/mojaloop/testing-toolkit-test-cases)'s as follows: + +| Postman Collection | Mojaloop Testing Toolkit | Description | +|---------|----------|---------| +| [MojaloopHub_Setup Postman Collection](https://github.com/mojaloop/postman/blob/master/MojaloopHub_Setup.postman_collection.json) and [MojaloopSims_Onboarding](https://github.com/mojaloop/postman/blob/master/MojaloopSims_Onboarding.postman_collection.json) | [TTK Hub setup and Simulator Provisioning Collection](https://github.com/mojaloop/testing-toolkit-test-cases/tree/master/collections/hub/provisioning) | Hub Setup and Simulator Provisioning | +| [Golden_Path_Mojaloop](https://github.com/mojaloop/postman/blob/master/Golden_Path_Mojaloop.postman_collection.json) | [TTK Golden Path Test Collection](https://github.com/mojaloop/testing-toolkit-test-cases/tree/master/collections/hub/golden_path) | Golden Path Tests | + +Pre-requisites: + +- The following postman environment file should be imported or customized as required when running the above listed Postman collections: [Mojaloop-Local-MojaSims.postman_environment.json](https://github.com/mojaloop/postman/blob/master/environments/Mojaloop-Local-MojaSims.postman_environment.json). +- Ensure you download the **latest patch release version** from the [Mojaloop Postman Git Repository Releases](https://github.com/mojaloop/postman/releases). For example if you install Mojaloop v12.0.**X**, ensure that you have the latest Postman collection patch version v12.0.**Y**. + +### 6. Overlay Services/3PPI + +As of [R.C. v13.1.0](https://github.com/mojaloop/helm/tree/release/v13.1.0) of Mojaloop, Third Party API is supported and will be published with the official release of Mojaloop v13.1.0. +which allows Third Party Payment Initiators (3PPIs) the ability to request an account link from a DFSP and initiate +payments on behalf of users. + +> Learn more about 3PPI: +> - Mojaloop's [Third Party API](https://github.com/mojaloop/mojaloop-specification/tree/master/thirdparty-api) +> - 3rd Party Use Cases: +> - [3rd Party Account Linking](https://sandbox.mojaloop.io/usecases/3ppi-account-linking.html) +> - [3rd Party Initiated Payments](https://sandbox.mojaloop.io/usecases/3ppi-transfer.html) + + +#### 6.1 Configuring a deployment for Third Party API support + +Third Party API support is **off** by default on the Mojaloop deployment. You can enable it by editing your `values.yaml` +file with the following settings: + +```yaml +... +account-lookup-service: + account-lookup-service: + config: + featureEnableExtendedPartyIdType: true # allows the ALS to support newer THIRD_PARTY_LINK PartyIdType + + account-lookup-service-admin: + config: + featureEnableExtendedPartyIdType: true # allows the ALS to support newer THIRD_PARTY_LINK PartyIdType + +... + +thirdparty: + enabled: true +... +``` + +In addition, the Third Party API has a number of dependencies that must be deployed manually for the thirdparty services +to run. [mojaloop/helm/thirdparty](https://github.com/mojaloop/helm/tree/master/thirdparty) contains details of these +dependencies, and also provides example k8s config files that install these dependencies for you. + +```bash +# install redis and mysql for the auth-service +kubectl apply --namespace demo -f https://raw.githubusercontent.com/mojaloop/helm/master/thirdparty/chart-auth-svc/example_dependencies.yaml +# install mysql for the consent oracle +kubectl apply --namespace demo -f https://raw.githubusercontent.com/mojaloop/helm/master/thirdparty/chart-consent-oracle/example_dependencies.yaml + +# apply the above changes to your values.yaml file, and update your mojaloop installation to deploy thirdparty services: +helm upgrade --install --namespace demo moja mojaloop/mojaloop -f values.yaml +``` + +Once the helm upgrade has completed, you can verify that the third party services are up and running: + +```bash +kubectl get po | grep tp-api +# tp-api-svc-b9bf78564-4g59d 1/1 Running 0 7m17s + +kubectl get po | grep auth-svc +# auth-svc-b75c954d4-9vq7w 1/1 Running 0 8m5s + +kubectl get po | grep consent-oracle +# consent-oracle-849cb69769-vq4rk 1/1 Running 0 8m31s + + +# and also make sure the ingress is exposed correctly +curl -H "Host: tp-api-svc.local" /health +# {"status":"OK","uptime":3545.77290063,"startTime":"2021-11-04T05:41:32.861Z","versionNumber":"11.21.0","services":[]} + +curl -H "Host: auth-service.local" /health + +# {"status":"OK","uptime":3682.48869561,"startTime":"2021-11-04T05:43:19.056Z","versionNumber":"11.10.1","services":[]} + +curl -H "Host: consent-oracle.local" /health +# {"status":"OK","uptime":3721.520096665,"startTime":"2021-11-04T05:43:48.382Z","versionNumber":"0.0.8","services":[]} +``` + +> You can also add the following entries to your `/etc/hosts` file to make it easy to talk to the thirdparty services +> +> ```bash +> tp-api-svc.local auth-service.local consent-oracle.local +> ``` + +#### 6.2 Validating and Testing the Third Party API + +Once you have deployed the Third Party services, you need to deploy some simulators that are capable of simulating +the Third Party scenarios. + +##### 6.2.1 Deploying the Simulators + +Once again, you can do this by modifying your `values.yaml` file, this time under the `mojaloop-simulator` entry: + +```yaml +... + +mojaloop-simulator: + simulators: + ... + pisp: + config: + thirdpartysdk: + enabled: true + dfspa: + config: + thirdpartysdk: + enabled: true + dfspb: {} +... +``` + +The above entry will create 3 new sets of mojaloop simulators: + +1. `pisp` - a PISP +2. `dfspa` - a DFSP that supports the Third Party API +3. `dfspb` - a normal DFSP simulator that doesn't support the Third Party API, but can receive payments + +##### 6.2.2 Provisioning the Environment + +Once the above simulators have been deployed and are up and running, it's time to configure the Mojaloop Hub +and simulators so we can test the Third Party API. + +Use the [Third Party Provisioning Collection](https://github.com/mojaloop/testing-toolkit-test-cases#third-party-provisioning-collection) +from the mojaloop/testing-toolkit-test cases to provision the Third Party environment and the simulators +you set up in the last step. + +##### 6.2.3 Run the Third Party API Test Collection + +Once the provisioning steps are completed, you can run the [Third Party Test Collection](https://github.com/mojaloop/testing-toolkit-test-cases#third-party-test-collection) +to test that the Third Party services are deployed and configured correctly. diff --git a/docs/technical/technical/deployment-guide/assets/diagrams/deployment/KubeInfrastructureArch.svg b/docs/technical/technical/deployment-guide/assets/diagrams/deployment/KubeInfrastructureArch.svg new file mode 100644 index 000000000..26b8dcd92 --- /dev/null +++ b/docs/technical/technical/deployment-guide/assets/diagrams/deployment/KubeInfrastructureArch.svg @@ -0,0 +1,2 @@ + + diff --git a/docs/technical/technical/deployment-guide/assets/diagrams/repositoryUpdate/repository-update-sequence.mmd b/docs/technical/technical/deployment-guide/assets/diagrams/repositoryUpdate/repository-update-sequence.mmd new file mode 100644 index 000000000..71f8607d9 --- /dev/null +++ b/docs/technical/technical/deployment-guide/assets/diagrams/repositoryUpdate/repository-update-sequence.mmd @@ -0,0 +1,30 @@ +graph TD + step1["Step 1: Base Libraries
    api-snippets
    ml-number
    central-services-logger
    central-services-metrics
    central-services-error-handling
    ml-testing-toolkit-shared-lib
    elastic-apm-node
    elastic-apm-node-opentracing"] + step2["Step 2: First-level Dependencies
    object-store-lib
    central-services-stream
    central-services-health
    inter-scheme-proxy-cache-lib"] + step3["Step 3: Second-level Dependencies
    event-sdk"] + step4["Step 4: Circular Dependency Group
    central-services-shared
    ml-schema-transformer-lib
    sdk-standard-components"] + step5["Step 5: Database Layer
    central-services-db"] + step6["Step 6: Platform Libraries
    logging-bc-public-types-lib
    platform-shared-lib-messaging-types-lib
    platform-shared-lib-nodejs-kafka-client-lib
    logging-bc-client-lib"] + step7["Step 7: Core Services
    central-ledger
    central-settlement"] + step8["Step 8: API Services
    sdk-scheme-adapter
    ml-api-adapter
    account-lookup-service
    auth-service"] + step9["Step 9: Remaining Services
    event-stream-processor
    event-sidecar
    central-event-processor
    bulk-api-adapter
    email-notifier
    ml-testing-toolkit
    ml-testing-toolkit-client-lib
    ml-testing-toolkit-ui
    quoting-service
    thirdparty-api-svc
    thirdparty-sdk
    transaction-requests-service
    als-oracle-pathfinder
    als-consent-oracle
    mojaloop-simulator
    simulator"] + note1["Note: The Step 4 repositories
    have circular dependencies.
    Update them as a unit."] + %% Clear update sequence arrows + step1 --> step2 + step2 --> step3 + step3 --> step4 + step4 --> step5 + %% Handle dependencies that can be updated in parallel + step5 --> step7 + step6 --> step8 + %% Platform libraries need special handling + step4 --> step6 + %% Final services depend on all previous updates + step7 --> step9 + step8 --> step9 + %% Connect notes + step4 --- note1 + %% Styling + classDef default fill:#f9f9f9,stroke:#333,stroke-width:1px; + classDef note fill:#ffffcc,stroke:#333,stroke-width:1px; + class note1 note; \ No newline at end of file diff --git a/docs/technical/technical/deployment-guide/assets/diagrams/repositoryUpdate/repository-update-sequence.svg b/docs/technical/technical/deployment-guide/assets/diagrams/repositoryUpdate/repository-update-sequence.svg new file mode 100644 index 000000000..6d55a9b6c --- /dev/null +++ b/docs/technical/technical/deployment-guide/assets/diagrams/repositoryUpdate/repository-update-sequence.svg @@ -0,0 +1 @@ +

    Step 1: Base Libraries
    api-snippets
    ml-number
    central-services-logger
    central-services-metrics
    central-services-error-handling
    ml-testing-toolkit-shared-lib
    elastic-apm-node
    elastic-apm-node-opentracing

    Step 2: First-level Dependencies
    object-store-lib
    central-services-stream
    central-services-health
    inter-scheme-proxy-cache-lib

    Step 3: Second-level Dependencies
    event-sdk

    Step 4: Circular Dependency Group
    central-services-shared
    ml-schema-transformer-lib
    sdk-standard-components

    Step 5: Database Layer
    central-services-db

    Step 6: Platform Libraries
    logging-bc-public-types-lib
    platform-shared-lib-messaging-types-lib
    platform-shared-lib-nodejs-kafka-client-lib
    logging-bc-client-lib

    Step 7: Core Services
    central-ledger
    central-settlement

    Step 8: API Services
    sdk-scheme-adapter
    ml-api-adapter
    account-lookup-service
    auth-service

    Step 9: Remaining Services
    event-stream-processor
    event-sidecar
    central-event-processor
    bulk-api-adapter
    email-notifier
    ml-testing-toolkit
    ml-testing-toolkit-client-lib
    ml-testing-toolkit-ui
    quoting-service
    thirdparty-api-svc
    thirdparty-sdk
    transaction-requests-service
    als-oracle-pathfinder
    als-consent-oracle
    mojaloop-simulator
    simulator

    Note: The Step 4 repositories
    have circular dependencies.
    Update them as a unit.

    \ No newline at end of file diff --git a/docs/technical/technical/deployment-guide/assets/diagrams/upgradeStrategies/helm-blue-green-upgrade-strategy.svg b/docs/technical/technical/deployment-guide/assets/diagrams/upgradeStrategies/helm-blue-green-upgrade-strategy.svg new file mode 100644 index 000000000..a5e597d9c --- /dev/null +++ b/docs/technical/technical/deployment-guide/assets/diagrams/upgradeStrategies/helm-blue-green-upgrade-strategy.svg @@ -0,0 +1,3 @@ + + +
    Target Data-layer Runtime Environment
    Kubernetes Cluster(s)
    Target Data-layer Runtime Environment...
    Mojaloop Runtime Environment
    Kubernetes Cluster(s)
    Mojaloop Runtime Environment...
    Mojaloop Target
    Deployment

    (New Release)
    Mojaloop Target...
    Mojaloop DMZ
    Mojaloop DMZ
    API
    Gateway
    API...
    DFSP(s)
    DFSP(...
    Sync & Data Migration

    (Transform data to new Schema)
    Sync & Data M...
    Backend Dependencies

    (MySQL, Kafka, etc)
    Backend Dependencies...
    Mojaloop Current
    Deployment
    +
    Backed Dependencies
    (MySQL, Kafka, etc)

    (Old Release)
    Mojaloop Current...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/technical/technical/deployment-guide/assets/diagrams/upgradeStrategies/helm-canary-upgrade-strategy.svg b/docs/technical/technical/deployment-guide/assets/diagrams/upgradeStrategies/helm-canary-upgrade-strategy.svg new file mode 100644 index 000000000..894431623 --- /dev/null +++ b/docs/technical/technical/deployment-guide/assets/diagrams/upgradeStrategies/helm-canary-upgrade-strategy.svg @@ -0,0 +1,3 @@ + + +
    Shared Data-layer Runtime Environment
    Kubernetes Cluster(s)
    Shared Data-layer Runtime Environment...
    Mojaloop Runtime Environment
    Kubernetes Cluster(s)
    Mojaloop Runtime Environment...
    Backend Dependencies

    (MySQL, Kafka, etc)
    Backend Dependencies...
    Mojaloop Current
    Deployment

    (Old Release)
    Mojaloop Current...
    Mojaloop Target
    Deployment

    (New Release)
    Mojaloop Target...
    Mojaloop DMZ
    Mojaloop DMZ
    API
    Gateway
    API...
    DFSP(s)
    DFSP(...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/technical/technical/deployment-guide/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.png b/docs/technical/technical/deployment-guide/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.png new file mode 100644 index 000000000..736a5190c Binary files /dev/null and b/docs/technical/technical/deployment-guide/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.png differ diff --git a/docs/technical/technical/deployment-guide/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.puml b/docs/technical/technical/deployment-guide/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.puml new file mode 100644 index 000000000..a87421d97 --- /dev/null +++ b/docs/technical/technical/deployment-guide/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.puml @@ -0,0 +1,107 @@ +@startuml dependency-vulnerability-management-process +!theme cerulean + +skinparam ActivityBackgroundColor #f0f0f0 +skinparam ActivityBorderColor #333333 +skinparam ArrowColor #333333 +skinparam backgroundColor white +skinparam ActivityFontColor black +skinparam ActivityFontSize 14 +skinparam noteFontColor black +skinparam ArrowFontColor black +skinparam PartitionFontColor #000000 +skinparam PartitionFontStyle bold +skinparam PartitionBorderColor #333333 +skinparam PartitionBackgroundColor #f8f8f8 + +title Dependency Vulnerability Management Process + +start + +partition "Vulnerability Detection Tools" { + :Identify Vulnerability; + fork + :GitHub Dependabot Alerts; + fork again + :npm run audit:check; + note right: audit-ci.jsonc with allowlist + fork again + :Grype Image Scan; + note right: .grype.yaml with ignore section + end fork +} + +partition "Triage Process" { + :Triage Vulnerability; + :Assess Severity Level; + fork + :Critical: 1-3 days; + note right #FF6666: Immediate attention + fork again + :High: 30 days; + note right #FFCC66: High priority + fork again + :Medium: 60 days; + note right #FFFF66: Medium priority + fork again + :Low: 90 days; + note right #99FF99: Low priority + end fork + :Take action based on severity level\nand fix date targets; +} + +partition "Update Process" { + :Select Single Module to Update; + :Update package.json; + :Run Tests; + if (Tests Pass?) then (Yes) + :Create Pull Request; + else (No) + if (Cannot Fix?) then (Yes) + fork + :Update audit-ci.jsonc; + note right #F9E0FF: For npm issues + fork again + :Update .grype.yaml; + note right #F9E0FF: For container issues + end fork + :Create Pull Request; + else (No) + :Adjust Update; + note right #F9E0FF + Consider Alternative Solutions + Contact Package Maintainer + end note + :Run Tests Again; + endif + endif + :Code Review Process; + if (Review Result) then (Approved) + :Merge PR; + else (Changes Requested) + :Update PR; + endif +} + +partition "CI/CD" { + :CI/CD Pipeline; + :Security Checks; + fork + :audit-ci Check; + fork again + :Grype Scan; + end fork + if (Checks Pass?) then (Yes) + :Release/Publish; + else (No) + :Fix Security Issues; + endif +} + +if (More Vulnerabilities?) then (Yes) + :Return to Select Module; +else (No) + stop +endif + +@enduml \ No newline at end of file diff --git a/docs/technical/technical/deployment-guide/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.svg b/docs/technical/technical/deployment-guide/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.svg new file mode 100644 index 000000000..0ef88f1e5 --- /dev/null +++ b/docs/technical/technical/deployment-guide/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.svg @@ -0,0 +1,305 @@ + + Dependency Vulnerability Management Process + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dependency Vulnerability Management Process + + + + Vulnerability Detection Tools + + Identify Vulnerability + + + GitHub Dependabot Alerts + + + audit-ci.jsonc with allowlist + + npm run audit:check + + + .grype.yaml with ignore section + + Grype Image Scan + + + + Triage Process + + Triage Vulnerability + + Assess Severity Level + + + + Immediate attention + + Critical: 1-3 days + + + High priority + + High: 30 days + + + Medium priority + + Medium: 60 days + + + Low priority + + Low: 90 days + + + Take action based on severity level + and fix date targets + + + Update Process + + Select Single Module to Update + + Update package.json + + Run Tests + + Tests Pass? + Yes + No + + Create Pull Request + + Cannot Fix? + Yes + No + + + + For npm issues + + Update audit-ci.jsonc + + + For container issues + + Update .grype.yaml + + + Create Pull Request + + + Consider Alternative Solutions + Contact Package Maintainer + + Adjust Update + + Run Tests Again + + + + Code Review Process + + Review Result + Approved + Changes Requested + + Merge PR + + Update PR + + + + CI/CD + + CI/CD Pipeline + + Security Checks + + + audit-ci Check + + Grype Scan + + + Checks Pass? + Yes + No + + Release/Publish + + Fix Security Issues + + + Return to Select Module + + Yes + More Vulnerabilities? + No + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/audit-check-script.png b/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/audit-check-script.png new file mode 100644 index 000000000..551ea6515 Binary files /dev/null and b/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/audit-check-script.png differ diff --git a/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/gh-dependabot-alert.png b/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/gh-dependabot-alert.png new file mode 100644 index 000000000..4c14b2661 Binary files /dev/null and b/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/gh-dependabot-alert.png differ diff --git a/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/gh-dependabot-alerts.png b/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/gh-dependabot-alerts.png new file mode 100644 index 000000000..a77a907b2 Binary files /dev/null and b/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/gh-dependabot-alerts.png differ diff --git a/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/grype-scan-vulnerabilities-ci.png b/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/grype-scan-vulnerabilities-ci.png new file mode 100644 index 000000000..d9d3a289b Binary files /dev/null and b/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/grype-scan-vulnerabilities-ci.png differ diff --git a/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/severity-id-allowed.png b/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/severity-id-allowed.png new file mode 100644 index 000000000..3a35c25b3 Binary files /dev/null and b/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/severity-id-allowed.png differ diff --git a/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/severity-level-allowed.png b/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/severity-level-allowed.png new file mode 100644 index 000000000..2c313578f Binary files /dev/null and b/docs/technical/technical/deployment-guide/assets/screenshots/vulnerabilityManagement/severity-level-allowed.png differ diff --git a/docs/technical/technical/deployment-guide/deployment-troubleshooting.md b/docs/technical/technical/deployment-guide/deployment-troubleshooting.md new file mode 100644 index 000000000..80b6bd732 --- /dev/null +++ b/docs/technical/technical/deployment-guide/deployment-troubleshooting.md @@ -0,0 +1,158 @@ +# Deployment Troubleshooting + +## 1. Known issues + +Refer to the **Mojaloop Helm Chart Release** notes for more information on known issues: [https://github.com/mojaloop/helm/releases](https://github.com/mojaloop/helm/releases). + +### 1.1. Nginx-Ingress Controller support for Mojaloop Helm release v13.x - v14.0x.x support for Kubernetes v1.20 - v1.21 + +If you are using Mojaloop `v13.x` - `v14.0.x`, and want to install the `Nginx-Ingress` controller, then it is recommended that you install `Nginx-Ingress Controller v0.47.0` along with `Kubernetes v1.20 - v1.21` due to breaking changes introduce in `Kubernetes v1.22`. + +If you are using helm, this can be done as follows: + +```bash +helm install ingress-nginx ingress-nginx --version="3.33.0" --repo https://kubernetes.thub.io/ingress-nginx +``` + +### 1.2. Nginx-Ingress Controller support for Mojaloop Helm release v12.x + +If you are installing Mojaloop v12.x with an Nginx-Ingress controller version newer than `v0.22.0`, ensure you create a custom [Mojaloop v12.0.0 values config](https://github.com/jaloop/helm/blob/v12.0.0/mojaloop/values.yaml) with the following changes prior to stall:** + +```YAML +## **LOOK FOR THIS LINE IN mojaloop/values.yaml CONFIG FILE** +mojaloop-simulator: + ingress: + ## nginx ingress controller >= v0.22.0 <-- **COMMENT THE FOLLOWING THREE LINES BELOW:** + # annotations: <-- COMMENTED + # nginx.ingress.kubernetes.io/rewrite-target: '/$2' <-- COMMENTED + # ingressPathRewriteRegex: (/|$)(.*) <-- COMMENTED + ## nginx ingress controller < v0.22.0 <-- **UNCOMMENT THE FOLLOWING THREE LINES LOW:** + annotations: + nginx.ingress.kubernetes.io/rewrite-target: '/' + ingressPathRewriteRegex: "/" +``` + +**Note: This is NOT necessary if you are installing Mojaloop v13.x or newer.** + +### 1.3. Docker Desktop Kubernetes support for Mojaloop v13.x - v14.0.x + +If you are installing Mojaloop `v13.x` - `v14.0.x`, on Windows or MacOS, it is recommend that you install [Docker Desktop v4.2.0](https://docs.docker.com/desktop/release-notes/#420) version as it comes packaged with Kubernetes v1.21.5 which meets Mojaloop `v13.x` - `v14.0.x` version which matches [Deployment Guide (1. Pre-requisites)](README.md#1-pre-requisites) recommendations. + +### 1.4. Mojaloop Helm release v10.x or less does not support Kubernetes v1.16 or greater + +#### 1.4.1 Description + +_Note: This is only applicable to Mojaloop Helm v10.x or less release._ + +When installing mojaloop helm charts, the following error occurs: + +```log +Error: validation failed: [unable to recognize "": no matches for kind "Deployment" in version "apps/v1beta2", unable to recognize "": no matches for kind "Deployment" in version "extensions/v1beta1", unable to recognize "": no matches for kind "StatefulSet" in version "apps/v1beta2", unable to recognize "": no matches for kind "StatefulSet" in version "apps/v1beta1"] +``` + +#### 1.4.2 Reason + +In version 1.16 of Kubernetes breaking change has been introduced (more about it [in "Deprecations and Removals" of Kubernetes release notes](https://kubernetes.io/docs/setup/release/notes/#deprecations-and-removals). The Kubernetes API versions `apps/v1beta1` and `apps/v1beta2`are no longer supported and and have been replaced by `apps/v1`. + +Mojaloop helm charts v10 or less refer to deprecated ids, therefore it's not possible to install v10- on Kubernetes version above 1.15 without manually modification. + +Refer to the following issue for more info: [mojaloop/helm#219](https://github.com/mojaloop/helm/issues/219) + +#### 1.4.3 Fixes + +Ensure that you are deploying Mojaloop Helm charts v10.x or less on v1.15 of Kubernetes. + +## 2. Deployment issues + +### 2.1. `ERR_NAME_NOT_RESOLVED` Error + +#### 2.1.1 Description + +The following error is displayed when attempting to access an end-point (e.g. central-ledger.local) via the Kubernetes Service directly in a browser: `ERR_NAME_NOT_RESOLVED` + +#### 2.1.2 Fixes + +1. Verify that Mojaloop was deployed correctly (by checking that the helm chart(s) was installed) by executing: + + ```bash + helm list + ``` + + If the helm charts are not listed, see the [Deployment Guide - 5.1. Mojaloop Helm Deployment](./README.md#51-mojaloop-helm-deployment) section to install a chart. + +2. Ensure that all the Mojaloop Pods/Containers have started up correctly and are available through the Kubernetes dashboard. + +3. Note that the Mojaloop deployment via Helm can take a few minutes to initially startup depending on the system's available resources and specification. Expect this to take anything between 2-10 minutes. + +### 2.3. MicroK8s - Connectivity Issues + +#### 2.3.1 Description + +My pods can’t reach the internet or each other (but my MicroK8s host machine can). + +An example of this is that the Central-Ledger logs indicate that there is an error with the Broker transport as per the following example: + +```log +2019-11-05T12:28:10.470Z - info: Server running at: +2019-11-05T12:28:10.474Z - info: Handler Setup - Registering {"type":"prepare","enabled":true}! +2019-11-05T12:28:10.476Z - info: CreateHandler::connect - creating Consumer for topics: [topic-transfer-prepare] +2019-11-05T12:28:10.515Z - info: CreateHandler::connect - successfully connected to topics: [topic-transfer-prepare] +2019-11-05T12:30:20.960Z - error: Consumer::onError()[topics='topic-transfer-prepare'] - Error: Local: Broker transport failure) +``` + +#### 2.3.2 Fixes + +Make sure packets to/from the pod network interface can be forwarded to/from the default interface on the host via the iptables tool. Such changes can be made persistent by installing the iptables-persistent package: + +```bash +sudo iptables -P FORWARD ACCEPT +sudo apt-get install iptables-persistent +``` + +or, if using ufw: + +```bash +sudo ufw default allow routed +``` + +The MicroK8s inspect command can be used to check the firewall configuration: + +```bash +microk8s.inspect +``` + +## 3. Ingress issues + +### 3.1. Ingress rules are not resolving for Nginx Ingress v0.22 or later when installing Mojaloop Helm v12.x or less + +#### 3.1.1 Description + +_Note: This is only applicable to Mojaloop Helm v12.x or less release._ + +Ingress rules are unable to resolve to the correct path based on the annotations specified in the [values.yaml](https://github.com/mojaloop/helm/blob/v12.0.0/mojaloop/values.yaml) configuration files when using Nginx Ingress controllers v0.22 or later. + +This is due to the changes introduced in Nginx Ingress controllers that are v0.22 or later as per the following link: https://kubernetes.github.io/ingress-nginx/examples/rewrite/#rewrite-target. + +#### 3.1.2 Fixes + +Make the following change to Ingress annotations (from --> to) in the values.yaml files: + +```yaml +nginx.ingress.kubernetes.io/rewrite-target: '/'` --> `nginx.ingress.kubernetes.io/rewrite-target: '/$1' +``` + +### 3.2. Ingress rules are not resolving for Nginx Ingress earlier than v0.22 + +#### 3.2.1 Description + +Ingress rules are unable to resolve to the correct path based on the annotations specified in the [values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml) configuration files when using Nginx Ingress controllers that are older than v0.22. + +This is due to the changes introduced in Nginx Ingress controllers that are v0.22 or later as per the following link: https://kubernetes.github.io/ingress-nginx/examples/rewrite/#rewrite-target. + +#### 3.2.2 Fixes + +Make the following change to all Ingress annotations (from --> to) in each of the values.yaml files: + +```yaml +nginx.ingress.kubernetes.io/rewrite-target: '/$1'` --> `nginx.ingress.kubernetes.io/rewrite-target: '/' +``` diff --git a/docs/technical/technical/deployment-guide/mojaloop-repository-update-guide.md b/docs/technical/technical/deployment-guide/mojaloop-repository-update-guide.md new file mode 100644 index 000000000..d4aa81c5d --- /dev/null +++ b/docs/technical/technical/deployment-guide/mojaloop-repository-update-guide.md @@ -0,0 +1,175 @@ +# Mojaloop Repository Update Sequence + +This document provides guidance on the order in which Mojaloop NodeJS repositories should be updated when releasing new features and/or maintaining Mojaloop. This is important to ensure that each of the services part of a Mojaloop Release use the correct Mojaloop repository dependency. This is the update as of Mojaloop RC v17; as Mojaloop evolves, this needs to be updated with new components (and clean up components that are removed). + +## Table of Contents + +- [NodeJS Repository Update Sequence](#nodejs-repository-update-sequence) + - [Table of Contents](#table-of-contents) + - [Repository Categories](#repository-categories) + - [Update Process](#update-process) + - [Testing Requirements](#testing-requirements) + - [Mojaloop Repo Sequence](#mojaloop-repo-sequence) + +## Repository Categories + +The following are the categories of Mojaloop NodeJS repositories: + +1. **Central Services libraries** + - `central-services-shared` + - `central-services-error-handling` + - `central-services-database` + - `central-services-stream` + - `central-services-metrics` + - `central-services-error` + - `central-services-logger` + - `sdk-standard-components` + +2. **Core Services** + - `account-lookup-service` + - `quoting-service` + - `central-ledger` + - `central-settlement` + - `central-bulk-transfers` + - `transaction-requests-service` + - `ml-api-adapter` + +3. **Event Components** + - `central-event-processor` + - `event-framework` + - `event-stream-processor` + - `elastic-apm-node` + - `elastic-apm-node-opentracing` + - `email-notifier` + - `event-sidecar` + +4. **Adapters, SDK and API** + - `sdk-scheme-adapter` + - `event-sdk` + - `thirdparty-sdk` + - `bulk-api-adapter` + - `thirdparty-api-svc` + - `als-consent-oracle` + - `als-oracle-pathfinder` + +5. **Testing** + - `ml-testing-toolkit` + - `ml-testing-toolkit-client-lib` + - `ml-testing-toolkit-ui` + - `ml-testing-toolkit-shared-lib` + - `mojaloop-simulator` + - `simulator` + +6. **Other libraries** + - `api-snippets` + - `auth-service` + - `ml-number` + - `object-store-lib` + - `inter-scheme-proxy-cache-lib` + - `database-lib` + +## Update Process + +1. **Identify Dependencies** + - Use `npm audit` to identify vulnerabilities + - Review `package.json` files for outdated dependencies + - Check for breaking changes in major version updates + +2. **Create Update Plan** + - Document all repositories that need updates + - Identify potential breaking changes + - Plan testing strategy for each component + +3. **Execute Updates** + - Start with core libraries + - Update one repository at a time + - Run tests after each update + - Document any issues or workarounds + +4. **Integration Testing** + - Test updated components together + - Verify end-to-end functionality + - Check for performance impacts (roadmap, post v17) + +## Testing Requirements + +For each repository, follow the testing instructions at README and run: + +1. **Unit Tests** + - Run existing test suite + - Add new tests for updated functionality + - Verify test coverage + +2. **Integration Tests** + - Test with dependent services + - Verify API compatibility + - Check event handling + +3. **End-to-End Tests** + - Run through Mojaloop testing toolkit + - Verify transaction flows + - Test error scenarios + + +## Mojaloop Repo Sequence + +The following table provides a detailed view of Mojaloop repositories and their dependencies. This information is crucial for understanding the correct order of updates when addressing dependency changes or vulnerabilities. + +| Sequence | Repo | Dependencies | +|---|---|---| +| 1 | api-snippets | | +| 2 | ml-number | | +| 3 | database-lib | | +| 4 | central-services-logger | | +| 5 | central-services-metrics | | +| 6 | central-services-error-handling | | +| 7 | ml-testing-toolkit-shared-lib | | +| 8 | logging-bc-public-types-lib | | +| 9 | platform-shared-lib-messaging-types-lib | | +| 10 | elastic-apm-node | | +| 11 | elastic-apm-node-opentracing | | +| 12 | object-store-libp | central-services-logger | +| 13 | central-services-stream | | +| 14 | central-services-health | central-services-error-handling, central-services-logger | +| 15 | event-sdk | central-services-stream, central-services-logger, central-services-stream | +| 16 | inter-scheme-proxy-cache-lib | central-services-logger, central-services-shared, inter-scheme-proxy-cache-lib, central-services-error-handling, central-services-logger, central-services-metrics, event-sdk | +| 17 | ml-schema-transformer-lib | central-services-error-handling, central-services-logger, central-services-shared, sdk-standard-components, ml-schema-transformer-lib | +| 18 | sdk-standard-components | | +| 19 | central-services-shared | | +| 20 | platform-shared-lib-nodejs-kafka-client-lib | | +| 21 | logging-bc-client-lib | | +| 22 | **account-lookup-service** | central-services-error-handling, central-services-health, central-services-logger, central-services-metrics, central-services-shared, central-services-stream, database-lib, event-sdk, inter-scheme-proxy-cache-lib, sdk-standard-components, sdk-standard-components, central-services-logger, central-services-shared, central-services-stream | +| 23 | **als-consent-oracle** | api-snippets, central-services-health, central-services-shared, sdk-standard-components, central-services-error-handling, central-services-logger, central-services-metrics, event-sdk | +| 24 | **als-oracle-pathfinder** | central-services-logger, central-services-shared | +| 25 | **auth-service** | api-snippets, central-services-health, central-services-shared, event-sdk, sdk-standard-components, central-services-error-handling, central-services-logger, central-services-metrics, event-sdk | +| 26 | **bulk-api-adapter** | central-services-error-handling, central-services-health, central-services-logger, central-services-metrics, central-services-shared, central-services-stream, event-sdk, object-store-lib | +| 27 | **central-event-processor** | central-services-error-handling, central-services-health, central-services-logger, central-services-metrics, central-services-shared, central-services-stream, event-sdk | +| 28 | **central-ledger** | central-services-error-handling, central-services-health, central-services-logger, central-services-metrics, central-services-shared, central-services-stream, database-lib, event-sdk, inter-scheme-proxy-cache-lib, ml-number, object-store-lib | +| 29 | **central-settlement** | central-ledger, central-services-database, central-services-error-handling, central-services-health, central-services-logger, central-services-shared, central-services-stream, event-sdk, ml-number | +| 30 | **email-notifier** | central-services-error-handling, central-services-health, central-services-logger, central-services-metrics, central-services-shared, central-services-stream, event-sdk | +| 31 | **event-sidecar** | central-services-logger, central-services-metrics, central-services-stream, event-sdk | +| 32 | **event-stream-processor** | central-services-health, central-services-logger, central-services-metrics, central-services-shared, central-services-stream, elastic-apm-node, elastic-apm-node-opentracing, event-sdk | +| 33 | **mojaloop-simulator** | central-services-logger | +| 34 | **ml-api-adapter** | central-services-error-handling, central-services-health, central-services-logger, central-services-metrics, central-services-shared, central-services-stream, event-sdk, sdk-standard-components, database-lib, inter-scheme-proxy-cache-lib | +| 35 | **ml-testing-toolkit** | central-services-logger, central-services-metrics, ml-schema-transformer-lib, ml-testing-toolkit-shared-lib, sdk-standard-components | +| 36 | **ml-testing-toolkit-client-lib** | central-services-logger, ml-testing-toolkit-shared-lib, sdk-standard-components | +| 37 | **ml-testing-toolkit-ui** | ml-testing-toolkit-shared-lib | +| 38 | **quoting-service** | central-services-error-handling, central-services-health, central-services-logger, central-services-metrics, central-services-shared, central-services-stream, event-sdk, inter-scheme-proxy-cache-lib, ml-number, sdk-standard-components | +| 39 | **simulator** (legacy, ALS oracle) | central-services-error-handling, central-services-logger, central-services-metrics, central-services-shared, event-sdk, sdk-standard-components | +| 40 | **sdk-scheme-adapter** | api-snippets, central-services-error-handling, central-services-logger, central-services-metrics, central-services-shared, event-sdk, sdk-standard-components | +| 41 | **thirdparty-api-svc** | api-snippets, central-services-shared, central-services-stream, central-services-error-handling, central-services-logger, central-services-metrics, event-sdk | +| 42 | **thirdparty-sdk** | api-snippets, central-services-error-handling, central-services-metrics, central-services-shared, sdk-scheme-adapter, sdk-standard-components | +| 43 | **transaction-requests-service** | central-services-error-handling, central-services-health, central-services-logger, central-services-metrics, central-services-shared, event-sdk, ml-testing-toolkit-shared-lib | + +### Update Sequence Visualization + +The following diagram illustrates the recommended update sequence for Mojaloop repositories, taking into account their dependencies and relationships: + +![Repository Update Sequence](./assets/diagrams/repositoryUpdate/repository-update-sequence.svg) + +This diagram provides a visual representation of the update sequence, showing: +1. The logical grouping of repositories +2. Dependencies between different groups +3. Special cases like circular dependencies +4. Parallel update possibilities +5. Different types of dependencies to consider \ No newline at end of file diff --git a/docs/technical/technical/deployment-guide/nodejs-dependency-update-guide.md b/docs/technical/technical/deployment-guide/nodejs-dependency-update-guide.md new file mode 100644 index 000000000..53d368de3 --- /dev/null +++ b/docs/technical/technical/deployment-guide/nodejs-dependency-update-guide.md @@ -0,0 +1,41 @@ +The following diagram illustrates the recommended update sequence for Mojaloop repositories, taking into account their dependencies and relationships: + +```mermaid +graph TD + step1["Step 1: Base Libraries
    api-snippets
    ml-number
    central-services-logger
    central-services-metrics
    central-services-error-handling
    ml-testing-toolkit-shared-lib
    elastic-apm-node
    elastic-apm-node-opentracing"] + step2["Step 2: First-level Dependencies
    object-store-lib
    central-services-stream
    central-services-health
    inter-scheme-proxy-cache-lib"] + step3["Step 3: Second-level Dependencies
    event-sdk"] + step4["Step 4: Circular Dependency Group
    central-services-shared
    ml-schema-transformer-lib
    sdk-standard-components"] + step5["Step 5: Database Layer
    central-services-db"] + step6["Step 6: Platform Libraries
    logging-bc-public-types-lib
    platform-shared-lib-messaging-types-lib
    platform-shared-lib-nodejs-kafka-client-lib
    logging-bc-client-lib"] + step7["Step 7: Core Services
    central-ledger
    central-settlement"] + step8["Step 8: API Services
    sdk-scheme-adapter
    ml-api-adapter
    account-lookup-service
    auth-service"] + step9["Step 9: Remaining Services
    event-stream-processor
    event-sidecar
    central-event-processor
    bulk-api-adapter
    email-notifier
    ml-testing-toolkit
    ml-testing-toolkit-client-lib
    ml-testing-toolkit-ui
    quoting-service
    thirdparty-api-svc
    thirdparty-sdk
    transaction-requests-service
    als-oracle-pathfinder
    als-consent-oracle
    mojaloop-simulator
    simulator"] + note1["Note: The Step 4 repositories
    have circular dependencies.
    Update them as a unit."] + %% Clear update sequence arrows + step1 --> step2 + step2 --> step3 + step3 --> step4 + step4 --> step5 + %% Handle dependencies that can be updated in parallel + step5 --> step7 + step6 --> step8 + %% Platform libraries need special handling + step4 --> step6 + %% Final services depend on all previous updates + step7 --> step9 + step8 --> step9 + %% Connect notes + step4 --- note1 + %% Styling + classDef default fill:#f9f9f9,stroke:#333,stroke-width:1px; + classDef note fill:#ffffcc,stroke:#333,stroke-width:1px; + class note1 note; +``` + +This diagram provides a visual representation of the update sequence, showing: +1. The logical grouping of repositories +2. Dependencies between different groups +3. Special cases like circular dependencies +4. Parallel update possibilities +5. Different types of dependencies to consider \ No newline at end of file diff --git a/docs/technical/technical/deployment-guide/upgrade-strategy-guide.md b/docs/technical/technical/deployment-guide/upgrade-strategy-guide.md new file mode 100644 index 000000000..8945deacc --- /dev/null +++ b/docs/technical/technical/deployment-guide/upgrade-strategy-guide.md @@ -0,0 +1,188 @@ +# Upgrade Strategy Guide + +This document provides instructions on how to upgrade existing Mojaloop installations. It assumes that Mojaloop is already installed using Helm, but these strategies can be applied in general. + +## Table of Contents + +- [Upgrade Strategy Guide](#upgrade-strategy-guide) + - [Table of Contents](#table-of-contents) + - [Helm Upgrades](#helm-upgrades) + - [Non-breaking Releases](#non-breaking-releases) + - [Breaking Releases](#breaking-releases) + - [Mojaloop installed without backend dependencies](#mojaloop-installed-without-backend-dependencies) + - [1. Target version has no datastore breaking changes](#1-target-version-has-no-datastore-breaking-changes) + - [Example Canary style deployment](#example-canary-style-deployment) + - [2. Target version has datastore breaking changes](#2-target-version-has-datastore-breaking-changes) + - [Mojaloop installed with backend dependencies](#mojaloop-installed-with-backend-dependencies) + - [Example Blue-green style deployment](#example-blue-green-style-deployment) + - [Upgrade Commands](#upgrade-commands) + - [Upgrade to v17.0.0](#upgrade-to-v17.0.0) + - [Testing the upgrade scenario from v16.0.0 to v17.0.0](#testing-the-upgrade-scenario-from-v16.0.0-to-v17.0.0) + +## Helm Upgrades + +This section discusses the strategies of how upgrades could be applied to an existing Mojaloop Helm deployment that uses the [Mojaloop Helm Charts](https://github.com/mojaloop/helm). + +The scope of the breaking changes described below are applicable to the Switch Operator's Helm deployment with no direct impact (i.e. no functional changes such as a new Mojaloop API Specification version) to Participants (e.g. Financial Services Providers). Such functional changes may be part of a Helm release, but are out of scope for this section. + +Recommendations: + +1. All upgrades should be tested and verified in a pre-production (Test or QA) environment +2. Always consult the release notes as there may be some known issues, or useful notes that are applicable when upgrading +3. The [migrate:list command](https://knexjs.org/#Migrations) can be used to list pending datastore changes in the following repositories: + - + - + +### Non-breaking Releases + +Non-breaking changes will require no additional or special actions (unless otherwise stated in the release notes) to be taken other than running a standard [Helm upgrade](https://helm.sh/docs/helm/helm_upgrade) command. + +Be aware of the following optional parameter flag(s) that will be useful when upgrading: + +``` + -i, --install if a release by this name doesn't already exist, run an install + --reuse-values when upgrading, reuse the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' is specified, this is ignored + --version string specify a version constraint for the chart version to use. This constraint can be a specific tag (e.g. 1.1.1) or it may reference a valid range (e.g. ^2.0.0). If this is not specified, the latest version is used +``` + +See the following example of how these parameters can be applied: + +```bash +helm --namespace ${NAMESPACE} ${RELEASE_NAME} upgrade --install mojaloop/mojaloop --reuse-values --version ${RELEASE_VERSION} +``` + +It is possible to rollback using the [Helm rollback](https://helm.sh/docs/helm/helm_rollback/) command if desired. + +### Breaking Releases + +There are several strategies that can be employed when upgrading between breaking releases depending on the following deployment topologies: + +1. Mojaloop installed without backend dependencies (e.g. Kafka, MySQL, MongoDB, etc), with backend dependencies managed separately. This is preferred and will provide the most flexibility in upgrading, especially when there are breaking changes + +2. Mojaloop installed with backend dependencies, with backend dependencies tightly coupled to the Helm installation + + > *NOTE: This process will be deprecated from Mojaloop v15.0.0 onwards (including v15) though example backend deployment support is provided for testing, QA. Refer to section [5. BREAKING CHANGES](https://github.com/mojaloop/helm/blob/master/.changelog/release-v15.0.0.md#5-breaking-changes) section in the [v15.0.0 Release Notes](https://github.com/mojaloop/helm/blob/master/.changelog/release-v15.0.0.md).* + + +#### Mojaloop installed without backend dependencies + +This is the preferred deployment topology as it will provide the most flexibility when upgrading. By separating out the backend dependencies, it will enable one to deploy the target version of Mojaloop as a new deployment. + +This new deployment can either point to the existing backend dependencies or will require new backend dependencies depending on the following: + +##### 1. Target version has no datastore breaking changes + +In this scenario, we can utilise a Canary style deployment strategy by configuring the new deployment to the existing backend dependencies. The new deployment will by default upgrade the datastore schemas as required by running the `migration` (see [Central-ledger](https://github.com/mojaloop/central-ledger/tree/master/migrations), [Account-lookup-service](https://github.com/mojaloop/account-lookup-service/tree/master/migrations)) scripts. Alternatively, the migration scripts can be disabled (e.g. [central-ledger](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml#L147), with Account-lookup-service similarly being configured) if required, and a manual upgrade SQL script can be prepared (see [migrate:list command](https://knexjs.org/#Migrations) to list pending changes) if preferred. + +There should be no disruption to the current Mojaloop deployment. + +As the backend dependencies are shared between the current and target deployments, it will also be possible to move a sub-set of users to the target Mojaloop deployment allowing for one to validate the new deployment with minimal impact, and also provide the ability for users to easily switch back to the current deployment. + +###### Example Canary style deployment + +![Helm Canary Upgrade Strategy](./assets/diagrams/upgradeStrategies/helm-canary-upgrade-strategy.svg) + +1. Customize the [Mojaloop Chart values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml) for the desired target Mojaloop release: + 1. Ensure backend-end configurations are set to the existing (shared) deployed Backend dependencies + 2. If applicable, ensure ingress-rules do not overwrite the current deployment configuration +2. Deploy the target Mojaloop release (Blue) + 1. Monitor the migration script logs for any upgrade errors via the `run-migration` containers: + - `kubectl -n ${NAMESPACE} logs -l app.kubernetes.io/name=centralledger-service -c run-migration` + - `kubectl -n ${NAMESPACE} logs -l app.kubernetes.io/name=account-lookup-service-admin -c run-migration` +3. Execute sanity tests on the Current Green deployment environment (verify impact of datastore changes, and allow for rollback, or partial switch-over for DFSPs, etc) +4. Execute sanity tests on the Target Blue deployment environment +5. Cut-over API Gateway (or upgrade target Ingress rules) to from Current Green to Target Blue deployment environment + +##### 2. Target version has datastore breaking changes + +#### Mojaloop installed without backend dependencies +In this scenario, we can utilise the inplace helm upgrade of backend dependencies. +A maintenance window need to be scheduled to stop "live" transaction on the current deployment to ensure data consistency, and allow for the switch-over to occur safely. This will cause a disruption, but can be somewhat mitigated by ensuring that the maintenance window is scheduled during the least busiest time. + +It is very important to take the backup of the database in case we need to rollback to previous version + +1. Schedule upgrade window +2. Backup the databases +3. Customize the [Mojaloop Chart values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml) for the desired target Mojaloop release +4. Uninstall the mojaloop services +5. Upgrade the backend dependencies using +```bash +helm upgrade ${RELEASE_NAME} mojaloop/example-mojaloop-backend --namespace ${NAMESPACE} --version ${RELEASE_VERSION} +``` +6. Install mojaloop services +```bash +helm install ${RELEASE_NAME} mojaloop/mojaloop --namespace ${NAMESPACE} --version ${RELEASE_VERSION} -f {$VALUES_FILE} +``` +7. Execute sanity tests +8. If you need to rollback then (make sure database backup was taken before the upgrade) + 1. use `helm rollback` command to rollback to previous version of backend dependencies + 2. load the database from the backup ( to ensure the datastore is in correct state) + 3. install previous version of mojaloop services + +#### Mojaloop installed with backend dependencies (Version 15 or older) + +In this scenario, we can utilise a Blue-green style deployment strategy by deploying new backend dependencies, and deploying the target Mojaloop release separately (with the additional benefit of aligning your deployment to the recommending deployment topology). + +Manual data migrating from the existing datastores to the new target backend dependencies will be required. It will also be necessary to keep the current and new datastores in sync as long as live transactions are being processed through the existing Mojaloop deployment. A maintenance window need to be scheduled to stop "live" transaction on the current deployment to ensure data consistency, and allow for the switch-over to occur safely. This will cause a disruption, but can be somewhat mitigated by ensuring that the maintenance window is scheduled during the least busiest time. + +##### Example Blue-green style deployment + +![Helm Blue-green Upgrade Strategy](./assets/diagrams/upgradeStrategies/helm-blue-green-upgrade-strategy.svg) + +1. Customize the [Mojaloop Chart values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml) for the desired target Mojaloop release: + 1. Ensure backend-end configurations are set to the target deployed Backend dependencies + 2. If applicable, ensure ingress-rules do not overwrite the current deployment configuration +2. Deploy the target Mojaloop release (Blue) +3. Create Migration process to sync and transform data into target deployed Backend datastore dependencies from Green to Blue +4. Schedule cut-over window +5. Execute cut-over during window + 1. Set current Green Backend datastore dependencies to read-only (where possible) + 2. Drain any remaining connections from Green + 3. Ensure Migration process is fully in-sync from Green to Blue + 4. Execute sanity tests on the Blue Target deployment environment + 5. Cut-over API Gateway (or upgrade target Ingress rules) to from Green Current to Blue Target deployment environment + + +## Upgrade Commands + +This document provides commands to upgrade existing Mojaloop installations. It assumes that Mojaloop is already installed using Helm. + +### Upgrade to v17.0.0 + +1. Upgrade the backend dependencies +```bash +helm upgrade backend mojaloop/example-mojaloop-backend --namespace ${NAMESPACE} --version v17.0.0 -f ${VALUES_FILE} +``` +2. Install the mojaloop services +```bash +helm install moja mojaloop/mojaloop --namespace ${NAMESPACE} --version v17.0.0 -f ${VALUES_FILE} +``` + +#### Testing the upgrade scenario from v16.0.0 to v17.0.0 + +1. Install backend dependencies v16.0.0 with persistence enabled (need to create databases manually since the initDb scripts will not run) +```bash +helm --namespace ${NAMESPACE} install ${RELEASE} mojaloop/example-mojaloop-backend --version 16.0.0 -f ${VALUES_FILE} +``` +2. Install the mojaloop services v16.0.0 and run tests to create data in databases +```bash +helm --namespace ${NAMESPACE} install ${RELEASE} mojaloop/mojaloop --version 16.0.0 -f ${VALUES_FILE} +``` +3. Uninstall the mojaloop services +```bash +helm delete ${RELEASE} --namespace ${NAMESPACE} +``` +4. Upgrade the backend dependencies to v17.0.0 (This will upgrade mysql/Kafka/MongoDB versions) +```bash +helm --namespace ${NAMESPACE} upgrade ${RELEASE} mojaloop/example-mojaloop-backend --version 17.0.0 -f ${VALUES_FILE} +``` +5. Install the mojaloop services v17.0.0 (This will run the knex migrations to upgrade the database schemas) +```bash +helm --namespace ${NAMESPACE} install ${RELEASE} mojaloop/mojaloop --version 17.0.0 -f ${VALUES_FILE} +``` +6. Run the GP Tests +```bash +helm test ${RELEASE} --namespace=${NAMESPACE} --logs +``` + + diff --git a/docs/technical/technical/event-framework/README.md b/docs/technical/technical/event-framework/README.md new file mode 100644 index 000000000..d1a0f5ece --- /dev/null +++ b/docs/technical/technical/event-framework/README.md @@ -0,0 +1,233 @@ +# Event Framework + +The purpose of the Event Framework is to provide a standard unified architecture to capture all Mojaloop events. + +_Disclaimer: This is experimental and is being implemented as a PoC. As such the design may change based on the evolution of the PoC's implementation, and any lessons learned._ + + +## 1. Requirements + +- Events will be produced by utilising a standard common library that will publish events to a sidecar component utilising a light-weight highly performant protocol (e.g. gRPC). +- Sidecar module will publish events to a singular Kafka topic that will allow for multiple handlers to consume and process the events as required. +- Kafka partitions will be determined by the event-type (e.g. log, audit, trace, errors etc). +- Each Mojaloop component will have its own tightly coupled Sidecar. +- Event messages will be produced to Kafka using the Trace-Id as the message key. This will ensure that all the messages part of the same trace (transaction) are stored in the same partition in order. + + +## 2. Architecture + +### 2.1 Overview + +![Event Framework Architecture](./assets/diagrams/architecture/architecture-event-framework.svg) + +### 2.2 Micro Service Pods + +![Pod Architecture](./assets/diagrams/architecture/architecture-event-sidecar.svg) + +### 2.3 Event Flow + +![Tracing Architecture](./assets/diagrams/architecture/architecture-event-trace.svg) + + +## 3. Event Envelope Model + +## 3.1 JSON Example + +```JSON +{ + "from": "noresponsepayeefsp", + "to": "payerfsp", + "id": "aa398930-f210-4dcd-8af0-7c769cea1660", + "content": { + "headers": { + "content-type": "application/vnd.interoperability.transfers+json;version=1.0", + "date": "2019-05-28T16:34:41.000Z", + "fspiop-source": "noresponsepayeefsp", + "fspiop-destination": "payerfsp" + }, + "payload": "data:application/vnd.interoperability.transfers+json;version=1.0;base64,ewogICJmdWxmaWxtZW50IjogIlVObEo5OGhaVFlfZHN3MGNBcXc0aV9VTjN2NHV0dDdDWkZCNHlmTGJWRkEiLAogICJjb21wbGV0ZWRUaW1lc3RhbXAiOiAiMjAxOS0wNS0yOVQyMzoxODozMi44NTZaIiwKICAidHJhbnNmZXJTdGF0ZSI6ICJDT01NSVRURUQiCn0" + }, + "type": "application/json", + "metadata": { + "event": { + "id": "3920382d-f78c-4023-adf9-0d7a4a2a3a2f", + "type": "trace", + "action": "span", + "createdAt": "2019-05-29T23:18:32.935Z", + "state": { + "status": "success", + "code": 0, + "description": "action successful" + }, + "responseTo": "1a396c07-47ab-4d68-a7a0-7a1ea36f0012" + }, + "trace": { + "service": "central-ledger-prepare-handler", + "traceId": "bbd7b2c7-3978-408e-ae2e-a13012c47739", + "parentSpanId": "4e3ce424-d611-417b-a7b3-44ba9bbc5840", + "spanId": "efeb5c22-689b-4d04-ac5a-2aa9cd0a7e87", + "startTimestamp": "2015-08-29T11:22:09.815479Z", + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + "tags": { + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + "transctionType": "transfer", + "parentEventType": "bulk-prepare", + "parentEventAction": "prepare" + } + } + } +} +``` + +## 3.2 Schema Definition + +### 3.2.1 Object Definition: EventMessage + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| id | string | Y | The id references the related message. | | +| from | string | N | If the value is not present in the destination, it means that the notification was generated by the connected node (server). | | +| to | string | Y | Mandatory for the sender and optional in the destination. The sender can ommit the value of the domain. | | +| pp | string | N | Optional for the sender, when is considered the identity of the session. Is mandatory in the destination if the identity of the originator is different of the identity of the from property. | | +| metadata | object `` | N | The sender should avoid to use this property to transport any kind of content-related information, but merely data relevant to the context of the communication. Consider to define a new content type if there's a need to include more content information into the message. | | +| type | string | Y | `MIME` declaration of the content type of the message. | | +| content | object \ | Y | The representation of the content. | | + +##### 3.2.1.1 Object Definition: MessageMetadata + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| event | object `` | Y | Event information. | | +| trace | object `` | Y | Trace information. | | + +##### 3.2.1.2 Object Definition: EventMetadata + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| id | string | Y | Generated UUIDv4 representing the event. | 3920382d-f78c-4023-adf9-0d7a4a2a3a2f | +| type | enum `` | Y | Type of event. | [`log`, `audit`, `error` `trace`] | +| action | enum `` | Y | Type of action. | [ `start`, `end` ] | +| createdAt | timestamp | Y | ISO Timestamp. | 2019-05-29T23:18:32.935Z | +| responseTo | string | N | UUIDv4 id link to the previous parent event. | 2019-05-29T23:18:32.935Z | +| state | object `` | Y | Object describing the state. | | + +##### 3.2.1.3 Object Definition: EventStateMetadata + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| status | enum `` | Y | The id references the related message. | success | +| code | number | N | The error code as per Mojaloop specification. | 2000 | +| description | string | N | Description for the status. Normally used to include an description for an error. | Generic server error to be used in order not to disclose information that may be considered private. | + +##### 3.2.1.4 Object Definition: EventTraceMetaData + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| service | string | Y | Name of service producing trace | central-ledger-prepare-handler | +| traceId | 32HEXDIGLC | Y | The end-to-end transaction identifier. | 664314d5b207d3ba722c6c0fdcd44c61 | +| spanId | 16HEXDIGLC | Y | Id for a processing leg identifier for a component or function. | 81fa25e8d66d2e88 | +| parentSpanId | 16HEXDIGLC | N | The id references the related message. | e457b5a2e4d86bd1 | +| sampled | number | N | Indicator if event message should be included in the trace `1`. If excluded it will be left the consumer to decide on sampling. | 1 | +| flags | number | N | Indicator if event message should be included in the trace flow. ( Debug `1` - this will override the sampled value ) | 0 | +| startTimestamp | datetime | N | ISO 8601 with the following format `yyyy-MM-dd'T'HH:mm:ss.SSSSSSz`. If not included the current timestamp will be taken. Represents the start timestamp of a span.| 2015-08-29T11:22:09.815479Z | +| finishTimestamp | datetime | N | ISO 8601 with the following format `yyyy-MM-dd'T'HH:mm:ss.SSSSSSz`. If not included the current timestamp will be taken. Represents the finish timestamp of a span | 2015-08-29T11:22:09.815479Z | +| tags | object `` | Y | The id references the related message. | success | + +_Note: HEXDIGLC = DIGIT / "a" / "b" / "c" / "d" / "e" / "f" ; lower case hex character. Ref: [WC3 standard for trace-context](https://www.w3.org/TR/trace-context/#field-value)._ + +##### 3.2.1.5 Object Definition: EventTraceMetaDataTags + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| transactionId | string | N | Transaction Id representing either a transfer, quote, etc | 659ee338-c8f8-4c06-8aff-944e6c5cd694 | +| transactionType | string | N | The transaction type represented by the transactionId. E.g. (transfer, quote, etc) | transfer | +| parentEventType | string | N | The event-type of the parent Span. | bulk-prepare | +| parentEventAction | string | N | The event-action of the parent Span. | prepare | +| tracestate | string | N | This tag is set if EventSDK environmental variable `EVENT_SDK_TRACESTATE_HEADER_ENABLED` is `true` or if parent span context has the `tracestate` header or tag included. The tag holds updated `tracestate` header value as per the W3C trace headers specification. [More here](#411-wc3-http-headers)| `congo=t61rcWkgMzE,rojo=00f067aa0ba902b7` | +| `` | string | N | Arbitary Key-value pair for additional meta-data to be added to the trace information. | n/a | + +##### 3.2.1.6 Enum: EventStatusType + +| Enum | Description | +| --- | --- | +| success | Event was processed successfully | +| fail | Event was processed with a failure or error | + +##### 3.2.1.7 Enum: EventType + +| Enum | Description | +| --- | --- | +| log | Event representing a general log entry. | +| audit | Event to be signed and persisted into the audit store. | +| trace | Event containing trace context information to be persisted into the tracing store. | + +##### 3.2.1.8 Enum: LogEventAction + +| Enum | Description | +| --- | --- | +| info | Event representing an `info` level log entry. | +| debug | Event representing a `debug` level log entry. | +| error | Event representing an `error` level log entry. | +| verbose | Event representing a `verbose` level log entry. | +| warning | Event representing a `warning` level log entry. | +| performance | Event representing a `performance` level log entry. | + +##### 3.2.1.9 Enum: AuditEventAction + +| Enum | Description | +| --- | --- | +| default | Standard audit action. | +| start | Audit action to represent the start of a process. | +| finish | Audit action to represent the end of a process. | +| ingress | Audit action to capture ingress activity. | +| egress | Audit action to capture egress activity. | + +##### 3.2.1.10 Enum: TraceEventAction + +| Enum | Description | +| --- | --- | +| span | Event action representing a span of a trace. | + + +## 4. Tracing Design + +### 4.1 HTTP Transports + +Below find the current proposed standard HTTP Transport headers for tracing. + +Mojaloop has yet to standardise on either standard, or if it will possible support both. + +#### 4.1.1 W3C Http Headers + +Refer to the following publication for more information: https://w3c.github.io/trace-context/ + +| Header | Description | Example | +| --- | --- | --- | +| traceparent | Dash delimited string of tracing information: \-\-\-\ | 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00 | +| tracestate | Comma delimited vendor specific format captured as follows: \=\| congo=t61rcWkgMzE,rojo=00f067aa0ba902b7 | + +Note: Before this specification was written, some tracers propagated X-B3-Sampled as true or false as opposed to 1 or 0. While you shouldn't encode X-B3-Sampled as true or false, a lenient implementation may accept them. + +Note: (Event-SDK)[https://github.com/mojaloop/event-sdk] since version v9.4.1 has methods to add key value tags in the tracestate, and since version v9.5.2 the tracestate is base64 encoded. To be able to use the tracestate consistently, use matching versions across all services in a system. + +#### 4.1.2 B3 HTTP Headers + +Refer to the following publication for more information: https://github.com/apache/incubator-zipkin-b3-propagation + +| Header | Description | Example | +| --- | --- | --- | +| X-B3-TraceId | Encoded as 32 or 16 lower-hex characters. | a 128-bit TraceId header might look like: X-B3-TraceId: 463ac35c9f6413ad48485a3953bb6124. Unless propagating only the Sampling State, the X-B3-TraceId header is required. | +| X-B3-SpanId | Encoded as 16 lower-hex characters. | a SpanId header might look like: X-B3-SpanId: a2fb4a1d1a96d312. Unless propagating only the Sampling State, the X-B3-SpanId header is required. | +| X-B3-ParentSpanId | header may be present on a child span and must be absent on the root span. It is encoded as 16 lower-hex characters. | A ParentSpanId header might look like: X-B3-ParentSpanId: 0020000000000001 | +| X-B3-Sampled | An accept sampling decision is encoded as `1` and a deny as `0`. Absent means defer the decision to the receiver of this header. | A Sampled header might look like: X-B3-Sampled: 1. | +| X-B3-Flags | Debug is encoded as `1`. Debug implies an accept decision, so don't also send the X-B3-Sampled header. | | + +### 4.2 Kafka Transports + +Refer to `Event Envelope Model` section. This defines the message that will be sent through the Kafka transport. + +Alternatively the tracing context could be stored in Kafka headers which are only supports v0.11 or later. Note that this would break support for older versions of Kafka. + +### 4.3 Known limitations + +- Transfer tracing would be limited to each of the transfer legs (i.e. Prepare and Fulfil) as a result of the Mojaloop API specification not catering for tracing information. The trace information will be send as part of the callbacks by the Switch, but the FSPs will not be required to respond appropriately with a reciprocal trace headers. diff --git a/mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-framework.svg b/docs/technical/technical/event-framework/assets/diagrams/architecture/architecture-event-framework.svg similarity index 100% rename from mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-framework.svg rename to docs/technical/technical/event-framework/assets/diagrams/architecture/architecture-event-framework.svg diff --git a/mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-sidecar.svg b/docs/technical/technical/event-framework/assets/diagrams/architecture/architecture-event-sidecar.svg similarity index 100% rename from mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-sidecar.svg rename to docs/technical/technical/event-framework/assets/diagrams/architecture/architecture-event-sidecar.svg diff --git a/mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-trace.svg b/docs/technical/technical/event-framework/assets/diagrams/architecture/architecture-event-trace.svg similarity index 100% rename from mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-trace.svg rename to docs/technical/technical/event-framework/assets/diagrams/architecture/architecture-event-trace.svg diff --git a/docs/technical/technical/event-stream-processor/README.md b/docs/technical/technical/event-stream-processor/README.md new file mode 100644 index 000000000..95db9223e --- /dev/null +++ b/docs/technical/technical/event-stream-processor/README.md @@ -0,0 +1,20 @@ +# Event Stream Processor Service + +Event Stream Processor consumes event messages from the `topic-events` topic as a result of messages published by the [event-sidecar](https://github.com/mojaloop/event-sidecar) service. Refer to [Event Framework](../event-framework/README.md) for more information on the overall architecture. + +The Service delivers logs, including audits, and traces to EFK stack with enabled APM plugin. Based on the event message type, the messages are delivered to different indexes in the Elasticsearch. + +## 1. Prerequisites + +The service logs all the events to Elasticsearch instance with enabled APM plugin. Sample docker-compose of the Elastic stack is available [here](https://github.com/mojaloop/event-stream-processor/blob/master/test/util/scripts/docker-efk/docker-compose.yml). The logs and audits are created under custom index template, while the trace data is stored to the default `apm-*` index. +Please, ensure that you have created the `mojatemplate` as it is described into the [event-stream-processor](https://github.com/mojaloop/event-stream-processor#111-create-template) service documentation. + +## 2. Architecture overview + +### 2.1. Flow overview +![Event Stream Processor flow overview](./assets/diagrams/architecture/event-stream-processor-overview.svg) + + +### 2.2 Trace processing flow sequence diagram +![](./assets/diagrams/sequence/process-flow.svg) + diff --git a/mojaloop-technical-overview/event-stream-processor/assets/diagrams/architecture/event-stream-processor-overview.svg b/docs/technical/technical/event-stream-processor/assets/diagrams/architecture/event-stream-processor-overview.svg similarity index 100% rename from mojaloop-technical-overview/event-stream-processor/assets/diagrams/architecture/event-stream-processor-overview.svg rename to docs/technical/technical/event-stream-processor/assets/diagrams/architecture/event-stream-processor-overview.svg diff --git a/mojaloop-technical-overview/event-stream-processor/assets/diagrams/sequence/process-flow.plantuml b/docs/technical/technical/event-stream-processor/assets/diagrams/sequence/process-flow.plantuml similarity index 100% rename from mojaloop-technical-overview/event-stream-processor/assets/diagrams/sequence/process-flow.plantuml rename to docs/technical/technical/event-stream-processor/assets/diagrams/sequence/process-flow.plantuml diff --git a/docs/technical/technical/event-stream-processor/assets/diagrams/sequence/process-flow.svg b/docs/technical/technical/event-stream-processor/assets/diagrams/sequence/process-flow.svg new file mode 100644 index 000000000..a85cf2bb6 --- /dev/null +++ b/docs/technical/technical/event-stream-processor/assets/diagrams/sequence/process-flow.svg @@ -0,0 +1,577 @@ + + Event Streaming Processor flow + + + Event Streaming Processor flow + + Central Services + + Event Stream Processor + + Cache + + Elasticsearch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Notification topic + + + Notification topic + Topic Observable + + + Topic Observable + + + Tracing Observable + + + Tracing Observable + + + Caching Observable + + + Caching Observable + + + Check For Last Span Observable + + + Check For Last Span Observable + + + Create Trace Observable + + + Create Trace Observable + + + Send Trace Handler + + + Send Trace Handler + + + Send Span Handler + + + Send Span Handler + + + Cache Handler + + + Cache Handler + + + Cache Storage + + + Cache Storage + + + APM + + + APM + + + Elasticsearch API + + + Elasticsearch API + + + + + + + + + + + + New Event Message Received + + + 1 + Consume Event Message + + + Message: + { + "from": "payeefsp", + "to": "payerfsp", + "id": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + "content": { + "headers": { + "content-type": "applicationvnd.interoperability.transfers+json;version=1.0", + "date": "2019-05-28T16:34:41.000Z", + "fspiop-source": "payeefsp", + "fspiop-destination": "payerfsp" + }, + "payload": <payload> + }, + "type": "application/json", + "metadata": { + "event": { + "id": "3920382d-f78c-4023-adf9-0d7a4a2a3a2f", + "type": "trace", + "action": "span", + "createdAt": "2019-05-29T23:18:32.935Z", + "state": { + "status": "success", + "code": 0, + "description": "action successful" + }, + "responseTo": "1a396c07-47ab-4d68-a7a0-7a1ea36f0012" + }, + "trace": { + "service": "central-ledger-prepare-handler", + "traceId": "bbd7b2c7bbd7b2c7", + "parentSpanId": "44ba9bbc5840", + "spanId": "2aa9cd0a7e87", + "startTimestamp": "2015-08-29T11:22:09.815479Z", + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + "tags": { + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + "transctionType": "transfer", + "parentEventType": "bulk-prepare", + "parentEventAction": "prepare" + } + } + } + } + + + 2 + Send message for log purposes to custom index + + + + + 3 + Verify its tracing event Message + + + 4 + Send Message to Tracing Observable + + + Cache Span + + + 5 + Send Span Context, + metadata.State and Content + from Message + + + { + spanContext: { + service: "central-ledger-prepare-handler", + traceId: "bbd7b2c7bbd7b2c7", + parentSpanId: "44ba9bbc5840", + spanId: "2aa9cd0a7e87", + startTimestamp: "2015-08-29T11:22:09.815479Z", + finishTimestamp: "2015-08-29T11:22:09.815479Z", + tags: { + transctionId: "659ee338-c8f8-4c06-8aff-944e6c5cd694", + transctionType: "transfer", + parentEventType: "bulk-prepare", + parentEventAction: "prepare" + }, + state: metadata.state, + content + } + + + 6 + Get cachedTrace by traceId + + + alt + [the span should not be cached] + + + 7 + currentSpan + + + 8 + store to APM + + + + + 9 + Complete + + + + + + + 10 + Validate transactionType, TransactionAction and service to match Config.START_CRITERIA && !parentSpandId + + + alt + [!cachedTrace] + + + + + 11 + Create new cachedTrace + + + { + spans: {}, + masterSpan: null, + lastSpan: null + } + + + alt + [!parentSpan] + + + + + + 12 + Generate MasterSpanId + + + + + + 13 + Make received span child of masterSpan + merge({ parentSpanId: MasterSpanId }, { ...spanContext }) + + + + + + 14 + Create MasterSpanContext merge({ tags: { ...tags, masterSpan: MasterSpanId } }, + { ...spanContext }, + { spanId: MasterSpanId, service: `master-${tags.transactionType}` }) + + + + + + 15 + Add masterSpan to cachedTrace + + + + 16 + Add span to cachedTrace + + + { + spans: { + 2aa9cd0a7e87: { + state, + content + spanContext: { + "service": "central-ledger-prepare-handler", + "traceId": "bbd7b2c7bbd7b2c7", + "parentSpanId": + MasterSpanId + , + "spanId": "2aa9cd0a7e87", + "startTimestamp": "2015-08-29T11:22:09.815479Z", + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + "tags": { + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + "transctionType": "transfer", + "parentEventType": "bulk-prepare", + "parentEventAction": "prepare" + } + } + }, +    + MasterSpanId: + { + state, + content, + MasterSpanContext + } + }, + masterSpan: + MasterSpanContext + , + lastSpan: null + } + + + 17 + Update cachedTrace to Cache + + + alt + [cachedTrace not staled or expired] + + + + + 18 + unsubscribe from Scheduler + + + 19 + record cachedTrace + + + + + + 20 + Reschedule scheduler for handling stale traces + + + 21 + Send traceId to check if last span has been received + and cached + + + Check for last span + + + 22 + Get cachedTrace by traceId + + + + + 23 + Sort spans by startTimestamp + + + loop + [for currentSpan of SortedSpans] + + + alt + [parentSpan] + + + + + 24 + isError = (errorCode in parentSpan + OR parentSpan status === failed + OR status === failed) + + + + + 25 + apply masterSpan and error tags from parent to current span in cachedTrace + + + alt + [!isLastSpan] + + + 26 + Update cachedTrace to Cache + + + alt + [cachedTrace not staled or expired] + + + + + 27 + unsubscribe from Scheduler + + + 28 + record cachedTrace + + + + + + 29 + Reschedule scheduler for handling stale traces + + + + + + 30 + Validate transactionType, TransactionAction, service and isError + to match Config.START_CRITERIA && !parentSpandId + + + + + 31 + cachedTrace.lastSpan = currentSpan.spanContext + + + 32 + Update cachedTrace to Cache + + + alt + [cachedTrace not staled or expired] + + + + + 33 + unsubscribe from Scheduler + + + 34 + record cachedTrace + + + + + + 35 + Reschedule scheduler for handling stale traces + + + 36 + Send traceId + + + Recreate Trace from Cached Trace + + + 37 + get cachedTrace by TraceId + + + alt + [cachedTrace.lastSpan AND cachedTrace.masterSpan] + + + + + 38 + currentSpan = lastSpan + + + + + 39 + resultTrace = [lastSpan] + + + loop + [for i = 0; i < cachedTrace.spans.length; i++] + + + + + 40 + get parentSpan of currentSpan + + + alt + [parentSpan] + + + + + 41 + insert parent span in resultTrace in front + + + + + + 42 + break loop + + + alt + [cachedTrace.masterSpan === currentSpan.spanId] + + + + + 43 + masterSpan.finishTimestamp = resultTrace[resultTrace.length - 1].finishTimestamp + + + 44 + send resultTrace + + + send Trace + + + loop + [trace elements] + + + 45 + send each span + + + 46 + send span to APM + + + + + 47 + unsubscribe scheduler for traceId + + + 48 + drop cachedTrace + + diff --git a/docs/technical/technical/fraud-services/README.md b/docs/technical/technical/fraud-services/README.md new file mode 100644 index 000000000..d44482e5b --- /dev/null +++ b/docs/technical/technical/fraud-services/README.md @@ -0,0 +1,5 @@ +# Fraud Services + +Provides an overview of the monitoring and preventative measures in consideration to prevent and discourage fraudulent activities within a Mojaloop scheme. + +Relevant artefacts available for public consumption are shared within [related-documents](./related-documents/documentation.md) section. diff --git a/mojaloop-technical-overview/fraud-services/related-documents/documentation.md b/docs/technical/technical/fraud-services/related-documents/documentation.md similarity index 100% rename from mojaloop-technical-overview/fraud-services/related-documents/documentation.md rename to docs/technical/technical/fraud-services/related-documents/documentation.md diff --git a/docs/technical/technical/ml-testing-toolkit/README.md b/docs/technical/technical/ml-testing-toolkit/README.md new file mode 100644 index 000000000..0260e22a2 --- /dev/null +++ b/docs/technical/technical/ml-testing-toolkit/README.md @@ -0,0 +1,16 @@ +Mojaloop Testing Toolkit +============================= + +The **Mojaloop Testing Toolkit** was designed to help Mojaloop Schemes scale effectively by easing the DFSP Onboarding process. Schemes can provide a set of rules and tests on the toolkit and DFSPs can use it for self testing (or self-certification in some cases). This ensures that DFSPs are well and truly ready with their implementations to be integrated with the Scheme and allows for a quick and smooth onboarding process for the Mojaloop Hubs, thereby increasing their scalability. + +This was initially aimed at FSPs/Participants that would like to participate in a Mojaloop scheme. However, in its current form, this tool set can potentially be used by both DFSPs and _Mojaloop Hubs_ to verify integration between the 2 entities. Intentionally built as a standard integration testing tool between a _Digital Financial Service Provider (DFSP)_ and the _Mojaloop Switch_ (Hub), to facilitate testing. + +For additional background on the Self Testing Toolkit, please see [Mojaloop Testing Toolkit](https://github.com/mojaloop/ml-testing-toolkit/blob/master/documents/Mojaloop-Testing-Toolkit.md). It would be to the particpant's benefit to familiarise themselves with the understanding of the [Architecture Diagram](https://github.com/mojaloop/ml-testing-toolkit/blob/master/documents/Mojaloop-Testing-Toolkit.md#7-architecture) that explains the various components and related flows. + +## Usage Guides + +For Web interface follow this [Usage Guide](https://github.com/mojaloop/ml-testing-toolkit/blob/master/documents/User-Guide.md) + +For Command line tool follow this [CLI User Guide](https://github.com/mojaloop/ml-testing-toolkit/blob/master/documents/User-Guide-CLI.md) + +**If you have your own DFSP implementation you can point the peer endpoint to Mojaloop Testing Toolkit on port 5000 and try to send requests from your implementation instead of using mojaloop-simulator.** diff --git a/docs/technical/technical/overview/README.md b/docs/technical/technical/overview/README.md new file mode 100644 index 000000000..c5c439207 --- /dev/null +++ b/docs/technical/technical/overview/README.md @@ -0,0 +1,24 @@ +# Mojaloop Hub + +There are several components that make up the Mojaloop ecosystem. The Mojaloop Hub is the primary container and reference we use to describe the core Mojaloop components. + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture: + +![Current Mojaloop Architecture Overview](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI18.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ + +These consist of: + +* The **Mojaloop API Adapters** (**ML-API-Adapter**) provide the standard set of interfaces a DFSP can implement to connect to the system for Transfers. A DFSP that wants to connect up can adapt our example code or implement the standard interfaces into their own software. The goal is for it to be as straightforward as possible for a DFSP to connect to the interoperable network. +* The **Central Services** (**CS**) provide the set of components required to move money from one DFSP to another through the Mojaloop API Adapters. This is similar to how money moves through a central bank or clearing house in developed countries. The Central Services contains the core Central Ledger logic to move money but also will be extended to provide fraud management and enforce scheme rules. +* The **Account Lookup Service** (**ALS**) provides a mechanism to resolve FSP routing information through the Participant API or orchestrate a Party request based on an internal Participant look-up. The internal Participant look-up is handled by a number of standard Oracle adapter or services. Example Oracle adapter/service would be to look-up Participant information from Pathfinder or a Merchant Registry. These Oracle adapters or services can easily be added depending on the schema requirements. +* The **Quoting Service** (**QA**) provides Quoting is the process that determines any fees and any commission required to perform a financial transaction between two FSPs. It is always initiated by the Payer FSP to the Payee FSP, which means that the quote flows in the same way as a financial transaction. +* The **Simulator** (**SIM**) mocks several DFSP functions as follows: + * Oracle end-points for Oracle Participant CRUD operations using in-memory cache; + * Participant end-points for Oracles with support for parameterized partyIdTypes; + * Parties end-points for Payer and Payee FSPs with associated callback responses; + * Transfer end-points for Payer and Payee FSPs with associated callback responses; and + * Query APIs to verify transactions (requests, responses, callbacks, etc) to support QA testing and verification. + +On either side of the Mojaloop Hub there is sample open source code to show how a DFSP can send and receive payments and the client that an existing DFSP could host to connect to the network. diff --git a/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI11.svg b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI11.svg new file mode 100644 index 000000000..df9396cae --- /dev/null +++ b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI11.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    Operational Monitoring
    Quality Assurance
    Quality Assurance
    Core Components
    Core Components
    API - Security / Policy / Ingress / Egress
    API - Security / Policy / Ingress / Egress
    Continuous Integration & Delivery
    Continuous Integration & Delivery
    Container Management & Orchestration
    Container Management & Orchestration
    Supporting Components
    Supporting Components
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    Helm...
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    Kubernetes...
    Docker
    (Container Engine)
    Docker...
    Infrastructure
    (AWS, Azure, On-Prem)
    Infrastructure...
    EFK - ElasticSearch / Fluentd / Kibana
    (Log Search / Collection / Monitoring / Tracing)
    EFK - ElasticSearch / Fluentd / Kibana...
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    Promfana - Prometheus / Grafana...
    Open Tracing
    (Distributed Tracing)
    Open Tracing...
    Rancher
    (Infrastructure Management)
    Rancher...
    Mojaloop API Adapter
    (API - Transfers)
    Mojaloop API Adapter...
    Central-Services
    (API - Operational Admin)
    Central-Services...
    Central-Services
    (Handler - Prepare)
    Central-Services...
    Central-Services
    (Handler - Position)
    Central-Services...
    Central-Services
    (Handler - Fulfil)
    Central-Services...
    Central-Services
    (Handler - Get Transfers)
    Central-Services...
    Central-Services
    (Handler - Timeout)
    Central-Services...
    Central-KMS
    (Future - Key Management Store)
    Central-KMS...
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    ALS - Account-Lookup-Service...
    ALS-Oracle-Pathfinder
    (MSISDN Lookup)
    ALS-Oracle-Pathfinder...
    Central-Event-Processor
    (CEP)
    Central-Event-Processor...
    Email-Notifier
    (Handler - Email)
    Email-Notifier...
    Central-Services
    (Handler - Admin)
    Central-Services...
    Circle-CI
    (Test, Build, Deploy)
    Circle-CI...
    Docker Hub
    (Container Repository)
    Docker Hub...
    NPM Org
    (NPM Repository)
    NPM Org...
    GitBooks
    (Documetation)
    GitBooks...
    API Gateway
    (Future - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)
    API Gateway...
    Central-Services
    (Handler - Bulk Prepare)
    Central-Services...
    Central-Services
    (Handler - Bulk Fulfil)
    Central-Services...
    Central-Services
    (Handler - Bulk Process)
    Central-Services...
    Mojaloop API Adapter
    (API - Bulk Transfers)
    Mojaloop API Adapter...
    Forensic-Logging
    (Future - Auditing)
    Forensic-Logging...
    Central-Settlements
    (API - Settlement)
    Central-Settlements...
    Event-Stream-Processor
    Logs, Error, Audits, Tracing)
    Event-Stream-Processor...
    Simulators
    (API, SDK, FSP & Oracle)
    Simulators...
    On-boarding
    (Postman - Scripts)
    On-boarding...
    Functional Tests
    (Postman - Scripts)
    Functional Tests...
    Self Testing Toolkit
    (
    POC UI)
    Self Testing Toolkit...
    License, Security & Audit
    (Dependencies)
    License, Security & Audit...
    Persistence
    Persistence
    Redis
    (SDK - Cache)
    Redis...
    MongoDB
    (CEP - Data)
    MongoDB...
    MySQL
    (Percona - Data)
    MySQL...
    Kafka
    (Message - Streaming)
    Kafka...
    Transaction Request Service
    (API - Transaction)
    Transaction Request Service...
    Software Dev Kits
    Software Dev Kits
    Oracle SDK
    (Participant Store)
    Oracle SDK...
    Mojaloop SDK 
    (FSP Payer/Payee)
    Mojaloop SDK...
    Event SDK
    (Audit, Log, Trace - Client/Server)
    Event SDK...
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    Event-Sidecar...
    Mojaloop API Adapter
    (Handler - Notifications)
    Mojaloop API Adapter...
    Quoting-Service
    (API - Quotes)
    Quoting-Service...
    Finance-Portal-UI
    (API - Bulk Transfers)
    Finance-Portal-UI...
    Settlement-Management
    (Closing, Recon report, Cronjob)
    Settlement-Management...
    Schema-Adapter
    (SDK - Parties, Participants, Quotes, Transfers)
    Schema-Adapter...
    IaC (Infra as Code) Tools
    (Future - Automated
    Prov / Depl / Upgrades)
    IaC (Infra as Code) Tools...
    Third Party API Adapter
    (PoC - API - Transfers)
    Third Party API Adapter...
    Third Party API Adapter
    (PoC - Handler - Notifications)
    Third Party API Adapter...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI12.svg b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI12.svg new file mode 100644 index 000000000..763c5697e --- /dev/null +++ b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI12.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    Operational Monitoring
    Quality Assurance
    Quality Assurance
    Core Components
    Core Components
    API - Security / Policy / Ingress / Egress
    API - Security / Policy / Ingress / Egress
    Continuous Integration & Delivery
    Continuous Integration & Delivery
    Container Management & Orchestration
    Container Management & Orchestration
    Supporting Components
    Supporting Components
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    Helm...
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    Kubernetes...
    Docker
    (Container Engine)
    Docker...
    Infrastructure
    (AWS, Azure, On-Prem)
    Infrastructure...
    EFK - ElasticSearch / Fluentd / Kibana
    (Log Search / Collection / Monitoring / Tracing)
    EFK - ElasticSearch / Fluentd / Kibana...
    Promfana - Prometheus / Grafana
    (Metrics - Collection / Monitoring)
    Promfana - Prometheus / Grafana...
    Open Tracing
    (Distributed Tracing)
    Open Tracing...
    Rancher
    (Infrastructure Management)
    Rancher...
    Mojaloop API Adapter
    (API - Transfers)
    Mojaloop API Adapter...
    Central-Services
    (API - Operational Admin)
    Central-Services...
    Central-Services
    (Handler - Prepare)
    Central-Services...
    Central-Services
    (Handler - Position)
    Central-Services...
    Central-Services
    (Handler - Fulfil)
    Central-Services...
    Central-Services
    (Handler - Get Transfers)
    Central-Services...
    Central-Services
    (Handler - Timeout)
    Central-Services...
    Central-KMS
    (Future - Key Management Store)
    Central-KMS...
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    ALS - Account-Lookup-Service...
    ALS-Oracle-Pathfinder
    (MSISDN Lookup)
    ALS-Oracle-Pathfinder...
    Central-Event-Processor
    (CEP)
    Central-Event-Processor...
    Email-Notifier
    (Handler - Email)
    Email-Notifier...
    Central-Services
    (Handler - Admin)
    Central-Services...
    Circle-CI
    (Test, Build, Deploy)
    Circle-CI...
    Docker Hub
    (Container Repository)
    Docker Hub...
    NPM Org
    (NPM Repository)
    NPM Org...
    GitBooks
    (Documetation)
    GitBooks...
    API Gateway (IaC)
    (API - Parties, Participants, Quotes, Transfers, Bulk Transfers; OAuth; MTLS)
    API Gateway (IaC)...
    Central-Services
    (Handler - Bulk Prepare)
    Central-Services...
    Central-Services
    (Handler - Bulk Fulfil)
    Central-Services...
    Central-Services
    (Handler - Bulk Process)
    Central-Services...
    Mojaloop API Adapter
    (API - Bulk Transfers)
    Mojaloop API Adapter...
    Forensic-Logging
    (Future - Auditing)
    Forensic-Logging...
    Central-Settlements
    (API - Settlements)
    Central-Settlements...
    Event-Stream-Processor
    (Logs, Error, Audits, Tracing)
    Event-Stream-Processor...
    Simulators
    (API, SDK, FSP & Oracle)
    Simulators...
    On-boarding
    (Postman - Scripts)
    On-boarding...
    Functional Tests
    (Postman - Scripts)
    Functional Tests...
    Testing Toolkit
    (
    UI, CLI & Backend)
    Testing Toolkit...
    License, Security & Audit
    (Dependencies)
    License, Security & Audit...
    Persistence
    Persistence
    Redis
    (SDK - Cache)
    Redis...
    MongoDB
    (CEP - Data)
    MongoDB...
    MySQL
    (Percona - Data)
    MySQL...
    Kafka
    (Message - Streaming)
    Kafka...
    Transaction Request Service
    (API - Transaction)
    Transaction Request Service...
    Software Dev Kits
    Software Dev Kits
    Oracle SDK
    (Participant Store)
    Oracle SDK...
    Mojaloop SDK 
    (FSP Payer/Payee)
    Mojaloop SDK...
    Event SDK
    (Audit, Log, Trace - Client/Server)
    Event SDK...
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    Event-Sidecar...
    Mojaloop API Adapter
    (Handler - Notifications)
    Mojaloop API Adapter...
    Quoting-Service
    (API - Quotes)
    Quoting-Service...
    Finance-Portal-UI
    (API - Bulk Transfers)
    Finance-Portal-UI...
    Settlement-Management
    (Closing, Recon report, Cronjob)
    Settlement-Management...
    Schema-Adapter
    (SDK - Parties, Participants, Quotes, Transfers)
    Schema-Adapter...
    IaC (Infra as Code) Tools
    (Automated Lab/Env Setup & Configuration)
    IaC (Infra as Code) Tools...
    Third Party API Adapter
    (PoC - API - Transfers)
    Third Party API Adapter...
    Third Party API Adapter
    (PoC - Handler - Notifications)
    Third Party API Adapter...
    Central-Settlements
    (Handler - Settlement Windows)
    Central-Settlements...
    Central-Settlements
    (Handler - Transfer Settlements)
    Central-Settlements...
    Viewer does not support full SVG 1.1
    diff --git a/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg new file mode 100644 index 000000000..06680fbae --- /dev/null +++ b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    Operational Monitoring
    Quality Assurance
    Quality Assurance
    Core Components
    Core Components
    API - Security / Policy / Ingress / Egress
    API - Security / Policy / Ingress / Egress
    Continuous Integration & Delivery
    Continuous Integration & Delivery
    Container Management & Orchestration
    Container Management & Orchestration
    Supporting Components
    Supporting Components
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    Helm...
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    Kubernetes...
    Docker
    (Container Engine)
    Docker...
    Infrastructure
    (AWS, Azure, On-Prem)
    Infrastructure...
    EFK - ElasticSearch / Fluentd / Kibana
    (Log Search / Collection / Monitoring / Tracing)
    EFK - ElasticSearch / Fluentd / Kibana...
    Promfana - Prometheus / Grafana
    (Metrics - Collection / Monitoring)
    Promfana - Prometheus / Grafana...
    Open Tracing
    (Distributed Tracing)
    Open Tracing...
    Rancher
    (Infrastructure Management)
    Rancher...
    Mojaloop API Adapter
    (API - Transfers)
    Mojaloop API Adapter...
    Central-Services
    (API - Operational Admin)
    Central-Services...
    Central-Services
    (Handler - Prepare)
    Central-Services...
    Central-Services
    (Handler - Position)
    Central-Services...
    Central-Services
    (Handler - Fulfil)
    Central-Services...
    Central-Services
    (Handler - Get Transfers)
    Central-Services...
    Central-Services
    (Handler - Timeout)
    Central-Services...
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    ALS - Account-Lookup-Service...
    ALS-Oracle-Pathfinder
    (MSISDN Lookup)
    ALS-Oracle-Pathfinder...
    Central-Event-Processor
    (CEP)
    Central-Event-Processor...
    Email-Notifier
    (Handler - Email)
    Email-Notifier...
    Central-Services
    (Handler - Admin)
    Central-Services...
    Circle-CI
    (Test, Build, Deploy)
    Circle-CI...
    Docker Hub
    (Container Repository)
    Docker Hub...
    NPM Org
    (NPM Repository)
    NPM Org...
    GitBooks
    (Documetation)
    GitBooks...
    API Gateway (IaC)
    (API - Parties, Participants, Quotes, Transfers, Bulk Transfers; OAuth; MTLS)
    API Gateway (IaC)...
    Central-Services
    (Handler - Bulk Prepare)
    Central-Services...
    Central-Services
    (Handler - Bulk Fulfil)
    Central-Services...
    Central-Services
    (Handler - Bulk Process)
    Central-Services...
    Mojaloop API Adapter
    (API - Bulk Transfers)
    Mojaloop API Adapter...
    Central-Settlements
    (API - Settlements)
    Central-Settlements...
    Event-Stream-Processor
    (Logs, Error, Audits, Tracing)
    Event-Stream-Processor...
    Simulators
    (API, SDK, FSP & Oracle)
    Simulators...
    On-boarding
    (Postman - Scripts)
    On-boarding...
    Functional Tests
    (Postman - Scripts)
    Functional Tests...
    Testing Toolkit
    (
    UI, CLI & Backend)
    Testing Toolkit...
    License, Security & Audit
    (Dependencies)
    License, Security & Audit...
    Persistence
    Persistence
    Redis
    (SDK - Cache)
    Redis...
    MongoDB
    (CEP - Data)
    MongoDB...
    MySQL
    (Percona - Data)
    MySQL...
    Kafka
    (Message - Streaming)
    Kafka...
    Transaction Request Service
    (API - Transaction)
    Transaction Request Service...
    Software Dev Kits
    Software Dev Kits
    Oracle SDK
    (Participant Store)
    Oracle SDK...
    Mojaloop SDK 
    (FSP Payer/Payee)
    Mojaloop SDK...
    Event SDK
    (Audit, Log, Trace - Client/Server)
    Event SDK...
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    Event-Sidecar...
    Mojaloop API Adapter
    (Handler - Notifications)
    Mojaloop API Adapter...
    Quoting-Service
    (API - Quotes)
    Quoting-Service...
    Finance-Portal-UI
    (API - Bulk Transfers)
    Finance-Portal-UI...
    Settlement-Management
    (Closing, Recon report, Cronjob)
    Settlement-Management...
    Schema-Adapter
    (SDK - Parties, Participants, Quotes, Transfers)
    Schema-Adapter...
    IaC (Infra as Code) Tools
    (Automated Lab/Env Setup & Configuration)
    IaC (Infra as Code) Tools...
    Third Party API Adapter
    (PoC - API - Transfers)
    Third Party API Adapter...
    Third Party API Adapter
    (PoC - Handler - Notifications)
    Third Party API Adapter...
    Central-Settlements
    (Handler - Deferred)
    Central-Settlements...
    Central-Settlements
    (Handler - Gross)
    Central-Settlements...
    Central-Settlements
    (Handler - Rules)
    Central-Settlements...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI18.svg b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI18.svg new file mode 100644 index 000000000..6e753c75d --- /dev/null +++ b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI18.svg @@ -0,0 +1,4 @@ + + + +
    Operational Monitoring
    Operational Monitoring
    Quality Assurance
    Quality Assurance
    Core Components
    Core Components
    API - Security / Policy / Ingress / Egress
    API - Security / Policy / Ingress / Egress
    Continuous Integration & Delivery
    Continuous Integration & Delivery
    Container Management & Orchestration
    Container Management & Orchestration
    Supporting Components
    Supporting Components
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    Helm...
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    Kubernetes...
    Docker
    (Container Engine)
    Docker...
    Infrastructure
    (AWS, Azure, On-Prem)
    Infrastructure...
    EFK - ElasticSearch / Fluentd / Kibana
    (Log Search / Collection / Monitoring / Tracing)
    EFK - ElasticSearch / Fluentd / Kibana...
    Promfana - Prometheus / Grafana
    (Metrics - Collection / Monitoring)
    Promfana - Prometheus / Grafana...
    Open Tracing
    (Distributed Tracing)
    Open Tracing...
    Infra management
    (IaC, Miniloop)
    Infra management...
    Mojaloop API Adapter
    (FSPIOP API - Transfers)
    Mojaloop API Adapter...
    Central-Services
    (API - Operational Admin)
    Central-Services...
    Central-Services
    (Handler - Prepare)
    Central-Services...
    Central-Services
    (Handler - Position)
    Central-Services...
    Central-Services
    (Handler - Fulfil)
    Central-Services...
    Central-Services
    (Handler - Get Transfers)
    Central-Services...
    Central-Services
    (Handler - Timeout)
    Central-Services...
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    ALS - Account-Lookup-Service...
    ALS-Oracle-Pathfinder
    (MSISDN Lookup)
    ALS-Oracle-Pathfinder...
    Central-Event-Processor
    (CEP)
    Central-Event-Processor...
    Email-Notifier
    (Handler - Email)
    Email-Notifier...
    Central-Services
    (Handler - Admin)
    Central-Services...
    Circle-CI
    (Test, Build, Deploy)
    Circle-CI...
    Docker Hub
    (Container Repository)
    Docker Hub...
    NPM Org
    (NPM Repository)
    NPM Org...
    GitBooks
    (Documetation)
    GitBooks...
    API Gateway (IaC)
    (FSPIOP API - Parties, Participants, Quotes, Transfers, Bulk Transfers; OAuth; MTLS)
    API Gateway (IaC)...
    Central-Services
    (Handler - Bulk Prepare)
    Central-Services...
    Central-Services
    (Handler - Bulk Fulfil)
    Central-Services...
    Central-Services
    (Handler - Bulk Process)
    Central-Services...
    Mojaloop API Adapter
    (API - Bulk Transfers)
    Mojaloop API Adapter...
    Central-Settlements
    (API - Settlements)
    Central-Settlements...
    Event-Stream-Processor
    (Logs, Error, Audits, Tracing)
    Event-Stream-Processor...
    Simulators
    (API, SDK, FSP & Oracle)
    Simulators...
    On-boarding
    (Postman - Scripts)
    On-boarding...
    Functional Tests
    (Postman - Scripts)
    Functional Tests...
    Testing Toolkit
    (Functional
    UI, CLI & Backend)
    Testing Toolkit...
    License, Security & Audit
    (Dependencies)
    License, Security & Audit...
    Persistence
    Persistence
    Redis
    (SDK - Cache)
    Redis...
    MongoDB
    (CEP - Data)
    MongoDB...
    MySQL
    (Percona - Data)
    MySQL...
    Kafka
    (Message - Streaming)
    Kafka...
    Transaction Request Service
    (API - Transaction)
    Transaction Request Service...
    Software Accelerators
    Software Accelerators
    Oracle SDK
    (Participant Store)
    Oracle SDK...
    Mojaloop SDK 
    (FSP Payer/Payee)
    Mojaloop SDK...
    Event SDK
    (Audit, Log, Trace - Client/Server)
    Event SDK...
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    Event-Sidecar...
    Mojaloop API Adapter
    (Handler - Notifications)
    Mojaloop API Adapter...
    Quoting-Service
    (API - Quotes)
    Quoting-Service...
    Finance-Portal-UI
    (micro-frontends)
    Finance-Portal-UI...
    Settlement-Management
    (Closing, Recon report, Cronjob)
    Settlement-Management...
    Schema-Adapter
    (SDK - Parties, Participants, Quotes, Transfers)
    Schema-Adapter...
    IaC (Infra as Code) Tools
    (Automated Lab/Env Setup & Configuration)
    IaC (Infra as Code) Tools...
    Third Party API Adapter
    (3PPI - API - Transfers)
    Third Party API Adapter...
    Third Party API Adapter
    (3PPI Handler - Notifications)
    Third Party API Adapter...
    Central-Settlements
    (Handler - Deferred)
    Central-Settlements...
    Central-Settlements
    (Handler - Gross)
    Central-Settlements...
    Central-Settlements
    (Handler - Rules)
    Central-Settlements...
    Business Operations Framework for 
    (Reporting
    )
    (Operations)
    (Monitoring)
    (self-service portals)
    Business Operations Frame...
    IAM, RBAC
    (Administration APIs; Ory - Keto, Kratos, Oathkeeper)
    IAM, RBAC...
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI3.svg b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI3.svg similarity index 100% rename from mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI3.svg rename to docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI3.svg diff --git a/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI5.svg b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI5.svg similarity index 100% rename from mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI5.svg rename to docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI5.svg diff --git a/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI6.svg b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI6.svg similarity index 100% rename from mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI6.svg rename to docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI6.svg diff --git a/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI7.svg b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI7.svg similarity index 100% rename from mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI7.svg rename to docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI7.svg diff --git a/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg b/docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg similarity index 100% rename from mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg rename to docs/technical/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg diff --git a/docs/technical/technical/overview/components-PI11.md b/docs/technical/technical/overview/components-PI11.md new file mode 100644 index 000000000..35b839657 --- /dev/null +++ b/docs/technical/technical/overview/components-PI11.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Current Components - PI11 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI11: + +![Mojaloop Architecture Overview PI11](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI11.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/docs/technical/technical/overview/components-PI12.md b/docs/technical/technical/overview/components-PI12.md new file mode 100644 index 000000000..d90d82eb9 --- /dev/null +++ b/docs/technical/technical/overview/components-PI12.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Current Components - PI12 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI12: + +![Mojaloop Architecture Overview PI12](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI12.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/docs/technical/technical/overview/components-PI14.md b/docs/technical/technical/overview/components-PI14.md new file mode 100644 index 000000000..d4c4e3887 --- /dev/null +++ b/docs/technical/technical/overview/components-PI14.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Current Components - PI14 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI14: + +![Mojaloop Architecture Overview PI14](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/docs/technical/technical/overview/components-PI18.md b/docs/technical/technical/overview/components-PI18.md new file mode 100644 index 000000000..d42df67ff --- /dev/null +++ b/docs/technical/technical/overview/components-PI18.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Current Components - PI18 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI18: + +![Mojaloop Architecture Overview PI18](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI18.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/mojaloop-technical-overview/overview/components-PI3.md b/docs/technical/technical/overview/components-PI3.md similarity index 100% rename from mojaloop-technical-overview/overview/components-PI3.md rename to docs/technical/technical/overview/components-PI3.md diff --git a/mojaloop-technical-overview/overview/components-PI5.md b/docs/technical/technical/overview/components-PI5.md similarity index 100% rename from mojaloop-technical-overview/overview/components-PI5.md rename to docs/technical/technical/overview/components-PI5.md diff --git a/mojaloop-technical-overview/overview/components-PI6.md b/docs/technical/technical/overview/components-PI6.md similarity index 100% rename from mojaloop-technical-overview/overview/components-PI6.md rename to docs/technical/technical/overview/components-PI6.md diff --git a/mojaloop-technical-overview/overview/components-PI7.md b/docs/technical/technical/overview/components-PI7.md similarity index 100% rename from mojaloop-technical-overview/overview/components-PI7.md rename to docs/technical/technical/overview/components-PI7.md diff --git a/docs/technical/technical/overview/components-PI8.md b/docs/technical/technical/overview/components-PI8.md new file mode 100644 index 000000000..3d18e7fac --- /dev/null +++ b/docs/technical/technical/overview/components-PI8.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Legacy Components - PI8 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI8: + +![Mojaloop Architecture Overview PI8](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/docs/technical/technical/quoting-service/README.md b/docs/technical/technical/quoting-service/README.md new file mode 100644 index 000000000..d6d086e66 --- /dev/null +++ b/docs/technical/technical/quoting-service/README.md @@ -0,0 +1,13 @@ +--- +version: 1.1 +--- + +# Quoting Service Overview +The **Quoting Service** (**QS**) _(refer to section `5.1`) as per the [Mojaloop {{ $page.frontmatter.version }} Specification](/api) implements the quoting phase of the various use-cases. + +_Note: In addition to individual quotes, the quoting service supports bulk quotes as well._ + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-quotes-1.0.0.svg) + diff --git a/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.plantuml b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.plantuml new file mode 100644 index 000000000..0405a9868 --- /dev/null +++ b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.plantuml @@ -0,0 +1,92 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- +******'/ + +@startuml +Title Retrieve Bulk Quote Information +participant "Payer FSP" as PayerFSP +participant "Switch\n[Quoting Service]" as Switch +participant "Payee FSP" as PayeeFSP + +autonumber +note right of PayerFSP: Payer FSP sends request to get bulk quote details \nto Payee FSP via the Switch +PayerFSP -\ Switch: GET /bulkQuotes/{ID} +note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** +end note +Switch -> Switch: Schema validation +PayerFSP \-- Switch: 202 Accepted +Switch -> Switch: Retrieve bulk quotes endpoint for Payee FSP +alt Payee FSP quotes endpoint is found + note right of Switch: Switch forwards request to Payee FSP (pass-through mode) + Switch -\ PayeeFSP: GET /bulkQuotes/{ID} + PayeeFSP --/ Switch: 202 Accepted + PayeeFSP -> PayeeFSP: Payee FSP retireves bulk quote + alt Payee FSP successfully retieves quote + note left of PayeeFSP: Payee FSP responds to quote request + PayeeFSP -\ Switch: PUT /quotes/{ID} + note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** + end note + Switch --/ PayeeFSP: 200 Ok + alt Response is ok + Switch -> Switch: Retrieve bulk quotes endpoint for the Payer FSP + alt Bulk Quotes callback endpoint found + note left of Switch: Switch forwards bulk quote response to Payer FSP + Switch -\ PayerFSP: PUT /bulkQuotes/{ID} + PayerFSP --/ Switch: 200 Ok + else Bulk Quotes callback endpoint not found + note right of Switch: Switch returns error to Payee FSP + Switch -\ PayeeFSP: PUT /bulkQuotes/{ID}/error + PayeeFSP --/ Switch : 200 Ok + end + else Response is invalid + note right of Switch: Switch returns error to Payee FSP + Switch -\ PayeeFSP: PUT /bulkQuotes/{ID}/error + PayeeFSP --/ Switch : 200 Ok + note over Switch, PayeeFSP #ec7063: Note that under this\nscenario the Payer FSP\nmay not receive a response + end + + else bulkQuote not found + note left of PayeeFSP: Payee FSP returns error to Switch\n **Error code: 3205** + PayeeFSP -\ Switch: PUT /bulkQuotes/{ID}/error + Switch --/ PayeeFSP: 200 OK + note left of Switch: Switch returns error to Payer FSP\n **Error code: 3205** + Switch -\ PayerFSP: PUT /bulkQuotes/{ID}/error + PayerFSP --/ Switch: 200 OK + end +else Payee FSP Bulk quotes endpoint is not found + note left of Switch + Switch returns error to Payer FSP + **Error code: 3201** + end note + PayerFSP /- Switch: PUT /bulkQuotes/{ID}error + PayerFSP --/ Switch: 200 OK +end +@enduml diff --git a/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.svg b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.svg new file mode 100644 index 000000000..5048df7d9 --- /dev/null +++ b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.svg @@ -0,0 +1,198 @@ + + Retrieve Bulk Quote Information + + + Retrieve Bulk Quote Information + + + + + + + + + Payer FSP + + Payer FSP + + Switch + [Quoting Service] + + Switch + [Quoting Service] + + Payee FSP + + Payee FSP + + + Payer FSP sends request to get bulk quote details + to Payee FSP via the Switch + + + 1 + GET /bulkQuotes/{ID} + + + Validate request against + Mojaloop interface specification + Error code: 300x, 310x + HTTP error response code: 4xx + + + + + 2 + Schema validation + + + 3 + 202 Accepted + + + + + 4 + Retrieve bulk quotes endpoint for Payee FSP + + + alt + [Payee FSP quotes endpoint is found] + + + Switch forwards request to Payee FSP (pass-through mode) + + + 5 + GET /bulkQuotes/{ID} + + + 6 + 202 Accepted + + + + + 7 + Payee FSP retireves bulk quote + + + alt + [Payee FSP successfully retieves quote] + + + Payee FSP responds to quote request + + + 8 + PUT /quotes/{ID} + + + Validate request against + Mojaloop interface specification + Error code: 300x, 310x + HTTP error response code: 4xx + + + 9 + 200 Ok + + + alt + [Response is ok] + + + + + 10 + Retrieve bulk quotes endpoint for the Payer FSP + + + alt + [Bulk Quotes callback endpoint found] + + + Switch forwards bulk quote response to Payer FSP + + + 11 + PUT /bulkQuotes/{ID} + + + 12 + 200 Ok + + [Bulk Quotes callback endpoint not found] + + + Switch returns error to Payee FSP + + + 13 + PUT /bulkQuotes/{ID}/error + + + 14 + 200 Ok + + [Response is invalid] + + + Switch returns error to Payee FSP + + + 15 + PUT /bulkQuotes/{ID}/error + + + 16 + 200 Ok + + + Note that under this + scenario the Payer FSP + may not receive a response + + [bulkQuote not found] + + + Payee FSP returns error to Switch +   + Error code: 3205 + + + 17 + PUT /bulkQuotes/{ID}/error + + + 18 + 200 OK + + + Switch returns error to Payer FSP +   + Error code: 3205 + + + 19 + PUT /bulkQuotes/{ID}/error + + + 20 + 200 OK + + [Payee FSP Bulk quotes endpoint is not found] + + + Switch returns error to Payer FSP + Error code: 3201 + + + 21 + PUT /bulkQuotes/{ID}error + + + 22 + 200 OK + + diff --git a/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.plantuml b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.plantuml new file mode 100644 index 000000000..dfcb1918b --- /dev/null +++ b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.plantuml @@ -0,0 +1,86 @@ +@startuml +Title Retrieve Quote Information +participant "Payer FSP" as PayerFSP +participant "Switch\n[Quoting\nService]" as Switch +database "Central Store" as DB +participant "Payee FSP" as PayeeFSP +autonumber +note right of PayerFSP: Payer FSP sends request to get quote details \nto Payee FSP via the Switch +PayerFSP -\ Switch: GET /quotes/{ID} +note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** +end note +Switch -> Switch: Schema validation +PayerFSP \-- Switch: 202 Accepted +Switch -> Switch: Retrieve quotes endpoint for Payee FSP +alt Payee FSP quotes endpoint is found + note right of Switch: Switch forwards request to Payee FSP (pass-through mode)\n + Switch -\ PayeeFSP: GET /quotes/{ID} + PayeeFSP --/ Switch: 202 Accepted + PayeeFSP -> PayeeFSP: Payee FSP retireves quote + alt Payee FSP successfully retieves quote + note left of PayeeFSP: Payee FSP responds to quote request + PayeeFSP -\ Switch: PUT /quotes/{ID} + Switch --/ PayeeFSP: 200 Ok + Switch -> Switch: Validate response (schema, headers (**Error code: 3100**)) + alt Response is ok + alt SimpleRoutingMode is FALSE + Switch -> Switch: Validate response (duplicate response check, handle resend scenario (**Error code: 3106**)) + alt Validation passed + Switch -\ DB: Persist quote response + activate DB + hnote over DB + quoteResponse + quoteResponseDuplicateCheck + quoteResponseIlpPacket + quoteExtensions + geoCode + end hnote + Switch \-- DB: Quote response saved + deactivate DB + end + end + alt SimpleRoutingMode is TRUE + Switch -> Switch: Retrieve quotes endpoint for the Payer FSP + else SimpleRoutingMode is FALSE + Switch -> Switch: Retrieve quote party endpoint (PAYER) + end + alt Quotes callback endpoint found + note left of Switch: Switch forwards quote response to Payer FSP\n + Switch -\ PayerFSP: PUT /quotes/{ID} + PayerFSP --/ Switch: 200 Ok + else Quotes callback endpoint not found + note right of Switch: Switch returns error to Payee FSP + Switch -\ PayeeFSP: PUT /quotes/{ID}/error + PayeeFSP --/ Switch : 200 Ok + end + else Response is invalid + note right of Switch: Switch returns error to Payee FSP + Switch -\ PayeeFSP: PUT /quotes/{ID}/error + PayeeFSP --/ Switch : 200 Ok + note over Switch, PayeeFSP #ec7063: Note that under this\nscenario the Payer FSP\nmay not receive a response + end + + else Quote not found + note left of PayeeFSP: Payee FSP returns error to Switch\n **Error code: 3205** + PayeeFSP -\ Switch: PUT quotes/{ID}/error + Switch --/ PayeeFSP: 200 OK + alt SimpleRoutingMode is FALSE + Switch -> Switch: Persist error data + end + note left of Switch: Switch returns error to Payer FSP\n **Error code: 3205** + Switch -\ PayerFSP: PUT quotes/{ID}/error + PayerFSP --/ Switch: 200 OK + end +else Payee FSP quotes endpoint is not found + note left of Switch + Switch returns error to Payer FSP + **Error code: 3201** + end note + PayerFSP /- Switch: PUT quotes/{ID}error + PayerFSP --/ Switch: 200 OK +end +@enduml diff --git a/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.svg b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.svg new file mode 100644 index 000000000..d413d4496 --- /dev/null +++ b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.svg @@ -0,0 +1,269 @@ + + Retrieve Quote Information + + + Retrieve Quote Information + + + + + + + + + + + + + + + Payer FSP + + Payer FSP + + Switch + [Quoting + Service] + + Switch + [Quoting + Service] + Central Store + + + Central Store + + + + Payee FSP + + Payee FSP + + + + Payer FSP sends request to get quote details + to Payee FSP via the Switch + + + 1 + GET /quotes/{ID} + + + Validate request against + Mojaloop interface specification + Error code: 300x, 310x + HTTP error response code: 4xx + + + + + 2 + Schema validation + + + 3 + 202 Accepted + + + + + 4 + Retrieve quotes endpoint for Payee FSP + + + alt + [Payee FSP quotes endpoint is found] + + + Switch forwards request to Payee FSP (pass-through mode) + <Payer based Rules> + + + 5 + GET /quotes/{ID} + + + 6 + 202 Accepted + + + + + 7 + Payee FSP retireves quote + + + alt + [Payee FSP successfully retieves quote] + + + Payee FSP responds to quote request + + + 8 + PUT /quotes/{ID} + + + 9 + 200 Ok + + + + + 10 + Validate response (schema, headers ( + Error code: 3100 + )) + + + alt + [Response is ok] + + + alt + [SimpleRoutingMode is FALSE] + + + + + 11 + Validate response (duplicate response check, handle resend scenario ( + Error code: 3106 + )) + + + alt + [Validation passed] + + + 12 + Persist quote response + + quoteResponse + quoteResponseDuplicateCheck + quoteResponseIlpPacket + quoteExtensions + geoCode + + + 13 + Quote response saved + + + alt + [SimpleRoutingMode is TRUE] + + + + + 14 + Retrieve quotes endpoint for the Payer FSP + + [SimpleRoutingMode is FALSE] + + + + + 15 + Retrieve quote party endpoint (PAYER) + + + alt + [Quotes callback endpoint found] + + + Switch forwards quote response to Payer FSP + <Payee whole request Rule> + + + 16 + PUT /quotes/{ID} + + + 17 + 200 Ok + + [Quotes callback endpoint not found] + + + Switch returns error to Payee FSP + + + 18 + PUT /quotes/{ID}/error + + + 19 + 200 Ok + + [Response is invalid] + + + Switch returns error to Payee FSP + + + 20 + PUT /quotes/{ID}/error + + + 21 + 200 Ok + + + Note that under this + scenario the Payer FSP + may not receive a response + + [Quote not found] + + + Payee FSP returns error to Switch +   + Error code: 3205 + + + 22 + PUT quotes/{ID}/error + + + 23 + 200 OK + + + alt + [SimpleRoutingMode is FALSE] + + + + + 24 + Persist error data + + + Switch returns error to Payer FSP +   + Error code: 3205 + + + 25 + PUT quotes/{ID}/error + + + 26 + 200 OK + + [Payee FSP quotes endpoint is not found] + + + Switch returns error to Payer FSP + Error code: 3201 + + + 27 + PUT quotes/{ID}error + + + 28 + 200 OK + + diff --git a/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.plantuml b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.plantuml new file mode 100644 index 000000000..ca4c1d30f --- /dev/null +++ b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.plantuml @@ -0,0 +1,99 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- +******'/ + +@startuml +Title Request Bulk Quote Creation +participant "Payer FSP" as PayerFSP +participant "Switch\n[Quoting Service]" as Switch +participant "Payee FSP" as PayeeFSP +autonumber + +note over PayerFSP, Switch: Payer FSP sends bulk quote request\nto Payee FSP via the Switch +PayerFSP -\ Switch: POST /bulkQuotes +note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** +end note +Switch -> Switch: Schema validation +PayerFSP \-- Switch: 202 Accepted +||| +Switch -> Switch: Bulk Quote request validation (rules engine etc.) +||| +Switch -> Switch: Duplicate check +||| +alt Request is a duplicate but not a resend +||| + note left of Switch + Switch returns error back to Payer FSP + **Error code: 3106** + end note + PayerFSP /- Switch: PUT /bulkQuotes/{ID}/error + PayerFSP --/ Switch: 200 OK +||| +else Request is a duplicate and a resend + Switch -> Switch: Switch handles resend scenario +end +||| +Switch -> Switch: Use fspiop-destination header to retrieve\n bulk quotes endpoint for Payee DFSP +alt Payee bulk quotes endpoint found + note right of Switch: Switch forwards bulk quote request to Payee FSP + Switch -\ PayeeFSP: POST /bulkQuotes + Switch \-- PayeeFSP: 202 OK + + PayeeFSP -> PayeeFSP: Payee FSP calculates individual quotes\nand responds with a bulk quote result + alt Payee bulkQuotes processing successful + note over PayeeFSP, Switch: Payee FSP sends bulk quote response back to Payer FSP via the Switch + Switch /- PayeeFSP: PUT /bulkQuotes/{ID} + Switch --/ PayeeFSP: 200 OK + + Switch -> Switch: Validate bulk quote response + Switch -> Switch: Duplicate check + alt Response is duplicate but not a resend + Switch -\ PayeeFSP: PUT /bulkQuotes/{ID}/error + Switch \-- PayeeFSP: 200 OK + end + alt Response is a duplicate and a resend + Switch -> Switch: Switch handles resend scenario + end + + note left of Switch: Switch forwards quote response to Payer FSP + PayerFSP /- Switch: PUT /bulkQuotes/{ID} + PayerFSP --/ Switch: 200 OK + else Payee rejects bulk quote or encounters an error + note left of PayeeFSP: Payee FSP sends error callback to Payer FSP via the Switch + Switch /- PayeeFSP: PUT /bulkQuotes/{ID}/error + Switch --/ PayeeFSP: 200 OK + note left of Switch: Switch forwards error callback to Payer FSP + PayerFSP /- Switch: PUT /bulkQuotes/{ID}/error + PayerFSP --/ Switch: 200 OK + end +else Payee FSP quotes endpoint not found + note left of Switch: Switch sends an error callback to Payer FSP \n **Error code: 3201** + PayerFSP /- Switch: PUT /bulkQuotes/{ID}/error + PayerFSP --\ Switch: 200 OK +end + +@enduml diff --git a/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.svg b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.svg new file mode 100644 index 000000000..d855d1f1f --- /dev/null +++ b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.svg @@ -0,0 +1,217 @@ + + Request Bulk Quote Creation + + + Request Bulk Quote Creation + + + + + + + + + + Payer FSP + + Payer FSP + + Switch + [Quoting Service] + + Switch + [Quoting Service] + + Payee FSP + + Payee FSP + + + Payer FSP sends bulk quote request + to Payee FSP via the Switch + + + 1 + POST /bulkQuotes + + + Validate request against + Mojaloop interface specification + Error code: 300x, 310x + HTTP error response code: 4xx + + + + + 2 + Schema validation + + + 3 + 202 Accepted + + + + + 4 + Bulk Quote request validation (rules engine etc.) + + + + + 5 + Duplicate check + + + alt + [Request is a duplicate but not a resend] + + + Switch returns error back to Payer FSP + Error code: 3106 + + + 6 + PUT /bulkQuotes/{ID}/error + + + 7 + 200 OK + + [Request is a duplicate and a resend] + + + + + 8 + Switch handles resend scenario + + + + + 9 + Use fspiop-destination header to retrieve + bulk quotes endpoint for Payee DFSP + + + alt + [Payee bulk quotes endpoint found] + + + Switch forwards bulk quote request to Payee FSP + + + 10 + POST /bulkQuotes + + + 11 + 202 OK + + + + + 12 + Payee FSP calculates individual quotes + and responds with a bulk quote result + + + alt + [Payee bulkQuotes processing successful] + + + Payee FSP sends bulk quote response back to Payer FSP via the Switch + + + 13 + PUT /bulkQuotes/{ID} + + + 14 + 200 OK + + + + + 15 + Validate bulk quote response + + + + + 16 + Duplicate check + + + alt + [Response is duplicate but not a resend] + + + 17 + PUT /bulkQuotes/{ID}/error + + + 18 + 200 OK + + + alt + [Response is a duplicate and a resend] + + + + + 19 + Switch handles resend scenario + + + Switch forwards quote response to Payer FSP + + + 20 + PUT /bulkQuotes/{ID} + + + 21 + 200 OK + + [Payee rejects bulk quote or encounters an error] + + + Payee FSP sends error callback to Payer FSP via the Switch + + + 22 + PUT /bulkQuotes/{ID}/error + + + 23 + 200 OK + + + Switch forwards error callback to Payer FSP + + + 24 + PUT /bulkQuotes/{ID}/error + + + 25 + 200 OK + + [Payee FSP quotes endpoint not found] + + + Switch sends an error callback to Payer FSP +   + Error code: 3201 + + + 26 + PUT /bulkQuotes/{ID}/error + + + 27 + 200 OK + + diff --git a/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.plantuml b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.plantuml new file mode 100644 index 000000000..86fb8f8b6 --- /dev/null +++ b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.plantuml @@ -0,0 +1,117 @@ +@startuml +Title Request Quote Creation +participant "Payer FSP" as PayerFSP +participant "Switch\n[Quoting\nService]" as Switch +database "Central Store" as DB +participant "Payee FSP" as PayeeFSP +autonumber + +note over PayerFSP, Switch: Payer FSP sends request for quote \nto Payee FSP via the Switch +PayerFSP -\ Switch: POST /quotes +note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** +end note +Switch -> Switch: Schema validation +PayerFSP \-- Switch: 202 Accepted +||| +Switch -> Switch: Quote request validation (rules engine etc.) +||| +alt SimpleRoutingMode === FALSE + Switch -> Switch: Duplicate check + ||| + alt Request is a duplicate but not a resend + ||| + note left of Switch + Switch returns error back to Payer FSP + **Error code: 3106** + end note + PayerFSP /- Switch: PUT /quotes/{ID}/error + PayerFSP --/ Switch: 200 OK + ||| + else Request is a duplicate and a resend + Switch -> Switch: Switch handles resend scenario + end + ||| + Switch -\ DB: Persist quote request + activate DB + hnote over DB + quoteDuplicateCheck + transactionReference + quote + quoteParty + quoteExtension + geoCode + end hnote + Switch \-- DB: Quote request saved + deactivate DB +end +||| +alt SimpleRoutingMode === TRUE + Switch -> Switch: Use fspiop-destination header to retrieve quotes endpoint for Payee FSP +else SimpleRoutingMode === FALSE + Switch -> Switch: Retireve Payee FSP endpoint using quote party information +end +||| +alt Payee quotes endpoint found + note right of Switch: Switch forwards quote request to Payee FSP + Switch -\ PayeeFSP: POST /quotes + Switch \-- PayeeFSP: 202 OK + + PayeeFSP -> PayeeFSP: Payee FSP presists and calculates quote + alt Payee quotes processing successful + note left of PayeeFSP: Payee FSP sends quote response back to Payer FSP via the Switch + Switch /- PayeeFSP: PUT /quotes/{ID} + Switch --/ PayeeFSP: 200 OK + + Switch -> Switch: Validate quote response + alt SimpleRoutingMode === FALSE + Switch -> Switch: Duplicate check + alt Response is duplicate but not a resend + Switch -\ PayeeFSP: PUT /quotes/{ID}/error + Switch \-- PayeeFSP: 200 OK + end + alt Response is a duplicate and a resend + Switch -> Switch: Switch handles resend scenario + end + Switch -\ DB: Persist quote response + activate DB + hnote over DB + quoteResponse + quoteDuplicateCheck + quoteResponseIlpPacket + geoCode + quoteExtension + end hnote + Switch \-- DB: Quote response saved + deactivate DB + end + note left of Switch: Switch forwards quote response to Payer FSP + PayerFSP /- Switch: PUT /quotes/{ID} + PayerFSP --/ Switch: 200 OK + else Payee rejects quotes or encounters and error + note left of PayeeFSP: Payee FSP sends error callback to Payer FSP via the Switch + Switch /- PayeeFSP: PUT /quotes/{ID}/error + Switch --/ PayeeFSP: 200 OK + alt SimpleRoutingMode === FALSE + Switch -\ DB: Store quote error + activate DB + hnote over DB + quoteError + end hnote + Switch \-- DB: Quote error saved + deactivate DB + end + note left of Switch: Switch forwards error callback to Payer FSP + PayerFSP /- Switch: PUT /quotes/{ID}/error + PayerFSP --/ Switch: 200 OK + end +else Payee FSP quotes endpoint not found + note left of Switch: Switch sends an error callback to Payer FSP \n **Error code: 3201** + PayerFSP /- Switch: PUT /quotes/{ID}/error + PayerFSP --\ Switch: 200 OK +end + +@enduml diff --git a/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.svg b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.svg new file mode 100644 index 000000000..963594b46 --- /dev/null +++ b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.svg @@ -0,0 +1,297 @@ + + Request Quote Creation + + + Request Quote Creation + + + + + + + + + + + + + + + + + + Payer FSP + + Payer FSP + + Switch + [Quoting + Service] + + Switch + [Quoting + Service] + Central Store + + + Central Store + + + + Payee FSP + + Payee FSP + + + + + + Payer FSP sends request for quote + to Payee FSP via the Switch + + + 1 + POST /quotes + + + Validate request against + Mojaloop interface specification + Error code: 300x, 310x + HTTP error response code: 4xx + + + + + 2 + Schema validation + + + 3 + 202 Accepted + + + + + 4 + Quote request validation (rules engine etc.) + + + alt + [SimpleRoutingMode === FALSE] + + + + + 5 + Duplicate check + + + alt + [Request is a duplicate but not a resend] + + + Switch returns error back to Payer FSP + Error code: 3106 + + + 6 + PUT /quotes/{ID}/error + + + 7 + 200 OK + + [Request is a duplicate and a resend] + + + + + 8 + Switch handles resend scenario + + + 9 + Persist quote request + + quoteDuplicateCheck + transactionReference + quote + quoteParty + quoteExtension + geoCode + + + 10 + Quote request saved + + + alt + [SimpleRoutingMode === TRUE] + + + + + 11 + Use fspiop-destination header to retrieve quotes endpoint for Payee FSP + + [SimpleRoutingMode === FALSE] + + + + + 12 + Retireve Payee FSP endpoint using quote party information + + + alt + [Payee quotes endpoint found] + + + Switch forwards quote request to Payee FSP + + + 13 + POST /quotes + + + 14 + 202 OK + + + + + 15 + Payee FSP presists and calculates quote + + + alt + [Payee quotes processing successful] + + + Payee FSP sends quote response back to Payer FSP via the Switch + + + 16 + PUT /quotes/{ID} + + + 17 + 200 OK + + + + + 18 + Validate quote response + + + alt + [SimpleRoutingMode === FALSE] + + + + + 19 + Duplicate check + + + alt + [Response is duplicate but not a resend] + + + 20 + PUT /quotes/{ID}/error + + + 21 + 200 OK + + + alt + [Response is a duplicate and a resend] + + + + + 22 + Switch handles resend scenario + + + 23 + Persist quote response + + quoteResponse + quoteDuplicateCheck + quoteResponseIlpPacket + geoCode + quoteExtension + + + 24 + Quote response saved + + + Switch forwards quote response to Payer FSP + + + 25 + PUT /quotes/{ID} + + + 26 + 200 OK + + [Payee rejects quotes or encounters and error] + + + Payee FSP sends error callback to Payer FSP via the Switch + + + 27 + PUT /quotes/{ID}/error + + + 28 + 200 OK + + + alt + [SimpleRoutingMode === FALSE] + + + 29 + Store quote error + + quoteError + + + 30 + Quote error saved + + + Switch forwards error callback to Payer FSP + + + 31 + PUT /quotes/{ID}/error + + + 32 + 200 OK + + [Payee FSP quotes endpoint not found] + + + Switch sends an error callback to Payer FSP +   + Error code: 3201 + + + 33 + PUT /quotes/{ID}/error + + + 34 + 200 OK + + diff --git a/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml new file mode 100644 index 000000000..4f3405364 --- /dev/null +++ b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml @@ -0,0 +1,68 @@ +@startuml +Title Quoting Service Sequences +participant "Payer DFSP" +participant "Switch\nQuoting\nService" as Switch +participant "Payee DFSP" + +autonumber +note over "Payer DFSP", Switch: Payer DFSP requests quote from Payee DFSP +"Payer DFSP" -\ Switch: POST /quotes +Switch --/ "Payer DFSP": 202 Accepted +Switch -> Switch: Validate Quote Request + +alt quote is valid + + Switch -> Switch: Persist Quote Data + note over Switch, "Payee DFSP": Switch forwards quote request to Payee DFSP\n + Switch -\ "Payee DFSP": POST /quotes + "Payee DFSP" --/ Switch: 202 Accepted + "Payee DFSP" -> "Payee DFSP": Calculate Fees/Charges + + alt Payee DFSP successfully calculates quote + + note over "Payee DFSP", Switch: Payee DFSP responds to quote request + "Payee DFSP" -\ Switch: PUT /quotes/{ID} + Switch --/ "Payee DFSP": 200 Ok + + Switch -> Switch: Validate Quote Response + + alt response is ok + + Switch -> Switch: Persist Response Data + + note over Switch, "Payer DFSP": Switch forwards quote response to Payer DFSP\n + + Switch -\ "Payer DFSP": PUT /quotes/{ID} + "Payer DFSP" --/ Switch: 200 Ok + + note over "Payer DFSP" #3498db: Payer DFSP continues\nwith transfer if quote\nis acceptable... + else response invalid + + note over Switch, "Payee DFSP": Switch returns error to Payee DFSP + + Switch -\ "Payee DFSP": PUT /quotes/{ID}/error + "Payee DFSP" --/ Switch : 200 Ok + + note over Switch, "Payee DFSP" #ec7063: Note that under this\nscenario the Payer DFSP\nmay not receive a response + + end + else Payee DFSP calculation fails or rejects the request + + note over "Payee DFSP", Switch: Payee DFSP returns error to Switch + + "Payee DFSP" -\ Switch: PUT quotes/{ID}/error + Switch --/ "Payee DFSP": 200 OK + Switch -> Switch: Persist error data + + note over "Payer DFSP", Switch: Switch returns error to Payer DFSP + + Switch -\ "Payer DFSP": PUT quotes/{ID}/error + "Payer DFSP" --/ Switch: 200 OK + + end +else quote invalid + note over "Payer DFSP", Switch: Switch returns error to Payer DFSP + Switch -\ "Payer DFSP": PUT quotes/{ID}/error + "Payer DFSP" --/ Switch: 200 OK +end +@enduml diff --git a/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.svg b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.svg new file mode 100644 index 000000000..bff0f162c --- /dev/null +++ b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.svg @@ -0,0 +1,183 @@ + + Quoting Service Sequences + + + Quoting Service Sequences + + + + + + + + Payer DFSP + + Payer DFSP + + Switch + Quoting + Service + + Switch + Quoting + Service + + Payee DFSP + + Payee DFSP + + + Payer DFSP requests quote from Payee DFSP + + + 1 + POST /quotes + + + 2 + 202 Accepted + + + + + 3 + Validate Quote Request + + + alt + [quote is valid] + + + + + 4 + Persist Quote Data + + + Switch forwards quote request to Payee DFSP + <Payer based Rules> + + + 5 + POST /quotes + + + 6 + 202 Accepted + + + + + 7 + Calculate Fees/Charges + + + alt + [Payee DFSP successfully calculates quote] + + + Payee DFSP responds to quote request + + + 8 + PUT /quotes/{ID} + + + 9 + 200 Ok + + + + + 10 + Validate Quote Response + + + alt + [response is ok] + + + + + 11 + Persist Response Data + + + Switch forwards quote response to Payer DFSP + <Payee whole request Rule> + + + 12 + PUT /quotes/{ID} + + + 13 + 200 Ok + + + Payer DFSP continues + with transfer if quote + is acceptable... + + [response invalid] + + + Switch returns error to Payee DFSP + + + 14 + PUT /quotes/{ID}/error + + + 15 + 200 Ok + + + Note that under this + scenario the Payer DFSP + may not receive a response + + [Payee DFSP calculation fails or rejects the request] + + + Payee DFSP returns error to Switch + + + 16 + PUT quotes/{ID}/error + + + 17 + 200 OK + + + + + 18 + Persist error data + + + Switch returns error to Payer DFSP + + + 19 + PUT quotes/{ID}/error + + + 20 + 200 OK + + [quote invalid] + + + Switch returns error to Payer DFSP + + + 21 + PUT quotes/{ID}/error + + + 22 + 200 OK + + diff --git a/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.plantuml b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.plantuml new file mode 100644 index 000000000..3275abff7 --- /dev/null +++ b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.plantuml @@ -0,0 +1,67 @@ +@startuml +Title Quoting Service Sequences +participant "Payer FSP" +participant "Switch\nQuoting\nService" as Switch +participant "Payee FSP" + +autonumber +note over "Payer FSP", Switch: Payer FSP requests quote from Payee FSP +"Payer FSP" -\ Switch: POST /quotes +Switch --/ "Payer FSP": 202 Accepted +Switch -> Switch: Validate Quote Request + +alt quote is valid + + Switch -> Switch: Persist Quote Data + note over Switch, "Payee FSP": Switch forwards quote request to Payee FSP\n + Switch -\ "Payee FSP": POST /quotes + "Payee FSP" --/ Switch: 202 Accepted + "Payee FSP" -> "Payee FSP": Calculate Fees/Charges + + alt Payee FSP successfully calculates quote + + note over "Payee FSP", Switch: Payee FSP responds to quote request + "Payee FSP" -\ Switch: PUT /quotes/{ID} + Switch --/ "Payee FSP": 200 Ok + + Switch -> Switch: Validate Quote Response + + alt response is ok + Switch -> Switch: Persist Response Data + + note over Switch, "Payer FSP": Switch forwards quote response to Payer FSP\n + + Switch -\ "Payer FSP": PUT /quotes/{ID} + "Payer FSP" --/ Switch: 200 Ok + + note over "Payer FSP" #3498db: Payer FSP continues\nwith transfer if quote\nis acceptable... + else response invalid + + note over Switch, "Payee FSP": Switch returns error to Payee FSP + + Switch -\ "Payee FSP": PUT /quotes/{ID}/error + "Payee FSP" --/ Switch : 200 Ok + + note over Switch, "Payee FSP" #ec7063: Note that under this\nscenario the Payer FSP\nmay not receive a response + + end + else Payee FSP calculation fails or rejects the request + + note over "Payee FSP", Switch: Payee FSP returns error to Switch + + "Payee FSP" -\ Switch: PUT quotes/{ID}/error + Switch --/ "Payee FSP": 200 OK + Switch -> Switch: Persist error data + + note over "Payer FSP", Switch: Switch returns error to Payer FSP + + Switch -\ "Payer FSP": PUT quotes/{ID}/error + "Payer FSP" --/ Switch: 200 OK + + end +else quote invalid + note over "Payer FSP", Switch: Switch returns error to Payer FSP + Switch -\ "Payer FSP": PUT quotes/{ID}/error + "Payer FSP" --/ Switch: 200 OK +end +@enduml diff --git a/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.svg b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.svg new file mode 100644 index 000000000..43af29f8a --- /dev/null +++ b/docs/technical/technical/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.svg @@ -0,0 +1,183 @@ + + Quoting Service Sequences + + + Quoting Service Sequences + + + + + + + + Payer FSP + + Payer FSP + + Switch + Quoting + Service + + Switch + Quoting + Service + + Payee FSP + + Payee FSP + + + Payer FSP requests quote from Payee FSP + + + 1 + POST /quotes + + + 2 + 202 Accepted + + + + + 3 + Validate Quote Request + + + alt + [quote is valid] + + + + + 4 + Persist Quote Data + + + Switch forwards quote request to Payee FSP + <Payer based Rules> + + + 5 + POST /quotes + + + 6 + 202 Accepted + + + + + 7 + Calculate Fees/Charges + + + alt + [Payee FSP successfully calculates quote] + + + Payee FSP responds to quote request + + + 8 + PUT /quotes/{ID} + + + 9 + 200 Ok + + + + + 10 + Validate Quote Response + + + alt + [response is ok] + + + + + 11 + Persist Response Data + + + Switch forwards quote response to Payer FSP + <Payee whole request Rule> + + + 12 + PUT /quotes/{ID} + + + 13 + 200 Ok + + + Payer FSP continues + with transfer if quote + is acceptable... + + [response invalid] + + + Switch returns error to Payee FSP + + + 14 + PUT /quotes/{ID}/error + + + 15 + 200 Ok + + + Note that under this + scenario the Payer FSP + may not receive a response + + [Payee FSP calculation fails or rejects the request] + + + Payee FSP returns error to Switch + + + 16 + PUT quotes/{ID}/error + + + 17 + 200 OK + + + + + 18 + Persist error data + + + Switch returns error to Payer FSP + + + 19 + PUT quotes/{ID}/error + + + 20 + 200 OK + + [quote invalid] + + + Switch returns error to Payer FSP + + + 21 + PUT quotes/{ID}/error + + + 22 + 200 OK + + diff --git a/docs/technical/technical/quoting-service/qs-get-bulk-quotes.md b/docs/technical/technical/quoting-service/qs-get-bulk-quotes.md new file mode 100644 index 000000000..a9479883a --- /dev/null +++ b/docs/technical/technical/quoting-service/qs-get-bulk-quotes.md @@ -0,0 +1,8 @@ +# GET Quote By ID + +Design for the retrieval of a Bulk Quote by an FSP. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.svg) + diff --git a/docs/technical/technical/quoting-service/qs-get-quotes.md b/docs/technical/technical/quoting-service/qs-get-quotes.md new file mode 100644 index 000000000..b9295912f --- /dev/null +++ b/docs/technical/technical/quoting-service/qs-get-quotes.md @@ -0,0 +1,8 @@ +# GET Quote By ID + +Design for the retrieval of a Quote by an FSP. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-get-quotes-1.1.0.svg) + diff --git a/docs/technical/technical/quoting-service/qs-post-bulk-quotes.md b/docs/technical/technical/quoting-service/qs-post-bulk-quotes.md new file mode 100644 index 000000000..bcaafa5fb --- /dev/null +++ b/docs/technical/technical/quoting-service/qs-post-bulk-quotes.md @@ -0,0 +1,8 @@ +# POST Quote + +Design for a Bulk Quote request by an FSP. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.svg) + diff --git a/docs/technical/technical/quoting-service/qs-post-quotes.md b/docs/technical/technical/quoting-service/qs-post-quotes.md new file mode 100644 index 000000000..6709b144a --- /dev/null +++ b/docs/technical/technical/quoting-service/qs-post-quotes.md @@ -0,0 +1,8 @@ +# POST Quote + +Design for a Quote request by an FSP. + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-post-quotes-1.2.0.svg) + diff --git a/docs/technical/technical/releases.md b/docs/technical/technical/releases.md new file mode 100644 index 000000000..6e245e478 --- /dev/null +++ b/docs/technical/technical/releases.md @@ -0,0 +1,195 @@ +# Mojaloop Release Process + +The Mojaloop Release process follows a community led approach, specifically technical work-stream led, in collaboration and consultation with the Product Council and the Design Authority (DA). + +The DA frames the policies, guidelines and technical criteria for the releases (such as quality metrics) while Product defines the feature and product requirements where such aspects are involved. This is executed by the relevant workstream(s). + +## 1. Mojaloop Release process +![YM8f9iPhGU1jAfr-dQUk4e34QMGPG1ZWnbmC4ERGpsqp70GJH2he2Nje4poq_dii642B82j-Cj-2-HuYTkEF4poIBg8rJSfWYagBVOMyt6PQs5_P2YRE9magU_jE](https://github.com/mojaloop/design-authority-project/assets/10507686/075e528c-d4b2-4100-a2b9-6d06d77155d0) + +Community event (PI level planning), workstreams, features, release quality, testing, checklist, release candidate, example epic, Release + +The Mojaloop Release process follows a +- community led approach +- specifically technical work-stream led +- in collaboration and consultation with the Product Council and +- the Design Authority (DA) + +Criteria, guidelines: +The DA frames policies, guidelines and technical criteria for the releases while Product defines the feature and product requirements +Example releases notes, criteria for v17.0.0, [v17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) + +Testing continues after the release is made as well and daily cron jobs run to test, until the next release is made, to ensure stability. + +**Current tasks and acceptance criteria for Mojaloop (helm) releases**: + +Example story: [3122](https://github.com/mojaloop/project/issues/3122) , [3847](https://github.com/mojaloop/project/issues/3847) + +The decisions on what features to include, which ones will be ready and included are not included as they happen during planning stages (and based on deliverables) + +- [x] Ensure all core services and services included in release follow standards for + - [x] Dependabot alerts + - [x] License files + - [x] License headers in source files + - [x] Snyk alerts + - [x] codeowners files + - [x] Branch protection rules on main branches verified + - [x] Review open issues + - [x] Review open pull requests + - [x] Review audit exceptions provided and clear / minimize the list +- [x] Update manifests for "release Pull Request (PR)" GH actions WF +- [x] Validate the PR released and the process +- [x] Deploy default values with RC on AWS moja* environment + - [x] Validate GP collection works with 100% + - [x] Validate FX, inter-scheme tests works with 100% +- [x] Deploy, validate RC on a second environment + - [x] Validate GP collection works with 100% + - [x] Validate FX, inter-scheme tests works with 100% +- [x] Identify issues with QA Scripts if any - fix them and retest +- [x] QA for bugs, regressions, log them +- [x] Fix bugs logged if critical +- [x] Validate with TTK GP collection +- [x] Test on-us configuration option (deploy time change) and verify on-us tests pass +- [x] TTK test-cases repo Release is published +- [x] Release notes for helm RC is drafted + - [x] Guidance for migration from Release (may have to be a separate story if sufficiently big / complex) +- [x] Update release notes with Upgrade Strategy Guide link +- [x] Helm Release is published +- [x] Deployment of released Helm on a dev envirnoment + - [x] Helm release is deployed on dev successfully + - [x] Regression testing on dev using TTK collections + - [x] GP collection + - [x] Core Bulk collection + - [x] Third-party collection + - [x] SDK Bulk collection + - [x] SDK R2P collection + - [x] ISO 20022 mode tests + - [x] FX collection (or tests) + - [x] Interscheme test collection + - [x] Validation using CGS Golden path regression tests + - [x] Test upgradability from previous release (v16.0.4 / v16.0.0) +- [x] Deployment of released Helm on a QA environment + - [x] Helm release is deployed on QA successfully + - [x] Validation using Golden path regression tests on QA + - [x] GP collection + - [x] Core Bulk collection + - [x] Third-party collection + - [x] SDK Bulk collection + - [x] SDK R2P collection + - [x] FX collection (or tests) + - [x] ISO 20022 mode tests + - [x] Interscheme test collection +- [x] Validate daily cronJobs on dev/qa for GP runs well and Cleanup scripts +- Validate that we can upgrade from the previous stable release, and this is also to pick up any "gotchas" that may need to be addressed as part of the release, or perhaps release notes need to be updated assuming that it would be up to the upgrader to deal with. + + +## 2. Mojaloop Release process - proposed updates: + +Propose release schedule and timelines + +1. Example: Feature freeze for a (major) release before six weeks prior to the next PI kick-off (or community event) +1. Freeze bug fixes (non critical) to be included four weeks prior to release date +1. RC to be validated by at least one downstream implementer such Mini-loop or IaC or Core-test-harness or another implementer +1. Release to move ahead on time if there are no high or medium priority bugs open in RC and validated on a dev environment and one downstream team / implementer +1. Streamline release numbers between various components of the Mojaloop platform, such as the Finance Portal +1. Include performance numbers with details on the setup on which the baselining was performed +1. Resource usage: capture resource footprint for a base release +1. Document support mechanisms for Mojaloop releases + +## 3. Mojaloop helm release contents + +Mojaloop services that support core functionality for the platform and other key services supporting them, along with tools needed for testing such as simulators + +Core Functionality with Configurability +1. Account Lookup + - Account Lookup Admin + - Oracles + - ALS (Account Lookup Service) +2. Quoting + - Support for persistent/pass-through modes (configurable) +3. Transfers (Clearing) + - Support for on-us transfers (configurable) +4. Settlement + - Support for various types, granularity, and frequency +5. Transaction Requests (Request-to-pay functionality) +6. 3PPI Services (Third-Party Provider Interface) +7. API Layer - For parties, quotes, transfers, and transaction requests +8. Notifications + - ML-API-Adapter +9. Currency Conversion +10. Extended Functionality + - Central Event Processor + - Email Notifier (prior to version 15) + - Traceability and Monitoring Support + - Instrumentation +11. Auditing + - Comprehensive auditing capabilities +12. Supporting Services & Tools for Testing + - ML TTK (Testing Toolkit) + - ML Simulator + - SDK-Scheme-Adapters + - Payment Manager Instances +13. Third-Party Scheme Adapters + - Integration with third-party schemes +14. Participant Life-Cycle Management + - Participant Creation + - Participant Updates +15. Participant Support + - Simple, Easily Usable Tools for Adopters (Example: [SDK-Scheme-Adapter](https://github.com/mojaloop/sdk-scheme-adapter), [Integration Toolkit](https://github.com/mojaloop/integration-toolkit/tree/main) ) + - Onboarding Functionality and Support + +## 4. Mojaloop Platform +1. Primary mojaloop (helm) release and config that supports + - Core clearing engine including support for Bulk + - Quoting + - Account lookup and supporting components + - Settlement engine + - API layer + - Support for request-to-pay (transaction requests) + - Participant life-cycle management + - Ref: Mojaloop helm release (example: v15.1.0) +2. PISP / 3PPI functionality +3. API Gateway(s) + - Provide a secure API layer + - Provide Ingress, Egress, IP filtering, firewalls + - Support security mechanisms: JWS, mTLS + - Reference: WSO2 +4. Security components: + - HSM where relevant / used + - Identity & access management + - Cert management + - Connection management +5. Finance Portal, Reporting + - Portals for Hub Operations, Business Operations teams + - Portals, capabilities for Technical Operations teams + - Ref: FP v3 based on Business Operations Framework +6. Monitoring Support: + - Operational support and tracing (example: EFK, Prometheus, Grafana, Loki) + - IaC uses Grafana, Prometheus and Loki +7. Use IaC as reference, example: https://github.com/mojaloop/iac-modules/releases/tag/v5.7.0 + + + +## Current Releases + +> *Note: The versions below are the latest published version for each distinct release artifact provided for reference. Consult the release notes for the respective Helm release to see which versions are included in the [Helm Charts Packaged Release](#helm-charts-packaged-releases) version.* + +* Helm: [![Git Releases](https://img.shields.io/github/release/mojaloop/helm.svg?style=flat)](https://github.com/mojaloop/helm/releases) +* Central-Ledger: [![Git Releases](https://img.shields.io/github/release/mojaloop/central-ledger.svg?style=flat)](https://github.com/mojaloop/central-ledger/releases) +* Ml-API-Adapter: [![Git Releases](https://img.shields.io/github/release/mojaloop/ml-api-adapter.svg?style=flat)](https://github.com/mojaloop/ml-api-adapter/releases) +* Account-Lookup-Service: [![Git Releases](https://img.shields.io/github/release/mojaloop/account-lookup-service.svg?style=flat)](https://github.com/mojaloop/account-lookup-service/releases) +* Quoting-Service: [![Git Releases](https://img.shields.io/github/release/mojaloop/quoting-service.svg?style=flat)](https://github.com/mojaloop/quoting-service/releases) +* Transaction-Request-Service: [![Git Releases](https://img.shields.io/github/release/mojaloop/transaction-requests-service.svg?style=flat)](https://github.com/mojaloop/transaction-requests-service/releases) +* Bulk-API-Adapter: [![Git Releases](https://img.shields.io/github/release/mojaloop/bulk-api-adapter.svg?style=flat)](https://github.com/mojaloop/bulk-api-adapter/releases) +* Central-Settlement: [![Git Releases](https://img.shields.io/github/release/mojaloop/central-settlement.svg?style=flat)](https://github.com/mojaloop/central-settlement/releases) +* Central-Event-Processor: [![Git Releases](https://img.shields.io/github/release/mojaloop/central-event-processor.svg?style=flat)](https://github.com/mojaloop/central-event-processor/releases) +* Email-Notifier: [![Git Releases](https://img.shields.io/github/release/mojaloop/email-notifier.svg?style=flat)](https://github.com/mojaloop/email-notifier/releases) +* SDK-Scheme-Adapter: [![Git Releases](https://img.shields.io/github/release/mojaloop/sdk-scheme-adapter.svg?style=flat)](https://github.com/mojaloop/sdk-scheme-adapter/releases) +* Thirdparty-SDK: [![Git Releases](https://img.shields.io/github/release/mojaloop/thirdparty-sdk.svg?style=flat)](https://github.com/mojaloop/thirdparty-sdk/releases) +* Thirdparty-Api-Svc: [![Git Releases](https://img.shields.io/github/release/mojaloop/thirdparty-api-svc.svg?style=flat)](https://github.com/mojaloop/thirdparty-api-svc/releases) +* Auth-Svc: [![Git Releases](https://img.shields.io/github/release/mojaloop/auth-service.svg?style=flat)](https://github.com/mojaloop/auth-service/releases) +* ML-Testing-Toolkit: [![Git Releases](https://img.shields.io/github/release/mojaloop/ml-testing-toolkit.svg?style=flat)](https://github.com/mojaloop/ml-testing-toolkit/releases) +* ML-Testing-Toolkit-Ui: [![Git Releases](https://img.shields.io/github/release/mojaloop/ml-testing-toolkit-ui.svg?style=flat)](https://github.com/mojaloop/ml-testing-toolkit-ui/releases) + + +For an exhaustive list of helm releases, please visit the [Helm release page](https://github.com/mojaloop/helm/releases). diff --git a/docs/technical/technical/sdk-scheme-adapter/BulkEnhancements/Readme.md b/docs/technical/technical/sdk-scheme-adapter/BulkEnhancements/Readme.md new file mode 100644 index 000000000..1d8e5d95c --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/BulkEnhancements/Readme.md @@ -0,0 +1,65 @@ +# SDK Support for Bulk Transfers - Overview +This design document describes how the SDK Scheme Adapter has been enhanced to support the bulk transfers use case. + +## Why? - Mojaloop bulk transfer limitations overcome +The implementation of bulk transfers within Mojaloop have the following limitations that this SDK bulk enhancement is designed to overcome. +1. Only individual transfers that are addressed to the same Payer DFSP may be included in a bulk quotes and bulk transfers call. +1. The number of individual quotes and transfers in each bulkQuotes and bulkTransfers respectively are limited to a maximum of 1000. +1. In order to allow bulk functionality, all Payee DFSP's need to create integration support for bulk messaging. I.e. If the bulk use case were to be introduced into an existing scheme, then all connecting DFSPs would need to upgrade their connections and integrations into their core banking systems. +1. There is currently no bulk discovery call. + +## SDK Scheme Adapter bulk enhancement requirements +The enhancements enable: +1. Transfers where the discovery has not yet been called. +1. No limit on number of transfers (limited by infrastructure, network capabilities but > 1k that ML FSPIOP specifies) +1. Payee integration support for bulk being optional +1. Optionally support + - a single call that performs Discovery, Agreement and Transfer + - independently accepting of party lookups + - independently accepting of quotes + - setting a fee limit on the auto acceptance of quotes + - the skipping of the discovery phase + - running only the discovery phase + - setting an expiration for the bulk message + - home transaction IDs for both the bulk message and the individual transfers. + - both synchronous API calls and asynchronous API calls + +## Features Implemented +The current implementation does not include all the features. All the features that have been completed are functional and can be used. Additional features and enhancements can be added to the existing functionality as prioritized by Mojaloop product and the community. This aligns with the MVP (Minimal Viable Product) agile concept. +These are the features that are currently implemented: + +|Feature|Implementation Status|Release Version| +|---|---|---| +|Asynchronous Mode| released | v14.1.0 RC| +|Synchronous Mode| not started | | +|Auto Accept Party| not started | | +|Auto Accept Quote (with fee limit)| not started | | +|Only Validate Party| not started | | +|Skip Party Lookup| not started | | +|Bulk Expiration| not started | | +|Payee SDK - Demultiplexing bulk quotes| not started | | +|Payee SDK - Demultiplexing bulk transfers| not started | | +|Mojaloop - Bulk Patch Notification| not started | | +|Payee SDK - Demultiplexing bulk patch notification| not started | | + +### Functional Diagram +![Functional Diagram](../assets/BulkSDKEnhancements.drawio.svg) + +## Architectural Diagram +The Event Sourcing architecture has split the implementation into four components +1. **Backend API** : +The backend API receives API call and produces corresponding domain events, and monitors domain events to produce API callbacks. +1. **Domain Event Handler**: +The Domain Event Handler consumes Domain Events and produces Command events. +1. **Command Event Handler**: +The Command Event Handler consumes command events and produces domain events +1. **FSPIOP API**: +The FSPIOP API monitors domain events and produces corresponding FSPIOP calls, and monitors API Callbacks to produce corresponding domain events. + +![Architectural Diagram](../assets/BulkSDKEnhancements-Architecture.drawio.svg) + + +## Overview Sequence Diagram +Here is a sequence diagram that outlines the role that the SDK Scheme Adapter will play in a bulk call, both for a Payer DFSP and a Payee DFSP. +![Bulk Transfer Sequence Diagram Overview](../assets/sequence/SDKBulkSequenceDiagram.svg) + diff --git a/docs/technical/technical/sdk-scheme-adapter/BulkEnhancements/SDKBulk-API-Design.md b/docs/technical/technical/sdk-scheme-adapter/BulkEnhancements/SDKBulk-API-Design.md new file mode 100644 index 000000000..aae29a0c9 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/BulkEnhancements/SDKBulk-API-Design.md @@ -0,0 +1,154 @@ +# SDK Support for Bulk Transfers - API +The Payer SDK Scheme Adapter enhancements have been added to the API under the \BulkTransactions endpoint. +- **POST** /bulkTransactions +- **PUT** /bulkTransactions +- **PUT** /bulkTransactions callback + +The Outbound Open API definition can be found [here](https://github.com/mojaloop/api-snippets/blob/master/sdk-scheme-adapter/v2_0_0/outbound/openapi.yaml). +The Inbound Open API definition can be found [here](https://github.com/mojaloop/api-snippets/blob/master/sdk-scheme-adapter/v2_0_0/inbound/openapi.yaml). + + +## Technical Sequence Diagram +![Technical Bulk Transfer Sequence Diagram](https://raw.githubusercontent.com/mojaloop/sdk-scheme-adapter/master/docs/design-bulk-transfers/assets/api-sequence-diagram.svg) + +## Error Tables for bulk transfers +[Table of Error Codes](./assets/sequence/BULK-ERRORCODES.md) + +### Discovery Phase +All the errors encountered during this phase will be accumulated in the mojaloop-connector and will be added to the `lastError` object and returned to the Payer FSP along with all other successful or failed transfers involved in the bulk transfer request. + +mojaloop-connector will act as a pass-through for all the errors returned by the switch + +``` + "lastError": { + "httpStatusCode": 202, + "mojaloopError": { + "errorInformation": { + "errorCode": "3204", + "errorDescription": "Party not found", + "extensionList": {"extension": [{"key": "string","value": "string"}]} + } + } + } +``` + +**Party Lookup Error Codes** + +| Error Description | Error Code | HTTP Code | Category | +|------------------------------------------------------------------------|-------------|------------------|-----------------------------------------------------------| +| Communication error | 1000 | 503 | Technical Error | +| Destination communication error | 1001 | 503 | Technical Error | +| Generic server error | 2000 | 503 | Processing Error | +| Internal server error | 2001 | 503 | Processing Error | +| Timeout Resolving Party | 2004 | 503 | Processing Error | +| Generic validation error | 3100 | 400 | Request Validation Error | +| Party not found | 3204 | 202 | Processing Error | + +### Agreement Phase +All the errors encountered during this phase will be accumulated in the mojaloop-connector and will be added to the `lastError` object and returned to the Payer FSP along with all other successful or failed transfers involved in the bulk transfer request. + +mojaloop-connector will act as a pass-through for all the errors returned by the switch + +``` + "lastError": { + "httpStatusCode": 202, + "mojaloopError": { + "errorInformation": { + "errorCode": "3204", + "errorDescription": "Party not found", + "extensionList": {"extension": [{"key": "string","value": "string"}]} + } + } + } +``` + +**Quotes Error Codes** + +| Error Description | Error Code | HTTP Code | Category | +|------------------------------------------------------------------------|-------------|------------------|-----------------------------------------------------------| +| Communication error | 1000 | 503 | Technical Error | +| Destination communication error | 1001 | 503 | Technical Error | +| Generic server error | 2000 | 503 | Technical Error | +| Internal server error | 2001 | 503 | Technical Error | +| Not implemented | 2002 | 501 | Processing Error | +| Service currently unavailable | 2003 | 503 | Processing Error | +| Server timed out | 2004 | 503 | Processing Error | +| Server busy | 2005 | 503 | Processing Error | +| Generic client error | 3000 | 400 | Request Validation Error | +| Unacceptable version requested | 3001 | 406 | Not acceptable Error | +| Unknown URI | 3002 | 404 | Not Found Error | +| Generic validation error | 3100 | 400 | Request Validation Error | +| Malformed syntax | 3101 | 400 | Request Validation Error | +| Missing mandatory element | 3102 | 400 | Request Validation Error | +| Too many elements | 3103 | 400 | Request Validation Error | +| Too large payload | 3104 | 400 | Request Validation Error | +| Invalid signature | 3105 | 403 | Forbidden Error | +| Destination FSP Error | 3201 | 404 | Not Found Error | +| Payer FSP ID not found | 3202 | 404 | Not Found Error | +| Payee FSP ID not found | 3203 | 404 | Not Found Error | +| Quote ID not found | 3205 | 404 | Not Found Error | +| Bulk quote ID not found | 3209 | 404 | Not Found Error | +| Generic expired error | 3300 | 503 | Processing Error | +| Quote expired | 3302 | 503 | Processing Error | +| Generic Payer error | 4000 | 400 | Request Validation Error | +| Generic Payer rejection | 4100 | 403 | Forbidden Error | +| Payer limit error | 4200 | 400 | Request Validation Error | +| Payer permission error | 4300 | 403 | Forbidden Error | +| Generic Payer blocked error | 4400 | 403 | Forbidden Error | +| Generic Payee error | 5000 | 503 | Processing Error | +| Payee FSP insufficient liquidity | 5001 | 503 | Processing Error | +| Generic Payee rejection | 5100 | 403 | Forbidden Error | +| Payee rejected quote | 5101 | 503 | Processing Error | +| Payee FSP unsupported transaction type | 5102 | 503 | Processing Error | +| Payee rejected quote | 5103 | 503 | Processing Error | +| Payee unsupported currency | 5106 | 503 | Processing Error | +| Payee limit error | 5200 | 503 | Processing Error | +| Payee permission error | 5300 | 403 | Forbidden Error | +| Generic Payee blocked error | 5400 | 403 | Forbidden Error | + + + +### Transfer Phase +All the errors encountered during this phase will be accumulated in the mojaloop-connector and will be added to the `lastError` object and returned to the Payer FSP along with all other successful or failed transfers involved in the bulk transfer request. + +mojaloop-connector will act as a pass-through for all the errors returned by the switch + +``` + "lastError": { + "httpStatusCode": 404, + "mojaloopError": { + "errorInformation": { + "errorCode": "3210", + "errorDescription": "Bulk transfer ID not found", + "extensionList": {"extension": [{"key": "string","value": "string"}]} + } + } + } +``` + +**Transfer Error Codes** + +| Error Description | Error Code | HTTP Code | Category | +|------------------------------------------------------------------------|-------------|------------------|-----------------------------------------------------------| +| Communication error | 1000 | 503 | Technical Error | +| Destination communication error | 1001 | 503 | Technical Error | +| Generic server error | 2000 | 503 | Processing Error | +| Internal server error | 2001 | 503 | Processing Error | +| Server timed out | 2004 | 503 | Processing Error | +| Generic validation error | 3100 | 400 | Request Validation Error | +| Bulk transfer ID not found | 3210 | 404 | Processing Error | +| Generic expired error | 3300 | 503 | Processing Error | +| Transaction request expired | 3301 | 503 | Processing Error | +| Transfer expired | 3303 | 503 | Processing Error | +| Generic Payee error | 5000 | 400 | Processing Error | +| Payee FSP insufficient liquidity | 5001 | 400 | Processing Error | +| Generic Payee rejection | 5100 | 400 | Processing Error | +| Payee rejected quote | 5101 | 400 | Processing Error | +| Payee FSP unsupported transaction type | 5102 | 400 | Processing Error | +| Payee FSP rejected quote | 5103 | 400 | Processing Error | +| Payee rejected transaction | 5104 | 400 | Processing Error | +| Payee FSP rejected transaction | 5105 | 400 | Processing Error | +| Payee unsupported currency | 5106 | 400 | Processing Error | +| Payee limit error | 5200 | 400 | Processing Error | +| Payee permission error | 5300 | 403 | Processing Error | +| Generic Payee blocked error | 5400 | 400 | Processing Error | diff --git a/docs/technical/technical/sdk-scheme-adapter/BulkEnhancements/SDKBulk-EventSourcing-Design.md b/docs/technical/technical/sdk-scheme-adapter/BulkEnhancements/SDKBulk-EventSourcing-Design.md new file mode 100644 index 000000000..13214e643 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/BulkEnhancements/SDKBulk-EventSourcing-Design.md @@ -0,0 +1,179 @@ +# SDK Support for Bulk Transfers - DDD and Event Sourcing Design +## Design overview +This diagram gives an overview of the SDK design. + +![Design Overview](../assets/overview-drawio.png) + +An http 202 response when posting a asynchronous request means that the the SDK has accepted the request, and that the request will be processed and a response provided. Because of the potential long delay's involved in processing large numbers of bulk payments in an asynchronous way. A new design approach in the SDK was necessary to meet the 202 response expectations. + +## DDD and Event sourcing design +An event sourcing and domain driven was chosen, as this solves all requirements of reliability and scalability while takeing advantage of the lib's and tools that have been built for the Mojaloop vNext architecture. + +## Bulk Payer DFSP SDK-Scheme-Adapter +### Outbound event sourcing sequence diagram +![Outbound sequence diagram](../assets/sequence/outbound-sequence.svg) + +## Payee DFSP SDK-Scheme-Adapter +### Inbound bulk quotes event sourcing sequence diagram +![Inbound bulk quotes sequence](../assets/sequence/inbound-bulk-quotes-sequence.svg) + +### Inbound bulk transfers event sourcing sequence diagram +![Inbound bulk transfers sequence](../assets/sequence/inbound-bulk-transfers-sequence.svg) + + +## Redis Store Data mapping for outbound bulk transfer +### 1. States (Global and individual) + +#### Command: +``` +HSET +``` +#### Key: +``` +outboundBulkTransaction_< bulkTransactionId > +``` + +#### Attributes: +- **bulkTransactionId**: bulkTransactionId +- **bulkHomeTransactionID**: Home transaction ID +- **request**: { + options: Options, + extensionList: Bulk Extension List +} +- **individualItem_< transactionId >**: Serialize ({ + id: transactionId + request: {} + state: Individual state + batchId: `` + partyRequest: {} + quotesRequest: {} + transfersRequest: {} + partyResponse: {} + quotesResponse: {} + transfersResponse: {} + lastError: {} + acceptParty: bool + acceptQuotes: bool +}) +- **state**: Global state + - RECEIVED + - DISCOVERY_PROCESSING +- **bulkBatch_< batchId >**: Serialize ({ + id: batchId + state: Individual state + - AGREEMENT_PROCESSING + - TRANSFER_PROCESSING + bulkQuoteId: `` + bulkTransferId: `` (Can be batchId) +}) +- **partyLookupTotalCount**: Total number of party lookup requests +- **partyLookupSuccessCount**: Total number of party lookup requests those are succeeded +- **partyLookupFailedCount**: Total number of party lookup requests those are failed +- **bulkQuotesTotalCount**: Total number of bulk quotes requests +- **bulkQuotesSuccessCount**: Total number of quotes requests those are succeeded +- **bulkQuotesFailedCount**: Total number of quotes requests those are failed +- **bulkTransfersTotalCount**: Total number of bulk transfers requests +- **bulkTransfersSuccessCount**: Total number of bulk transfers requests those are succeeded +- **bulkTransfersFailedCount**: Total number of bulk transfers requests those are failed + +::: tip Notes +- Kafka messages should contain bulkID. +- To update the global state use the command `HSET bulkTransaction_< bulkTransactionId > state < stateValue >` +::: + +### 2. For mapping individual callbacks with individual bulk items + +#### Command: +``` +HSET outboundBulkCorrelationMap +``` + +#### Attributes: +- partyLookup_``_``(_``): "{ bulkTransactionId: ``, transactionId: `` }" +- bulkQuotes_``: "{ bulkTransactionId: ``, batchId: `` }" +- bulkTransfers_``: "{ bulkTransactionId: ``, batchId: ``, bulkQuoteId: `` }" +- bulkHomeTransactionId_``: "{ bulkTransactionId: `` }" + +::: tip Notes: +- We can use `HKEYS` command to fetch all the individual transfer IDs in a bulk to iterate +::: + +## Redis message format for inbound bulk transfer +### 1. Bulk Quotes +#### Command: +``` +HSET +``` +#### Key: +``` +inboundBulkQuotes_< bulkQuotesId > +``` + +#### Attributes: +- **bulkQuotesId**: bulkQuotesId +- **individualItem_< quotesId >**: Serialize ({ + id: quotesId + request: {} + state: Individual state + quotesRequest: {} + quotesResponse: {} + lastError: {} +}) +- **state**: Global state + - RECEIVED + - PROCESSING +- **bulkQuotesTotalCount**: Total number of bulk quotes requests +- **bulkQuotesSuccessCount**: Total number of quotes requests those are succeeded +- **bulkQuotesFailedCount**: Total number of quotes requests those are failed + +::: tip Notes +- Kafka messages should contain bulkQuotesId. +- To update the global state use the command `HSET bulkQuotes_< bulkQuotesId > state < stateValue >` +::: + +### 2. Bulk Transfers +#### Command: +``` +HSET +``` +#### Key: +``` +inboundBulkTransfer_< bulkTransferId > +``` + +#### Attributes: +- **bulkTransferId**: bulkTransferId +- **individualItem_< transferId >**: Serialize ({ + id: transferId + request: {} + state: Individual state + transfersRequest: {} + transfersResponse: {} + lastError: {} +}) +- **state**: Global state + - RECEIVED + - PROCESSING +- **bulkTransferTotalCount**: Total number of bulk transfers requests +- **bulkTransferSuccessCount**: Total number of transfers requests those are succeeded +- **bulkTransferFailedCount**: Total number of transfers requests those are failed + +::: tip Notes +- Kafka messages should contain bulkTransferId. +- To update the global state use the command `HSET bulkTransfer_< bulkTransferId > state < stateValue >` +::: + +### 3. For mapping individual callbacks with individual bulk items + +#### Command: +``` +HSET inboundBulkCorrelationMap +``` + +#### Attributes: +- quotes_``: "{ bulkQuoteId: `` }" +- transfers_``: "{ bulkTransferId: ``, bulkQuoteId: `` }" + +::: tip Notes: +- We can use `HKEYS` command to fetch all the individual transfer IDs in a bulk to iterate +::: diff --git a/docs/technical/technical/sdk-scheme-adapter/BulkEnhancements/SDKBulk-Tests.md b/docs/technical/technical/sdk-scheme-adapter/BulkEnhancements/SDKBulk-Tests.md new file mode 100644 index 000000000..2bea1c00c --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/BulkEnhancements/SDKBulk-Tests.md @@ -0,0 +1,201 @@ +# SDK Support for Bulk Transfers - Tests +## Test Strategy +The quality of the delivered solution is as good a the quality of the tests and testing strategy adopbted. The distributed nature of this event sourcing solution affected the testing strategy chosen. Multiple types of test were created, each supporting the others and designed to pick bugs as quickly as possible. + +The Command event handler and the domain event handler have both unit tests and narrow integration tests as the base testing. The FSPIOP API and backend API components have only unit tests. +Great emphasis was put on the functional tests which then tested the four components working together in both happy and unhappy path scenarios. + +### Narrow integration tests +These tests are written in jest and assert for example the updated state store and produced events based on a command event generated. + +**Command Handler Integration Test Harness** + +![Local Test Setup](../assets/CHIntegrationTestHarness.drawio.svg) + +### The functional test testharness +The functional test makes use of the TTK which simulates both the Payer and the Payee DFSP backends. + +:::tip Note +This test harness tests both the Payer SDK and the Payee SDK. +::: + +![Local Test Setup](../assets/bulk-functional-local-test-setup.drawio.svg) + +:::tip Note +These test can be run on the local checked out monorepo, and are run in the CI pipeline, and are included in the helm as helm tests used to confirm deployment. +::: + +## Payer DFSP Integration Test Matrix + +
    + +|Test Cases|C1|C2|C3|C4|C5|C6|C7|C8|C9|C10|C11|C12| +|---|---|---|---|---|---|---|---|---|---|---|---|---| +|INT D-1||||x||||||||| +|INT D-2||x||||||||||| +|INT D-3||x||||||||||| +|INT D-4|x|||||||||||| +|INT D-5|||x|||||||||| +|INT D-6|||x|||||||||| +|INT A-1||||||x||||||| +|INT A-2|||||x|||||||| +|INT T-1|||||||||||x|| +|INT T-2||||||||||x||| +|INT T-3|||||||||x|||| +|INT T-4|||||||||||x|| +|INT T-5|||||||x|||||| +|INT T-6||||||||||||x| + +
    + +## Payer DFSP Functional Test Matrix + +
    + +|Test Cases|B1|B2|B3|B4|B5|F1|F2|F3|F4|F5|F6|F7|F8|F9|D1|D2|D3|D4|D5|D6|D7|D8|D9|D10|D11|D12|D13|D14|D15|D16|D17|D18|D19|D20|C1|C2|C3|C4|C5|C6|C7|C8|C9|C10|C11|C12| +|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| +|FUNC 1|x|x|x|x|x|x|x||x|x||x|x||x|x|x|x|x|x|x|x|x|x|x|x|x|||x|x|x|x|x|x|x|x|x|x|x|x||x|x|x|x +|FUNC 2|x|x||||x||x|||||||x|x|x|x|x||||||||||||||||x|x|x||||||||| +|FUNC 3|x|x||||x||x|||||||x|x|x|x|x||||||||||||||||x|x|x||||||||| +|FUNC 4|x|x||||x||x|||||||x|x|x|x|x||||||||||||||||x|x|x||||||||| +|FUNC 5|x|x||||x||x|||||||x|x|x|x|x||||||||||||||||x|x|x||||||||| +|FUNC 6|x|x||||x||x|||||||x|x|x|x|x||||||||||||||||x|x|x||||||||| +|TC-BQ1|x|x|x|||x|x||x||x||||x|x|x|x|x|x|x|x|x|x|||||||||||x|x|x|x|x|x|||||x|x +|TC-BQ2|x|x|x|||x|x||x|x|||||x|x|x|x|x|x|x|x|x|x|||||||||||x|x|x|x|x|x|||||x|x +|TC-BQ3|x|x|x|||x|x||x|x|||||x|x|x|x|x|x|x|x|x|x|x||||||||||x|x|x|x|x|x|||||| +|TC-BQ4|x|x|x|||x|x||x|x|||||x|x|x|x|x|x|x|x|x|x|x||||||||||x|x|x|x|x|x|||||| +|TC-BQ5|x|x|x|||x|x||x|x|||||x|x|x|x|x|x|x|x|x|x|x||||||||||x|x|x|x|x|x|||||| +|TC-BQ6|x|x|x|||x|x||x|x|||||x|x|x|x|x|x|x|x|x|x|x||||||||||x|x|x|x|x|x|||||| +|TC-BQ7|x|x|x|||x|x||x|x|||||x|x|x|x|x|x|x|x|x|x|x||||||||||x|x|x|x|x|x|||||| +|TC-BQ8|x|x|x|||x|x||x|x|||||x|x|x|x|x|x|x|x|x|x|x||||||||||x|x|x|x|x|x|||||| +|TC-BQ9|x|x|x|||x|x||x|x|x||||x|x|x|x|x|x|x|x|x|x|x||||||||||x|x|x|x|x|x|||||| +|TC-BQ10|x|x|x|||x|x||x||x||||x|x|x|x|x|x|x|x|x|x|||||||||||x|x|x|x|x|x|||||x|x| +|TC-BQ11|x|x|x|||x|x||x|x|||||x|x|x|x|x|x|x|x|x|x|x||||||||||x|x|x|x|x|x||||||| +|TC-BQ13|x|x|x|||x|x||x|x|||||x|x|x|x|x|x|x|x|x|x|x||||||||||x|x|x|x|x|x||||||| +|TC-BT1|x|x|x|x|x|x|x||x|x||x||x|x|x|x|x|x|x|x|x|x|x|x|x|x|||x|x||||x|x|x|x|x|x|x||x|x|x|x| +|TC-BT2|x|x|x|x|x|x|x||x|x||x||x|x|x|x|x|x|x|x|x|x|x|x|x|x|||x|x||||x|x|x|x|x|x|x||x|x|x|x| +|TC-BT3|x|x|x|x|x|x|x||x|x|x|x||x|x|x|x|x|x|x|x|x|x|x|x|x|x|||x|x||||x|x|x|x|x|x|x||x|x|x|x| +|TC-BT4|x|x|x|x|x|x|x||x|x|x|x||x|x|x|x|x|x|x|x|x|x|x|x|x|x|||x|x||||x|x|x|x|x|x|x||x|x|x|x| +|TC-BT5|x|x|x|x|x|x|x||x|x||x||x|x|x|x|x|x|x|x|x|x|x|x|x|x|||x|x||||x|x|x|x|x|x|x||x|x|x|x| +|TC-BT6|x|x|x|x|x|x|x||x|x||x||x|x|x|x|x|x|x|x|x|x|x|x|x|x|||x|x||||x|x|x|x|x|x|x||x|x|x|x| +|TC-BT7|x|x|x|x|x|x|x||x|x||x||x|x|x|x|x|x|x|x|x|x|x|x|x|x|||x|x||||x|x|x|x|x|x|x||x|x|x|x| +|TC-BT8|x|x|x|x|x|x|x||x|x||x||x|x|x|x|x|x|x|x|x|x|x|x|x|x|||x|x||||x|x|x|x|x|x|x||x|x|x|x| + +
    + +## Payer DFSP Features reference +|#|Outbound Features|Detail| +|---|---|---| +|B1|Backend API|POST /bulkTransactions SDKBulkRequest| +|B2|Backend API|Event SDKOutboundBulkAcceptPartyInfoRequested| +|B3|Backend API|PUT /bulkTransactions/{bulkTransactionId} Accept Party| +|B4|Backend API|PUT /bulkTransactions/{bulkTransactionId} Accept Quote| +|B5|Backend API|PUT /bulkTransactions/{bulkTransactionId} Results| +|F1|FSPIOP API|GET /parties| +|F2|FSPIOP API|PUT /parties/{Type}/{ID}| +|F3|FSPIOP API|PUT /parties/{Type}/{ID}/error| +|F4|FSPIOP API|POST /bulkQuotes| +|F5|FSPIOP API|PUT /bulkQuotes/{ID}| +|F6|FSPIOP API|PUT /bulkQuotes/{ID}/error| +|F7|FSPIOP API|POST /bulkTransfers| +|F8|FSPIOP API|PUT /bulkTransfers/{ID}| +|F9|FSPIOP API|PUT /bulkTransfers/{ID}/error| +|D1|Domain Event Handler|SDKOutboundBulkRequestReceived| +|D2|Domain Event Handler|SDKOutboundBulkPartyInfoRequested| +|D3|Domain Event Handler|PartyInfoCallbackReceived| +|D4|Domain Event Handler|PartyInfoCallbackProcessed| +|D5|Domain Event Handler|SDKOutboundBulkPartyInfoRequestProcessed| +|D6|Domain Event Handler|SDKOutboundBulkAcceptPartyInfoReceived| +|D7|Domain Event Handler|SDKOutboundBulkAutoAcceptPartyInfoRequested| +|D8|Domain Event Handler|SDKOutboundBulkAcceptPartyInfoProcessed| +|D9|Domain Event Handler|BulkQuotesCallbackReceived| +|D10|Domain Event Handler|BulkQuotesCallbackProcessed| +|D11|Domain Event Handler|SDKOutboundBulkQuotesRequestProcessed| +|D12|Domain Event Handler|SDKOutboundBulkAcceptQuoteReceived| +|D13|Domain Event Handler|SDKOutboundBulkAcceptQuoteProcessed| +|D14|Domain Event Handler|SDKOutboundBulkAutoAcceptQuoteRequested| +|D15|Domain Event Handler|SDKOutboundBulkAutoAcceptQuoteProcessed| +|D16|Domain Event Handler|BulkTransfersCallbackReceived| +|D17|Domain Event Handler|BulkTransfersCallbackProcessed| +|D18|Domain Event Handler|SDKOutboundBulkTransfersRequestProcessed| +|D19|Domain Event Handler|SDKOutboundBulkResponseSent| +|D20|Domain Event Handler|SDKOutboundBulkResponseSentProcessed| +|C1|Command Event Handler|ProcessSDKOutboundBulkRequest| +|C2|Command Event Handler|ProcessSDKOutboundBulkPartyInfoRequest| +|C3|Command Event Handler|ProcessPartyInfoCallback| +|C4|Command Event Handler|ProcessSDKOutboundBulkAcceptPartyInfo| +|C5|Command Event Handler|ProcessSDKOutboundBulkQuotesRequest| +|C6|Command Event Handler|ProcessBulkQuotesCallback| +|C7|Command Event Handler|ProcessSDKOutboundBulkAcceptQuote| +|C8|Command Event Handler|ProcessSDKOutboundBulkAutoAcceptQuote| +|C9|Command Event Handler|ProcessSDKOutboundBulkTransfersRequest| +|C10|Command Event Handler|ProcessBulkTransfersCallback| +|C11|Command Event Handler|PrepareSDKOutboundBulkResponse| +|C12|Command Event Handler|ProcessSDKOutboundBulkResponseSent| + +## Test Cases reference + +|Group|# test case|Test Type|Status|Detail| +|--- |--- |--- |--- |--- | +|**Discovery** - Comand Handler Integration Tests||||| +|(process_bulk_accept_party_info.test.ts)|INT D-1|Integration|Pass|Given inbound command event ProcessSDKOutboundBulkAcceptPartyInfo is received Then the logic should loop through individual transfer in the bulk request And update the individual transfer state to DISCOVERY_ACCEPTED or DISCOVERY_REJECTED based on the value in the incoming event And update the overall global state to DISCOVERY_ACCEPTANCE_COMPLETED And outbound event SDKOutboundBulkAcceptPartyInfoProcessed should be published| +|(process_bulk_party_info_request.test.ts)|INT D-2|Integration|Pass|Given Party info does not already exist for none of the individual transfers. And Party Lookup is not skipped When inbound command event ProcessSDKOutboundBulkPartyInfoRequest is received Then the global state should be updated to DISCOVERY_PROCESSING And PartyInfoRequested kafka event should be published for each individual transfer. And State for individual transfer should be updated to DISCOVERY_PROCESSING| +|(process_bulk_party_info_request.test.ts)|INT D-3|Integration|Pass|Given Party info exists for individual transfers. And Party Lookup is not skipped When inbound command event ProcessSDKOutboundBulkPartyInfoRequest is received Then the global state should be updated to DISCOVERY_PROCESSING. And PartyInfoRequested outbound event should not be published for each individual transfer. And State for individual transfer should be updated to RECEIVED.| +|(process_bulk_request.test.ts)|INT D-4|Integration|Pass|When inbound command event ProcessSDKOutboundBulkRequest is received Then outbound event SDKOutboundBulkPartyInfoRequested should be published And Global state should be updated to RECEIVED.| +|(process_party_info_callback.test.ts)|INT D-5|Integration|Pass|Given receiving party info does not exist And receiving party lookup was successful When inbound command event ProcessPartyInfoCallback is received Then the state for individual successful party lookups should be updated to DISCOVERY_SUCCESS And the data in redis for individual transfer should be updated with received party info And outbound event PartyInfoCallbackProcessed event should be published And if all lookups are incomplete, outbound event ProcessSDKOutboundBulkPartyInfoRequestProcessed should not be published And neither outbound event SDKOutboundBulkAutoAcceptPartyInfoRequested/SDKOutboundBulkAutoAcceptPartyInfoRequested should be published| +|(process_party_info_callback.test.ts)|INT D-6|Integration|Pass|Given receiving party info does not exist And receiving party lookup was successful When inbound command event ProcessPartyInfoCallback is received Then the state for individual successful party lookups should be updated to DISCOVERY_SUCCESS And the data in redis for individual transfer should be updated with received party info And outbound event PartyInfoCallbackProcessed event should be published And if all lookups are complete, outbound event ProcessSDKOutboundBulkPartyInfoRequestProcessed should be published And if auto accept party is false, outbound event SDKOutboundBulkAcceptPartyInfoRequested should be published.| +|**Agreement** - Comand Handler Integration Tests||||| +|(process_bulk_quotes_callback.test.ts)|INT A-1|Integration|Pass|Given the BulkTransaction with Options { synchronous: false, onlyValidateParty: true, skipPartyLookup: false, autoAcceptParty: false, autoAcceptQuote: false } And callback for quote batch is successful And the callback has a combination of success and failed responses for individual quotes When Inbound command event ProcessBulkQuotesCallback is received Then the logic should update the individual batch state to AGREEMENT_COMPLETED or AGREEMENT_FAILED, And for each individual transfers in the batch, the state could be AGREEMENT_SUCCESS or AGREEMENT_FAILED accordingly And the individual quote data in redis should be updated with the response And the global BulkTransaction state should be AGREEMENT_ACCEPTANCE_PENDING And domain event BulkQuotesCallbackProcessed should be published And domain event SDKOutboundBulkQuotesRequestProcessed should be published| +|(process_bulk_quotes_callback.test.ts)|INT A-2|Integration|Pass|When Inbound command event ProcessSDKOutboundBulkQuotesRequest is received Then the logic should update the global state to AGREEMENT_PROCESSING, And create batches based on FSP that has DISCOVERY_ACCEPTED state And also has config maxEntryConfigPerBatch And publish BulkQuotesRequested per each batch And update the state of each batch to AGREEMENT_PROCESSING.| +|**Transfers** - Comand Handler Integration Tests||||| +|(prepare_sdk_outbound_bulk_response.test.ts)|INT T-1|Integration|Pass|Given the BulkTransaction with Options { synchronous: false, onlyValidateParty: true, skipPartyLookup: false, autoAcceptParty: false, autoAcceptQuote: false } When inbound command event PrepareSDKOutboundBulkResponseCmdEvt is received And SDKOutboundBulkResponsePreparedDmEvt should be published for each transfer batch And the Bulk Transaction global state should be updated to RESPONSE_PROCESSING| +|(process_bulk_transfers_callback.test.ts )|INT T-2|Integration|Pass|Given the BulkTransaction with Options { synchronous: false, onlyValidateParty: true, skipPartyLookup: false, autoAcceptParty: false, autoAcceptQuote: false } When inbound command event ProcessBulkTransfersCallbackCmdEvt is received Then the transfer batch state should be updated to TRANSFERS_COMPLETED States of failed quotes should remain AGREEMENT_FAILED And the logic should loop through individual transfers in the batch and update the state to TRANSFER_SUCCESS or TRANSFER_FAILED And BulkTransferProcessedDmEvt should be published for each transfer batch And domain event BulkQuotesCallbackProcessed should be published And domain event SDKOutboundBulkQuotesRequestProcessed should be published And domain event SDKOutboundBulkAutoAcceptQuoteProcessedDmEvt should be published And domain event BulkTransfersRequestedDmEvt should be published And domain event BulkTransfersCallbackProcessed should be published And domain event SDKOutboundBulkTransfersRequestProcessed should be published| +|(process_bulk_transfers_request.test.ts)|INT T-3|Integration|Pass|Given the BulkTransaction with Options { synchronous: false, onlyValidateParty: true, skipPartyLookup: false, autoAcceptParty: false, autoAcceptQuote: false } And callback for quote batch is successful And the callback has a combination of success and failed responses for individual quotes When Inbound command event ProcessSDKOutboundBulkTransfersRequestCmdEvt is received Then the global Bulk Transaction State should be updated to TRANSFERS_PROCESSING And the individual batch state should be equal to either TRANSFERS_PROCESSING or TRANSFERS_FAILED, And for each individual transfers in the batch, the state AGREEMENT_ACCEPTED or AGREEMENT_REJECTED depending on the acceptQuotes = TRUE/FALSE, And for each individual transfers in an AGREEMENT_FAILED state should not be altered, And the individual quote data in redis should be updated with the response And domain event BulkQuotesCallbackProcessed should be published And domain event SDKOutboundBulkQuotesRequestProcessed should be published And domain event SDKOutboundBulkAutoAcceptQuoteProcessedDmEvt should be published And domain event BulkTransfersRequestedDmEvt should be published| +|(process_prepare_bulk_response.test.ts)|INT T-4|Integration|Pass|When inbound command event PrepareSDKOutboundBulkResponseCmdEvt is received Then SDKOutboundBulkResponsePreparedDmEvnt should be published| +|(process_sdk_outbound_bulk_accept_quote.test.ts)|INT T-5|Integration|Pass|Given the BulkTransaction with Options { synchronous: false, onlyValidateParty: true, skipPartyLookup: false, autoAcceptParty: false, autoAcceptQuote: false } And callback for quote batch is successful And the callback has a combination of success and failed responses for individual quotes When Inbound command event ProcessSDKOutboundBulkAcceptQuote is received Then the global Bulk Transaction State should be updated to AGREEMENT_ACCEPTANCE_COMPLETED And the individual batch state should be equal to either AGREEMENT_COMPLETED or AGREEMENT_FAILED, And for each individual transfers in the batch, the state AGREEMENT_ACCEPTED or AGREEMENT_REJECTED depending on the acceptQuotes = TRUE/FALSE, And the individual quote data in redis should be updated with the response And domain event BulkQuotesCallbackProcessed should be published And domain event SDKOutboundBulkQuotesRequestProcessed should be published And domain event SDKOutboundBulkAutoAcceptQuoteProcessedDmEvt should be published And domain event BulkTransfersRequestedDmEvt should be published| +|(process_sdk_outbound_bulk_response_sent.test.ts)#|INT T-6|Integration|Pass|Given the BulkTransaction with Options { synchronous: false, onlyValidateParty: true, skipPartyLookup: false, autoAcceptParty: false, autoAcceptQuote: false } When inbound command event ProcessSDKOutboundBulkResponseSentCmdEvt is received And SDKOutboundBulkResponseSentProcessedDmEvt should be published for each transfer batch And the Bulk Transaction global state should be updated to RESPONSE_SENT | +|**Happy Path:** (bulk-happy-path.json)||||| +|- 1 transfer with acceptParty and acceptQuote set to true||||| +||TC-BHP1|Functional|Pass|4 transfers to 2 dfsps, with acceptParty and acceptQuote set to true| +||TC-BHP2|Validation|Pass|Bulk transaction having a format error| +|**Parties Errors:** (bulk-parties-error-cases.json)||||| +|- 1 transfer in the request||||| +||TC-BP1|Functional|Pass|Receiver sends error for in parties response| +||TC-BP2|Functional|Pass|Receiver timesout| +||TC-BP3|Functional|Pass|skipPartyLookup is false and receiver ifo exists in the request.| +|- 2 transfers in the request||||| +||TC-BP4|Functional|Pass|Receiver sends an error response for one of the transfers| +||TC-BP5|Functional|Pass|Receiver times out sending response for one of the transfers| +||TC-BP6|Functional|Pass|Do not get any response from the receiver for both the transfers| +|**Quotes Errors:** (bulk-quotes-error-cases.json)||||| +|- 2 transfers having the same receiver fsp id ||||| +|- acceptParty for all transfers||||| +||TC-BQ1|Functional|Pass|Receiver fsp fails the entire batch | +||TC-BQ2|Functional|Pass|Receiver fsp times out the entire batch| +||TC-BQ3|Functional|Pass|Receiver fsp sends only one response and skips the other| +||TC-BQ4|Functional|Out of scope for MVP|Receiver fsp sends one success response and one failure response (Not Implemented - Issue 3015)| +|- acceptParty varying||||| +||TC-BQ5|Functional|Pass|One true, one false| +||TC-BQ6|Functional|Out of scope for MVP| Accept party false for all responses - Then only party details and no quote respone, final state to be COMPLETED (Not Implemented - Issue 3015)| +||TC-BQ7|Functional|Out of scope for MVP|True is sent only for one quote in PUT /bulkTxn acceptParty, ignoring second one (Not Implemented - Issue 3015)| +||TC-BQ8|Functional|Out of scope for MVP|false is sent only for one quote in PUT /bulkTxn acceptParty, ignoring second one - (Not Implemented - Issue 3015)| +|- 2 transfers having different receiver fsp ids - acceptParty for all transfers||||| +||TC-BQ9|Functional|Pass|One batch sends an error | +||TC-BQ10|Functional|Pass|Both batches sends error| +||TC-BQ11|Functional|Pass|One batch times out| +|- 3 transfers with 2 transfers having 1 receiver fsp id and the other having a different one||||| +||TC-BQ12|Functional|Out of scope for MVP|- The batch with 2 transfers sends only 1 transfer response and the other batch sends the success response (Not implemented - issue 3015)| +||TC-BQ13|Functional|Out of scope for MVP|Error in switch for unsupported currency - (issue - | +|**Transfers Errors:** (bulk-transfer-errors.json)||||| +|- One bulkTransfer with 2 transfers ||||| +|- acceptQuote for all transfers||||| +||TC-BT1|Functional|Pass|Receiver fails the entire batch | +||TC-BT2|Functional|Pass|Receiver times out for the entire batch| +||TC-BT3|Functional|Out of scope for MVP|Receiver fsp sends only one response and skips the other (Not Implemented - Issue 3015)| +||TC-BT4|Functional|Intermittent Failures|Receiver fsp sends one success response and one failure - ( Issue: 3019 )| +|- acceptQuote varying||||| +||TC-BT5|Functional|Out of scope for MVP|One true one false - TC2 - Bug 2958| +||TC-BT6|Functional|Out of scope for MVP|Accept quote - All false (Not Implemented - Issue 3015)| +||TC-BT7|Functional|Out of scope for MVP|True is sent only for one transfer in PUT /bulkTxn acceptParty, ignoring second one - (Not Implemented - Issue 3015)| +||TC-BT8|Functional|Out of scope for MVP|false is sent only for one transfer in PUT /bulkTxn acceptParty, ignoring second one - (Not Implemented - Issue 3015)| + diff --git a/docs/technical/technical/sdk-scheme-adapter/IntegrationBulkFlowPatterns.md b/docs/technical/technical/sdk-scheme-adapter/IntegrationBulkFlowPatterns.md new file mode 100644 index 000000000..40e0e5f79 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/IntegrationBulkFlowPatterns.md @@ -0,0 +1,29 @@ +# Integration Core Banking Systems using Bulk transfers +There are three patterns that can be used when building the Payer DFSP integrations for bulk transfers. +1. **Three phase** transfer integration. This aligns with the three Mojaloop transaction phases. I.e. Discovery, Agreement and Transfer. +1. **Double API Integration** integration. This pattern is described in detail in the sequence diagram below. It involves combining the Discovery and Agreement phases; as the first phase; the results are presented to the Payer for confirmation; following which the Transfer phase is executed as the second phase. +![Payer DFSP Double Integration API Flow Pattern](./assets/sequence/PayerDFSPBulkDoubleIntegrationApiPattern.svg) +1. **Single API Integration** integrations. This pattern is described in detail in the sequence diagram below. Here all three phases are combined to produce a single synchronous transfer call. +![Payer DFSP Single Integration API Flow Pattern](./assets/sequence/PayerDFSPBulkSingleIntegrationApiPattern.svg) + + +::: tip 2-Phased Commit +All Payer DFSP Integration Patterns support a 2 phased (reservation and commit phase) commit. +::: + +## Payee DFSP requirements +The updates to the SDK Scheme Adapter will ensure that DFSP that have build integrations in to Mojaloop will not be required to make any change in order to support the receiving of bulk transfers. I.e. the SDK scheme adapter will receive bulk transfer messages and convert them to individual transfer messages. +If a Payee DFSP would like to take advantage of the bulk transfer message, integration for bulk messages can be implemented when it makes sense to do so for each Payee DFSP. + + +## Ideal Payee Integration Flow Pattern + +Here the AML checks and fees are calculated in the Agreement Phase, and the transfer phase is performed in two phases namely a reserved and commit phase. + +![Payee DFSP Bulk Integration Ideal Pattern](./assets/sequence/PayeeDFSPBulkIdealPattern.svg) + +## Vendor API only supports Single API call +If the Core Banking Systems only support a single API call to perform all transfer related checks and phases. This is the pattern that is most commonly supported. +### Call Transfer on the Patch Notification +![Payee DFSP Integration during Patch Notification](./assets/sequence/PayeeDFSPBulkSingleIntegrationApiOnPatch.svg) +A failure at anytime after the PATCH notification **[Step 19]** will result in a reconciliation error. This can be catered for by building in recompensation methods. E.g. initiate a refund transfer if an error occurs after step 19. diff --git a/docs/technical/technical/sdk-scheme-adapter/IntegrationFlowPatterns.md b/docs/technical/technical/sdk-scheme-adapter/IntegrationFlowPatterns.md new file mode 100644 index 000000000..057a793c7 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/IntegrationFlowPatterns.md @@ -0,0 +1,43 @@ +# Integrating Core Banking Systems to Mojaloop Patterns + +When integrating core banking system into a modern, real-time, push based transaction flow can come with some challenges. These are largely based on what vendor provided integration API's are on offer. This documents discusses what an ideal integration should look like, some of the typical limitations seen in vendor API's, and flow patterns that are used to overcome some of these limitations and a discussion on the risks. + +## Payer DFSP Integration Patterns + +There are three patterns that can be used when building the Payer DFSP integrations +1. **Three phase** transfer integration. This aligns with the three Mojaloop transaction phases. I.e. Discovery, Agreement and Transfer. +1. **Double API Integration** integration. This pattern is described in detail in the sequence diagram below. It involves combining the Discovery and Agreement phases; as the first phase; the results are presented to the Payer for confirmation; following which the Transfer phase is executed as the second phase. +![Payer DFSP Double Integration API Flow Pattern](./assets/sequence/PayerDFSPDoubleIntegrationApiPattern.svg) +1. **Single API Integration** integrations. This pattern is described in detail in the sequence diagram below. Here all three phases are combined to produce a single synchronous transfer call. +![Payer DFSP Single Integration API Flow Pattern](./assets/sequence/PayerDFSPSingleIntegrationApiPattern.svg) + +::: tip 2-Phased Commit +All Payer DFSP Integration Patterns support a 2 phased (reservation and commit phase) commit. +::: + +## Payee DFSP ideal integration pattern +Ideally a vendor's API's will provide the following. +1. To be able to perform AML checks ahead of and independent of the transfer. +1. To be able to calculate the fees of a transfer ahead of and independent of the transfer. +1. To be able to perform the transfer in two phases. I.e. A reserve phase, and then a committing phase. + +If these are available in the Vendor's API, then an ideal integration can be built that reduces reconciliation errors when unexpected errors occur, and has the lowest risk to the DFSP. + +### Ideal Payee Integration Flow Pattern + +Here the AML checks and fees are calculated in the Agreement Phase, and the transfer phase is performed in two phases namely a reserved and commit phase. + +![Payee DFSP Integration Ideal Pattern](./assets/sequence/PayeeDFSPIdealPattern.svg) + +::: warning Common limitation +A common limitation in Vendor API's is that all these functions are combined into a single phase single API call to make a transfer. +::: + +## Vendor API only supports Single API call +If the Core Banking Systems only support a single API call to perform all transfer related checks and phases, there there are two patterns that should be considered. +1. Call Transfer on the Patch Notification +![Payee DFSP Integration during Patch Notification](./assets/sequence/PayeeDFSPSingleIntegrationApiOnPatchPattern.svg) +A failure at anytime after the PATCH notification **[Step 17]** will result in a reconciliation error. This can be catered for by building in recompensation methods. E.g. initiate a refund transfer if an error occurs after step 17. +1. Call Transfer in the Transfer phase. +![Payee DFSP Integration during transfer phase](./assets/sequence/PayeeDFSPSingleIntegrationApiOnTransferPattern.svg) +This pattern is usually not recommended as aborting a transfer is not normally possible. If the transfer is against an internal account e.g. for a loan repayment, then this pattern becomes favorable. diff --git a/docs/technical/technical/sdk-scheme-adapter/README.md b/docs/technical/technical/sdk-scheme-adapter/README.md new file mode 100644 index 000000000..46bcc96bb --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/README.md @@ -0,0 +1,56 @@ +# SDK Scheme Adapter +A scheme adapter is a service that interfaces between a Mojaloop API compliant switch and a DFSP backend platform that does not natively implement the Mojaloop API. + +The API between the scheme adapter and the DFSP backend is synchronous HTTP while the interface between the scheme adapter and the switch is native Mojaloop API. There is one exception to this, and that is the bulk integrations that can be configured to either be synchronous or asynchronous. + +The SDK-Scheme-Adapter is supported by the Mojaloop Community, and is regarded as a reference for the best practice method for a DFSP to connect to a Mojaloop API. More commonly the SDK-Scheme-Adapter is used and deployed directly into the solution. Below is a summary of the different ways in which this can be done. + +## SDK Adoption Models +Depending on the Scheme Rules, there are four common modes in which DFSPs interact with the central Mojaloop Hub. This summary highlights the role that the SDK-Scheme-Adpater plays in each of the modes and provides a brief overview of each mode and highlights how the DFSPs benefit. + +### 1. DFSP using third party solution e.g. Payment Manager that makes use of the SDK Scheme Adapter + +There are a number of third party solutions that provide support, tooling and integrations into backend systems that makes use of the SDK-Scheme-Adapter in order to provide support for synchronous integration (using the Mojaloop best practice means) to connect to the Mojaloop API. + +Payment Manager an open sourced* tool is an example of this. Payment manager provides additional benefits to this, more information can be found [here](https://rtplex.io/). Payment Manager deployments can be either Saas or self hosted. + +![SDK-Scheme-Adapter Mode 1](./assets/SDKSchemeAdapterMode1.svg) + +- SDK Scheme Adapter is used directly in their custom integration implementation. +- As the SDK-Scheme-Adapter is maintained by the community, this tool provides an upgrade path for using new Mojaloop API versions. +- Standardised solution for rapid onboarding +- Core Connector developed jointly with System Integrators or Banking Software Vendors +- Payment Manager UX has supporting Bussiness Operations and Security Onboarding and Maintenance automation + +:::tip Open Source Components +These are all Apache License v2.0. This was especially chosen as it would not violate many organizations' policies. Apache License v2.0 has no “copy-left” constraints, so adopters can customize elements, such as core connectors without having to share those private details back to the community. +::: + + +### 2. DFSP using their own Core Connector with SDK Scheme Adapter + +In this case the DFSP chooses to develop a custom Core Connector between their back-end and the Mojaloop SDK Scheme Adaptor. They are able to use the open source guidelines to develop the Core Connector . + +![SDK-Scheme-Adapter Mode 2](./assets/SDKSchemeAdapterMode2.svg) + +- SDK Scheme Adapter is used directly in their custom integration implementation. +- As the SDK-Scheme-Adapter is maintained by the community, this tool provides an upgrade path for using new Mojaloop API versions. +- Developed using the Open source Core Connector guidelines +- Mojaloop Community Support +- Operated by DFSPs Technical Operations + +### 3. DFPS Own built Mojaloop Connection Solution + +There is no standard Connection used and the DFSP chooses to develop their own connection to the Mojaloop Hub. + +![SDK-Scheme-Adapter Mode 3](./assets/SDKSchemeAdapterMode3.svg) + +- Developed using Open Source design documentation +- Mojaloop Community Support +- Operated by DFSP Tech Ops +- SDK Scheme Adapter is possibly used as a reference +- This implementation directly interacts with Mojaloop's asynchronous APIs + + + + diff --git a/docs/technical/technical/sdk-scheme-adapter/RequestToPay.md b/docs/technical/technical/sdk-scheme-adapter/RequestToPay.md new file mode 100644 index 000000000..f2caef27a --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/RequestToPay.md @@ -0,0 +1,29 @@ +# Request To Pay (R2P) - use-case support + +This documentation describes how the SDK Scheme Adaptor supports the request to pay use case. The request to pay use case is the bases for all Payee initiated transfers. Support for this use-case requires every DFSP in a Mojaloop switch to automatically process a transfer once a request to perform a transfer is received and validated. Having support for this use-case in the SDK-scheme-adapter is important as it minimised the development effort that each DFSP needs to make if a Scheme mandates participant support for this use case. This use case is particularly interesting from a testing perspective, as it enables remote testing as both a Payer DFSP and a Payee DFSP. + +> Important: +> +> 1. Not all features have been fully tested and aligned to the FSPIOP Specification, please refer to the following epic for progress on this: [#3344 - Enhance SDK Scheme Adaptor to support the request to Pay use case](https://github.com/mojaloop/project/issues/3344); +> 2. There are currently no end-to-end tests verifying the full functionality which includes Authentication via OTP. See the following [Testing Toolkit Test Case collection release](https://github.com/mojaloop/testing-toolkit-test-cases/releases) for what is currently tested: [testing-toolkit-test-cases@v15.0.1](https://github.com/mojaloop/testing-toolkit-test-cases/releases/tag/v15.0.1); and +> 3. Not all failure cases may have been fully implemented. Once again refer to the epic [#3344](https://github.com/mojaloop/project/issues/3344). +> + +## Sequence Diagram + +1. The Payee DFSP initiates the R2P use case with **POST** /RequestToPay API call. +2. The Payee DFSP optionally can validate the Payer. +3. The Payer DFSP executes the R2P request with a **POST** /requestToPayTransfer API call. If the Authentication type is not provided in this call, then the flow assumes that the Payer will confirm the transfer and terms through a **PUT** /requestToPayTransfer, otherwise the appropriate authentication flow is executed. + +The diagram summarises this flow. + + +![R2P Sequence Diagram](./assets/sequence/requestToPaySDK-R2P-SequenceDiagram.svg) + +## Detailed sequence diagram + +Below is a more detailed sequence diagram for the request to pay use case and the SDK Scheme Adapter API calls. + +![R2P Detailed Sequence Diagram](./assets/sequence/SDKrequestToPay.svg) + + diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/BulkSDKEnhancements-Architecture.drawio.svg b/docs/technical/technical/sdk-scheme-adapter/assets/BulkSDKEnhancements-Architecture.drawio.svg new file mode 100644 index 000000000..579441a56 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/BulkSDKEnhancements-Architecture.drawio.svg @@ -0,0 +1,3 @@ + + +
    SDK-Scheme-Adapter with Bulk Enabled
    SDK-Scheme-Adapter with Bulk Enabled
    Payer DFSP

    Core banking system / Beneficiary Management System
    Payer DFSP...
    Mojaloop FSPIOP
    Mojaloop FSPIOP
    Backend API
    Backend API
    Domain Event Handler
    Domain Ev...
    Command Event Handler
    Command Event...
    FSPIOP API
    FSPIOP API
    Producer
    Producer
    Consumer
    Consumer
    Producer
    Producer
    Consumer
    Consumer
    Producer
    Producer
    Consumer
    Consumer
    Producer
    Producer
    Consumer
    Consumer
    State
    Store
    State...
    State
    Store
    State...
    Infrastructure
    Infrastructure
    State
    Store
    State...
    Producer
    Producer
    Consumer
    Consumer
    Dependency Injection
    Dependency Injection
    Kafka
    Kafka
    Domain Events 
    Domain...
    Command Events 
    Command...
    Redis
    Redis
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/BulkSDKEnhancements.drawio b/docs/technical/technical/sdk-scheme-adapter/assets/BulkSDKEnhancements.drawio new file mode 100644 index 000000000..b308a656b --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/BulkSDKEnhancements.drawio @@ -0,0 +1 @@ +7Vxtc6M2EP41nmk/xAMSrx+TOLnMtJmmzc302m8yCKMLRj4hkri/vhIIDAi/JdhxcsnNZZAQAvbZZ3e1KzKCl/PnLwwt4lsa4mQEjBkj4QhORgCY4r/oWKAZbnXIEffkv6rTUL05CXHWGsgpTThZtDsDmqY44K0+xBh9ag+LaKI/xn2AEqz1/k1CHpe9HnBX/TeYzOLqRqbjl2fmqBqsHjyLUUifGl3wagQvGaW8PJo/X+JESqaSS3nd9Zqz9YMxnPJdLsj/DazfEP6GF06ef7m8QR78ceaUszyiJFcvfIeWmImuyfX9nXpwvqykwWiehlhOaIzgxVNMOL5foECefRLgir6YzxPRMsVhiLK4GCsbEU25AtP0ZJskySVNKCsmhlEUgSAQ/Y+YcSLEf56QWSrOcbqorlaPIWfLOKMPuHF96Ewd2xFn1PuIWfDzWkGZtfiFUmI6x5wtxZD2Bcuy5Sj4nlboW6bCOG4gD301ECkFm9UTr0ARBwqXPTCqNL8B0i39jhIqRAOMm3z6OpikbK/RnCTyhW9w8oglAG3IgKlDFiLsRUEfGE7g4WnUA1s/uANAZpvuNtBgJcbjgAY1zLLw4SwLYjzHZyhECy5Z9hrcGOWIE5qq0bsRp0s7W/5T4xr95U8vtsVPh9DWMCgCt00909BhNK0+7tkH456t4fjl6utImtpr8WKcCFfURRGHwoOoZkpTXGDVBJYyHtMZTVHyu+Rwicx3zPlSCRTlnLbBFhJky2/q+qLxj2yM7ao5eW6enCxVq8Sv8lzOjnQ3y4nCc+kvRXua0OCh7LomSdKvS6GNvdDq0xkPTGGhMwma4uQCBQ+zQiDVECWkTKg6SWfqyUuxSlm+UJuMsQEMr61QVtlkOBHUeWzP3Kc7avI7SsQ965mhZ7Sndez2FBnNWYDVVU2X3JnIhm5nIjjuTMURm2G+YapqII2iDHNN4Wu5vJwDrkaBLYbrBfrdVD7Y1PczASO0O0pv+FvUfn/V1ImyVf/xM+EFJceGD1VbPqA5NjzVXD2ebCwbjTvMiAAGs+bzdzs382VXhgikCn3c5K0UpKW2bRhYxr1rOSfQMqvgSOk0NAbhnOm1fUO9HtiXcxBaY9fezN8TIJ3pHMevKB02G/qrvMpa9X2ZTwHmC3xKFGEn6I0xQ9efGvv4iR1Y4Pfr9is11+tENTUjtmjbUJrk95hvJxGiuRALB2cmDyYkC6gI3ZbVGXGj+mQ9mlU9f+GMCozlKxS3X1AuZE1QUggrIAsimpmM22ISxHItXIRqwJgW1xQESqVkaSRtTozVclNeIuLZqivD7JEIwLo8EAEmb2vxerO+zhEgFSUH4kmludXC5zkJQ3nD3ii8Tbum77IHWs90AwNQBwaNWBi4PUsa71ChcI/bf98WSawZ97dI2BQ65PbpnO+4EDnDWiRzjZoMbZK6SnNgk2Sa223S+YxhsVaWD7CLTbpChaUps1YGkaZkwegjkbpYGRS6WAiFzFPCpQyF4okxmEWUzcXR+e3v4rdYnwcPWWGg5HUolL8DmhXmjMq8WChtZV7at2IKXN6ZM5RmUc+ifgdzVavOOmV7Z+YKWPrC/cjGCn4aq53WPUMaK3AYY9WJ/OGR4ycTbDdWX2vyv9BWMfwjxxkvjRUtjVeAi+YT4XFtwiorMxbHIgzLk8IOCbAKM5UIQRfXlNZL3uCX7FdxlFJOIoLD8WcwJbOF9psHU6anKdXdH/cqsTjNk4c/cxFUHym3WOcxfKdlxxzobLRk7yApuUO4tjnJ0perGdBmAqUHWxMv6yLBVeLFcKsIvU6fj4bIvFhGO9upkWJr5uUI2RJ9kdumU2Wgj8soc2yAdmTggffOqFen+Q/MqCo62M6oNeFKXT4wLcNqE8oehFDQ1TKQNcdOiVN63l/uDaiSNRqRshgtCjoEXMK9rXzZjRGmlHM6H9VloAvVnpxZ3qr3a8FAy+oJjtulzteHDX5nIwCw9UWN1RMzHKwWWW0k2VSI+XAgdCp4fSvL44LQl7r44CB4/poM9puBoFflj+PXm1VJ0HHR1oGcNDyMkz5owXGr84XGRo2Tzhe2mV+vw1+bTmhHs3Bvz7u+jqh58ROoIwJLo8olTSPC5uXmIVWEkXtZpPxJKtOh6tQxGXXihHr9OrKPbgMSCjgbCSUMFtB2wwwTznYIBdx9N8McIZTVOCDwwBEJCCqEdItSNFPFBuM+n2bLjOP58fy6CzS/7nWU1tL0HRzA08OOo3/zaEvfnzxFvFVv6VnRJwlZZJJ0FWD5XHBZEJAm21HbeeHctBDVDjYNoEEw6RDM0pOXdh8o9qFA0ReGUVEa21YJ+2jAAF/bSQSdN8ZGzyu3sFHs+eDAOCfGGKiv3H9CVGAn8nbgG6OyfheC8MVpCwznR05VMW91VBTzOtH0muKdXh8sb1GVCDvQb6vKKZx6oBuyFtcfb+wUXzc+TgDGMPrjdqp4ph6b1N9atT4OONgnHmAI/bnIkwcxdEKyac6yKggtisKckdkMM6lIP5/anA1W/u18VOK9ud7skL068Q31O+zL/cAb6t9g+7vrjw3Tsmzg+Z7nGG4nKw6tse+ZruM4ru0b/gs/R4GgkyBw4NjvTnYCOS2orwo/P8oa9eatdiDq50dZ7/GjLNj3VdbJbuvfM05pquc6hX5nm84Ou4NfNFd/SKBUsdXfWoBX/wM=7V3blpu4Ev0aP7YXQkjAY1/SmT6ZrOlMP0xy3jDINmkMPhj35Xz9SIDMRcLQNhho21lJTCEEVG1tVRVWMYG3q7evobVefg8c4k1UZRG6zgTeTVQV0L9UsLYWpCBgLZ7c/3Ohkkq3rkM2hYZREHiRuy4K7cD3iR0VZFYYBq/FZvPAEy/jybY8Ikj/cZ1omUgNVc/kfxB3seQnAthM9qws3ji98M3ScoLXnAh+mcDbMAii5Nvq7ZZ4TDNcL8lx9xV7dxcWEj9qcoD+nx//De6dHw/fyOzX5ufXV/frjytDS7p5sbxtesdPd9+unuwlWZGra8daRySk+19dejeqcrP1nul/X3xr5hEnva/onSsrDLa+Q9j5lAm8eV26EXlaWzbb+0ptT2XLaOXRLUC/OtZmGbdlG5soDJ53Gqa6uZkHfpRaHyC6/ULCyKV2ufbchU+FUbDmrdILSDXCGpK3SiWBneopIEmwIlH4TpvwA4zUWu/Jtpluvma21/RUtszZHXGhlcJrses6Mwn9klrlIxbSBTUTh0I03QzCaBksAt/yvmTSm6IhsjZ/BkxrscZ/kyh6TxVsbaOgaBzy5kY/c99/sa6mKN26e0t7jjfe+YZP75cddKVMFQC4JDlUQyoXZEfHW4XDH0noUr1RzCXCIi6gBBebyAqjazawqWTmBfYzF9673u52fIc38QOfJJJ0PztNomKm1/24oWYItqFN9tiLc5IVLki0px2U4zAknhW5L8XraB1UfKhko36iYi9io9J9oV8XUayURMQ0zu6cUzH+35Zx1g3IvpYPmRUAy1uxjq6Sbq5pA4DXb8kxpV4erfeYdO7unx4njNXSTsPyaei9zySy5IIFseTWhnC3p7m92yAk9Cpmlv/s+gt2we+biKxi9d4zZic+mbu2a8Uo/G75dGJbkVgVT2lL+ZmOmQLmdATeBl4QxsfCOWJ/UtXl5Mlnxwa5PTj+7K7jKOrXiswPsEj9QJFQP+iM+tVBj9LvwW/LY/OJqtBx+vDXYwuwbRFMjkWMuS0FjW2Q2bwd0GBjcKgxjD4dBu4VJLO+3tBjAFMFFv0FA6NP4C8cMb+nhz4GbjyuU7ypilnAm6ozr6zQSeKhpMfl44FSV0CDQleKZmafUr+JRyP0S/VkveearVmDTfUd7EZIdtr9l7m/Pf2SXEE2YHbaPnwMQYF5byz7mWKACq8fH44kqhwisWQWnBNsS4nL0c2ZorRDXGUgASQSlynhrV0c3jpviZHoXbCyXJ/Fmy+JJ/KH5Tsecw07Vf9crVA/nmHUkrMB1Xr1y+LM7tSPBPXfBquVFUP+pPo3bCLX/8xAGmoJ/ho9dZ3+ATipAbBgAO5WdU45BDiI6DKdm1iHVkuYR7AB5sFJKUfkHEHPC6ro9SSfUmS5r0k+s3ccEavGVNVz065eUBKkuzUV6UBTDfYvFFSmaVPVyB2PNYkK4ZR3EP+L9a40qpxCo3uMKer5g6oCp1IVNOpVtVlaa/bVfvdcOtpDWD/UZwkv/DnbCajnsojZ4q9tRLshqTyNFDV6u9kNYwVJ6CIMIuq0BiztairdhVp7EFWdsC0OlyuApkjPhotqGiKvK1M+++YNz8BhdmVrU7D1Yxg4W1symVINRUWTFtWaBiR5G6QiK02N21SjLCIScuYr13HicE+GoeKEkoNAY/o/xH7a1DQhUk0NAB1rOlAFc0FmrnS3ggyDD5N9g1ZTu+I3Wea0X37js6nkScWQ6I6b5EJ3+61c83xqFHSnifHzbeBvtqszoLuauGNkdCcGJR3QXU2oDKmDbBRgPzanWO9v0sBy3Q52lrg4xY3Mqn+GWeKMneL99hvZLIF6DPor+G0kTjFqEE5c6C4F2MjpDokB0Lk4xTX2GxvdidFNB3RXE0fENFaA/cicYnSS3PseA47HKUbis7nLLFGFqLHPEmLEfS5OcY39xjZL9Bf0V/HbWJziSw6gkZU/Qw4AiTmAs3GKP1UOAJ8kB1DzAxNt7Jli3N/jRVwRow11lsBiOH2ZJaoQNfJZAosR97k4xTX2G9ss0V/QX8VvI3GK8SUH0MjKnyEHgMUcwLk4xTX2GxvdyXIAuRV89avvqhbfPdEhRhos/jzmDPGK0Ubr9E5APHhaMJgKDkRdzXSKwRQWVwaoJpjyXE6eFsxdqJGHFuxsdYAsKXKB0nChBJE2UCjpjYPM9ldod7OEorSWTZMsLNFki3l21T7aH65iXuvBn4cW1c/WjrZsOJQ0fuh6HrXsYqXTe5PyKrvCKVXlVQ6fyPUKk/VnEtEiktX0TclwkMQGZN54+ybko44vD01HnWTluyEzsNKVgbk32ENwWaMqqNdpCsgWe0LUlaYaJGv7wmuf0WOCoEozYp2vtefxYybJhyBIgvrOyj0AcTYfT27sSIaqsRcsEpTMVkCBorFU2JWtTvLLoRYYCkjSYcCQqEpTy+Un2lNWg1zhWZJUxdP9QZOUrLrAWDJax5LUfnsNjqR00Tm4I2tCdePb7Lof/N+UlBj4h2m5D9aVbJ9S95WCwhI3T+1q1BniqPtmzZ+tz2G4j5f+PGRiNNXC8ISiTWUm7S53I4tx8kk6bpAsC+eReSTm5Iq1dTZUbK2YSfzZJgn895dd3BfpisWzcsCqZlkkSTfVl0Iq4iQb0IfU5kpNfqVMDZ4jy9kZSezMZUdW9ULFOQCaJfg0LemlKzUdVdTwyjriDYP5fEMKbdoqraXL3LpDEFwqTzRQCDcorfMpIFyq0qaVJ7VDIawBc2rmP8MDdK8FmrOizL8muQqL8nKLdOPjBRNzY4GXS8yKIcqquDatX9dKueWkio44EI6EMyw9UmjKpK2Bqt8ingVQgW5BJS2w2ahKZ6/A0ypyT0cCD5g9A88cDvC6YLMCsFLo5XGlHMB4jcvntQO8bhhPKz9ELc/gHQOPPysaAvC6YLxW6g73yniom5LGEPTLeAYYDvDGwngnBh7qBHiIPzDuC3ji84wL8AYFPNyNj4f7Zjw4HOCNZao9rY+HOvLx1CLjndzHE3/Y/jdx3I0AxzN5IFGznBEUU2EIiBm9kz58MHqNDS+vIuv21SKYw4v/Wlk78MUiWDep0kt9aVMT5NdSNeKdj75bBJffFZLeQuWV7m8/6eTdIma/gW5hFF3ez9P2ICq9D+qI9/Ng/gOo076fB0NQPu3+y9zf/qNjiG5mr0RNmmdvjYVf/gU=5Vrdc+I2EP9reAxjSf58TAJcM3eZ0iG93j11HFsB94zl2uKA/vVd25KxJZMQaiBDH2Cs1Vof+/Hb1coDcr/cfMr8dPHIQhoPsDHPonBARgOMEfyAkPpz2iIUHLPoH0k0BHUVhTRvMXLGYh6lbWLAkoQGvEXzs4yt22wvLNaXMQv8mGrUP6KQLyqqi50d/RcazRdyImR7Vc/Sl8xi4fnCD9m6QSLjAbnPGOPV03JzT+NCMlIu1XuTPb31wjKa8ENecKbf53/dPnz98uckHbvh42NKnm7EKD/9eCU2PPW3NAPSbPRZrJtvpTAytkpCWoxnDMjdehFxOkv9oOhdg26BtuDLGFoIHl+iOL5nMcvKd8lkMrY8D+hiRppxutm7FVQLCMyGsiXl2RZYxAvYsapXtoJbyni9U1FNWzTVI4m+sIJ5PfZOcvAghPcOQeJOQdKTCPJ+7E36EaRlGB9NkEQTZK/SG9sjYzTuR3qEtM2QIF162D6r9My3pUeT8LbAQWglLKFtaVXcNJyr8PemTBp7tjq2LGkZjX0e/WwP3yUGMcOURTBxLXLTaRusSRRJ5myVBVS81UTDNwaqdScH4n42p1wbqNRKve3jFWXtB96HR01nYKO8raicZ+wHlYYtFNm0dUHy42ieQDMA/cHw5K6w+Aji263oWEZhWEzT6UdtT+vDZRTkJrbuMmaH+ZzMYez9uH3NejC9D6YHpwO47LgQ9jM8zHm57YrwwkpH3qnF/nvFZMdNXmaMt8CA3HSz65SjPD19lgPBQqux2uMDuTHn1VoAaluAaeoW4J7TAtx3ha4g9vM8CtqqoJuIf4PnG2NowPYqwvdCZkPXxKI92gghlo1tozGlWQR7KZRT0kI/X5Qif09khAWXIeitFOdSERQbSu7sGEMTIceGiGi5Lib4uICq5eSOsrQ9ARUU6m8bbGnBkO9fP7IUu0Xo1XWp/HJdO1OtVtBrdPc0W0ZDaE9/nT0NCgeaPK/iH0+b5HrhBeG22HEHvJw1wMj8rg98QUPDcFvwgiz3w8DLhRN0Re+qQg/FE+1oStyh5xHLMkzbsTwkw9eZ8nWkV0pw4dKfxsKjQVM8ovn1erSpBo6O065zVo/Way7v9uhD3e5S7mRjLVof6U5qwq8enHsKz7aWBhivrkvll+s6aXhGepGJ/L+c2Tb3wPSlsn/0vspVd3hOYCXfmo0qOBNLtnfBuWxtm62ewnPlRx82PCswgOwj031LBSb7MDzpzYX1AppZpti/qy48eRhdrx+rp3hkXTrN1gtqVksv9cnnqvWiXg3gDr10JUvEPZVeugpsRx5/5IGmQlcsCy17Tj4SlI02KDtvgfJJqy8fHafVKg1WryeOxmk1gewp78MKEBHz9bxP5ZcbPG3ep9cY7VfAyfCDlE/5tq5EZ7Is7AfQ89uKcXq9EIbV282Lp4h6Vc1fcXYbBBTUBOF+W9X9X/w4px06q3krxTV5r1WHRC2Wdlzvd6GYmsz195lEj1U4GUNEJEIHhqEhQl4zFBWXBficJ4TDCngHRKiL3iNohT6vpwhVG+mZThJYr+wdddNYXiAql413EE8KTdKcR8kcnm7g94UBHhTDUr5KBxhWbSQM/mbriAcLeHimfE1pUlrPlmYveVpIIwkFgZaEfVeY/rJAkuQ5Tw+7vswo7MN/LhkMAZPVzsruwwFNZAgwjXU3sEbd+NiJo23YK/YjPvtDrmyLHUhV/aebCfXIpGOi3fXJk2qWB2AiNHff91X2uvsEkoz/BQ==7Vpbd5s4EP41fkwOIMD4MXbSJtm0zTZ7afuyRwbZVg3IFXJs59evZCRAIN8S3/ZsHhKjYRAw8803oxEt0EvmHymcjD6RCMUtxxpSHLXAdctxbP7HBRM4RJpAaDzhFyW0pHSKI5RpioyQmOGJLgxJmqKQaTJIKZnpagMSNx/jKYQxakj/xhEb5dLAaZfyW4SHI3Uj2+/kZxKolOWDZyMYkVlFBG5aoEcJYflRMu+hWFhG2SW/7sOKs8WDUZSybS6YfOz+ShP848vt4CrLfo5/BJ27CznLM4yn8oXv0gGFGaPTkE0pko/OFsoelEzTCIkprRbozkaYoacJDMXZGXcvl41YEvORzQ8HJGXSg45QH+A47pGYUC5IScrl3Qhmo+V0Qp/flowLOztqBnl3ofGMKMPcO1cxHqZcxoi4pXwJfg7NV1rHLmzOkYhIghhdcBV5gWNJvy3ysetJt81Kr7sKg6OqxwMphBJYw2Lu0hn8QPrD7Jtf7t38MXpIX7qzC/j4D5xR9tdFAZzS+iji4JRDQtmIDEkK45tS2tX9U+o8EGGppQ1/IsYW0i1wyojuMzTH7Fvl+LucShxfz6sDYSngXHpy/Igo5i+OqNJJuRGKmcTge3VQzrUcLaqj+lQ6LoCOLNtbakDKrkR4l9Bayj5gYXQ5daQ0+jEJx7lIKtg1eLYcMAhCFIbF7Stn+oEn8KGAJ7yyHnbciWRKQ6l1/Xv46etn8OJ+/vP+no5Y79tkrCKRP/MQsTWoAGYYUxRDhp/15zBBcnkptwNcVBQmBKcsq8z8KARldPgqGmR0eC7QuWaDvoqcMhzyJyiDo3iVN8RLk8w40XFS4DKS8n9PDDK0/CWC2azeCKZDlBmj7AH2eZrSIgNKzgm5bwU0G2SU4CjKgxBl+AX2l/MJmEjz8sm9bsu7NuA3FrfrwnA8XAZwjSS1jCbnLRPLBt5bwy0r2dC6BG3fz+faDVkNKNgaEC7sGluSwSDjeK9z5W5wWBdQFTS0HD9mIufgZ344FIcSErmc36Zyyqi9BI5ZuwYinu4n4jBcxJgzMgWb02U/5+6HfiEoAPFlyvg0KgtmFeRUkeTvJxe6HT0XenYzFwamVGjtIRUafekYfFmzt7DT5E2BsqFAcF3dKJ5IfXWz2G2DXYB3ILOAzWY5FQwp4ZGFiaDFTr304xk0gigYGHOrHwaoP9gWyKvRstKRflv5TXFSKal4UjlNA3j7UAB3G558pCSahjzP1D3KzcF0h+k2lDnDUGtvn8BMCNEry1fRziu8BfRCwuQp2wJNVzngQJ7yzoGK/I38bAcGo7gFZe3dLP47Fa1Ey3+LitoNT/ZImk2T/wEVrffW2VFRp+GpryjCzfXMebhpm05PPYqLzs/bSbMgyYI07Yb7fFPxdqj2TnN98hscjOG798yxp68j3aCZ8o7rvaDhvrsUM8yXkzwArT9QxhqePEL37jSdsshDQeSaUmjg9IHvb9ng2LWPtkt/TOLowrr0PF9fyRU9iTd2Ohy3xjD1znDe25NXlfjbtRln+/p9QLvW+N+gr57L2Iwrr95rh8YcQ80EpjfsJCFaCcqyVY26Q7fDVRfbyhvdx+xjq9irhqeth6eMnzI6DQXuFn1s1fRXx8UbGpv+alB/vePGuN4rX70oWccFTsdf0Z88bD+dJys9ndnrQ7iu7znBeYRwswN1v8x8MgFaTyHFk2YmVEvBaRJfhYxUa5Nl4/2RZFgu2fqEMZIYipd8668SqiRfEfaKjd9myBlLlWbhtI+CJdCTDDDsJwJDweIfrGBxz4k+rSPQ576Km237A3uhNm9LajvJNqBbryTaayqJvVUJ3kmAqzLiZVttcK/fCX8HqGH77dgA9YC+c+WvK3X3BdBmR7hHkgSmERfe8p9YdM4sgUfxy0wrw52+qjlVSnNrm/q+YQ1uO4acto9WpZkawGmpYXtmMJXLZ7tWfx1brNsW2PhVy4rO64HTWVBLZ+uq6s1swYfl13y5evnBI7j5Fw==vVfbctowEP0aHtvxNcBjuCSZaUjpOJ2kecko9mIrCMsjCzD9+kpY8gWbQFInD8xoj1aLdHb3SO7Z41V2zVASzWgApGcZIcNBz570LMsUPwEkKIQaID08/FeDhkLXOIC05sgpJRwnddCncQw+r2GIMbqtuy0oaW7D8xGBBvqAAx7l6MDql/gN4DDSf2ReDPOZFdLOauNphAK6rUD2tGePGaU8H62yMRDJjObFvU+my2fr1+3iCe6oO/x992x/y4NdvWdJcQQGMe82tJWH3iCyVnxNrry5Oi/faRIZXccByEBmzx5tI8zBS5AvZ7eiJgQW8RVR0xtgHIsEXBIcxgLjVDosaMw9FfHcAyk/GRCySjrVAa+BroCznXBRs32Vqp0uOWVvy8w7jsKiatZ1jpEqrrAIXTIqBorUdoKHwfJ+Zv4c3D5la8/DlMUkVTmpEtyzLoj421GAN2IYyuEc7VaSCbmLfPKF6TmNiH+vrGgJMkOxqGV2zP9oRo3TGT2ShnMzeDRdtuHU82U382WaLfkadJCu1v3aDaIgEHKiTMp4REMaIzIt0VGdytLnlsrC3xP4CpzvlBSiNad1eiHD/LEy/iNDfXeVNclU5L2x00YsjvtYNSqrpFku21t6XcoR45dSRgXgE5Sm2NfwFSZ6SylndFkIplXUwLktm9I18+ENP5V4ye6bjc2AII43dTFvS7taOqd430iqwiz3QBH6B5Ujzh0CV6sOiqfYxsfryTmir8YI+UuIg0a5iUsmkcMIMiSqSBCfAMNiG6KzC3SuIet07y5wBvoWNt+dx/Old3hAtOOe18ruZ7Vyv0H9jL4iIpvSMm7WL81OJ0S8QeAMSr/iKnMP77I2bbS+UhsHLVfZkepdEMiUyAj9CY7oTROukFxX1eLttTeWwP2oELRDpfqoNH5EhjtWRfX0zEXpdG2fVM9qrRht7x4N/qfMuk69WAs10CHykzdkthHIOdBr2/havR42atyb/BCA50ewAjG4DFAitbiD91T3mmGfIcID93M0uPX1azboHFMmaRznH3e0EyK7f5g2ng0tRPa7ucyEWX5C5mVcfmXb038=3VjbcpswEP0aP7aDuTjOY2znMpOk4w6Tado3FdagRCAihI379ZWMuFngYI+TmfYhE/awWqOze46FR9Y8ym8ZSsJH6gMZmUbAsD+yFiPTHIs/ASQogBYgM1z8pwQNhWbYh7SVyCklHCdt0KNxDB5vYYgxummnrSjRH8P1EAEN/YF9Hhbo1Lyo8TvAQVh+0HhyWdyJUJmsHjwNkU83Dci6HllzRikvrqJ8DkQyU/IydfntNyOdrd/Qr8VYMLF0yZei2M0xS6otMIj5eUubRek1Ipnia3HjLtV++bYkkdEs9kEWGo+s2SbEHNwEefLuRsyEwEIeEXV7DYxj0YArgoNYYJzKhBWNuasqDt2QypMFIW+0U23wFmgEnG1Firp7oVq1LZup4k3dedtWWNjqugKRGq6gKl0zKi4UqUcQbGlcgi/mU4WU8ZAGNEbkukZnNduGiOqcByqZ3HH8ApxvlbZQxmm7A5Bj/ty4/ilLfXVUtMhV5V2wLYNYbPe5GTRWybBetovKdSlHjF9JXQrAIyhNsVfCN5iUj5RyRl8rBYoWzo6bgZRmzIMDebayEsQCOFTPKfJkFw5OFAOCOF63XeTs42H36M+YIe8VYl+bHmFCibwMIUdiKASPCTAsHgZYjS5LyHxfrSucQ+nS46PbMlyal3vStB1NmpUKm9J0zqDMh7URfyfrJ/fpjdzb7sSZvcTVYJ2uzPQVuBf+IzItv7yMTjEOVLGYSD1JgI2UTnmdUeeOrvPO9hrd0/g5snY0Wc+zlNNIYHPKYPdvd7qh7P9ReCXVQxI3PkjinVuYaG14pC+ISH2axl32W3cAQsQxFAZw+hmnGWf/OGPpx5mx2UHo9KMIvdAI7R3fFYFceUW3bfRYToPkPbdtOVjTenU7O9UlT3Hk0/2t37cGnGMmA88x74mvAgc7o/qMJcViw/Ww2u1hrb7wyxLFztWq5nvKXiF7z0YsY69QQY1WaDfQ1cZPPxcY2oy7i3sBuF4IkbTuKx8l0oz7X5KM9w2kxwuGDlKvZ1gDzllT5yweLML65bdgv/59wLr+Cw==1VZLc9owEP41HNsxFo/0GF5hJk2GKYekR8VebAVhMfIaTH9911jyEyhtSWd68Iz202q9+valDhtv0gfNt+GT8kF2XCfQwu+wScd1u/QRsOUB1IBMYyl+WNAxaCJ8iGuKqJREsa2Dnooi8LCGca3Vvq62UrLtxtLjElroi/AxzNE7d1jicxBBaH/UHXzJdzbcKhvH45D7al+B2LTDxlopzFebdAwyY8bykp+bndktHNMQ4TUHvu2fHx5XjzDnXff5hYvJ8N75ZKzsuEzMhSez5cI4jAfLglZJ5ENmqNtho30oEJZb7mW7ewoqYSFupNnegUZBDN5LEUSEocoUVirCpbFo/0qKkJ69TrcgiVIH1AZQH0jFHrC8HizzRt6XYWIDg4W1EBmQm0wICtsle7QwBP4Gmf0Wb+BTMhlRaQxVoCIupyU6Kpl1SCp1vqqMtSOf74B4MIXAE1R1tiEV+FpZf89Mfe4baZIay0fhYIWIrvtaFSqnMrE8dpTsuRi5xvusiAjwJI9j4Vl4JqR1KUat1kW5UAxHOTEZG5ejTeSpRHtwgWTX1DzXAeAFPXY6ezRIjmJX9+PmmeCeKStnxL01RH4rUag5bLNlCCmn+BNlW9CCnAFdogsLub8uwpVIwXbPbhGBv6u4fqPiev1WxRXFVa24/kcVHGvRPE5iVBvCntQ7l1kNuc44nwSCaHWdpZJJvvwPI8CaPe9UBNi/jECvFYEK8fPkrd0RpaRJDVfQd+N50R80uGPteVHMlCp3dx/F3bDF3dmkXElITd+lluyfacFtuMJnfdAUj5GjsAb0wqLHN5v3n06LGzZ9dmXT751OgWqInVNPAgtePR3MPxZK0FXK+mx0yJ7TyJ38ouZU9a3WMNRrGGJNQzkTLUPHPCwufio1SSyfnLl6+Spn058= \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/BulkSDKEnhancements.drawio.svg b/docs/technical/technical/sdk-scheme-adapter/assets/BulkSDKEnhancements.drawio.svg new file mode 100644 index 000000000..728a19418 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/BulkSDKEnhancements.drawio.svg @@ -0,0 +1,3 @@ + + +
    Payer DFSP
    Payer DFSP
    Mojaloop Hub
    Mojaloop Hub
    sdk-scheme-adapter
    sdk-scheme-adapter
    GET /parties
    GET /parties
    Discovery
    Resolve all potential recipients which might be at any of the DFSPs on the service
    Discovery...
    Agreement
    Each DFSP is provided the opportunity to perform AML checks and add costs or discounts to each transfer
    Agreement...
    Transfer
    Each DFSP is requested to proceed with the transfer. Results are collated and DFSP(s) notified.
    Transfer...
    POST /bulkQuotes
    POST /bulkQuotes
    POST /bulkTransfers
    POST /bulkTransfers
    Payee DFSP
    Payee...
    Confirmation of party information
    Confirmation of party information
    Beneficiary Management Subsystem
    Benefi...
    batch transfers
    batch tran...
    for each transfer
    for each t...
    for each batch
    for each b...
    for each batch
    for each b...
    Confirmation to proceed with transfer
    Confirmation to proceed with trans...
    Bulk Disbursement is triggered
    Bulk Disbursement is triggered
    GET /parties
    GET /parties
    Discovery
    Resolve all potential recipients which might be at any of the DFSPs
    Discovery...
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/CHIntegrationTestHarness.drawio.svg b/docs/technical/technical/sdk-scheme-adapter/assets/CHIntegrationTestHarness.drawio.svg new file mode 100644 index 000000000..d139c9f6c --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/CHIntegrationTestHarness.drawio.svg @@ -0,0 +1,3 @@ + + +
    Infrastructure
    Infrastructure
    Assert on State Store Changes
    Assert on State Store Changes
    State
    Store
    State...
    Producer
    Producer
    Consumer
    Consumer
    Redis
    Redis
    Kafka
    Kafka
    Initiates Test
    Initiates Test
    Assert on Kafka messges
    Assert on Kafka messges
    Jest Test Script
    Jest...
    Command Handler under test
    Command Handler...
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/SDKSchemeAdapterMode1.svg b/docs/technical/technical/sdk-scheme-adapter/assets/SDKSchemeAdapterMode1.svg new file mode 100644 index 000000000..483b2dc7c --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/SDKSchemeAdapterMode1.svg @@ -0,0 +1,3 @@ + + +
    DFSP
    DFSP
    Payment
    Manager
    Payment...
    DFSP Backend
    DFSP Backend
    Mojaloop Hub
    Mojaloop Hub
    SDK Scheme Adapter
    SDK Scheme Ada...
    Core Connector
    Core Connec...
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/SDKSchemeAdapterMode2.svg b/docs/technical/technical/sdk-scheme-adapter/assets/SDKSchemeAdapterMode2.svg new file mode 100644 index 000000000..b3143177b --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/SDKSchemeAdapterMode2.svg @@ -0,0 +1,3 @@ + + +
    DFSP
    DFSP
    DFSP Backend
    DFSP Backend
    Custom Core Connector
    Custom Core Conn...
    Mojaloop Hub
    Mojaloop Hub
    SDK Scheme Adapter
    SDK Scheme Ada...
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/SDKSchemeAdapterMode3.svg b/docs/technical/technical/sdk-scheme-adapter/assets/SDKSchemeAdapterMode3.svg new file mode 100644 index 000000000..814b57fa0 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/SDKSchemeAdapterMode3.svg @@ -0,0 +1,3 @@ + + +
    DFSP
    DFSP
    DFSP Backend
    DFSP Backend
    Custom Mojaloop Connection Solution
    Custom Mojaloop Conne...
    Mojaloop Hub
    Mojaloop Hub
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/bulk-functional-local-test-setup.drawio.svg b/docs/technical/technical/sdk-scheme-adapter/assets/bulk-functional-local-test-setup.drawio.svg new file mode 100644 index 000000000..ab1c426df --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/bulk-functional-local-test-setup.drawio.svg @@ -0,0 +1,3 @@ + + +
    Payer SDK
    Payer SDK
    Payee SDK
    Payee SDK
    Payer SIM
    Payer...
    Payee SIM
    Payee...
    TTK
    TTK
    1. POST /bulkTxn
    1. POS...
    2. GET /parties
    2. GET /par...
    3. GET /parties
    3. GET /parti...
    4. PUT /parties/ID
    4. PUT...
    5. PUT /bulkTxn/ID
    5. PUT /bul...
    6. PUT /bulkTxn/ID acptPty
    accptQuote
    6. PUT /bulkT...
    autoAcceptParty: false
    autoAcceptQuote: false
    autoAcceptParty: false...
    Bulk testing - Local setup, no Switch between payerfsp and payeefsp 
    Bulk testing - Local setup, no Switch between payerfsp and payeefsp 
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/overview-drawio.png b/docs/technical/technical/sdk-scheme-adapter/assets/overview-drawio.png new file mode 100644 index 000000000..855dcba55 Binary files /dev/null and b/docs/technical/technical/sdk-scheme-adapter/assets/overview-drawio.png differ diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/BULK-ERRORCODES.md b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/BULK-ERRORCODES.md new file mode 100644 index 000000000..f03f6e0be --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/BULK-ERRORCODES.md @@ -0,0 +1,141 @@ +# Bulk Transfers + +## Error Cases +### Discovery Phase +All the errors encountered during this phase will be accumulated in the mojaloop-connector and will be added to the `lastError` object and returned to the Payer FSP along with all other successful or failed transfers involved in the bulk transfer request. + +mojaloop-connector will act as a pass-through for all the errors returned by the switch + +``` + "lastError": { + "httpStatusCode": 202, + "mojaloopError": { + "errorInformation": { + "errorCode": "3204", + "errorDescription": "Party not found", + "extensionList": {"extension": [{"key": "string","value": "string"}]} + } + } + } +``` + +**Party Lookup Error Codes** + +| Error Description | Error Code | HTTP Code | Category | +|------------------------------------------------------------------------|-------------|------------------|-----------------------------------------------------------| +| Communication error | 1000 | 503 | Technical Error | +| Destination communication error | 1001 | 503 | Technical Error | +| Generic server error | 2000 | 503 | Processing Error | +| Internal server error | 2001 | 503 | Processing Error | +| Timeout Resolving Party | 2004 | 503 | Processing Error | +| Generic validation error | 3100 | 400 | Request Validation Error | +| Party not found | 3204 | 202 | Processing Error | + +### Agreement Phase +All the errors encountered during this phase will be accumulated in the mojaloop-connector and will be added to the `lastError` object and returned to the Payer FSP along with all other successful or failed transfers involved in the bulk transfer request. + +mojaloop-connector will act as a pass-through for all the errors returned by the switch + +``` + "lastError": { + "httpStatusCode": 202, + "mojaloopError": { + "errorInformation": { + "errorCode": "3204", + "errorDescription": "Party not found", + "extensionList": {"extension": [{"key": "string","value": "string"}]} + } + } + } +``` + +**Quotes Error Codes** + +| Error Description | Error Code | HTTP Code | Category | +|------------------------------------------------------------------------|-------------|------------------|-----------------------------------------------------------| +| Communication error | 1000 | 503 | Technical Error | +| Destination communication error | 1001 | 503 | Technical Error | +| Generic server error | 2000 | 503 | Technical Error | +| Internal server error | 2001 | 503 | Technical Error | +| Not implemented | 2002 | 501 | Processing Error | +| Service currently unavailable | 2003 | 503 | Processing Error | +| Server timed out | 2004 | 503 | Processing Error | +| Server busy | 2005 | 503 | Processing Error | +| Generic client error | 3000 | 400 | Request Validation Error | +| Unacceptable version requested | 3001 | 406 | Not acceptable Error | +| Unknown URI | 3002 | 404 | Not Found Error | +| Generic validation error | 3100 | 400 | Request Validation Error | +| Malformed syntax | 3101 | 400 | Request Validation Error | +| Missing mandatory element | 3102 | 400 | Request Validation Error | +| Too many elements | 3103 | 400 | Request Validation Error | +| Too large payload | 3104 | 400 | Request Validation Error | +| Invalid signature | 3105 | 403 | Forbidden Error | +| Destination FSP Error | 3201 | 404 | Not Found Error | +| Payer FSP ID not found | 3202 | 404 | Not Found Error | +| Payee FSP ID not found | 3203 | 404 | Not Found Error | +| Quote ID not found | 3205 | 404 | Not Found Error | +| Bulk quote ID not found | 3209 | 404 | Not Found Error | +| Generic expired error | 3300 | 503 | Processing Error | +| Quote expired | 3302 | 503 | Processing Error | +| Generic Payer error | 4000 | 400 | Request Validation Error | +| Generic Payer rejection | 4100 | 403 | Forbidden Error | +| Payer limit error | 4200 | 400 | Request Validation Error | +| Payer permission error | 4300 | 403 | Forbidden Error | +| Generic Payer blocked error | 4400 | 403 | Forbidden Error | +| Generic Payee error | 5000 | 503 | Processing Error | +| Payee FSP insufficient liquidity | 5001 | 503 | Processing Error | +| Generic Payee rejection | 5100 | 403 | Forbidden Error | +| Payee rejected quote | 5101 | 503 | Processing Error | +| Payee FSP unsupported transaction type | 5102 | 503 | Processing Error | +| Payee rejected quote | 5103 | 503 | Processing Error | +| Payee unsupported currency | 5106 | 503 | Processing Error | +| Payee limit error | 5200 | 503 | Processing Error | +| Payee permission error | 5300 | 403 | Forbidden Error | +| Generic Payee blocked error | 5400 | 403 | Forbidden Error | + + + +### Transfer Phase +All the errors encountered during this phase will be accumulated in the mojaloop-connector and will be added to the `lastError` object and returned to the Payer FSP along with all other successful or failed transfers involved in the bulk transfer request. + +mojaloop-connector will act as a pass-through for all the errors returned by the switch + +``` + "lastError": { + "httpStatusCode": 404, + "mojaloopError": { + "errorInformation": { + "errorCode": "3210", + "errorDescription": "Bulk transfer ID not found", + "extensionList": {"extension": [{"key": "string","value": "string"}]} + } + } + } +``` + +**Transfer Error Codes** + +| Error Description | Error Code | HTTP Code | Category | +|------------------------------------------------------------------------|-------------|------------------|-----------------------------------------------------------| +| Communication error | 1000 | 503 | Technical Error | +| Destination communication error | 1001 | 503 | Technical Error | +| Generic server error | 2000 | 503 | Processing Error | +| Internal server error | 2001 | 503 | Processing Error | +| Server timed out | 2004 | 503 | Processing Error | +| Generic validation error | 3100 | 400 | Request Validation Error | +| Bulk transfer ID not found | 3210 | 404 | Processing Error | +| Generic expired error | 3300 | 503 | Processing Error | +| Transaction request expired | 3301 | 503 | Processing Error | +| Transfer expired | 3303 | 503 | Processing Error | +| Generic Payee error | 5000 | 400 | Processing Error | +| Payee FSP insufficient liquidity | 5001 | 400 | Processing Error | +| Generic Payee rejection | 5100 | 400 | Processing Error | +| Payee rejected quote | 5101 | 400 | Processing Error | +| Payee FSP unsupported transaction type | 5102 | 400 | Processing Error | +| Payee FSP rejected quote | 5103 | 400 | Processing Error | +| Payee rejected transaction | 5104 | 400 | Processing Error | +| Payee FSP rejected transaction | 5105 | 400 | Processing Error | +| Payee unsupported currency | 5106 | 400 | Processing Error | +| Payee limit error | 5200 | 400 | Processing Error | +| Payee permission error | 5300 | 403 | Processing Error | +| Generic Payee blocked error | 5400 | 400 | Processing Error | diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPBulkIdealPattern.PlantUML b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPBulkIdealPattern.PlantUML new file mode 100644 index 000000000..8f7e09906 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPBulkIdealPattern.PlantUML @@ -0,0 +1,89 @@ +@startuml PayeeDFSPBulkIdealPattern +/'***** +-------------- +******'/ + +skinparam activityFontSize 4 +skinparam activityDiamondFontSize 30 +skinparam activityArrowFontSize 22 +skinparam defaultFontSize 22 +skinparam noteFontSize 22 +skinparam monochrome true +' declare title +' title PayeeDFSPBulkIdealPattern +' declare actors +participant "Mojaloop\nSwitch" as Switch +box "Payment Manager\nPayee DFSP" #LightGrey +participant "SDK Scheme Adapter" as MC +participant "Core\nConnector" as CC +end box +participant "Core banking solution" as CBS +autonumber 1 1 "[0]" + +== Payee DFSP integration - Discovery == + +Switch->MC: **GET** /parties/{Type}/{Id} +MC-->Switch: HTTP 202 Response +MC->CC: **GET** /parties/{Type}/{Id} +activate MC +CC->CBS: **GET** [account lookup] +CBS-->CC: Response +CC-->MC: Response +deactivate MC +alt If Success response +MC-->Switch: **PUT** /parties/{Type}/{Id} (or /parties/{Type}/{Id}/{SubId}) +else if Error response +MC-->Switch: **PUT** /parties/{Type}/{Id}/error (or /parties/{Type}/{Id}/{SubId}/error) +end + +== Payee DFSP integration - Quote and Transfer - 2 phase commit with prior AML check == + +Switch->MC: **POST** /bulkquotes +MC-->Switch: HTTP 202 Response +loop X times for each transfer in bulk message + MC->CC: **POST** /quoterequest + activate MC + CC->CBS: **AML** checks + CBS-->CC: Response + CC->CBS: **Calculate Fees** + CBS-->CC: Response + CC-->MC: Response + deactivate MC + MC->MC: Update transaction status \nand attach quote response +end Loop +MC-->Switch: **PUT** /bulkquotes/{Id} +Switch->Switch: Pass Quote to Payer +note left +Obtain consent to +proceed with the transfer +Via **POST** /bulktransfers +end note + Switch-> Switch: Perform liquidity(NDC)check + Switch->Switch: Reserve Funds at indivial transfer level + Switch->MC: **POST** /bulktransfers + loop X times for each transfer in bulk message + MC->CC: Create & Reserve Transfer\n **POST** /transfers + activate MC + CC->CBS: Reserve funds + CBS-->CC: response (homeTransactionId) + CC-->MC: response (homeTransactionId) + deactivate MC + MC->MC: Generate Fulfilment + MC -> MC:Update transaction status \nand attach transfer response + end Loop + MC-->Switch: **PUT** /bulktransfers/{id} (BulkStatus='PROCESSING') + Switch-->Switch: Commit funds at indivial transfer level in DFSP ledgers + Switch -> MC: **PATCH** /bulktransfers/{id} (BulkStatus='COMPLETED') + loop X times for each transfer in bulk message + MC->CC: Commit Transfer\n **PATCH** /transfers/{id} \n(TransferStatus='COMMITTED', homeTransactionId) + activate MC + CC->CBS: Commit funds + CBS->CBS: Release funds to Payee + CBS-->CC: response + CC-->MC: response + deactivate MC + end loop + + + +@enduml \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPBulkIdealPattern.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPBulkIdealPattern.svg new file mode 100644 index 000000000..f4c0069b0 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPBulkIdealPattern.svg @@ -0,0 +1,183 @@ +Payment ManagerPayee DFSPMojaloopSwitchMojaloopSwitchSDK Scheme AdapterSDK Scheme AdapterCoreConnectorCoreConnectorCore banking solutionCore banking solutionPayee DFSP integration - Discovery[1]GET/parties/{Type}/{Id}[2]HTTP 202 Response[3]GET/parties/{Type}/{Id}[4]GET[account lookup][5]Response[6]Responsealt[If Success response][7]PUT/parties/{Type}/{Id} (or /parties/{Type}/{Id}/{SubId})[if Error response][8]PUT/parties/{Type}/{Id}/error (or /parties/{Type}/{Id}/{SubId}/error)Payee DFSP integration - Quote and Transfer - 2 phase commit with prior AML check[9]POST/bulkquotes[10]HTTP 202 Responseloop[X times for each transfer in bulk message][11]POST/quoterequest[12]AMLchecks[13]Response[14]Calculate Fees[15]Response[16]Response[17]Update transaction statusand attach quote response[18]PUT/bulkquotes/{Id}[19]Pass Quote to PayerObtain consent toproceed with the transferViaPOST/bulktransfers[20]Perform liquidity(NDC)check[21]Reserve Funds at indivial transfer level[22]POST/bulktransfersloop[X times for each transfer in bulk message][23]Create & Reserve Transfer POST/transfers[24]Reserve funds[25]response (homeTransactionId)[26]response (homeTransactionId)[27]Generate Fulfilment[28]Update transaction statusand attach transfer response[29]PUT/bulktransfers/{id} (BulkStatus='PROCESSING')[30]Commit funds at indivial transfer level in DFSP ledgers[31]PATCH/bulktransfers/{id} (BulkStatus='COMPLETED')loop[X times for each transfer in bulk message][32]Commit Transfer PATCH/transfers/{id}(TransferStatus='COMMITTED', homeTransactionId)[33]Commit funds[34]Release funds to Payee[35]response[36]response \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPBulkSingleIntegrationApiOnPatch.PlantUML b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPBulkSingleIntegrationApiOnPatch.PlantUML new file mode 100644 index 000000000..438ef1779 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPBulkSingleIntegrationApiOnPatch.PlantUML @@ -0,0 +1,84 @@ +@startuml PayeeDFSPBulkSingleIntegrationApiOnPatch +/'***** +-------------- +******'/ + +skinparam activityFontSize 4 +skinparam activityDiamondFontSize 30 +skinparam activityArrowFontSize 22 +skinparam defaultFontSize 22 +skinparam noteFontSize 22 +skinparam monochrome true +' declare title +' title PayeeDFSPBulkSingleIntegrationApiOnPatch +' declare actors +participant "Mojaloop\nSwitch" as Switch +box "Payment Manager\nPayee DFSP" #LightGrey +participant "SDK Scheme Adapter" as MC +participant "Core\nConnector" as CC +end box +participant "Core banking solution" as CBS +autonumber 1 1 "[0]" + +== Payee DFSP integration - Quote and Transfer - single AML check & transfer during PATCH == + +Switch->MC: **POST** /bulkquotes +MC-->Switch: HTTP 202 Response +loop X times for each transfer in bulk message + MC->CC: **POST** /quoterequest + activate MC + CC->CC: Do nothing + CC-->MC: Response + deactivate MC + MC->MC: Update transaction status \nand attach quote response +end Loop +MC-->Switch: **PUT** /bulkquotes/{Id} + +Switch->Switch: Pass Quote to Payer DFSP +note left +Obtain consent to +proceed with the transfer +Via **POST** /bulktransfers +end note + Switch-> Switch: Perform liquidity(NDC)check + Switch->Switch: Reserve Funds at indivial transfer level + Switch->MC: **POST** /bulktransfers + loop X times for each transfer in bulk message + MC->CC: **POST** /transfers + activate MC + CC->CC: Do Nothing + CC-->MC: response + deactivate MC + MC->MC: Generate Fulfilment + MC -> MC:Update transaction status \nand attach transfer response + end Loop + MC-->Switch: **PUT** /bulktransfers/{id} (BulkStatus='PROCESSING') + Switch-->Switch: Commit funds at indivial transfer level in DFSP ledgers + Switch -> MC: **PATCH** /bulktransfers/{id} (BulkStatus='COMPLETED') + loop X times for each transfer in bulk message + MC->CC: Commit Transfer\n **PATCH** /transfers/{id} (TransferStatus='COMMITTED') + activate MC + CC->CBS: Performn AML checks and transfer funds + alt if (AML checks pass) + CBS->CBS: Release funds to Payee + CBS-->CC: response + CC-->MC: response + else if (AML checks fail) + CBS->CBS: Compensation action for AML failure. \n Return error response. + CBS-->CC: response + CC-->MC: response + deactivate MC + rnote left MC + Payee DFSP AML checks / other errors result in: + + **Reconciliation Error** + Payer has sent funds + Payer DFSP has sent funds + Hub considers that the Payee DFSP has received funds + Payee DFSP has rejected the transaction + Payee has not received funds + endrnote + end + end Loop + +@enduml \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPBulkSingleIntegrationApiOnPatch.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPBulkSingleIntegrationApiOnPatch.svg new file mode 100644 index 000000000..5fe598782 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPBulkSingleIntegrationApiOnPatch.svg @@ -0,0 +1,173 @@ +Payment ManagerPayee DFSPMojaloopSwitchMojaloopSwitchSDK Scheme AdapterSDK Scheme AdapterCoreConnectorCoreConnectorCore banking solutionCore banking solutionPayee DFSP integration - Quote and Transfer - single AML check & transfer during PATCH[1]POST/bulkquotes[2]HTTP 202 Responseloop[X times for each transfer in bulk message][3]POST/quoterequest[4]Do nothing[5]Response[6]Update transaction statusand attach quote response[7]PUT/bulkquotes/{Id}[8]Pass Quote to Payer DFSPObtain consent toproceed with the transferViaPOST/bulktransfers[9]Perform liquidity(NDC)check[10]Reserve Funds at indivial transfer level[11]POST/bulktransfersloop[X times for each transfer in bulk message][12]POST/transfers[13]Do Nothing[14]response[15]Generate Fulfilment[16]Update transaction statusand attach transfer response[17]PUT/bulktransfers/{id} (BulkStatus='PROCESSING')[18]Commit funds at indivial transfer level in DFSP ledgers[19]PATCH/bulktransfers/{id} (BulkStatus='COMPLETED')loop[X times for each transfer in bulk message][20]Commit Transfer PATCH/transfers/{id} (TransferStatus='COMMITTED')[21]Performn AML checks and transfer fundsalt[if (AML checks pass)][22]Release funds to Payee[23]response[24]response[if (AML checks fail)][25]Compensation action for AML failure.Return error response.[26]response[27]responsePayee DFSP AML checks / other errors result in: Reconciliation ErrorPayer has sent fundsPayer DFSP has sent fundsHub considers that the Payee DFSP has received fundsPayee DFSP has rejected the transactionPayee has not received funds \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPIdealPattern.PlantUML b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPIdealPattern.PlantUML new file mode 100644 index 000000000..dace0ab8b --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPIdealPattern.PlantUML @@ -0,0 +1,80 @@ +@startuml PayeeDFSPIdealPattern +/'***** +-------------- +******'/ + +skinparam activityFontSize 4 +skinparam activityDiamondFontSize 30 +skinparam activityArrowFontSize 22 +skinparam defaultFontSize 22 +skinparam noteFontSize 22 +skinparam monochrome true +' declare title +' title PayeeDFSPIdealPattern +' declare actors +participant "Mojaloop\nSwitch" as Switch +box "Payment Manager\nPayee DFSP" #LightGrey +participant "SDK Scheme Adapter" as MC +participant "Core\nConnector" as CC +end box +participant "Core banking solution" as CBS +autonumber 1 1 "[0]" + +== Payee DFSP integration - Discovery == + +Switch->MC: **GET** /parties/{Type}/{Id} +MC-->Switch: HTTP 202 Response +MC->CC: **GET** /parties/{Type}/{Id} +activate MC +CC->CBS: **GET** [account lookup] +CBS-->CC: Response +CC-->MC: Response +deactivate MC +alt If Success response +MC-->Switch: **PUT** /parties/{Type}/{Id} (or /parties/{Type}/{Id}/{SubId}) +else if Error response +MC-->Switch: **PUT** /parties/{Type}/{Id}/error (or /parties/{Type}/{Id}/{SubId}/error) +end + +== Payee DFSP integration - Quote and Transfer - 2 phase commit with prior AML check == + +Switch->MC: **POST** /quotes +MC-->Switch: HTTP 202 Response +MC->CC: **POST** /quoterequest +activate MC +CC->CBS: **AML** checks (velocity,etc...) +CBS-->CC: Response +CC->CBS: **Calculate Fees** +CBS-->CC: Response +CC-->MC: Response +deactivate MC +MC-->Switch: **PUT** /quotes/{Id} +Switch->Switch: Pass Quote to Payer +note left +Obtain consent to +proceed with the transfer +Via **POST** /transfers +end note + Switch-> Switch: Perform liquidity(NDC)check + Switch->Switch: Reserve Funds + Switch->MC: **POST** /transfers + MC->CC: Create & Reserve Transfer\n **POST** /transfers + activate MC + CC->CBS: Reserve funds + CBS-->CC: response (homeTransactionId) + CC-->MC: response (homeTransactionId) + deactivate MC + MC->MC: Generate Fulfilment + MC->Switch: **PUT** /transfers/{id} (TransferStatus='RESERVED', fulfullment) + Switch->Switch: Commit funds in DFSP ledgers + Switch->MC: **PATCH** /transfers/{id} (TransferStatus='COMMITTED') + MC->CC: Commit Transfer\n **PATCH** /transfers/{id} \n(TransferStatus='COMMITTED', homeTransactionId) + activate MC + CC->CBS: Commit funds + CBS->CBS: Release funds to Payee + CBS-->CC: response + CC-->MC: response + deactivate MC + + +@enduml \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPIdealPattern.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPIdealPattern.svg new file mode 100644 index 000000000..577ff3030 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPIdealPattern.svg @@ -0,0 +1,165 @@ +Payment ManagerPayee DFSPMojaloopSwitchMojaloopSwitchSDK Scheme AdapterSDK Scheme AdapterCoreConnectorCoreConnectorCore banking solutionCore banking solutionPayee DFSP integration - Discovery[1]GET/parties/{Type}/{Id}[2]HTTP 202 Response[3]GET/parties/{Type}/{Id}[4]GET[account lookup][5]Response[6]Responsealt[If Success response][7]PUT/parties/{Type}/{Id} (or /parties/{Type}/{Id}/{SubId})[if Error response][8]PUT/parties/{Type}/{Id}/error (or /parties/{Type}/{Id}/{SubId}/error)Payee DFSP integration - Quote and Transfer - 2 phase commit with prior AML check[9]POST/quotes[10]HTTP 202 Response[11]POST/quoterequest[12]AMLchecks (velocity,etc...)[13]Response[14]Calculate Fees[15]Response[16]Response[17]PUT/quotes/{Id}[18]Pass Quote to PayerObtain consent toproceed with the transferViaPOST/transfers[19]Perform liquidity(NDC)check[20]Reserve Funds[21]POST/transfers[22]Create & Reserve Transfer POST/transfers[23]Reserve funds[24]response (homeTransactionId)[25]response (homeTransactionId)[26]Generate Fulfilment[27]PUT/transfers/{id} (TransferStatus='RESERVED', fulfullment)[28]Commit funds in DFSP ledgers[29]PATCH/transfers/{id} (TransferStatus='COMMITTED')[30]Commit Transfer PATCH/transfers/{id}(TransferStatus='COMMITTED', homeTransactionId)[31]Commit funds[32]Release funds to Payee[33]response[34]response \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPSingleIntegrationApiOnPatch.PlantUML b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPSingleIntegrationApiOnPatch.PlantUML new file mode 100644 index 000000000..1f12dce39 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPSingleIntegrationApiOnPatch.PlantUML @@ -0,0 +1,76 @@ +@startuml PayeeDFSPSingleIntegrationApiOnPatchPattern +/'***** +-------------- +******'/ + +skinparam activityFontSize 4 +skinparam activityDiamondFontSize 30 +skinparam activityArrowFontSize 22 +skinparam defaultFontSize 22 +skinparam noteFontSize 22 +skinparam monochrome true +' declare title +' title PayeeDFSPSingleIntegrationApiOnPatch +' declare actors +participant "Mojaloop\nSwitch" as Switch +box "Payment Manager\nPayee DFSP" #LightGrey +participant "SDK Scheme Adapter" as MC +participant "Core\nConnector" as CC +end box +participant "Core banking solution" as CBS +autonumber 1 1 "[0]" +== Payee DFSP integration - Quote and Transfer - single AML check & transfer during PATCH == + +Switch->MC: **POST** /quotes +MC-->Switch: HTTP 202 Response +MC->CC: **POST** /quoterequest +activate MC +CC->CC: Do nothing +CC-->MC: Response +deactivate MC +MC-->Switch: **PUT** /quotes/{Id} + +Switch->Switch: Pass Quote to Payer +note left +Obtain consent to +proceed with the transfer +Via **POST** /transfers +end note + Switch-> Switch: Perform liquidity(NDC)check + Switch->Switch: Reserve Funds + Switch->MC: **POST** /transfers + MC->CC: **POST** /transfers + activate MC + CC->CC: Do Nothing + CC-->MC: response + deactivate MC + MC->MC: Generate Fulfilment + MC-->Switch: **PUT** /transfers/{id} (TransferStatus='RESERVED', fulfullment) + Switch-->Switch: Commit funds in DFSP ledgers + + Switch->MC: **PATCH** /transfers/{id} (TransferStatus='COMMITTED') + MC->CC: Commit Transfer\n **PATCH** /transfers/{id} (TransferStatus='COMMITTED') + activate MC + CC->CBS: Perform AML checks and transfer funds + alt if (AML checks pass) + CBS->CBS: Release funds to Payee + CBS-->CC: response + CC-->MC: response + else if (AML checks fail) + CBS->CBS: Compensation action for AML failure. \n Return error response. + CBS-->CC: response + CC-->MC: response + rnote left MC + Payee DFSP AML error checks (and other errors) result in: + + **Reconciliation Error** + Payer has sent funds + Payer DFSP has sent funds + Hub considers that the Payee DFSP has received funds + Payee DFSP has rejected the transaction + Payee has not received funds + endrnote + end + deactivate MC + +@enduml \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPSingleIntegrationApiOnPatchPattern.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPSingleIntegrationApiOnPatchPattern.svg new file mode 100644 index 000000000..ed8a23a77 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPSingleIntegrationApiOnPatchPattern.svg @@ -0,0 +1,157 @@ +Payment ManagerPayee DFSPMojaloopSwitchMojaloopSwitchSDK Scheme AdapterSDK Scheme AdapterCoreConnectorCoreConnectorCore banking solutionCore banking solutionPayee DFSP integration - Quote and Transfer - single AML check & transfer during PATCH[1]POST/quotes[2]HTTP 202 Response[3]POST/quoterequest[4]Do nothing[5]Response[6]PUT/quotes/{Id}[7]Pass Quote to PayerObtain consent toproceed with the transferViaPOST/transfers[8]Perform liquidity(NDC)check[9]Reserve Funds[10]POST/transfers[11]POST/transfers[12]Do Nothing[13]response[14]Generate Fulfilment[15]PUT/transfers/{id} (TransferStatus='RESERVED', fulfullment)[16]Commit funds in DFSP ledgers[17]PATCH/transfers/{id} (TransferStatus='COMMITTED')[18]Commit Transfer PATCH/transfers/{id} (TransferStatus='COMMITTED')[19]Perform AML checks and transfer fundsalt[if (AML checks pass)][20]Release funds to Payee[21]response[22]response[if (AML checks fail)][23]Compensation action for AML failure.Return error response.[24]response[25]responsePayee DFSP AML error checks (and other errors) result in: Reconciliation ErrorPayer has sent fundsPayer DFSP has sent fundsHub considers that the Payee DFSP has received fundsPayee DFSP has rejected the transactionPayee has not received funds \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPSingleIntegrationApiOnTransfer.PlantUML b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPSingleIntegrationApiOnTransfer.PlantUML new file mode 100644 index 000000000..c9e8b2a41 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPSingleIntegrationApiOnTransfer.PlantUML @@ -0,0 +1,67 @@ +@startuml PayeeDFSPSingleIntegrationApiOnTransferPattern +/'***** +-------------- +******'/ + +skinparam activityFontSize 4 +skinparam activityDiamondFontSize 30 +skinparam activityArrowFontSize 22 +skinparam defaultFontSize 22 +skinparam noteFontSize 22 +skinparam monochrome true +' declare title +' title PayeeDFSPSingleIntegrationApiOnTransfer +' declare actors +participant "Mojaloop\nSwitch" as Switch +box "Payment Manager\nPayee DFSP" #LightGrey +participant "SDK Scheme Adapter" as MC +participant "Core\nConnector" as CC +end box +participant "Core banking solution" as CBS +autonumber 1 1 "[0]" + +== Payee DFSP integration - Quote and Transfer - single AML check & transfer during POST transfer == + +Switch->MC: **POST** /quotes +MC-->Switch: HTTP 202 Response +MC->CC: **POST** /quoterequest +activate MC +CC->CC: Do nothing +CC-->MC: Response +deactivate MC +MC-->Switch: **PUT** /quotes/{Id} + +Switch->Switch: Pass Quote to Payer +note left +Obtain consent to +proceed with the transfer +Via **POST** /transfers +end note + Switch-> Switch: Perform liquidity(NDC)check + Switch->Switch: Reserve Funds + Switch->MC: **POST** /transfers + MC->CC: **POST** /transfers + activate MC + CC->CBS: Perform AML checks and transfer funds + CBS->CBS: Release of funds to Payee + CBS-->CC: response (homeTransactionId) + CC-->MC: response (homeTransactionId) + deactivate MC + MC->MC: Generate Fulfilment + MC-->Switch: **PUT** /transfers/{id} (TransferStatus='RESERVED', fulfullment) + Switch->Switch: Commit funds in DFSP ledgers + alt if (Transfer status == 'ABORTED') + Switch->MC: **PATCH** /transfers/{id} (TransferStatus='ABORTED', homeTransactionId) + MC->CC: Abort Transfer\n **PATCH** /transfers/{id} (TransferStatus='ABORTED') + CC->CBS: Abort Transfer + CBS->CBS: Compensate action for abort + CBS-->CC: response + else if (Transfer status == 'COMMITTED') + Switch->MC: **PATCH** /transfers/{id} (TransferStatus='COMMITTED', homeTransactionId) + MC->CC: **PATCH** /transfers/{id} (TransferStatus='COMMITTED') + CC->CC: Do nothing + CC-->MC: response + end + + +@enduml \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPSingleIntegrationApiOnTransferPattern.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPSingleIntegrationApiOnTransferPattern.svg new file mode 100644 index 000000000..811cbdc15 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayeeDFSPSingleIntegrationApiOnTransferPattern.svg @@ -0,0 +1,139 @@ +Payment ManagerPayee DFSPMojaloopSwitchMojaloopSwitchSDK Scheme AdapterSDK Scheme AdapterCoreConnectorCoreConnectorCore banking solutionCore banking solutionPayee DFSP integration - Quote and Transfer - single AML check & transfer during POST transfer[1]POST/quotes[2]HTTP 202 Response[3]POST/quoterequest[4]Do nothing[5]Response[6]PUT/quotes/{Id}[7]Pass Quote to PayerObtain consent toproceed with the transferViaPOST/transfers[8]Perform liquidity(NDC)check[9]Reserve Funds[10]POST/transfers[11]POST/transfers[12]Perform AML checks and transfer funds[13]Release of funds to Payee[14]response (homeTransactionId)[15]response (homeTransactionId)[16]Generate Fulfilment[17]PUT/transfers/{id} (TransferStatus='RESERVED', fulfullment)[18]Commit funds in DFSP ledgersalt[if (Transfer status == 'ABORTED')][19]PATCH/transfers/{id} (TransferStatus='ABORTED', homeTransactionId)[20]Abort Transfer PATCH/transfers/{id} (TransferStatus='ABORTED')[21]Abort Transfer[22]Compensate action for abort[23]response[if (Transfer status == 'COMMITTED')][24]PATCH/transfers/{id} (TransferStatus='COMMITTED', homeTransactionId)[25]PATCH/transfers/{id} (TransferStatus='COMMITTED')[26]Do nothing[27]response \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPBulkDoubleIntegrationApi.PlantUML b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPBulkDoubleIntegrationApi.PlantUML new file mode 100644 index 000000000..7d193ae2c --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPBulkDoubleIntegrationApi.PlantUML @@ -0,0 +1,100 @@ +@startuml PayerDFSPBulkDoubleIntegrationApiPattern +/'***** +-------------- +******'/ + +skinparam activityFontSize 4 +skinparam activityDiamondFontSize 30 +skinparam activityArrowFontSize 22 +skinparam defaultFontSize 22 +skinparam noteFontSize 22 +skinparam monochrome true +' declare title +' title PayerDFSPBulkDoubleIntegrationApi +' declare actors +participant "Core banking solution" as CBS +box "Payment Manager\nPayer DFSP" #LightGrey +participant "Core\nConnector" as CC +participant "Mojaloop\nConnector" as MC +end box +participant "Mojaloop\nSwitch" as Switch +autonumber 1 1 "[0]" + +== Payer DFSP integration - 2 phase commit - with user confirmation == + +CBS->CC: **POST** /bulkTransactions\n(AUTO_ACCEPT_PARTY = true, AUTO_ACCEPT_QUOTES = **false**, synchronous = false) +Loop n times (in parallel) + hnote left of CC + For each individual transfer + in bulk message + end hnote + CC -> CC: validate MSISDN & Prefix +end Loop +CC->MC: **POST** /bulkTransactions\n(AUTO_ACCEPT_PARTY = true, AUTO_ACCEPT_QUOTES = **false**, synchronous = false) +activate MC +loop N times & within bulkExpiration timelimit (in parallel) +hnote left of MC + For each transfer + in bulk message +end hnote + activate MC + MC->Switch: **GET** /parties/{Type}/{ID}/{SubId} + Switch-->MC: HTTP 202 response + Switch->Switch: Determine Payee DFSP using oracle + Switch->Switch: Lookup Payee Information from Payee DFSP\n using **GET** /parties + Switch->MC: **PUT** /parties/{Type}/{ID}/{SubId} + MC-->Switch: HTTP 200 Response +end Loop + +rnote left MC + Accept Party +endrnote + +loop Quote Processing (M times & within bulkExpiration timelimit in parallel) + hnote left of MC + For each payee DFSP + in bulk message + end hnote + MC->MC: Check bulkExpiration + MC->MC: Create bulkTransactionId + MC -> MC: Calculate bulk expiry \nbased on both expirySeconds config and \nbulkExpiration + MC->Switch: **POST** /bulkquotes + Switch-->MC: HTTP 202 response + Switch->Switch: Pass on quote to Payee DFSP\n using **POST** /bulkquotes + Switch->MC: **PUT** /bulkquotes/{Id} + MC-->Switch: HTTP 200 Response +end loop + MC->CC: **PUT** /bulkTransactions/{Id} + + deactivate MC + CC->CBS: **PUT** /bulkTransactions/{Id} + + +CBS->CBS: Obtain concent from Payer on Fees and Payee Info +CBS->CBS: Reserve funds +CBS->CC: **PUT** /bulkTransactions/{bulkhometransferId} +CC->MC: **PUT** /bulkTransactions/{bulktransactionId} + +loop Transfer Processing (M times & within bulkExpiration timelimit in parallel) + hnote left of MC + For each payee DFSP + in bulk message + end hnote + + activate MC + MC->Switch: **POST** /bulktransfers + Switch-->MC: HTTP 202 response + Switch->Switch: Reserve Payer DFSP funds + Switch->Switch: Pass on transfer to Payee DFSP\n using **POST** /bulktransfers + Switch->Switch: Commit Payer DFSP funds + Switch->MC: **PUT** /bulktransfers/{Id} + MC-->Switch: HTTP 200 Response +end loop + +MC->CC: **PUT** /bulkTransactions/{Id} + +deactivate MC +CC->CBS: **PUT** /bulkTransactions/{Id} +CBS->CBS: Commit funds + +@enduml \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPBulkDoubleIntegrationApiPattern.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPBulkDoubleIntegrationApiPattern.svg new file mode 100644 index 000000000..19e336a0a --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPBulkDoubleIntegrationApiPattern.svg @@ -0,0 +1,205 @@ +Payment ManagerPayer DFSPCore banking solutionCore banking solutionCoreConnectorCoreConnectorMojaloopConnectorMojaloopConnectorMojaloopSwitchMojaloopSwitchPayer DFSP integration - 2 phase commit - with user confirmation[1]POST/bulkTransactions(AUTO_ACCEPT_PARTY = true, AUTO_ACCEPT_QUOTES =false, synchronous = false)loop[n times (in parallel)]For each individual transferin bulk message[2]validate MSISDN & Prefix[3]POST/bulkTransactions(AUTO_ACCEPT_PARTY = true, AUTO_ACCEPT_QUOTES =false, synchronous = false)loop[N times & within bulkExpiration timelimit (in parallel)]For each transferin bulk message[4]GET/parties/{Type}/{ID}/{SubId}[5]HTTP 202 response[6]Determine Payee DFSP using oracle[7]Lookup Payee Information from Payee DFSPusingGET/parties[8]PUT/parties/{Type}/{ID}/{SubId}[9]HTTP 200 ResponseAccept Partyloop[Quote Processing (M times & within bulkExpiration timelimit in parallel)]For each payee DFSPin bulk message[10]Check bulkExpiration[11]Create bulkTransactionId[12]Calculate bulk expirybased on both expirySeconds config andbulkExpiration[13]POST/bulkquotes[14]HTTP 202 response[15]Pass on quote to Payee DFSPusingPOST/bulkquotes[16]PUT/bulkquotes/{Id}[17]HTTP 200 Response[18]PUT/bulkTransactions/{Id}[19]PUT/bulkTransactions/{Id}[20]Obtain concent from Payer on Fees and Payee Info[21]Reserve funds[22]PUT/bulkTransactions/{bulkhometransferId}[23]PUT/bulkTransactions/{bulktransactionId}loop[Transfer Processing (M times & within bulkExpiration timelimit in parallel)]For each payee DFSPin bulk message[24]POST/bulktransfers[25]HTTP 202 response[26]Reserve Payer DFSP funds[27]Pass on transfer to Payee DFSPusingPOST/bulktransfers[28]Commit Payer DFSP funds[29]PUT/bulktransfers/{Id}[30]HTTP 200 Response[31]PUT/bulkTransactions/{Id}[32]PUT/bulkTransactions/{Id}[33]Commit funds \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPBulkSingleIntegrationApi.PlantUML b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPBulkSingleIntegrationApi.PlantUML new file mode 100644 index 000000000..38e3d8d6c --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPBulkSingleIntegrationApi.PlantUML @@ -0,0 +1,95 @@ +@startuml PayerDFSPBulkSingleIntegrationApiPattern +/'***** +-------------- +******'/ + +skinparam activityFontSize 4 +skinparam activityDiamondFontSize 30 +skinparam activityArrowFontSize 22 +skinparam defaultFontSize 22 +skinparam noteFontSize 22 +skinparam monochrome true +' declare title +' title PayerDFSPBulkSingleIntegrationApi +' declare actors +participant "Core banking solution" as CBS +box "Payment Manager\nPayer DFSP" #LightGrey +participant "Core\nConnector" as CC +participant "SDK Scheme Adapter" as MC +end box +participant "Mojaloop\nSwitch" as Switch +autonumber 1 1 "[0]" + +== Payer DFSP integration - 2 phase commit - single phase == + +CBS->CBS: Reserve funds +CBS->CC: **POST** /bulkTransactions \n(AUTO_ACCEPT_PARTY = true, AUTO_ACCEPT_QUOTES = true, synchronous = false) +Loop n times (in parallel) + hnote left of CC + For each individual transfer + in bulk message + end hnote + CC -> CC: validate MSISDN & Prefix +end Loop +CC->MC: **POST** /bulkTransactions \n(AUTO_ACCEPT_PARTY = true, AUTO_ACCEPT_QUOTES = true, synchronous = false) +activate MC +loop N times & within bulkExpiration timelimit (in parallel) +hnote left of MC + For each transfer + in bulk message +end hnote + MC->Switch: **GET** /parties/{Type}/{ID}/{SubId} + Switch-->MC: HTTP 202 response + Switch->Switch: Determine Payee DFSP using oracle + Switch->Switch: Lookup Payee Information from Payee DFSP\n using **GET** /parties + Switch->MC: **PUT** /parties/{Type}/{ID}/{SubId} + MC-->Switch: HTTP 200 Response + MC -> MC: Update transaction status and\n attach get parties response + MC -> MC: Add to next phase FSP bulk call +end Loop + +rnote left MC + Accept Party +endrnote + +loop Quote Processing (M times & within bulkExpiration timelimit in parallel) + hnote left of MC + For each payee DFSP + in bulk message + end hnote + MC->MC: Check bulkExpiration + MC->MC: Create bulkTransactionId + MC -> MC: Calculate bulk expiry \nbased on both expirySeconds config and \nbulkExpiration + MC->Switch: **POST** /bulkquotes + Switch-->MC: HTTP 202 response + Switch->Switch: Pass on bulkquote to Payee DFSP\n using **POST** /bulkquotes + Switch->MC: **PUT** /bulkquotes/{Id} + MC-->Switch: HTTP 200 Response +end loop + +rnote left MC + Accept Quote +endrnote +loop Transfer Processing (M times & within bulkExpiration timelimit in parallel) + hnote left of MC + For each payee DFSP + in bulk message + end hnote + MC -> MC: Confirm Fees meets auto accept levels\n and bulkExpiration timelimit not reached \n-> Update Transfer Status + + MC->Switch: **POST** /bulktransfers + Switch-->MC: HTTP 202 response + Switch->Switch: Reserve Payer DFSP funds + Switch->Switch: Pass on transfer to Payee DFSP\n using **POST** /bulktransfers + Switch->Switch: Commit Payer DFSP funds + Switch->MC: **PUT** /bulktransfers/{Id} + MC-->Switch: HTTP 200 Response +end loop + +MC->CC: **PUT** /bulkTransactions/{Id} + +deactivate MC +CC->CBS: **PUT** /bulkTransactions/{Id} +CBS->CBS: Commit funds + +@enduml \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPBulkSingleIntegrationApiPattern.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPBulkSingleIntegrationApiPattern.svg new file mode 100644 index 000000000..e136c59bd --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPBulkSingleIntegrationApiPattern.svg @@ -0,0 +1,195 @@ +Payment ManagerPayer DFSPCore banking solutionCore banking solutionCoreConnectorCoreConnectorSDK Scheme AdapterSDK Scheme AdapterMojaloopSwitchMojaloopSwitchPayer DFSP integration - 2 phase commit - single phase[1]Reserve funds[2]POST/bulkTransactions(AUTO_ACCEPT_PARTY = true, AUTO_ACCEPT_QUOTES = true, synchronous = false)loop[n times (in parallel)]For each individual transferin bulk message[3]validate MSISDN & Prefix[4]POST/bulkTransactions(AUTO_ACCEPT_PARTY = true, AUTO_ACCEPT_QUOTES = true, synchronous = false)loop[N times & within bulkExpiration timelimit (in parallel)]For each transferin bulk message[5]GET/parties/{Type}/{ID}/{SubId}[6]HTTP 202 response[7]Determine Payee DFSP using oracle[8]Lookup Payee Information from Payee DFSPusingGET/parties[9]PUT/parties/{Type}/{ID}/{SubId}[10]HTTP 200 Response[11]Update transaction status andattach get parties response[12]Add to next phase FSP bulk callAccept Partyloop[Quote Processing (M times & within bulkExpiration timelimit in parallel)]For each payee DFSPin bulk message[13]Check bulkExpiration[14]Create bulkTransactionId[15]Calculate bulk expirybased on both expirySeconds config andbulkExpiration[16]POST/bulkquotes[17]HTTP 202 response[18]Pass on bulkquote to Payee DFSPusingPOST/bulkquotes[19]PUT/bulkquotes/{Id}[20]HTTP 200 ResponseAccept Quoteloop[Transfer Processing (M times & within bulkExpiration timelimit in parallel)]For each payee DFSPin bulk message[21]Confirm Fees meets auto accept levelsand bulkExpiration timelimit not reached-> Update Transfer Status[22]POST/bulktransfers[23]HTTP 202 response[24]Reserve Payer DFSP funds[25]Pass on transfer to Payee DFSPusingPOST/bulktransfers[26]Commit Payer DFSP funds[27]PUT/bulktransfers/{Id}[28]HTTP 200 Response[29]PUT/bulkTransactions/{Id}[30]PUT/bulkTransactions/{Id}[31]Commit funds \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPDoubleIntegrationApiPattern.PlantUML b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPDoubleIntegrationApiPattern.PlantUML new file mode 100644 index 000000000..540789924 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPDoubleIntegrationApiPattern.PlantUML @@ -0,0 +1,66 @@ +@startuml PayerDFSPDoubleIntegrationApiPattern +/'***** +-------------- +******'/ + +skinparam activityFontSize 4 +skinparam activityDiamondFontSize 30 +skinparam activityArrowFontSize 22 +skinparam defaultFontSize 22 +skinparam noteFontSize 22 +skinparam monochrome true +' declare title +' title Core-Connector transactional flow patterns +' declare actors +participant "Core banking solution" as CBS +box "Payment Manager\nPayer DFSP" #LightGrey +participant "Core\nConnector" as CC +participant "SDK Scheme Adapter" as MC +end box +participant "Mojaloop\nSwitch" as Switch +autonumber 1 1 "[0]" + +== Payer DFSP integration - 2 phase commit - with user confirmation == + +CBS->CC: **POST** /sendMoney \n(AUTO_ACCEPT_PARTY = true, AUTO_ACCEPT_QUOTES = **false**) +CC->MC: **POST** /transfers +activate MC +MC->Switch: **GET** /parties/{Type}/{ID}/{SubId} +Switch-->MC: HTTP 202 response +Switch->Switch: Determine Payee DFSP using oracle +Switch->Switch: Lookup Payee Information from Payee DFSP\n using **GET** /parties +Switch->MC: **PUT** /parties/{Type}/{ID}/{SubId} +MC-->Switch: HTTP 200 Response +rnote left MC + Accept Party +endrnote +MC->Switch: **POST** /quotes +Switch-->MC: HTTP 202 response +Switch->Switch: Pass on quote to Payee DFSP\n using **POST** /quotes +Switch->MC: **PUT** /quotes/{Id} +MC-->Switch: HTTP 200 Response +MC-->CC: Response +deactivate MC +CC-->CBS: Response +CBS->CBS: Obtain concent from Payer on Fees and Payee Info +CBS->CBS: Reserve funds +CBS->CC: **PUT** /sendmoney/{transferId} +CC->MC: **PUT** /transfers + +activate MC +MC->Switch: **POST** /transfers +Switch-->MC: HTTP 202 response +Switch->Switch: Reserve Payer DFSP funds +Switch->Switch: Pass on transfer to Payee DFSP\n using **POST** /transfers +Switch->Switch: Commit Payer DFSP funds +Switch->MC: **PUT** /transfers/{Id} +MC-->Switch: HTTP 200 Response +MC-->CC: response +deactivate MC +CC-->CBS: response +alt if (transferStatus== 'COMMITTED') +CBS->CBS: Finalise transfer +else else +CBS->CBS: Rollback transfer +end +@enduml \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPDoubleIntegrationApiPattern.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPDoubleIntegrationApiPattern.svg new file mode 100644 index 000000000..175a64e31 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPDoubleIntegrationApiPattern.svg @@ -0,0 +1,137 @@ +Payment ManagerPayer DFSPCore banking solutionCore banking solutionCoreConnectorCoreConnectorSDK Scheme AdapterSDK Scheme AdapterMojaloopSwitchMojaloopSwitchPayer DFSP integration - 2 phase commit - with user confirmation[1]POST/sendMoney(AUTO_ACCEPT_PARTY = true, AUTO_ACCEPT_QUOTES =false)[2]POST/transfers[3]GET/parties/{Type}/{ID}/{SubId}[4]HTTP 202 response[5]Determine Payee DFSP using oracle[6]Lookup Payee Information from Payee DFSPusingGET/parties[7]PUT/parties/{Type}/{ID}/{SubId}[8]HTTP 200 ResponseAccept Party[9]POST/quotes[10]HTTP 202 response[11]Pass on quote to Payee DFSPusingPOST/quotes[12]PUT/quotes/{Id}[13]HTTP 200 Response[14]Response[15]Response[16]Obtain concent from Payer on Fees and Payee Info[17]Reserve funds[18]PUT/sendmoney/{transferId}[19]PUT/transfers[20]POST/transfers[21]HTTP 202 response[22]Reserve Payer DFSP funds[23]Pass on transfer to Payee DFSPusingPOST/transfers[24]Commit Payer DFSP funds[25]PUT/transfers/{Id}[26]HTTP 200 Response[27]response[28]responsealt[if (transferStatus== 'COMMITTED')][29]Finalise transfer[else][30]Rollback transfer \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPSingleIntegrationApiPattern.PlantUML b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPSingleIntegrationApiPattern.PlantUML new file mode 100644 index 000000000..4884dec9c --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPSingleIntegrationApiPattern.PlantUML @@ -0,0 +1,63 @@ +@startuml PayerDFSPSingleIntegrationApiPattern +/'***** +-------------- +******'/ + +skinparam activityFontSize 4 +skinparam activityDiamondFontSize 30 +skinparam activityArrowFontSize 22 +skinparam defaultFontSize 22 +skinparam noteFontSize 22 +skinparam monochrome true +' declare title +' title Payer DFSP Single Phase Integration Pattern +' declare actors +participant "Core banking solution" as CBS +box "Payment Manager" #LightGrey +participant "Core\nConnector" as CC +participant "SDK Scheme Adapter" as MC +end box +participant "Mojaloop\nSwitch" as Switch +autonumber 1 1 "[0]" + +== Payer DFSP integration - 2 phase commit - single phase == + +CBS->CBS: Reserve funds +CBS->CC: **POST** /sendMoney \n(AUTO_ACCEPT_PARTY = true, AUTO_ACCEPT_QUOTES = true) +CC->MC: **POST** /transfers +activate MC +MC->Switch: **GET** /parties/{Type}/{ID}/{SubId} +Switch-->MC: HTTP 202 response +Switch->Switch: Determine Payee DFSP using oracle +Switch->Switch: Lookup Payee Information from Payee DFSP\n using **GET** /parties +Switch->MC: **PUT** /parties/{Type}/{ID}/{SubId} +MC-->Switch: HTTP 200 Response +rnote left MC + Accept Party +endrnote +MC->Switch: **POST** /quotes +Switch-->MC: HTTP 202 response +Switch->Switch: Pass on quote to Payee DFSP\n using **POST** /quotes +Switch->MC: **PUT** /quotes/{Id} +MC-->Switch: HTTP 200 Response +rnote left MC + Accept Quote +endrnote +MC->Switch: **POST** /transfers +Switch-->MC: HTTP 202 response +Switch->Switch: Reserve Payer DFSP funds +Switch->Switch: Pass on transfer to Payee DFSP\n using **POST** /transfers +Switch->Switch: Calculate fees +Switch->Switch: Commit Payer DFSP funds +Switch->MC: **PUT** /transfers/{Id} +MC-->Switch: HTTP 200 Response +MC-->CC: response +deactivate MC +CC-->CBS: response +alt if (transferStatus== 'COMMITTED') +CBS->CBS: Finalise transfer +else else +CBS->CBS: Rollback transfer +end + +@enduml \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPSingleIntegrationApiPattern.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPSingleIntegrationApiPattern.svg new file mode 100644 index 000000000..8c3b55365 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/PayerDFSPSingleIntegrationApiPattern.svg @@ -0,0 +1,131 @@ +Payment ManagerCore banking solutionCore banking solutionCoreConnectorCoreConnectorSDK Scheme AdapterSDK Scheme AdapterMojaloopSwitchMojaloopSwitchPayer DFSP integration - 2 phase commit - single phase[1]Reserve funds[2]POST/sendMoney(AUTO_ACCEPT_PARTY = true, AUTO_ACCEPT_QUOTES = true)[3]POST/transfers[4]GET/parties/{Type}/{ID}/{SubId}[5]HTTP 202 response[6]Determine Payee DFSP using oracle[7]Lookup Payee Information from Payee DFSPusingGET/parties[8]PUT/parties/{Type}/{ID}/{SubId}[9]HTTP 200 ResponseAccept Party[10]POST/quotes[11]HTTP 202 response[12]Pass on quote to Payee DFSPusingPOST/quotes[13]PUT/quotes/{Id}[14]HTTP 200 ResponseAccept Quote[15]POST/transfers[16]HTTP 202 response[17]Reserve Payer DFSP funds[18]Pass on transfer to Payee DFSPusingPOST/transfers[19]Calculate fees[20]Commit Payer DFSP funds[21]PUT/transfers/{Id}[22]HTTP 200 Response[23]response[24]responsealt[if (transferStatus== 'COMMITTED')][25]Finalise transfer[else][26]Rollback transfer \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/SDKBulkSequenceDiagram.plantuml b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/SDKBulkSequenceDiagram.plantuml new file mode 100644 index 000000000..362d9c085 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/SDKBulkSequenceDiagram.plantuml @@ -0,0 +1,132 @@ +@startuml +/'******** +-------------- +*********'/ + +skinparam activityFontSize 4 +skinparam activityDiamondFontSize 30 +skinparam activityArrowFontSize 22 +skinparam defaultFontSize 22 +skinparam noteFontSize 22 +skinparam monochrome true +' declare title +' title Bulk Transactions pattern using the Mojaloop Connector +' declare actors + +box "Payer DFSP" #LightGrey + participant "Backend System" as MFICC + participant "sdk-scheme-adapter" as MFIMC +end box +participant "Mojaloop\nSwitch" as MJW +box "Payee DFSP" #LightGrey + participant "sdk-scheme-adapter" as PayeeFSPMC + participant "Backend System" as PayeeFSPCC +end box + +== MVP Bulk Transfers using SDK-Scheme-Adapter == + +autonumber 1 1 "[0]" +MFICC->>MFIMC: **POST** /bulkTransactions +note left +Bulk Disbursement is triggerd +by beneficiary management sub-system +end note + +loop Discovery Processing: For each individualTransfer in bulk message +hnote left of MFIMC + Resolving all potential recipients + which might be at any of the DFSPs + on the service. +end hnote + MFIMC ->> MJW: **GET** /parties/* + activate MFIMC + MJW->MJW: query oracle to \ndetermine Payee DFSP + MJW->>PayeeFSPMC: **GET** /parties/* + PayeeFSPMC->PayeeFSPCC: **GET** /parties/* + note right + Lookup / validate party information + end note + PayeeFSPMC-->>MJW: **PUT** /parties/{type}/{id} + MJW-->>MFIMC: **PUT** /parties/{type}/{id} + deactivate MFIMC + +end Loop + MFIMC-->>MFICC: **PUT** /bulkTransactions/{bulkTransactionId} + MFICC->>MFIMC: **PUT** /bulkTransactions/{bulkTransactionId} + note left + Confirmation of party integration + end note + +MFIMC->MFIMC: Group Valid Transfers into batches +loop Agreement Processing: For each batch in bulk message +hnote left of MFIMC + Each DFSP is provided the opportunity to + perform AML checks and add costs + or discounts to each transfer. +end hnote + MFIMC ->> MJW: **POST** /bulkquotes + activate MFIMC + MJW->>PayeeFSPMC: **POST** /bulkquotes + alt if (HasSupportForBulkQuotes) + PayeeFSPMC->PayeeFSPCC: **POST** /bulkquotes + note right + Bulk AML checks + Bulk Fee calculations + end note + else if (!HasSupportForBulkQuotes) + loop X times for each transfer in bulk message + PayeeFSPMC->PayeeFSPCC: **POST** /quoterequests + note right + AML checks + Fee calculations + end note + end Loop + end + PayeeFSPMC-->>MJW: **PUT** /bulkquotes/{id) + MJW-->>MFIMC: **PUT** /bulkquotes/{id) + deactivate MFIMC +end loop + + MFIMC-->>MFICC: **PUT** /bulkTransactions/{bulkTransactionId} + MFICC->>MFIMC: **PUT** /bulkTransactions/{bulkTransactionId} + note left + confirmation of quote integration + end note + +loop Transfer Processing: For each batch in bulk message + hnote left of MFIMC + Each DFSP is messaged to proceed + with the transfer. Results + are captured and returned. + end hnote + MFIMC ->> MJW: **POST** /bulktransfers + activate MFIMC + MJW-> MJW: Perform liquidity(NDC) check\n at individual transfer level + MJW->MJW: Reserve Funds + MJW ->> PayeeFSPMC: **POST** /bulktransfers + alt if (HasSupportForBulkTransfers) + PayeeFSPMC->PayeeFSPCC: **POST** /bulktransfers + note right + Bulk Transfer integration + end note + else if (!HasSupportForBulkTransfers) + loop X times for each transfer in bulk message + PayeeFSPMC->PayeeFSPCC: **POST** /transfers + note right + Single Transfer integration + end note + end Loop + end + PayeeFSPMC -->> MJW: **PUT** /bulktransfers/{id} (BulkStatus) + MJW->MJW: Commit funds at indivial transfer level + MJW-->>MFIMC:**PUT** /bulktransfers/{id} + + deactivate MFIMC +end loop +MFIMC-->>MFICC:Callback Response \n**PUT** /bulkTransactions/{bulkTransactionId}\nTransfer Response (success & fail) +note left + Result of bulk disbursement received. +end note + + +@enduml \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/SDKBulkSequenceDiagram.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/SDKBulkSequenceDiagram.svg new file mode 100644 index 000000000..a6fc96ca3 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/SDKBulkSequenceDiagram.svg @@ -0,0 +1,295 @@ + + + + + Payer DFSP + + Payee DFSP + + + + + + + + + + + + + + + + + Backend System + + Backend System + + sdk-scheme-adapter + + sdk-scheme-adapter + + Mojaloop + Switch + + Mojaloop + Switch + + sdk-scheme-adapter + + sdk-scheme-adapter + + Backend System + + Backend System + + + + + + + + MVP Bulk Transfers using SDK-Scheme-Adapter + + + + [1] + POST + /bulkTransactions + + + Bulk Disbursement is triggerd + by beneficiary management sub-system + + + loop + [Discovery Processing: For each individualTransfer in bulk message] + + Resolving all potential recipients + which might be at any of the DFSPs + on the service. + + + + [2] + GET + /parties/* + + + + + [3] + query oracle to + determine Payee DFSP + + + + [4] + GET + /parties/* + + + [5] + GET + /parties/* + + + Lookup / validate party information + + + + [6] + PUT + /parties/{type}/{id} + + + + [7] + PUT + /parties/{type}/{id} + + + + [8] + PUT + /bulkTransactions/{bulkTransactionId} + + + + [9] + PUT + /bulkTransactions/{bulkTransactionId} + + + Confirmation of party integration + + + + + [10] + Group Valid Transfers into batches + + + loop + [Agreement Processing: For each batch in bulk message] + + Each DFSP is provided the opportunity to + perform AML checks and add costs + or discounts to each transfer. + + + + [11] + POST + /bulkquotes + + + + [12] + POST + /bulkquotes + + + alt + [if (HasSupportForBulkQuotes)] + + + [13] + POST + /bulkquotes + + + Bulk AML checks + Bulk Fee calculations + + [if (!HasSupportForBulkQuotes)] + + + loop + [X times for each transfer in bulk message] + + + [14] + POST + /quoterequests + + + AML checks + Fee calculations + + + + [15] + PUT + /bulkquotes/{id) + + + + [16] + PUT + /bulkquotes/{id) + + + + [17] + PUT + /bulkTransactions/{bulkTransactionId} + + + + [18] + PUT + /bulkTransactions/{bulkTransactionId} + + + confirmation of quote integration + + + loop + [Transfer Processing: For each batch in bulk message] + + Each DFSP is messaged to proceed + with the transfer. Results + are captured and returned. + + + + [19] + POST + /bulktransfers + + + + + [20] + Perform liquidity(NDC) check + at individual transfer level + + + + + [21] + Reserve Funds + + + + [22] + POST + /bulktransfers + + + alt + [if (HasSupportForBulkTransfers)] + + + [23] + POST + /bulktransfers + + + Bulk Transfer integration + + [if (!HasSupportForBulkTransfers)] + + + loop + [X times for each transfer in bulk message] + + + [24] + POST + /transfers + + + Single Transfer integration + + + + [25] + PUT + /bulktransfers/{id} (BulkStatus) + + + + + [26] + Commit funds at indivial transfer level + + + + [27] + PUT + /bulktransfers/{id} + + + + [28] + Callback Response + PUT + /bulkTransactions/{bulkTransactionId} + Transfer Response (success & fail) + + + Result of bulk disbursement received. + + diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/SDKrequestToPay.plantuml b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/SDKrequestToPay.plantuml new file mode 100644 index 000000000..2485c6f54 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/SDKrequestToPay.plantuml @@ -0,0 +1,195 @@ +@startuml + +actor "Payer" as Payer +box Payer DFSP +participant "Core Banking System" as PayerDFSP +participant "SDK" as PayerSDK +end box +participant "Mojaloop" as Mojaloop #d4f2f9 + +box Payee DFSP +participant "SDK" as PayeeSDK +participant "Core Banking System" as PayeeDFSP +end box +actor "Payee" as Payee +autonumber 1 "[0]" + +alt if (User Initiated OTP) +Payer->PayerDFSP: Generate an OTP for me +PayerDFSP->PayerDFSP:Generate +PayerDFSP-->Payer: Here is your OTP +end +=== Payee initiated request to pay (R2P) == +Payee->PayeeDFSP: I would like \nto receive 1000 TZS\n from +1234567890 +PayeeDFSP->PayeeDFSP: Payer not within Payee System + +PayeeDFSP->PayeeSDK: **POST** /requestToPayTransfer +note right +{ + "requestToPayTransactionId": "string", + "from": { + "type": "CONSUMER", + "idType": "MSISDN", + "idValue": "+1234567890", + "idSubValue": "string" + }, + "to": {...}, + "amountType": "RECEIVE", + "currency": "TZS", + "amount": "1000.0", + "scenario": {...}, + "initiator": "PAYEE", + "initiatorType": "CONSUMER", + "note": "Note sent to Payee." +} +end note +activate PayeeSDK + +PayeeSDK->>Mojaloop: **GET** /parties +Mojaloop->>PayerSDK: **GET** /parties +PayerSDK->PayerDFSP: **GET** /parties +PayerDFSP->PayerDFSP: Lookup Validate Payer Account +PayerDFSP-->PayerSDK: return Payer information +note left +Payer information +end note +PayerSDK->>Mojaloop: **PUT** /parties +Mojaloop->>PayeeSDK: **PUT** /parties + +alt If AutoAcceptParty = false + PayeeSDK-->PayeeDFSP: **POST**\n /requestToPayTransfer \n(synchronous return) + note left +{ + "requestToPayTransactionId": "string", + "from": { + "type": "CONSUMER", + "idType": "MSISDN", + "idValue": "1234567890", + "idSubValue": "string", + "displayName": "ryZ037pWP'lHu,Tu9,Tjl MRMbdMSpRGAHt4m6 2jk5L4'ePRWT", + "firstName": "Henrik", + "middleName": "Johannes", + "lastName": "Karlsson", + "dateOfBirth": "1966-06-16", + "fspId": "string", + "extensionList": [] + }, + "to": {...}, + "amountType": "RECEIVE", + "currency": "TZS", + "amount": "1000.0", + "transactionType": "TRANSFER", + "note": "Note sent to Payee.", + "currentState": "WAITING_FOR_PARTY_ACCEPTANCE", +} + end note +PayeeDFSP->PayeeSDK: **PUT** /requestToPay/\n{requestToPayId} +note right + { + acceptParty: true + } +end note +else +PayeeSDK->PayeeSDK: Automatically \nAcceptParty by updating\n status +end + +PayeeSDK->>Mojaloop: **POST** /transactionRequests +Mojaloop->>PayerSDK: **POST** /transactionRequests +PayerSDK->PayerDFSP: **POST** /transactionRequests +PayerDFSP->PayerDFSP: Validate request\n to pay request +PayerDFSP-->PayerSDK: return +PayerSDK->>Mojaloop: **PUT** /transactionRequests/{ID} +note left +{ + "transactionId": "b51ec534-ee48-4575-b6a9-ead2955b8069", + "transactionRequestState": "RECEIVED", + "AuthenticationType": {} + "extensionList": {extension:[]} +} +end note +Mojaloop->>PayeeSDK: **PUT** /transactionRequests +PayeeSDK-->PayeeDFSP: return +deactivate PayeeSDK + +=== Payer DFSP executes R2P request == + +PayerDFSP->PayerSDK: **POST** /RequestToPayTransfer +note left +Initiate R2P with AuthType +end note +activate PayerSDK +PayerSDK->>Mojaloop: **POST** /quotes +Mojaloop->>PayeeSDK: **POST** /quotes +PayeeSDK->PayeeDFSP: **POST** /quoterequest +PayeeDFSP->PayeeSDK: return quote +PayeeSDK->>Mojaloop: **PUT** /quotes +Mojaloop->>PayerSDK: **PUT** /quotes + +PayerSDK-->PayerDFSP: return \n(**POST** /RequestToPayTransfer) +deactivate PayerSDK + +alt if AuthenticateType is null +PayerDFSP->Payer: Present payment terms\n to Payer for acceptance +Payer->PayerDFSP: I accept the payment terms +else if AuthenticateType is OTP +alt if (Automatic generated OTP) + +PayerDFSP->PayerDFSP: Generate OTP +PayerDFSP->Payer: Present OTP to Payer +end + +loop x retries +PayerDFSP->PayerSDK: **PUT** /RequestToPayTransfer +note left + accept quote = true + retries left = x +end note + +PayerSDK->>Mojaloop: **GET** \n/authorizations/\n{transactionRequestID} +Mojaloop->>PayeeSDK: **GET** \n/authorizations/\n{transactionRequestID} +PayeeSDK->PayeeDFSP: **GET** \n/auth/{authtype}/{requestToPayId} +PayeeDFSP->Payee: Get Payee to get\n Payer to enter OTP\n on POS +Payer->PayeeDFSP: Enter OTP +PayeeDFSP-->PayeeSDK: return OTP +note right +{ + "otpValue": "string" +} +end note +PayeeSDK->>Mojaloop: **PUT** /authorizations/{ID} +Mojaloop->>PayerSDK: **PUT** /authorizations/{ID} +PayerSDK-->PayerDFSP: synchronous return \n **POST** /requestToPayTransfer/\n{requestToPayTransactionId} +PayerDFSP->PayerDFSP: Validate OTP + +end loop + +end + + + +alt if can proceed with transfer +PayerDFSP->PayerDFSP: Reserve funds against \nPayer's account +PayerDFSP-->PayerSDK: **PUT** \n/requestToPayTransfer/\n{requestToPayTransactionId} + +PayerSDK->>Mojaloop: **POST** /transfers +activate PayerSDK +Mojaloop->>PayeeSDK: **POST** /transfers +PayeeSDK-->PayeeDFSP: **PUT** / **POST**\n /requestToPayTransfer/\n{requestToPayTransactionId}\n return +PayeeDFSP->Payee: Notify user +PayeeSDK->>Mojaloop: **PUT** /transfers \nreturn fulfilment +Mojaloop->>PayerSDK: **PUT** /transfers +deactivate PayerSDK +PayerSDK->PayerDFSP: **POST** \n/newAPI \nNotify payer of transfer +PayerDFSP->PayerDFSP: Commit transfer \nto Payer's account +PayerDFSP->Payer: Notify Payer + +else if rejected + +PayerDFSP-->PayerSDK: return +PayerSDK->>Mojaloop: **PUT** \n/requestToPayTransfer/\n{requestToPayTransactionId}\n rejected +Mojaloop->>PayeeSDK: **PUT**\n /requestToPayTransfer/\n{requestToPayTransactionId}\n rejected +PayeeSDK-->X PayeeDFSP: return rejected +end + + +@enduml \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/SDKrequestToPay.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/SDKrequestToPay.svg new file mode 100644 index 000000000..f734170e5 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/SDKrequestToPay.svg @@ -0,0 +1,532 @@ + + + + + Payer DFSP + + Payee DFSP + + + + + + + + + + + + + + + + + Payer + + + Payer + + + + Core Banking System + + Core Banking System + + SDK + + SDK + + Mojaloop + + Mojaloop + + SDK + + SDK + + Core Banking System + + Core Banking System + Payee + + + Payee + + + + + + + + alt + [if (User Initiated OTP)] + + + [1] + Generate an OTP for me + + + + + [2] + Generate + + + [3] + Here is your OTP + + + + + Payee initiated request to pay (R2P) + + + [4] + I would like + to receive 1000 TZS + from +1234567890 + + + + + [5] + Payer not within Payee System + + + [6] + POST + /requestToPayTransfer + + + { + "requestToPayTransactionId": "string", + "from": { + "type": "CONSUMER", + "idType": "MSISDN", + "idValue": "+1234567890", + "idSubValue": "string" + }, + "to": {...}, + "amountType": "RECEIVE", + "currency": "TZS", + "amount": "1000.0", + "scenario": {...}, + "initiator": "PAYEE", + "initiatorType": "CONSUMER", + "note": "Note sent to Payee." + } + + + + [7] + GET + /parties + + + + [8] + GET + /parties + + + [9] + GET + /parties + + + + + [10] + Lookup Validate Payer Account + + + [11] + return Payer information + + + Payer information + + + + [12] + PUT + /parties + + + + [13] + PUT + /parties + + + alt + [If AutoAcceptParty = false] + + + [14] + POST + /requestToPayTransfer + (synchronous return) + + + { + "requestToPayTransactionId": "string", + "from": { + "type": "CONSUMER", + "idType": "MSISDN", + "idValue": "1234567890", + "idSubValue": "string", + "displayName": "ryZ037pWP'lHu,Tu9,Tjl MRMbdMSpRGAHt4m6 2jk5L4'ePRWT", + "firstName": "Henrik", + "middleName": "Johannes", + "lastName": "Karlsson", + "dateOfBirth": "1966-06-16", + "fspId": "string", + "extensionList": [] + }, + "to": {...}, + "amountType": "RECEIVE", + "currency": "TZS", + "amount": "1000.0", + "transactionType": "TRANSFER", + "note": "Note sent to Payee.", + "currentState": "WAITING_FOR_PARTY_ACCEPTANCE", + } + + + [15] + PUT + /requestToPay/ + {requestToPayId} + + + { + acceptParty: true + } + + + + + + [16] + Automatically + AcceptParty by updating + status + + + + [17] + POST + /transactionRequests + + + + [18] + POST + /transactionRequests + + + [19] + POST + /transactionRequests + + + + + [20] + Validate request + to pay request + + + [21] + return + + + + [22] + PUT + /transactionRequests/{ID} + + + { + "transactionId": "b51ec534-ee48-4575-b6a9-ead2955b8069", + "transactionRequestState": "RECEIVED", + "AuthenticationType": {} + "extensionList": {extension:[]} + } + + + + [23] + PUT + /transactionRequests + + + [24] + return + + + + + Payer DFSP executes R2P request + + + [25] + POST + /RequestToPayTransfer + + + Initiate R2P with AuthType + + + + [26] + POST + /quotes + + + + [27] + POST + /quotes + + + [28] + POST + /quoterequest + + + [29] + return quote + + + + [30] + PUT + /quotes + + + + [31] + PUT + /quotes + + + [32] + return + ( + POST + /RequestToPayTransfer) + + + alt + [if AuthenticateType is null] + + + [33] + Present payment terms + to Payer for acceptance + + + [34] + I accept the payment terms + + [if AuthenticateType is OTP] + + + alt + [if (Automatic generated OTP)] + + + + + [35] + Generate OTP + + + [36] + Present OTP to Payer + + + loop + [x retries] + + + [37] + PUT + /RequestToPayTransfer + + + accept quote = true + retries left = x + + + + [38] + GET +   + /authorizations/ + {transactionRequestID} + + + + [39] + GET +   + /authorizations/ + {transactionRequestID} + + + [40] + GET +   + /auth/{authtype}/{requestToPayId} + + + [41] + Get Payee to get + Payer to enter OTP + on POS + + + [42] + Enter OTP + + + [43] + return OTP + + + { + "otpValue": "string" + } + + + + [44] + PUT + /authorizations/{ID} + + + + [45] + PUT + /authorizations/{ID} + + + [46] + synchronous return +   + POST + /requestToPayTransfer/ + {requestToPayTransactionId} + + + + + [47] + Validate OTP + + + alt + [if can proceed with transfer] + + + + + [48] + Reserve funds against + Payer's account + + + [49] + PUT +   + /requestToPayTransfer/ + {requestToPayTransactionId} + + + + [50] + POST + /transfers + + + + [51] + POST + /transfers + + + [52] + PUT + / + POST + /requestToPayTransfer/ + {requestToPayTransactionId} + return + + + [53] + Notify user + + + + [54] + PUT + /transfers + return fulfilment + + + + [55] + PUT + /transfers + + + [56] + POST +   + /newAPI + Notify payer of transfer + + + + + [57] + Commit transfer + to Payer's account + + + [58] + Notify Payer + + [if rejected] + + + [59] + return + + + + [60] + PUT +   + /requestToPayTransfer/ + {requestToPayTransactionId} + rejected + + + + [61] + PUT + /requestToPayTransfer/ + {requestToPayTransactionId} + rejected + + + + [62] + return rejected + + diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/inbound-bulk-quotes-sequence.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/inbound-bulk-quotes-sequence.svg new file mode 100644 index 000000000..c395e3caa --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/inbound-bulk-quotes-sequence.svg @@ -0,0 +1 @@ +Mojaloop SwitchSDK FSPIOP APISDK Inbound Domain Event HandlerSDK Inbound Command Event HandlerSDK Backend APICore Connector Payeetopic-sdk-inbound-domain-eventstopic-sdk-inbound-command-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-command-eventstopic-sdk-inbound-domain-eventsloop[for each transfer in bulk]alt[Bulk quotes supported][Bulk quotes NOT supported]topic-sdk-inbound-command-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-command-eventsPOST /bulkquotesProcess Trace HeadersInboundBulkQuotesRequestReceivedAcceptedProcessInboundBulkQuotesRequestUpdate the bulk state: RECEIVEDCheck if bulkQuotes supported by payeeSDKBulkQuotesRequestedUpdate the bulk state: PROCESSINGProcess outbound Trace HeadersPOST /bulkQuotesAcceptedPUT /bulkQuotesProcess inbound Trace HeadersSDKBulkQuotesCallbackReceivedAcceptedQuoteRequestedUpdate the individual state: QUOTES_PROCESSINGProcess outbound Trace HeadersPOST /quotesSynchronous responseProcess Inbound Trace HeadersQuotesResponseReceivedProcessQuotesResponseUpdate the individual state: QUOTES_SUCCESS / QUOTES_FAILEDQuotesResponseProcessedCheck the status of the remaining items in the bulkProcessInboundBulkQuotesRequestCompleteUpdate the bulk state: COMPLETEDInboundBulkQuotesRequestProcessedUpdate the bulk state: RESPONSE_PROCESSINGProcess Outbound Trace HeadersPUT /bulkQuotes/{bulkQuoteId}AcceptedInboundBulkQuotesReponseSentProcessInboundBulkQuotesReponseSentUpdate bulk state "RESPONSE_SENT"Mojaloop SwitchSDK FSPIOP APISDK Inbound Domain Event HandlerSDK Inbound Command Event HandlerSDK Backend APICore Connector Payee \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/inbound-bulk-transfers-sequence.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/inbound-bulk-transfers-sequence.svg new file mode 100644 index 000000000..6deaf1f7a --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/inbound-bulk-transfers-sequence.svg @@ -0,0 +1 @@ +Mojaloop SwitchSDK FSPIOP APISDK Inbound Domain Event HandlerSDK Inbound Command Event HandlerSDK Backend APICore Connector Payeetopic-sdk-inbound-domain-eventstopic-sdk-inbound-command-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-domain-eventstopic-sdk-command-eventstopic-sdk-domain-eventsloop[for each transfer in bulk]alt[Bulk transfers supported][Bulk transfers NOT supported]topic-sdk-inbound-command-eventstopic-sdk-inbound-domain-eventstopic-sdk-domain-eventstopic-sdk-inbound-command-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-command-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-domain-eventstopic-sdk-command-eventstopic-sdk-domain-eventsloop[for each transfer in bulk]alt[Bulk transfers supported][Bulk transfers NOT supported]topic-sdk-inbound-command-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-domain-eventstopic-sdk-inbound-command-eventsalt[bulkStatus == 'ACCEPTED']POST /bulkTransfersProcess Trace HeadersInboundBulkTransfersRequestReceivedAcceptedProcessInboundBulkTransfersRequestUpdate the bulk state: RECEIVEDCheck if bulkQuotes supported by payeeSDKBulkTransfersRequestedUpdate the bulk state: PROCESSINGProcess outbound Trace HeadersPOST /bulkTransfersAcceptedPUT /bulkTransfersProcess inbound Trace HeadersSDKBulkTransfersCallbackReceivedAcceptedTransferRequestedUpdate the individual state: TRANSFERS_PROCESSINGProcess outbound Trace HeadersPOST /transfersSynchronous ResponseProcess Inbound Trace HeadersTransfersCallbackReceivedProcessTransfersCallbackUpdate the individual state: TRANSFERS_SUCCESS / TRANSFERS_FAILEDTransfersCallbackProcessedCheck the status of the remaining items in the bulkProcessInboundBulkTransfersRequestCompleteUpdate the bulk state: COMPLETED?InboundBulkTransfersRequestProcessedUpdate the bulk state: RESPONSE_PROCESSINGProcess Outbound Trace HeadersPUT /bulkTransfers/{bulkTransferId}AcceptedInboundBulkTransfersResponseSentProcessInboundBulkTransfersResponseSentUpdate bulk state "RESPONSE_SENT"Check bulkStatusPATCH /bulkTransfers/{bulkTransferId}AcceptedProcess Trace HeadersInboundBulkTransfersPatchRequestReceivedAcceptedProcessInboundBulkTransfersPatchRequestUpdate the bulk state: PATCH_RECEIVEDCheck if bulkTransfers supported by payeeSDKBulkTransfersPatchRequestedUpdate the bulk state: PATCH_PROCESSINGProcess outbound Trace HeadersPATCH /bulkTransfers/{bulkTransferId}AcceptedResponse to Patch /bulkTransfersProcess inbound Trace HeadersSDKBulkTransfersPatchCallbackReceivedAcceptedTransfersPatchRequestedUpdate the individual state: TRANSFERS_PATCH_PROCESSINGProcess outbound Trace HeadersPATCH /transfers/{transferId}AcceptedProcess Inbound Trace HeadersTransfersPatchCallbackReceivedAcceptedProcessTransfersPatchCallbackUpdate the individual state: TRANSFERS_PATCH_SUCCESS / TRANSFERS_PATCH_FAILEDTransfersPatchCallbackProcessedCheck the status of the remaining items in the bulkProcessInboundBulkTransfersPatchRequestCompleteUpdate the bulk state: COMPLETEDInboundBulkTransfersPatchRequestProcessedUpdate the bulk state: RESPONSE_PROCESSINGProcess Outbound Trace HeadersPUT /bulkTransfers/{bulkTransferId}AcceptedInboundBulkTransfersPatchResponseSentProcessInboundBulkTransfersPatchResponseSentUpdate bulk state "PATCH_RESPONSE_SENT"Mojaloop SwitchSDK FSPIOP APISDK Inbound Domain Event HandlerSDK Inbound Command Event HandlerSDK Backend APICore Connector Payee \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/outbound-sequence.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/outbound-sequence.svg new file mode 100644 index 000000000..d611c2057 --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/outbound-sequence.svg @@ -0,0 +1 @@ +Core ConnectorSDK Backend APISDK Outbound Domain Event HandlerSDK Outbound Command Event HandlerSDK FSPIOP APIMojaloop Switchtopic-sdk-outbound-domain-eventstopic-sdk-outbound-command-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-command-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-domain-eventsalt[party info already exists][party info doesn't exist]topic-sdk-outbound-command-eventstopic-sdk-outbound-domain-eventsloop[Party Lookup per transfer]topic-sdk-outbound-domain-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-command-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-command-eventsalt[autoAcceptParty == false][autoAcceptParty == true (In future we can make this optional and an external service can handle this)]loop[for each transfer in bulk]topic-sdk-outbound-domain-eventstopic-sdk-outbound-command-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-command-eventsloop[through items in batch]topic-sdk-outbound-domain-eventsloop[BulkQuotes requests per batch]topic-sdk-outbound-domain-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-command-eventsloop[for each individual transfer in bulk]topic-sdk-outbound-domain-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-command-eventsloop[for each individual transfer in bulk]topic-sdk-outbound-domain-eventsalt[autoAcceptQuote == false][autoAcceptQuote == true]topic-sdk-outbound-command-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-command-eventsloop[through items in batch]topic-sdk-outbound-domain-eventsloop[BulkTransfers requests per each batch and include only items with AGREEMENT_ACCEPTED]topic-sdk-outbound-domain-eventstopic-sdk-outbound-command-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-domain-eventstopic-sdk-outbound-command-eventsSDKBulkRequest1Scheme Validation2Process Trace Headers3SDKOutboundBulkRequestReceived4Accepted5ProcessSDKOutboundBulkRequest6Store initial data into redis (Generate UUIDs and map to persistent model, break the JSON into smaller parts)7Update global state "RECEIVED"8SDKOutboundBulkPartyInfoRequested9ProcessSDKOutboundBulkPartyInfoRequest10Update global state "DISCOVERY_PROCESSING"11Update the global state to DISCOVERY_RECEIVED12PartyInfoCallbackReceived13Update the party request14PartyInfoRequested (includes info for SDK for making a party call)15Set individual state: DISCOVERY_PROCESSING16Process outbound Trace Headers17GET /parties18PUT /parties19Process Inbound Trace Headers20PartyInfoCallbackReceived21ProcessPartyInfoCallback22Update the individual state: DISCOVERY_SUCCESS / DISCOVERY_FAILED23Update the party response24PartyInfoCallbackProcessed25Check the status of the remaining items in the bulk26Update global state "DISCOVERY_COMPLETED"27SDKOutboundBulkPartyInfoRequestProcessed28check options.autoAcceptParty in redis29SDKOutboundBulkAcceptPartyInfoRequested30Update global state "DISCOVERY_ACCEPTANCE_PENDING"31Process outbound Trace Headers32PUT /bulkTransactions/{bulkTransactionId}33Accepted34PUT /bulkTransactions/{bulkTransactionId}35Process inbound Trace Headers36SDKOutboundBulkAcceptPartyInfoReceived37Accepted38ProcessSDKOutboundBulkAcceptPartyInfo39SDKOutboundBulkAutoAcceptPartyInfoRequested40Create SDKOutboundBulkAcceptPartyInfo with acceptParty=true for individual items with DISCOVERY_SUCCESS state41ProcessSDKOutboundBulkAcceptPartyInfo42Update the individual state: DISCOVERY_ACCEPTED / DISCOVERY_REJECTED43Update global state "DISCOVERY_ACCEPTANCE_COMPLETED"44SDKOutboundBulkAcceptPartyInfoProcessed45ProcessSDKOutboundBulkQuotesRequest46Update global state "AGREEMENT_PROCESSING"47Create bulkQuotes batches from individual items with DISCOVERY_ACCEPTED state per FSP and maxEntryConfigPerBatch48Update bulkQuotes request49BulkQuotesRequested50Update the batch state: AGREEMENT_PROCESSING51Process outbound Trace Headers52POST /bulkQuotes53Accepted54PUT /bulkQuotes55Process inbound Trace Headers56BulkQuotesCallbackReceived57Accepted58ProcessBulkQuotesCallback59Update the batch state: AGREEMENT_COMPLETED / AGREEMENT_FAILED60Update the individual state: AGREEMENT_SUCCESS / AGREEMENT_FAILED61Update the quote response62BulkQuotesCallbackProcessed63Check the status of the remaining items in the bulk64Update global state "AGREEMENT_COMPLETED"65SDKOutboundBulkQuotesRequestProcessed66check autoAcceptQuote67SDKOutboundBulkAcceptQuoteRequested68Update global state "AGREEMENT_ACCEPTANCE_PENDING"69Process outbound Trace Headers70PUT /bulkTransactions/{bulkTransactionId}71Accepted72PUT /bulkTransactions/{bulkTransactionId}73Process inbound Trace Headers74SDKOutboundBulkAcceptQuoteReceived75Accepted76ProcessSDKOutboundBulkAcceptQuote77Update the individual state: AGREEMENT_ACCEPTED / AGREEMENT_REJECTED78Update global state "AGREEMENT_ACCEPTANCE_COMPLETED"79SDKOutboundBulkAcceptQuoteProcessed80SDKOutboundBulkAutoAcceptQuoteRequested81ProcessSDKOutboundBulkAutoAcceptQuote82Check fee limits83Update the individual state: AGREEMENT_ACCEPTED / AGREEMENT_REJECTED84Update global state "AGREEMENT_ACCEPTANCE_COMPLETED"85SDKOutboundBulkAutoAcceptQuoteProcessed86ProcessSDKOutboundBulkTransfersRequest87Update global state "TRANSFERS_PROCESSING"88Update the request89BulkTransfersRequested90Update the batch state: TRANSFERS_PROCESSING91Process outbound Trace Headers92POST /bulkTransfers93Accepted94PUT /bulkTransfers95Process inbound Trace Headers96BulkTransfersCallbackReceived97Accepted98ProcessBulkTransfersCallback99Update the batch state: TRANSFERS_COMPLETED / TRANSFERS_FAILED100Update the individual state: TRANSFERS_SUCCESS / TRANSFERS_FAILED101Update the transfer response102BulkTransfersCallbackProcessed103Check the status of the remaining items in the bulk104Update global state "TRANSFERS_COMPLETED"105SDKOutboundBulkTransfersRequestProcessed106PrepareSDKOutboundBulkResponse107Build response from redis state108SDKOutboundBulkResponsePrepared109Update global state "RESPONSE_PROCESSING"110Process outbound Trace Headers111Send the response as callback112Accepted113SDKOutboundBulkResponseSent114ProcessSDKOutboundBulkResponseSent115Update global state "RESPONSE_SENT"116SDKOutboundBulkResponseSentProcessed117Core ConnectorSDK Backend APISDK Outbound Domain Event HandlerSDK Outbound Command Event HandlerSDK FSPIOP APIMojaloop Switch \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/assets/sequence/requestToPaySDK-R2P-SequenceDiagram.svg b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/requestToPaySDK-R2P-SequenceDiagram.svg new file mode 100644 index 000000000..998a7145b --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/assets/sequence/requestToPaySDK-R2P-SequenceDiagram.svg @@ -0,0 +1,4 @@ + + + +
    Payee
    Core
    Payee...
    POST /transactionRequest
    POST /transactionRequest
    (Add authenticationType)
    (Add authenticationType)
    PUT /transactionRequest
    PUT /transactionRequest
    Payer SDK
    Payer...
    Payee SDK
    Payee...
    POST /transactionRequest
    POST /transactionRequest
    PUT /transactionRequest
    PUT /transactionRequest
    Switch
    Switch
    Payer
    Core
    Payer...
    POST /RequestToPay
    POST /RequestToPay
    (Add authenticationType,
    rename homeTxId to homeR2PTrxId
    )
    (Add authenticationType,...
    POST /transactionRequest
    POST /transactionRequest
    RES: POST /RequestToPay
    RES: POST /RequestToPay
    POST /quotes
    POST /quotes
    POST /quotes
    POST /quotes
    POST /quotesrequest
    POST /quotesrequest
    (Add homeR2PTrxId)
    (Add homeR2PTrxId)
    PUT /quotes
    PUT /quotes
    PUT /quotes
    PUT /quotes
    PUT /RequestToPay
    PUT /RequestToPay
    RES: PUT /RequestToPay
    RES: PUT /RequestToPay
    RES: PUT /requestToPayTransfer
    RES: PUT /requestToPayTransfer
    (Add authResponse)
    (Add authResponse)
    RES: POST /transactionRequest
    RES: POST /transactionRequest
    (Add homeR2PTxId (optional),
    rename transferAmount to 
    transactionRequestState 
    )
    (Add homeR2PTxId (optional),...
    POST /requestToPayTransfer
    POST /requestToPayTransfer
    (Add homeR2PTxId,
    Add authenticationType,
    Rename rTPayTrxId to tReqId)
    (Add homeR2PTxId,...
    GET /authorizations
    GET /authorizations
    (authenticationType hardcoded,
    retriesLeft hardcoded
    )
    (authenticationType hardcoded,...
    Accept payment and terms
    and generate OTP
    Accept pay...
    GET /authorizations
    GET /authorizations
    GET /otp
    GET /otp
    (rename rtpId to
    tRequestId,
    Add homeR2PTrxId,
    Add retriesLeft
    )
    (rename rtpId to...
    PUT /authorizations
    PUT /authorizations
    PUT /authorizations
    PUT /authorizations
    If OTP
    If OTP
    RES: POST /requestToPayTransfer
    RES: POST /requestToPayTransfer
    PUT /requestToPayTransfer
    PUT /requestToPayTransfer
    (accept quote,
    Add retriesLeft)
    (accept quote,...
    PUT /requestToPayTransfer
    PUT /requestToPayTransfer
    (accept quote/auth)
    (accept quote/auth)
    RES: PUT /requestToPayTransfer
    RES: PUT /requestToPayTransfer
    Payer
    Payer
    POST /transfers
    POST /transfers
    POST /transfers
    POST /transfers
    PUT /transfers
    PUT /transfers
    PUT /transfers
    PUT /transfers
    Payer provides OTP
    Payer prov...
    Payer
    Payer
    POST /transfers
    POST /transfers
    (Add transactionRequestId, 
    Add homeR2PTrxId
    )
    (Add transactionRequestId,...
    Validate Payer Details
    Validate P...
    Payer
    Payer
    Calculate fees and set terms.
    Present to Payer to validate.
    Calculate...
    Payer
    Payer
    PoS - Point of Sale device at Merchant
    PoS - Point of Sale devic...
    Payee PoS
    Payee PoS
    Payee Pos
    Payee Pos
    Payee PoS
    Payee PoS
    PUT /parties
    PUT /parties
    GET /parties
    GET /parties
    PUT /Parties
    PUT /Parties
    GET /parties
    GET /parties
    GET /parties
    GET /parties
    PoS displays
    Payment Confirmation
    PoS displa...
    Payer
    Payer
    Payee PoS
    Payee PoS
    Validate RTP
    Validate R...
    Initiate RTP with
    AuthType
    Initiate R...
    Validate OTP
    Validate O...
    Retry on
    OTP Failure
    Retry...
    PUT /requestToPayTransfer
    PUT /requestToPayTransfer
    (reject)
    (reject)
    RES: PUT /requestToPayTransfer
    RES: PUT /requestToPayTransfer
    PUT /transactionRequest
    PUT /transactionRequest
    (rejected state)
    (rejected state)
    PUT /RequestToPay
    PUT /RequestToPay
    (rejected state)
    (rejected state)
    If Rejected
    If Rejected
    PUT /transactionRequest
    PUT /transactionRequest
    (rejected state)
    (rejected state)
    If Accepted
    If Accepted
    Payer Receives
    Payment Confirmation
    Payer Rece...
    Payer
    Payer
    Payer Receives
    Rejection Notification
    Payer Rece...
    Payer
    Payer
    PoS displays
    Rejection Notification
    PoS displa...
    Payer
    Payer
    Payee PoS
    Payee PoS
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/docs/technical/technical/sdk-scheme-adapter/usage/README.md b/docs/technical/technical/sdk-scheme-adapter/usage/README.md new file mode 100644 index 000000000..9d0dfdeda --- /dev/null +++ b/docs/technical/technical/sdk-scheme-adapter/usage/README.md @@ -0,0 +1,44 @@ +# SDK usage tested scenario's overview +A scheme adapter is a service that interfaces between a Mojaloop API compliant switch and a DFSP backend platform that does not natively implement the Mojaloop API. + +The API between the scheme adapter and the DFSP backend is synchronous HTTP while the interface between the scheme adapter and the switch is native Mojaloop API. + +This document provides different ways of setups that a DFSP can test using the scheme adapter. + +# Scenarios +There are number of scenarios those we tested and documented as follows. + +* [[Scheme Adapter + Mock DFSP Backend] -> [Scheme Adapter + Mojaloop Simulator]](./scheme-adapter-to-scheme-adapter/README.md) +* [[Scheme Adapter + Mock DFSP Backend] -> [Local K8S cluster]](./scheme-adapter-and-local-k8s/README.md) +* [[Scheme Adapter + Mojaloop Simulator] -> [Public hosted WSO2 enabled Mojaloop Switch]](./scheme-adapter-and-wso2-api-gateway/README.md) + +## [Scheme Adapter + Mock DFSP Backend] -> [Scheme Adapter + Mojaloop Simulator] + +The scheme adpater can be used in combination with some already implemented mock backends "Mock DFSP Backend" and "Mojaloop Simulator". The below are the links for the repositories. + +https://github.com/mojaloop/sdk-mock-dfsp-backend.git + +https://github.com/mojaloop/mojaloop-simulator.git + +The idea is to combine scheme adapter with mock DFSP backend on oneside and with mojaloop simulator on another side. Consider one side is payer dfsp and another side is payee dfsp. By following this example, you can send and recieve funds from one dfsp to another. + +Please [click here](./scheme-adapter-to-scheme-adapter/README.md) for the documentation. + +![SchemeAdapterToSchemeAdapter](./scheme-adapter-to-scheme-adapter/scheme-adapter-to-scheme-adapter-overview.png) + +## [Scheme Adapter + Mock DFSP Backend] -> [Local K8S cluster] + +Then if we want to include a switch inbetween the DFSPs, we can simulate that environment using a local K8S cluster. Please follow the onboarding documentation of local K8S cluster here (https://mojaloop.io/documentation/deployment-guide/). + +Please [click here](./scheme-adapter-and-local-k8s/README.md) for the documentation. + +![SchemeAdapterAndK8S](./scheme-adapter-and-local-k8s/scheme-adapter-and-local-k8s-overview.png) + +## [Scheme Adapter + Mojaloop Simulator] -> [Public hosted WSO2 enabled Mojaloop Switch] + +If you have access to the WSO2 Mojaloop API, you can test that by the following documentation. In the above two scenarios, we didn't use token authentication and SSL encryption capabilities of scheme adapter. We are going to use those capabilites in this section. + +Please [click here](./scheme-adapter-and-wso2-api-gateway/README.md) for the documentation. + + +![SchemeAdapterAndWSO2APIGateway](./scheme-adapter-and-wso2-api-gateway/scheme-adapter-and-wso2-api-gateway-overview.png) diff --git a/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/README.md b/docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/README.md similarity index 100% rename from mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/README.md rename to docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/README.md diff --git a/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/Mojaloop-Local.postman_environment_modified.json b/docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/Mojaloop-Local.postman_environment_modified.json similarity index 100% rename from mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/Mojaloop-Local.postman_environment_modified.json rename to docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/Mojaloop-Local.postman_environment_modified.json diff --git a/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json b/docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json similarity index 100% rename from mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json rename to docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json diff --git a/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/scheme-adapter-and-local-k8s-overview.png b/docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/scheme-adapter-and-local-k8s-overview.png similarity index 100% rename from mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/scheme-adapter-and-local-k8s-overview.png rename to docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/scheme-adapter-and-local-k8s-overview.png diff --git a/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/README.md b/docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/README.md similarity index 100% rename from mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/README.md rename to docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/README.md diff --git a/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/scheme-adapter-and-wso2-api-gateway-overview.png b/docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/scheme-adapter-and-wso2-api-gateway-overview.png similarity index 100% rename from mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/scheme-adapter-and-wso2-api-gateway-overview.png rename to docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/scheme-adapter-and-wso2-api-gateway-overview.png diff --git a/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/README.md b/docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/README.md similarity index 100% rename from mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/README.md rename to docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/README.md diff --git a/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/scheme-adapter-to-scheme-adapter-overview.png b/docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/scheme-adapter-to-scheme-adapter-overview.png similarity index 100% rename from mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/scheme-adapter-to-scheme-adapter-overview.png rename to docs/technical/technical/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/scheme-adapter-to-scheme-adapter-overview.png diff --git a/docs/technical/technical/security/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.png b/docs/technical/technical/security/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.png new file mode 100644 index 000000000..736a5190c Binary files /dev/null and b/docs/technical/technical/security/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.png differ diff --git a/docs/technical/technical/security/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.puml b/docs/technical/technical/security/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.puml new file mode 100644 index 000000000..a87421d97 --- /dev/null +++ b/docs/technical/technical/security/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.puml @@ -0,0 +1,107 @@ +@startuml dependency-vulnerability-management-process +!theme cerulean + +skinparam ActivityBackgroundColor #f0f0f0 +skinparam ActivityBorderColor #333333 +skinparam ArrowColor #333333 +skinparam backgroundColor white +skinparam ActivityFontColor black +skinparam ActivityFontSize 14 +skinparam noteFontColor black +skinparam ArrowFontColor black +skinparam PartitionFontColor #000000 +skinparam PartitionFontStyle bold +skinparam PartitionBorderColor #333333 +skinparam PartitionBackgroundColor #f8f8f8 + +title Dependency Vulnerability Management Process + +start + +partition "Vulnerability Detection Tools" { + :Identify Vulnerability; + fork + :GitHub Dependabot Alerts; + fork again + :npm run audit:check; + note right: audit-ci.jsonc with allowlist + fork again + :Grype Image Scan; + note right: .grype.yaml with ignore section + end fork +} + +partition "Triage Process" { + :Triage Vulnerability; + :Assess Severity Level; + fork + :Critical: 1-3 days; + note right #FF6666: Immediate attention + fork again + :High: 30 days; + note right #FFCC66: High priority + fork again + :Medium: 60 days; + note right #FFFF66: Medium priority + fork again + :Low: 90 days; + note right #99FF99: Low priority + end fork + :Take action based on severity level\nand fix date targets; +} + +partition "Update Process" { + :Select Single Module to Update; + :Update package.json; + :Run Tests; + if (Tests Pass?) then (Yes) + :Create Pull Request; + else (No) + if (Cannot Fix?) then (Yes) + fork + :Update audit-ci.jsonc; + note right #F9E0FF: For npm issues + fork again + :Update .grype.yaml; + note right #F9E0FF: For container issues + end fork + :Create Pull Request; + else (No) + :Adjust Update; + note right #F9E0FF + Consider Alternative Solutions + Contact Package Maintainer + end note + :Run Tests Again; + endif + endif + :Code Review Process; + if (Review Result) then (Approved) + :Merge PR; + else (Changes Requested) + :Update PR; + endif +} + +partition "CI/CD" { + :CI/CD Pipeline; + :Security Checks; + fork + :audit-ci Check; + fork again + :Grype Scan; + end fork + if (Checks Pass?) then (Yes) + :Release/Publish; + else (No) + :Fix Security Issues; + endif +} + +if (More Vulnerabilities?) then (Yes) + :Return to Select Module; +else (No) + stop +endif + +@enduml \ No newline at end of file diff --git a/docs/technical/technical/security/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.svg b/docs/technical/technical/security/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.svg new file mode 100644 index 000000000..0ef88f1e5 --- /dev/null +++ b/docs/technical/technical/security/assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.svg @@ -0,0 +1,305 @@ + + Dependency Vulnerability Management Process + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dependency Vulnerability Management Process + + + + Vulnerability Detection Tools + + Identify Vulnerability + + + GitHub Dependabot Alerts + + + audit-ci.jsonc with allowlist + + npm run audit:check + + + .grype.yaml with ignore section + + Grype Image Scan + + + + Triage Process + + Triage Vulnerability + + Assess Severity Level + + + + Immediate attention + + Critical: 1-3 days + + + High priority + + High: 30 days + + + Medium priority + + Medium: 60 days + + + Low priority + + Low: 90 days + + + Take action based on severity level + and fix date targets + + + Update Process + + Select Single Module to Update + + Update package.json + + Run Tests + + Tests Pass? + Yes + No + + Create Pull Request + + Cannot Fix? + Yes + No + + + + For npm issues + + Update audit-ci.jsonc + + + For container issues + + Update .grype.yaml + + + Create Pull Request + + + Consider Alternative Solutions + Contact Package Maintainer + + Adjust Update + + Run Tests Again + + + + Code Review Process + + Review Result + Approved + Changes Requested + + Merge PR + + Update PR + + + + CI/CD + + CI/CD Pipeline + + Security Checks + + + audit-ci Check + + Grype Scan + + + Checks Pass? + Yes + No + + Release/Publish + + Fix Security Issues + + + Return to Select Module + + Yes + More Vulnerabilities? + No + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/audit-check-script.png b/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/audit-check-script.png new file mode 100644 index 000000000..551ea6515 Binary files /dev/null and b/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/audit-check-script.png differ diff --git a/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/gh-dependabot-alert.png b/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/gh-dependabot-alert.png new file mode 100644 index 000000000..4c14b2661 Binary files /dev/null and b/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/gh-dependabot-alert.png differ diff --git a/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/gh-dependabot-alerts.png b/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/gh-dependabot-alerts.png new file mode 100644 index 000000000..a77a907b2 Binary files /dev/null and b/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/gh-dependabot-alerts.png differ diff --git a/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/grype-scan-vulnerabilities-ci.png b/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/grype-scan-vulnerabilities-ci.png new file mode 100644 index 000000000..d9d3a289b Binary files /dev/null and b/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/grype-scan-vulnerabilities-ci.png differ diff --git a/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/severity-id-allowed.png b/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/severity-id-allowed.png new file mode 100644 index 000000000..3a35c25b3 Binary files /dev/null and b/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/severity-id-allowed.png differ diff --git a/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/severity-level-allowed.png b/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/severity-level-allowed.png new file mode 100644 index 000000000..2c313578f Binary files /dev/null and b/docs/technical/technical/security/assets/screenshots/vulnerabilityManagement/severity-level-allowed.png differ diff --git a/docs/technical/technical/security/dependency-vulnerability-management.md b/docs/technical/technical/security/dependency-vulnerability-management.md new file mode 100644 index 000000000..66fffbb04 --- /dev/null +++ b/docs/technical/technical/security/dependency-vulnerability-management.md @@ -0,0 +1,613 @@ +# Mojaloop Dependency Vulnerability Management Guide + +This guide outlines the process for managing security vulnerabilities in dependencies of Mojaloop organization GitHub repositories . + +This guide focuses primarily on dependency vulnerabilities. For vulnerabilities discovered in Mojaloop's own code (rather than in dependencies), please email detailed information to security@mojaloop.io and follow the Coordinated Vulnerability Disclosure (CVD) policy. + +The Mojaloop CVD policy provides a structured process for reporting, validating, and remediating security vulnerabilities in Mojaloop code. It ensures responsible disclosure that balances the need to protect users while providing transparent information about security issues. The policy includes clear timelines for response, validation, remediation, and public disclosure, allowing the Mojaloop Security team to address vulnerabilities in a coordinated manner that minimizes risk to adopters and users of the software. + +## Table of Contents + +- [Executive Summary](#executive-summary) +- [Overview](#overview) +- [Quickstart Guide](#quickstart-guide) +- [Detailed Guide](#detailed-guide) + - [1. Understanding what is a Vulnerability and where to find them](#1-understanding-what-is-a-vulnerability-and-where-to-find-them) + - [2. ProcessFlow for Handling Dependency Vulnerability Updates](#2-processflow-for-handling-dependency-vulnerability-updates) + - [3. Practical Guide to package.json Updates](#3-practical-guide-to-packagejson-updates) + - [4. Code Review Best Practices for Security PRs](#4-code-review-best-practices-for-security-prs) + - [5. Developer Onboarding and Dependency Vulnerability Management Education](#5-developer-onboarding-and-dependency-vulnerability-management-education) + - [6. Continuous Improvement](#6-continuous-improvement) + - [7. Conclusion](#7-conclusion) +- [Tools and Resources](#tools-and-resources) +- [Related Documentation](#related-documentation) + +## Executive Summary + +This guide provides a structured approach for handling security vulnerabilities in dependencies of Mojaloop repositories. It addresses the current need for a standardized process that can help developers understand vulnerability reports (namely GitHub Dependabot alerts, results on npx audit and grype scans), implement proper fixes, and prioritize security updates across the codebase. + +## Overview + +Mojaloop's dependency vulnerability management process is designed to: +- Identify security vulnerabilities in dependencies and code +- Assess the impact and severity of vulnerabilities +- Prioritize remediation efforts +- Track and verify fixes +- Maintain security compliance + +## Quickstart Guide + +This quickstart provides essential steps for managing vulnerabilities in Mojaloop repositories without background information. For detailed explanations, see the comprehensive sections that follow. + +### 1. Detect Vulnerabilities + +- Run `npm run audit:check` to identify npm package vulnerabilities +- Check GitHub Dependabot alerts in the Security tab of your repository(if you have access to Security tab) +- Use Grype to scan container images, triggered automatically if using Mojaloop orb for CircleCI and report can be reviewed in CircleCI (if you have access to CircleCI) + +### 2. Assess and Prioritize + +- **Critical**: Fix within 1-3 business days +- **High**: Fix within 30 days +- **Medium**: Fix within 60 days +- **Low**: Fix within 90 days + +### 3. Fix Process + +1. Take action based on severity level and fix date targets +2. Select a single module to update +3. Update the vulnerable dependency in package.json +4. Run tests as intructed in repo's README to verify functionality +5. If tests pass, create a pull request +6. If tests fail and you cannot fix: + - Add to allowlist in audit-ci.jsonc (for npm packages) + - Add to ignore section in .grype.yaml (for container vulnerabilities) +7. Include complete fix vulnerability details in the PR + +### 4. PR Template + +```markdown +## Security Fix: [GHSA-ID or CVE-ID] + +### Vulnerability Details +- Severity: [Critical/High/Medium/Low] +- Affected Package: [package-name] +- Vulnerable Versions: [version range] +- Fixed Version: [version number] + +### Description +Brief description of the vulnerability and its potential impact. + +### Changes +- Updated [package-name] from [old-version] to [new-version] + +### Testing +- [X] Unit tests pass +- [X] Integration tests pass +- [X] Manual testing performed +``` + +### 5. Review and Merge + +- Ensure version update properly fixes the vulnerability +- Verify minimum changes to package.json +- Confirm all tests pass +- Check for unintended side effects +- Merge after approval + +## Detailed Guide + +The following sections provide comprehensive explanations, background information, and detailed procedures for vulnerability management in Mojaloop repositories. + +## 1. Understanding what is a Vulnerability and where to find them + +A vulnerability is identified by a Common Vulnerabilities and Exposures (CVE) id, which is a standardized identifier for publicly known security vulnerabilities. + +### Vulnerability Identifier Systems: CVE and GHSA + +#### CVE (Common Vulnerabilities and Exposures) +CVEs are standardized identifiers for publicly known cybersecurity vulnerabilities, maintained by the MITRE Corporation and funded by the U.S. Department of Homeland Security. Each CVE has a unique identifier in the format CVE-YYYY-NNNNN (year-number). + +#### GHSA (GitHub Security Advisory) +GHSA identifiers are GitHub-specific vulnerability identifiers used in the GitHub Advisory Database. They follow the format GHSA-XXXX-YYYY-ZZZZ, where X, Y, and Z are alphanumeric characters. + +#### Relationship Between CVE and GHSA +- A GHSA may reference one or more CVEs, as GitHub may consolidate multiple related vulnerabilities +- Not all GHSAs have corresponding CVEs, especially for newly discovered vulnerabilities +- GitHub often assigns a GHSA identifier before a CVE is assigned by MITRE +- Both systems describe the same vulnerabilities but may contain slightly different information: + - CVEs are the industry standard used across security tools and databases + - GHSAs often contain more ecosystem-specific information and may include remediation advice for GitHub users + +#### How Identifiers Appear Across Tools + +- **GitHub Dependabot Alerts**: Display both the GHSA and CVE identifiers (when a CVE is assigned) + + ![GitHub Dependabot Alerts List](./assets/screenshots/vulnerabilityManagement/gh-dependabot-alerts.png) + *Dependabot alerts view at GitHub Security* + + ![GitHub Dependabot Alert Details](./assets/screenshots/vulnerabilityManagement/gh-dependabot-alert.png) + *Detailed dependabot alert* + +- **npm run audit:check**: Results show GHSA identifiers for vulnerabilities + + ![Audit Check Script](./assets/screenshots/vulnerabilityManagement/audit-check-script.png) + *Execution of npm run audit:check script* + + ![Severity Level Allowed](./assets/screenshots/vulnerabilityManagement/severity-level-allowed.png) + *Increase vulnerability passing level to low, previous was moderate* + + ![Severity ID Allowed](./assets/screenshots/vulnerabilityManagement/severity-id-allowed.png) + *Allowlist vulnerability ID provided to ignore when running npm run audit:check* + +- **Grype Scan**: Displays vulnerabilities with GHSA identifiers + + ![Grype Scan Vulnerabilities](./assets/screenshots/vulnerabilityManagement/grype-scan-vulnerabilities-ci.png) + *Grype Scan vulnerabilities detected in CircleCI* + +#### Accessing Detailed Vulnerability Information + +GHSA identifiers can be used as direct URLs to access detailed vulnerability information. Simply append the GHSA ID to the GitHub security advisory base URL: + +``` +https://github.com/[owner]/[repo]/security/advisories/[GHSA-ID] +``` + +or use the generic GitHub Advisory Database URL: + +``` +https://github.com/advisories/[GHSA-ID] +``` + +For example, a vulnerability in the multer package can be accessed at: +https://github.com/expressjs/multer/security/advisories/GHSA-44fp-w29j-9vj5 + +Similarly, when a CVE has been assigned to a vulnerability, you can access the official CVE record using the CVE ID in the following URL format: + +``` +https://www.cve.org/CVERecord?id=[CVE-ID] +``` + +For the same multer vulnerability example, corresponding CVE information can be found at: +https://www.cve.org/CVERecord?id=CVE-2025-47935 + +#### Vulnerability Information Sources + +**GitHub Security Advisory pages include:** +- Detailed vulnerability descriptions +- Affected and patched versions +- CVE IDs (when assigned) +- Severity scores (typically CVSS) +- Remediation guidance +- References to related issues and commits + +**CVE Record pages include:** +- Official vulnerability descriptions +- References to related resources +- Affected products and versions +- Standardized severity information +- Attribution information + +When investigating vulnerabilities, it's often valuable to check both sources as they may contain complementary information. + +When working with Mojaloop vulnerabilities, you may encounter both types of identifiers: +- CVEs in general security bulletins and tools like npm audit +- GHSAs in GitHub Dependabot alerts and in .grype.yaml configuration files + +GitHub Dependabot alerts section in a GitHub repo can be found by navigating to the Security tab on the top menu and then under Vulnerability alerts, click on Dependabot. Here you will find a list of alerts. Finally, click one of the alerts to review details. + +Note: Please notice that your GitHub account must have granted permission to access Security tab. Also, Dependabot must be enabled for the given repo. Please contact Mojaloop GitHub Admin if need help with these. + +### 1.1 Vulnerability Severity Levels + +Vulnerabilities are classified using the following four severity levels: + +- **Critical**: Vulnerabilities that require immediate attention. These typically include remote code execution, authentication bypasses, or other severe flaws that could lead to a complete system compromise. +- **High**: Serious vulnerabilities that should be addressed before the end of a Program Increment (PI), with a target of 30 days. These may include injection vulnerabilities, insecure deserialization, or cross-site scripting issues that could lead to significant data exposure. +- **Medium**: Moderate risk vulnerabilities that should be addressed within the current PI if possible, with a target of 60 days. These may include information disclosure, cross-site request forgery, or other vulnerabilities with mitigating factors. +- **Low**: Minor issues that pose minimal risk. These should still be addressed but at a lower priority, with a target of 90 days. + +**Note on CVE IDs**: When a vulnerability report does not include a CVE, it may mean: +1. The vulnerability is newly discovered and hasn't yet been assigned a CVE +2. The issue is specifically related to the way code is implemented in your project +3. The vulnerability is in a development dependency that doesn't affect production environments + +A missing CVE doesn't mean the vulnerability isn't important - it should still be assessed based on its severity and potential impact. + +### 1.2 Understanding Package/Dependency Version Ranges in Dependabot alerts + +Version ranges in Dependabot alerts define which versions of a package/dependency are affected. Please noticed how in a Dependabot alert the what is refer to as package corresponds to a dependency in the package.json of the NodeJS project. Dependencies and there pacakges follwong Semantic Versioning. Understanding these notations is crucial: + +- **`<=M.m.p`**: All versions less than or equal to the specified version are vulnerable. + - Example: `<=1.2.3` means all versions up to and including 1.2.3 are vulnerable. + +- **Range using `>M.m.p 1.0.0 <1.2.0` means all versions after 1.0.0 and before 1.2.0 are vulnerable. + +Other common version specifiers you'll encounter include: + +- **Caret (`^`)**: Allows changes that don't modify the leftmost non-zero digit. + - Example: `^1.2.3` allows updates to any version from 1.2.3 up to but not including 2.0.0. + - For `^0.2.3`, allows updates to any version from 0.2.3 up to but not including 0.3.0. + - For `^0.0.3`, allows updates to any version from 0.0.3 up to but not including 0.0.4. + +- **Tilde (`~`)**: Allows patch-level changes if a minor version is specified. + - Example: `~1.2.3` allows updates to any version from 1.2.3 up to but not including 1.3.0. + +## Vulnerability Sources + +Vulnerabilities can be introduced through: +1. Direct dependencies +2. Transitive dependencies +3. Runtime environments +4. Infrastructure components +5. Custom code + +## Detection and Assessment + +### Vulnerability Detection Tools + +Mojaloop employs multiple tools to detect vulnerabilities: + +1. **GitHub Dependabot Alerts** + - Automatic detection of vulnerabilities in GitHub repositories + - Provides detailed information about affected versions and available fixes + - Available in the Security tab of GitHub repositories + - **Assets Scanned**: NodeJS application dependencies declared in package.json files within GitHub repositories + +2. **npm audit via audit-ci** + - Run locally using `npm run audit:check` + - Configurable via `audit-ci.jsonc` with allowlist for known issues + - Integrated in CI/CD pipelines to prevent vulnerable code from being deployed + - **Assets Scanned**: Direct and transitive NodeJS dependencies in package.json and package-lock.json files + +3. **Grype Image Scanning** + - Container image vulnerability scanner + - Configurable through `.grype.yaml` with an ignore section for known issues + - Scans for vulnerabilities in container images and dependencies + - **Assets Scanned**: Docker container images, including base images, installed OS packages, and application dependencies + - NOTE: Please notice that grype also scans Docker image if the given repo produces one and vulnerabilities can be found in images, if so, please be aware that an update to base image at Mojaloop CircleCI orb is needed. + +### Configuration Files for Vulnerability Management + +1. **audit-ci.jsonc** + - Contains an allowlist of vulnerabilities that can be temporarily ignored + - Used when a vulnerability cannot be fixed immediately + - Uses GHSA IDs to identify vulnerabilities to ignore + - Should include justification and tracking information for each allowed vulnerability + - Example format: + ```json + { + "allowlist": [ + { + "id": "GHSA-XXXX-YYYY-ZZZZ", + "reason": "No patch available yet, workaround implemented, tracking in issue #123" + } + ] + } + ``` + +2. **.grype.yaml** + - Configuration file for Grype container scanning + - Contains ignore section with GHSA vulnerability IDs + - Uses GHSA IDs to specify which vulnerabilities should be ignored + - Used for container-specific vulnerabilities that cannot be immediately addressed + - Example format: + ```yaml + ignore: + - vulnerability: GHSA-XXXX-YYYY-ZZZZ + package: + name: package-name + version: 1.2.3 + until: "2023-12-31" + reason: "Investigating alternative solutions, not exploitable in our context" + ``` + +### Automated Scanning +- Regular dependency scanning using npm audit +- Container image scanning +- Infrastructure vulnerability scanning +- Static code analysis + +### Manual Review +- Security code reviews +- Penetration testing +- Threat modeling +- Compliance audits + +## 2. ProcessFlow for Handling Dependency Vulnerability Updates + +The following diagram illustrates the dependency vulnerability management process for Mojaloop repositories: + +![Dependency Vulnerability Management Process](./assets/diagrams/vulnerabilityManagement/dependency-vulnerability-management-process.png) + +### 2.1 Standard Process + +1. **Triage** + - Regularly review GitHub Dependabot alerts. + - Classify/Review based on severity (Critical, High, Medium, Low). + - Track vulnerabilities in the existing private GitHub project repository dedicated to security vulnerabilities. Access to this repository is restricted and granted only on a need-to-know basis. Contact the Mojaloop Security Committee if you need access. + +2. **Update Process** + - **Step 1**: Choose a single module(a mojaloop service or library) with a reported vulnerability. + - **Step 2**: Make the required dependency update in the package.json. + - **Step 3**: Perform smoke tests to ensure functionality is not broken. Please follow details on this on the given repo README file. + - **Step 4**: If tests pass, proceed create a pull request. + - **Step 5**: Create Pull Requests for each module with the single security patch. + - **Step 6**: Include detailed information in the PR about the vulnerability being fixed, including its CVE ID and the dependencies being updated in the package.json along with any details as needed. + +3. **Important Principles** + - **Isolation**: Handle one vulnerability fix at a time. + - **No Bundling**: Don't bundle multiple unrelated security patches together. + - **Clean History**: Rebase commits for a clean history. + - **Thorough Testing**: Always run tests after making changes as instructed in README file for the given repo. + +### 2.2 Prioritization Framework + +- **Critical Severity**: Immediate attention required; aim to fix within 1-3 business days. +- **High Severity**: Fix before the end of the current Program Increment (PI), target 30 days. +- **Medium Severity**: Fix before the end of the current PI if possible, target 60 days. +- **Low Severity**: Address during regular maintenance cycles, target 90 days. + +### 2.3 Vulnerability Assessment Criteria + +Mojaloop follows OpenSSF and OWASP practices when assessing vulnerabilities. The ultimate decisions regarding vulnerability management are taken by the Mojaloop Security Committee. + +When determining whether to fix or allowlist/ignore a vulnerability: +- When a vulnerability fix exists, it should be applied. +- A vulnerability should only be allowlisted or ignored if the fix breaks existing functionality, which must be confirmed by either automated tests (as descrcribed on the given repo README) failing or through manual testing. +- For zero-day vulnerabilities, the Mojaloop Security Committee will provide guidance on handling procedures as necessary on a case by case basis. + +## 3. Practical Guide to package.json Updates + +### 3.1 Recommended Tools + +- **npm run audit:check**: To scan for vulnerabilities the audit:check script should help you identify vulnerabilities and should match those listed in GitHub Dependabot + ```bash + npm run audit:check + ``` + +- **npm run dep:check & npm run dep:update**: To help manage dependency updates, can be used, be mindful of making changes in bulk as it will be harder to track what breaks functionality. NOTE: Updating dependencies needs its own management guide. + +- **.ncurc.yaml**: To declare which dependencies should reject upgrade as it might break functionality. Used as last resource. + + +### 3.2 Step-by-Step Process + +1. **Identify the vulnerable package**: + ```bash + npm audit + ``` + +2. **Update a single package**: + ```bash + # For direct dependencies + npm update [package-name] + + # For fixing specific vulnerabilities + npm run audi:fix + + # For more complex cases with breaking changes + npm audit fix --force # Use with caution + ``` + +3. **Test the update**: + ```bash + npm test + # Run other project-specific tests + ``` + +4. **Commit changes and create a PR**: + ```bash + git checkout -b fix/security-vulnerability-[CVE-ID] + git add package.json package-lock.json + git commit -m "fix: update [package] to fix [CVE-ID]" + git push origin fix/security-vulnerability-[CVE-ID] + ``` + +### 3.3 Handling Challenging Cases + +When `npm run audit:fix` doesn't resolve the issue: + +1. **For dependencies without patches available**: + - Check if the vulnerability is actually exploitable in your specific use case. + - Consider alternative packages. + - Contact the package maintainer to report the issue. + - Document the vulnerability with a detailed explanation of risk assessment. + +2. **When fixes break functionality**: + - If tests fail after dependency updates and no immediate solution is available: + - For npm package vulnerabilities: Add to the allowlist in `audit-ci.jsonc` + - For container vulnerabilities: Add to the ignore section in `.grype.yaml` + - Document the reasons for allowlisting/ignoring and include: + - Issue tracking number + - Detailed explanation of the risk + - Target date for resolution + - Any mitigating controls implemented + +3. **CI/CD Integration**: + - Security checks are integrated into CI/CD pipelines + - Critical vulnerabilities will fail the pipeline unless properly allowlisted/ignored + - All allowlisted/ignored vulnerabilities should be regularly reviewed + - Regular scanning should be performed to detect new vulnerabilities + +### 3.4 Container Vulnerability Management + +When working with Docker containers: + +1. **Grype Configuration**: + - Grype is used for scanning container images for vulnerabilities + - For detailed guidance on configuring Grype, use Mojaloop CircleCI Orb and refer to the [Mojaloop CI Config Orb documentation](https://github.com/mojaloop/ci-config-orb-build?tab=readme-ov-file#vulnerability-image-scan-configuration) + +2. **Base Image Security**: + - Mojaloop services typically use Node.js Alpine images + - The current base image used can be found at: [node:22.15.1-alpine3.21](https://hub.docker.com/layers/library/node/22.15.1-alpine3.21/images/sha256-d1068d8b737ffed2b8e9d0e9313177a2e2786c36780c5467ac818232e603ccd0) + - This page lists any vulnerabilities present in the base image, and the grype image scan also detect any vulnerabilities. + +## Update Strategy + +When addressing vulnerabilities: +1. Follow the repository update sequence as outlined in the [Mojaloop Repository Update Guide](./mojaloop-repository-update-guide.md) +2. Prioritize critical and high-severity vulnerabilities +3. Consider the impact on dependent services +4. Test thoroughly in non-production environments +5. Plan for coordinated updates across affected services + +## 4. Code Review Best Practices for Security PRs + +1. **Focused PRs**: PRs should address a single vulnerability. + +2. **Required Information in PRs**: + - CVE ID or vulnerability identifier + - Severity level + - Description of the vulnerability + - Description of the fix + - Testing performed + - Potential impact assessment + +3. **Review Checklist**: + - Verify the version update actually fixes the vulnerability + - Check for minimum changes to package.json + - Ensure tests still pass + - Verify smoke tests were performed per README and leverage test code harness + - Check for unintended side effects + +4. **Example PR Description Template**: + ```markdown + ## Security Fix: [CVE-ID] + + ### Vulnerability Details + - Severity: [Critical/High/Medium/Low] + - Affected Package: [package-name] + - Vulnerable Versions: [version range] + - Fixed Version: [version number] + + ### Description + Brief description of the vulnerability and its potential impact. + + ### Changes + - Updated [package-name] from [old-version] to [new-version] + + ### Testing + - [X] Unit tests pass + - [X] Integration tests pass + - [X] Manual testing performed + - [X] Leverage test code harness in developers laptop + - [X] CI/CD test code harness and/or Golden Path tests + + ### Additional Notes + Any other relevant information. + ``` + +## Reporting and Communication + +- Centralize vulnerability tracking and control access +- Document all identified issues +- Track remediation status +- Communicate updates to stakeholders +- Follow responsible disclosure practices + +## 5. Developer Onboarding and Dependency Vulnerability Management Education + +To use vulnerability management as an entry point for new Mojaloop developers: + +### 5.1 Educational Resources + +- Create a dedicated section in documentation about vulnerability management +- Include practical examples and walkthroughs +- Provide links to external resources about Node.js security + +### 5.2 Mentoring Process + +1. **Assign Simple Vulnerabilities**: Start new developers with low-priority vulnerability fixes. +2. **Paired Reviews**: Have experienced developers review PRs from newcomers. +3. **Progressive Responsibility**: Gradually assign more complex security issues. + +### 5.3 Documentation Updates + +- Maintain a knowledge base of common vulnerability patterns in the codebase +- Document lessons learned from previous vulnerability fixes +- Update this dependency vulnerability management guide as processes evolve + +### 5.4 Security in Daily Development + +During the developer onboarding process, this dependency vulnerability management document will be shared with all developers and adherence will be enforced through code reviews during PRs. Several open source security scanning tools for IDE integration are currently under investigation to further improve developer workflow. + +## Best Practices + +1. **Prevention** + - Regular dependency updates + - Security-focused development practices + - Automated security testing + - Secure coding guidelines + +2. **Response** + - Clear escalation paths + - Defined response timelines + - Regular security reviews + - Continuous monitoring + +3. **Documentation** + - Vulnerability tracking + - Remediation procedures + - Security incident reports + - Lessons learned + +## 6. Continuous Improvement + +### 6.1 Regular Security Reviews + +- Conduct weekly reviews of new vulnerability reports +- Track metrics on time-to-fix by severity level +- Compare performance against industry standards + +### 6.2 Automation Opportunities + +- Explore adoption of open source DefectDojo to centralize and automate vulnerability lifecycle management + - [DefectDojo Community](https://defectdojo.com/community) + - [DefectDojo GitHub Repository](https://github.com/DefectDojo/django-DefectDojo) + - [OWASP DefectDojo Project](https://owasp.org/www-project-defectdojo/) + - [DefectDojo Documentation](https://docs.defectdojo.com/en/about_defectdojo/about_docs/) +- Implement pre-commit hooks for dependency checking +- Set up scheduled jobs for regular security audits + +### 6.3 Knowledge Sharing + +- Create and maintain documentation and training on vulnerability management +- Create walkthrough videos for common vulnerability fixes +- Establish a security champions program within the community + +## 7. Conclusion + +By implementing this structured approach to dependency vulnerability management, the Mojaloop community can ensure consistent, timely, and effective responses to security issues. This process not only improves the security posture of the codebase but also provides an excellent opportunity to onboard new developers and build security awareness throughout the community. + +Dependency vulnerability management is not just about fixing issues, it's about building a security mindset. + +## Tools and Resources + +- [What is a CVE (Common Vulnerabilities and Exposures)?](https://www.ibm.com/think/topics/cve) +- [Mojaloop Documentation](https://docs.mojaloop.io/) +- [Node.js Security Best Practices](https://nodejs.org/en/learn/getting-started/security-best-practices) +- [npm Audit Documentation](https://docs.npmjs.com/cli/v10/commands/npm-audit) +- [Semantic Versioning Specification](https://semver.org/) +- [npm Semver Calculator](https://semver.npmjs.com/) +- [GitHub Security Features](https://docs.github.com/en/code-security) +- [GitHub Dependabot quickstart guide](https://docs.github.com/en/code-security/getting-started/dependabot-quickstart-guide) +- [Mojaloop CI Config - Vulnerability Image Scan Configuration](https://github.com/mojaloop/ci-config-orb-build?tab=readme-ov-file#vulnerability-image-scan-configuration) +- [DefectDojo Community](https://defectdojo.com/community) +- [DefectDojo GitHub Repository](https://github.com/DefectDojo/django-DefectDojo) +- [OWASP DefectDojo Project](https://owasp.org/www-project-defectdojo/) +- [DefectDojo Documentation](https://docs.defectdojo.com/en/about_defectdojo/about_docs/) +- npm audit +- GitHub Security Advisories +- Container scanning tools +- Static analysis tools +- Security monitoring systems + +## Related Documentation + +- [Upgrade Strategy Guide](./upgrade-strategy-guide.md) +- [Mojaloop Repository Update Guide](./mojaloop-repository-update-guide.md) +- [Deployment Troubleshooting](./deployment-troubleshooting.md) +- [Mojaloop Coordinated Vulnerability Disclosure Policy](https://docs.mojaloop.io/community/contributing/cvd.html) + \ No newline at end of file diff --git a/docs/technical/technical/security/security-overview.md b/docs/technical/technical/security/security-overview.md new file mode 100644 index 000000000..9971c0d3a --- /dev/null +++ b/docs/technical/technical/security/security-overview.md @@ -0,0 +1,179 @@ + +

    Mojaloop Vulnerability Management Process

    + +Contents: +1. [Introduction](#1-introduction) +2. [Security committee](#2-security-committee) +3. [Handling a possible vulnerability](#3-handling-a-possible-vulnerability) +4. [Mojaloop Vulnerability Management Processes in Place](#4-mojaloop-vulnerability-management-processes-in-place) +5. [Scope](#5-scope) + +

    1. Introduction

    + +This document outlines the Mojaloop Vulnerability Management Process, providing guidelines for the Mojaloop community on identifying, reporting, assessing, and addressing security vulnerabilities within Mojaloop software. By adhering to recognized security standards, such as ISO 27001, Mojaloop ensures a consistent approach to maintaining security and resilience. + +This process is based on Mojaloop's established processes, ensuring a well-defined scope and guidelines that adopters of the software can rely on. It emphasizes responsible handling of vulnerabilities until verified fixes are available and properly communicated. + +A structured, transparent, and effective vulnerability management process is essential for maintaining trust and safeguarding the Mojaloop ecosystem. + +

    2. Security Committee

    + +Mojaloop's vulnerability management process is supported by a designated "Security Committee," a core group responsible for coordinating all aspects of vulnerability management. This committee oversees the process, including: + +1. Reviewing and validating vulnerability reports. +2. Deciding on the acceptance or rejection of reported vulnerabilities. +3. Defining appropriate fixes and planning announcements. +4. Coordinating releases that include security patches. + +The Security Committee is composed of core contributors and community leaders who ensure the efficient and secure handling of vulnerabilities within Mojaloop. Its structure and responsibilities are designed to maintain the security and integrity of the Mojaloop ecosystem. + +

    3. Handling a Possible Vulnerability

    + +Mojaloop vulnerability disclosure (CVD) policy: [https://docs.mojaloop.io/community/contributing/cvd.html](https://docs.mojaloop.io/community/contributing/cvd.html) + +The default process for managing a possible security vulnerability in Mojaloop is outlined in the above link. Projects that require a different process must document it clearly and publicly. + +The process for general third-party dependencies and other open source modules is outlined in the [dependency vulnerability management](dependency-vulnerability-management.md) guide. + +

    Security for Mojaloop Community Members

    + +Mojaloop community members and member organizations play a vital role in the vulnerability management process, particularly in handling potential vulnerabilities according to defined procedures. The following guidance outlines the expected steps: + +* Avoid entering details of security vulnerabilities in public bug trackers, unless access is strictly limited. +* Security communications should be limited to private channels designated for this purpose. These channels are not notification systems for the general public. + +

    Work in Private

    + +Information about a vulnerability should not be made public until a formal announcement is issued at the end of the process. This means: + +* **Do not create public issue tracker tickets (e.g. GitHub/Zenhub) to track the issue**, as this would make it public. +* **Messages associated with code commits should not reference the security nature of the commit.** +* **Discussions regarding the vulnerability, potential fixes, and announcements should occur on private channels**, such as a project-specific security mailing list or a private channel for maintainers. +* Work with Mojaloop security team (security at mojaloop dot io) to follow the CVD process: https://docs.mojaloop.io/community/contributing/cvd.html + +

    Report

    + +The person discovering the issue (the reporter) should report the vulnerability by completing the report and emailing it to: **[security@mojaloop.io](mailto:security@mojaloop.io)** . Report templates can be follow the bug template here: https://github.com/mojaloop/project/issues . + +List of issues that are deemed relevant: +1. Security issues / vulnerabilities in Mojaloop core services (application codebase) +2. Security issues / vulnerabilities in Mojaloop supporting services +3. Wide-spread or day-zero issues in latest versions of critical dependencies Mojaloop's core and supporting services use (such as nodejs, kafka, mysql) + +List of issues that are not deemed critical or of low priority and responses may be delayed: + +1. Vulnerabilities regarding [mojaloop.io](mojaloop.io) website +2. Vulnerabilities regarding [docs.mojaloop.io](docs.mojaloop.io) website + +

    Acknowledge

    + +The Mojaloop security team should send an email to the original reporter to acknowledge receipt of the report. This acknowledgment should ideally include a copy to the relevant private security mailing list. + +

    Investigate and Respond

    + +The team investigates the report and either rejects or accepts it. + +1. Information may be shared with domain experts privately, provided they understand it is not for public disclosure. +2. If rejected, the team explains the decision to the reporter, with a copy to the relevant security mailing list. +3. If accepted, the team notifies the reporter that the report is being addressed. + +

    Resolve

    + +* The team agrees on a fix, typically on a private list. +* Details of the vulnerability and the fix should be documented to generate draft announcements. +* The reporter may be provided with a copy of the fix and the draft announcement for comment. +* The fix is committed without any reference in the commit message that it relates to a security vulnerability. +* A release that includes the fix is created. More details are included in the Mojaloop CVD policy. + +

    Announce

    + +* After the release, the vulnerability and fix are publicly announced. +* The announcement should be sent to relevant destinations, including the vulnerability reporter, project security lists, and possibly public security lists. + +

    Complete

    + +The project's public security pages should be updated with information about the vulnerability, ensuring transparency for users. + +

    4. Mojaloop Vulnerability Management Processes in Place

    + +Mojaloop has established a series of robust processes and tools to manage vulnerabilities throughout the software development lifecycle, ensuring alignment with industry best practices, including ISO 27001 standards for vulnerability identification and mitigation. + +

    Vulnerability Management

    + +Continuous monitoring of open-source components for vulnerabilities is integrated into the CI/CD pipeline. This process is automated to assess each release, commit, and pull request, leveraging Node Package Manager (NPM) for dependency vulnerability assessments. + +

    Static Application Security Testing (SAST)

    + +Mojaloop uses multiple tools for SAST, providing detailed insights into code-level vulnerabilities by leveraging public vulnerability databases, including: + +1. **GitHub Security Tools:** Including Dependabot for dependency scanning (relying on GitHub’s Advisory Database), CodeQL for code analysis, and Secret Scanning to prevent the inclusion of sensitive information. +2. **SonarCloud:** Analyzes every commit, pull request, and release for code quality and security issues, utilizing vulnerability data from public databases such as CVE (Common Vulnerabilities and Exposures). + +

    Software Bill of Materials (SBOM) and Dependency Management

    + +An SBOM tool is used to generate an inventory of third-party dependencies, allowing for: + +1. Identification of vulnerabilities and license compliance issues. +2. Regular reporting for regulatory and security assessments. +3. Ongoing monitoring of library versions across all repositories. +4. Ensuring well maintained and managed packages / dependencies are used and outdated ones are managed accordingly. + +Here's more information about SBOM in Mojaloop: https://github.com/mojaloop/ml-depcheck-utility?tab=readme-ov-file#sbom-generation-tool-for-mojaloop-repositories + +

    Container Security

    + +Container images are scanned for vulnerabilities using Grype before release. Grype is configured following best practices and stricter configurations are recommended for adopters. Grype configuration from the CI Orb Mojaloop uses: https://github.com/mojaloop/ci-config-orb-build?tab=readme-ov-file#vulnerability-image-scan-configuration . + +

    License Compliance

    + +An automated license scanner ensures that only components with compatible licenses are used. Compliance checks are integrated into the CI/CD processes, blocking non-compliant code from being merged or deployed. + +

    Provenance of Images

    + +Following Mojaloop Release (v17.1.0), Mojaloop's helm charts are signed at publishing and can be verified at install / deploy time (This feature has native helm support in helm), to ensure provenance of artefacts related to charts. In the future this can be extended to other artefacts such as images. + +

    Mojaloop CI/CD Security Process

    + +Mojaloop employs a CI/CD pipeline that automatically integrates security checks throughout the software development process. This ensures consistent security application without manual oversight. Branch protection rules enforce continuous checks on every commit, pull request, and release. + +CI/CD Security Integration: + +1. **Container Security: **… +2. **License Compliance:** … +3. **Dependency Vulnerability Scanning:** … + +All critical vulnerabilities are logged, and the CI/CD pipeline will block publishing images or packages until these issues are resolved. These automated security measures in the CI/CD pipeline guarantee that code is continuously tested, secure, and compliant, maintaining high security standards across the development process. + +

    Coordinated Vulnerability Disclosure (CVD)

    + +Mojaloop operates a CVD process, ensuring responsible parties have adequate time to address and remedy vulnerabilities before public disclosure. + +Mojaloop vulnerability disclosure (CVD) policy: [https://docs.mojaloop.io/community/contributing/cvd.html](https://docs.mojaloop.io/community/contributing/cvd.html) + +

    Reporting and Compliance

    + +Comprehensive reports are generated after each scan, detailing outcomes, remediation actions, and their effectiveness. + +All reports are stored for auditing and compliance, ensuring transparency and accountability. + +Report from license scanning at helm level is provided with Mojaloop release notes (also confirms that license scanning step has passed and only includes allowed licenses). The license summary file is attached to the release notes (present at the bottom): [https://github.com/mojaloop/helm/releases/tag/v17.0.0](https://github.com/mojaloop/helm/releases/tag/v17.0.0) provides an example. + +Image scanning reports are present for review in the CI tool (circleCI) to record either failure or pass result (but the workflow moves forward only if this step passes). For example / reference, a sample Grype scanning result here: [https://app.circleci.com/pipelines/github/mojaloop/account-lookup-service/2165/workflows/d420ef53-85a7-46d3-af1e-1527baf3a207/jobs/16509/artifacts](https://app.circleci.com/pipelines/github/mojaloop/account-lookup-service/2165/workflows/d420ef53-85a7-46d3-af1e-1527baf3a207/jobs/16509/artifacts) (though this might go out-of-date with time, it is given as an example) + +

    5. Scope

    + +The Mojaloop vulnerability management process applies to all components that are part of the Mojaloop Helm release. + +This includes: + +1. All core components and services are explicitly defined in the Mojaloop Helm charts. +2. Dependencies included within the Mojaloop Helm release, which are automatically scanned as part of the vulnerability management process. + +Exclusions: + +1. Repositories that are not part of the Mojaloop core release are considered non-production and are excluded from the vulnerability management process. +2. External components required for a typical Mojaloop deployment (e.g., MySQL, Redis, MongoDB, Kafka) are not maintained by the Mojaloop Foundation and are excluded from this vulnerability management process meant for Mojaloop's application codebase, though they are part of the general vulnerability management (as third-party OSS dependencies). + +This approach ensures that the Mojaloop core components are consistently secured, while also clarifying the boundary of responsibility regarding external dependencies and providing guidance regarding other (or third-party) OSS packages, dependencies and tools. + +

    diff --git a/docs/technical/technical/transaction-requests-service/README.md b/docs/technical/technical/transaction-requests-service/README.md new file mode 100644 index 000000000..91e0efc1a --- /dev/null +++ b/docs/technical/technical/transaction-requests-service/README.md @@ -0,0 +1,9 @@ +# Transaction Requests Service + +## Sequence Diagram + +![](./assets/diagrams/sequence/trx-service-overview-spec.svg) + + +* The transaction-requests-service is a mojaloop core service that enables Payee initiated use cases such as "Merchant Request to Pay". +* This is a pass through service which also includes Authorizations. diff --git a/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.plantuml b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.plantuml new file mode 100644 index 000000000..0d4005e68 --- /dev/null +++ b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.plantuml @@ -0,0 +1,64 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- + ******'/ + + +@startuml +Title Transaction Requests Service - Authorizations +participant "Payer FSP" +participant "Switch\ntransaction-requests-service" as Switch +participant "Payee FSP" + +autonumber +"Payee FSP" --\ "Payee FSP": Lookup, Transaction request,\nprocessing not shown here +note over "Payee FSP", Switch: Payee FSP generates a transaction-request to the Payer FSP +"Payer FSP" --> "Payer FSP": Do quote, generate OTP\nnotify user (not shown here) +"Payer FSP" -\ Switch: GET /authorizations/{TransactionRequestID} +Switch --/ "Payer FSP": 202 Accepted + +alt authorization request is valid + + Switch -> Switch: Validate GET /authorizations/{TransactionRequestID} (internal validation) + Switch -> Switch: Retrieve corresponding end-points for Payee FSP + note over Switch, "Payee FSP": Switch forwards GET /authorizations request to Payee FSP + Switch -\ "Payee FSP": GET /authorizations/{TransactionRequestID} + "Payee FSP" --/ Switch: 202 Accepted + "Payee FSP" -> "Payee FSP": Process authorization request\n(Payer approves/rejects transaction\nusing OTP) + + note over Switch, "Payee FSP": Payee FSP responds with PUT /authorizations//{TransactionRequestID} + "Payee FSP" -\ Switch: PUT /authorizations//{TransactionRequestID} + Switch --/ "Payee FSP": 200 Ok + + note over "Payer FSP", Switch: Switch forwards PUT /authorizations//{TransactionRequestID} to Payer FSP + Switch -> Switch: Retrieve corresponding end-points for Payer FSP + Switch -\ "Payer FSP": PUT /authorizations//{TransactionRequestID} + "Payer FSP" --/ Switch: 200 Ok + + +else authorization request is invalid + note over "Payer FSP", Switch: Switch returns error callback to Payer FSP + Switch -\ "Payer FSP": PUT /authorizations/{TransactionRequestID}/error + "Payer FSP" --/ Switch: 200 OK + "Payer FSP" --> "Payer FSP": Validate OTP sent by Payee FSP +end +@enduml diff --git a/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.svg b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.svg new file mode 100644 index 000000000..58173614d --- /dev/null +++ b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.svg @@ -0,0 +1,132 @@ + + Transaction Requests Service - Authorizations + + + Transaction Requests Service - Authorizations + + + + + + Payer FSP + + Payer FSP + + Switch + transaction-requests-service + + Switch + transaction-requests-service + + Payee FSP + + Payee FSP + + + + + 1 + Lookup, Transaction request, + processing not shown here + + + Payee FSP generates a transaction-request to the Payer FSP + + + + + 2 + Do quote, generate OTP + notify user (not shown here) + + + 3 + GET /authorizations/{TransactionRequestID} + + + 4 + 202 Accepted + + + alt + [authorization request is valid] + + + + + 5 + Validate GET /authorizations/{TransactionRequestID} (internal validation) + + + + + 6 + Retrieve corresponding end-points for Payee FSP + + + Switch forwards GET /authorizations request to Payee FSP + + + 7 + GET /authorizations/{TransactionRequestID} + + + 8 + 202 Accepted + + + + + 9 + Process authorization request + (Payer approves/rejects transaction + using OTP) + + + Payee FSP responds with PUT /authorizations//{TransactionRequestID} + + + 10 + PUT /authorizations//{TransactionRequestID} + + + 11 + 200 Ok + + + Switch forwards PUT /authorizations//{TransactionRequestID} to Payer FSP + + + + + 12 + Retrieve corresponding end-points for Payer FSP + + + 13 + PUT /authorizations//{TransactionRequestID} + + + 14 + 200 Ok + + [authorization request is invalid] + + + Switch returns error callback to Payer FSP + + + 15 + PUT /authorizations/{TransactionRequestID}/error + + + 16 + 200 OK + + + + + 17 + Validate OTP sent by Payee FSP + + diff --git a/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.plantuml b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.plantuml new file mode 100644 index 000000000..655cf6e07 --- /dev/null +++ b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.plantuml @@ -0,0 +1,93 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- + ******'/ + + +@startuml +Title Transaction Requests Service - Create +participant "Payer FSP" +participant "Switch\ntransaction-requests-service" as Switch +participant "Payee FSP" + +autonumber +"Payee FSP" -\ "Payee FSP": Lookup process\n(not shown here) +note over "Payee FSP", Switch: Payee FSP generates a transaction-request to the Payer FSP +"Payee FSP" -\ Switch: POST /transactionRequests +Switch -> Switch: Validate POST /transactionRequests schema +Switch --/ "Payee FSP": 202 Accepted + +alt transaction-request is valid + + Switch -> Switch: Validate POST /transactionRequests (internal validation) + Switch -> Switch: Retrieve corresponding end-points for Payer FSP + note over Switch, "Payer FSP": Switch forwards POST /transactionRequests request to Payer FSP + Switch -\ "Payer FSP": POST /transactionRequests + "Payer FSP" --/ Switch: 202 Accepted + "Payer FSP" -> "Payer FSP": Process transaction-request + + alt Payer FSP successfully processes transaction-request + + note over "Payer FSP", Switch: Payer FSP responds to POST /transactionRequests + "Payer FSP" -\ Switch: PUT /transactionRequests/{ID} + Switch --/ "Payer FSP": 200 Ok + + Switch -> Switch: Validate PUT /transactionRequests/{ID} + + alt response is ok + + note over Switch, "Payee FSP": Switch forwards transaction-request response to Payee FSP + Switch -> Switch: Retrieve corresponding end-points for Payee FSP + + Switch -\ "Payee FSP": PUT /transactionRequests/{ID} + "Payee FSP" --/ Switch: 200 Ok + + note over "Payee FSP" #3498db: Wait for a quote, transfer by Payer FSP\nor a rejected transaction-request + else response invalid + + note over Switch, "Payer FSP": Switch returns error to Payer FSP + + Switch -\ "Payer FSP": PUT /transactionRequests/{ID}/error + "Payer FSP" --/ Switch : 200 Ok + + note over Switch, "Payer FSP" #ec7063: Note that under this\nscenario the Payee FSP\nmay not receive a response + + end + else Payer FSP calculation fails or rejects the request + + note over "Payer FSP", Switch: Payer FSP returns error to Switch + + "Payer FSP" -\ Switch: PUT /transactionRequests/{ID}/error + Switch --/ "Payer FSP": 200 OK + + note over "Payee FSP", Switch: Switch returns error to Payee FSP + + Switch -\ "Payee FSP": PUT /transactionRequests/{ID}/error + "Payee FSP" --/ Switch: 200 OK + + end +else transaction-request is invalid + note over "Payee FSP", Switch: Switch returns error to Payee FSP + Switch -\ "Payee FSP": PUT /transactionRequests/{ID}/error + "Payee FSP" --/ Switch: 200 OK +end +@enduml diff --git a/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.svg b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.svg new file mode 100644 index 000000000..c602dd78a --- /dev/null +++ b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.svg @@ -0,0 +1,185 @@ + + Transaction Requests Service - Create + + + Transaction Requests Service - Create + + + + + + + + Payer FSP + + Payer FSP + + Switch + transaction-requests-service + + Switch + transaction-requests-service + + Payee FSP + + Payee FSP + + + + + 1 + Lookup process + (not shown here) + + + Payee FSP generates a transaction-request to the Payer FSP + + + 2 + POST /transactionRequests + + + + + 3 + Validate POST /transactionRequests schema + + + 4 + 202 Accepted + + + alt + [transaction-request is valid] + + + + + 5 + Validate POST /transactionRequests (internal validation) + + + + + 6 + Retrieve corresponding end-points for Payer FSP + + + Switch forwards POST /transactionRequests request to Payer FSP + + + 7 + POST /transactionRequests + + + 8 + 202 Accepted + + + + + 9 + Process transaction-request + + + alt + [Payer FSP successfully processes transaction-request] + + + Payer FSP responds to POST /transactionRequests + + + 10 + PUT /transactionRequests/{ID} + + + 11 + 200 Ok + + + + + 12 + Validate PUT /transactionRequests/{ID} + + + alt + [response is ok] + + + Switch forwards transaction-request response to Payee FSP + + + + + 13 + Retrieve corresponding end-points for Payee FSP + + + 14 + PUT /transactionRequests/{ID} + + + 15 + 200 Ok + + + Wait for a quote, transfer by Payer FSP + or a rejected transaction-request + + [response invalid] + + + Switch returns error to Payer FSP + + + 16 + PUT /transactionRequests/{ID}/error + + + 17 + 200 Ok + + + Note that under this + scenario the Payee FSP + may not receive a response + + [Payer FSP calculation fails or rejects the request] + + + Payer FSP returns error to Switch + + + 18 + PUT /transactionRequests/{ID}/error + + + 19 + 200 OK + + + Switch returns error to Payee FSP + + + 20 + PUT /transactionRequests/{ID}/error + + + 21 + 200 OK + + [transaction-request is invalid] + + + Switch returns error to Payee FSP + + + 22 + PUT /transactionRequests/{ID}/error + + + 23 + 200 OK + + diff --git a/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.plantuml b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.plantuml new file mode 100644 index 000000000..17262a24a --- /dev/null +++ b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.plantuml @@ -0,0 +1,90 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- + ******'/ + + +@startuml +Title Transaction Requests Service - Query +participant "Payer FSP" +participant "Switch\ntransaction-requests-service" as Switch +participant "Payee FSP" + +autonumber +note over "Payee FSP", Switch: Payee FSP requests the status of a transaction-request at the Payer FSP.\nID here is the ID of prevoiusly created transaction-request +"Payee FSP" -\ Switch: GET /transactionRequests/{ID} +Switch -> Switch: Validate GET /transactionRequests/{ID} +Switch --/ "Payee FSP": 202 Accepted + +alt transaction-request query is valid + + Switch -> Switch: Retrieve corresponding end-points for Payer FSP + note over Switch, "Payer FSP": Switch forwards GET /transactionRequests/{ID} request to Payer FSP + Switch -\ "Payer FSP": GET /transactionRequests/{ID} + "Payer FSP" --/ Switch: 202 Accepted + "Payer FSP" -> "Payer FSP": Retrieve transaction-request + + alt Payer FSP successfully retrieves transaction-request + + note over "Payer FSP", Switch: Payer FSP responds with the\nPUT /transactionRequests/{ID} callback + "Payer FSP" -\ Switch: PUT /transactionRequests/{ID} + Switch --/ "Payer FSP": 200 Ok + + Switch -> Switch: Validate PUT /transactionRequests/{ID} + + alt response is ok + + note over Switch, "Payee FSP": Switch forwards transaction-request response to Payee FSP + Switch -> Switch: Retrieve corresponding end-points for Payee FSP + + Switch -\ "Payee FSP": PUT /transactionRequests/{ID} + "Payee FSP" --/ Switch: 200 Ok + + else response invalid + + note over Switch, "Payer FSP": Switch returns error to Payer FSP + + Switch -\ "Payer FSP": PUT /transactionRequests/{ID}/error + "Payer FSP" --/ Switch : 200 Ok + + note over Switch, "Payer FSP" #ec7063: Note that under this\nscenario the Payee FSP\nmay not receive a response + + end + else Payer FSP is unable to retrieve the transaction-request + + note over "Payer FSP", Switch: Payer FSP returns error to Switch + + "Payer FSP" -\ Switch: PUT /transactionRequests/{ID}/error + Switch --/ "Payer FSP": 200 OK + + note over "Payee FSP", Switch: Switch returns error to Payee FSP + + Switch -\ "Payee FSP": PUT /transactionRequests/{ID}/error + "Payee FSP" --/ Switch: 200 OK + + end +else transaction-request is invalid + note over "Payee FSP", Switch: Switch returns error to Payee FSP + Switch -\ "Payee FSP": PUT /transactionRequests/{ID}/error + "Payee FSP" --/ Switch: 200 OK +end +@enduml diff --git a/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.svg b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.svg new file mode 100644 index 000000000..c2f12614b --- /dev/null +++ b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.svg @@ -0,0 +1,170 @@ + + Transaction Requests Service - Query + + + Transaction Requests Service - Query + + + + + + + + Payer FSP + + Payer FSP + + Switch + transaction-requests-service + + Switch + transaction-requests-service + + Payee FSP + + Payee FSP + + + Payee FSP requests the status of a transaction-request at the Payer FSP. + ID here is the ID of prevoiusly created transaction-request + + + 1 + GET /transactionRequests/{ID} + + + + + 2 + Validate GET /transactionRequests/{ID} + + + 3 + 202 Accepted + + + alt + [transaction-request query is valid] + + + + + 4 + Retrieve corresponding end-points for Payer FSP + + + Switch forwards GET /transactionRequests/{ID} request to Payer FSP + + + 5 + GET /transactionRequests/{ID} + + + 6 + 202 Accepted + + + + + 7 + Retrieve transaction-request + + + alt + [Payer FSP successfully retrieves transaction-request] + + + Payer FSP responds with the + PUT /transactionRequests/{ID} callback + + + 8 + PUT /transactionRequests/{ID} + + + 9 + 200 Ok + + + + + 10 + Validate PUT /transactionRequests/{ID} + + + alt + [response is ok] + + + Switch forwards transaction-request response to Payee FSP + + + + + 11 + Retrieve corresponding end-points for Payee FSP + + + 12 + PUT /transactionRequests/{ID} + + + 13 + 200 Ok + + [response invalid] + + + Switch returns error to Payer FSP + + + 14 + PUT /transactionRequests/{ID}/error + + + 15 + 200 Ok + + + Note that under this + scenario the Payee FSP + may not receive a response + + [Payer FSP is unable to retrieve the transaction-request] + + + Payer FSP returns error to Switch + + + 16 + PUT /transactionRequests/{ID}/error + + + 17 + 200 OK + + + Switch returns error to Payee FSP + + + 18 + PUT /transactionRequests/{ID}/error + + + 19 + 200 OK + + [transaction-request is invalid] + + + Switch returns error to Payee FSP + + + 20 + PUT /transactionRequests/{ID}/error + + + 21 + 200 OK + + diff --git a/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.plantuml b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.plantuml new file mode 100644 index 000000000..d88913d33 --- /dev/null +++ b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.plantuml @@ -0,0 +1,138 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation +- Name Surname + +* Henk Kodde +-------------- +******'/ + +@startuml transactionRequests + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title How to use the /transactionRequests service + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee + +' declare actors +participant "Payer\nFSP" as payerfsp +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as payeefsp +actor "<$actor>\nPayee" as Payee + +' start flow +payeefsp <- Payee: I would like to receive\nfunds from +123456789 +activate payeefsp +payeefsp <- payeefsp: Lookup +123456789\n(process not shown here) +Switch <<- payeefsp: **POST /transactionRequest/**\n(Payee information,\ntransaction details) +activate Switch +Switch -->> payeefsp: **HTTP 202** (Accepted) +payerfsp <<- Switch: **POST /transactionRequests/**\n(Payee information,\ntransaction details) +activate payerfsp +payerfsp -->> Switch: **HTTP 202** (Accepted) +payeefsp -> payeefsp: Perform optional validation +payerfsp ->> Switch: **PUT /transactionRequests/**\n(Received status) +payerfsp <<-- Switch: **HTTP 200** (OK) +deactivate payerfsp +Switch ->> payeefsp: **PUT /transactionRequests/**\n(Received status) +Switch <<-- payeefsp: **HTTP 200** (OK) +deactivate Switch +payeefsp -> payeefsp: Wait for either quote and\ntransfer, or rejected\ntransaction request by Payer +payeefsp <[hidden]- payeefsp +deactivate payeefsp +@enduml diff --git a/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.svg b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.svg new file mode 100644 index 000000000..81ddcf167 --- /dev/null +++ b/docs/technical/technical/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + Payer + FSP + + Optional + Switch + + Payee + FSP + + Payee + + + + + + + + I would like to receive + funds from +123456789 + + + + + Lookup +123456789 + (process not shown here) + + + + POST /transactionRequest/ + (Payee information, + transaction details) + + + + HTTP 202 + (Accepted) + + + + POST /transactionRequests/ + (Payee information, + transaction details) + + + + HTTP 202 + (Accepted) + + + + + Perform optional validation + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + PUT /transactionRequests/ + <ID> + (Received status) + + + + HTTP 200 + (OK) + + + + + Wait for either quote and + transfer, or rejected + transaction request by Payer + + diff --git a/docs/technical/technical/transaction-requests-service/authorizations.md b/docs/technical/technical/transaction-requests-service/authorizations.md new file mode 100644 index 000000000..6617f1780 --- /dev/null +++ b/docs/technical/technical/transaction-requests-service/authorizations.md @@ -0,0 +1,8 @@ +# Transaction Requests + +GET /authorizations/{TransactionRequestID} and PUT /authorizations/{TransactionRequestID} to support authorizations in "Merchant Request to Pay" and other Payee initiated use cases + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.svg) + diff --git a/docs/technical/technical/transaction-requests-service/transaction-requests-get.md b/docs/technical/technical/transaction-requests-service/transaction-requests-get.md new file mode 100644 index 000000000..5d13358e2 --- /dev/null +++ b/docs/technical/technical/transaction-requests-service/transaction-requests-get.md @@ -0,0 +1,8 @@ +# Transaction Requests - Query + +GET /transactionRequests and PUT /transacionRequests to suppport "Merchant Request to Pay" + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.svg) + diff --git a/docs/technical/technical/transaction-requests-service/transaction-requests-post.md b/docs/technical/technical/transaction-requests-service/transaction-requests-post.md new file mode 100644 index 000000000..8bf3c6073 --- /dev/null +++ b/docs/technical/technical/transaction-requests-service/transaction-requests-post.md @@ -0,0 +1,8 @@ +# Transaction Requests + +POST /transactionRequests and PUT /transacionRequests to suppport "Merchant Request to Pay" + +## Sequence Diagram + +![](./assets/diagrams/sequence/seq-trx-req-service-1.0.0.svg) + diff --git a/glossary.md b/glossary.md deleted file mode 100644 index 65b9763a1..000000000 --- a/glossary.md +++ /dev/null @@ -1,8 +0,0 @@ -# Glossary of Terms - -| Term | Definition | Notes | -| --- | --- | --- | -| DFSP | Digital Financial Service Provider | | -| FSP | Financial Service Provider | | -| K8s | Short name for [Kubernetes](https://kubernetes.io/) | Read more here [https://kubernetes.io](https://kubernetes.io) | -| ALS | [Account-Lookup Service](mojaloop-technical-overview/account-lookup-service/README.md) | Refer to [Documentation](mojaloop-technical-overview/account-lookup-service/README.md) | diff --git a/index.js b/index.js deleted file mode 100644 index b248afdbc..000000000 --- a/index.js +++ /dev/null @@ -1,34 +0,0 @@ -/***** - License - -------------- - Copyright © 2017 Bill & Melinda Gates Foundation - The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - Contributors - -------------- - This is the official list of the Mojaloop project contributors for this file. - Names of the original copyright holders (individuals or organizations) - should be listed with a '*' in the first column. People who have - contributed from an organization can be listed under the organization - that actually holds the copyright for their contributions (see the - Gates Foundation organization for an example). Those individuals should have - their names indented and be marked with a '-'. Email address can be added - optionally within square brackets . - - * Gates Foundation - - Name Surname - - * Miguel de Barros - - -------------- - ******/ - -const express = require('express') -const app = express() -app.use(express.static(__dirname + '/_book')) - -app.listen(process.env.PORT || 8989) diff --git a/infra/README.md b/infra/README.md new file mode 100644 index 000000000..70953e512 --- /dev/null +++ b/infra/README.md @@ -0,0 +1,89 @@ +# infra + +Mojaloop Documentation Site is hosted on AWS CloudFront, with Terraform to automate the creation and management +of the site. + +This document is for maintainers of Mojaloop's documentation site, but this repo can also serve as a good template + for automating the deployment of static hosting with cloudfront functions. + +## Requirements + +- `terraform` +- AWS credentials and necessary IAM permissions to create, update destroy s3 buckets, dynamodb tables, CloudFront CDNs + +## Deploy + +```bash +# sign in with MFA +aws-mfa + +# initialize the shared terraform state (if not done already) +cd ./state + +terraform init + +# for some reason I need to set this env var for tf 0.14+ +AWS_SHARED_CREDENTIALS_FILE=$HOME/.aws/credentials +terraform plan +terraform apply + + + +cd ../src +# first time only +terraform init \ + -backend-config="bucket=docs.mojaloop.io-state" \ + -backend-config="region=eu-west-2" \ + -backend-config="dynamodb_table=docs.mojaloop.io-lock" + + +# see what changes are needed +terraform plan + +# apply the terraform +terraform apply +``` + +## Manual Steps: + +It's up to you to configure the DNS and SSL Certificates. I didn't want to add this here +because the `docs.mojaloop.io` domain is not configured by us, so there is no point in +automating it. + +Additionally, domains are slow moving and tend to often need manual intervention at some point. + +### Configure the DNS: + +1. Log in to Route53 > Hosted Zones > select your domain (for example `moja-lab.live`) +2. "Create Record" with the following details: +- Record Name: `docs-preview2` +- Type: `CNAME` +- Value: `d1n6mdji42j0gb.cloudfront.net` - value from terraform output: `website_cdn_root_domain_name` +3. "Create Records" + +### Attach the CI user to the IAM groups + +In order to use this tooling in CI/CD, you need to manually attach a CI user to the groups +created by terraform, in this case `docs-preview2.moja-lab.live-infra-group` and +`docs-preview2.moja-lab.live-infra-infra` + +### Upload your site! + +Build and upload the site to your terraform-managed s3 bucket: + +```bash +AWS_REGION=us-east-2 BUCKET_NAME=docs-preview.moja-lab.live-root DOMAIN=docs-preview.moja-lab.live ../scripts/_deploy_preview_s3.sh +``` + + +## Configure Redirects + +In order to support the gradual migration to docs 2.0, we need to be able to configure the CDN +to fall back to legacy docs that haven't yet been migrated, also be able to redirect legacy +links to updated pages in order to avoid broken links once we switch over to docs 2.0. + + +For this, we use cloudfront functions, which are lightweight Javascript functions that allow you +to control the behaviour of requests and responses of the CDN. + +The redirect behaviour can be configured in `./src/redirect/index.js` \ No newline at end of file diff --git a/infra/src/.terraform.lock.hcl b/infra/src/.terraform.lock.hcl new file mode 100755 index 000000000..0e7cea3fa --- /dev/null +++ b/infra/src/.terraform.lock.hcl @@ -0,0 +1,21 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "3.64.2" + constraints = "~> 3.64.2" + hashes = [ + "h1:oFsgTmmt/eJ8KLo59PSmYu/irUHJiPnQEey0VqaOOck=", + "zh:0b029a2282beabfe410eb2969e18ca773d3473415e442be4dc8ce0eb6d1cd8c5", + "zh:3209de3266a1138f1ccb09f094fdd98b6f55afc06e291db0abe092ec5dbe7640", + "zh:40648266551631cbc15f8a76e80faf300510e3b38c2544d43fc25e37e6802727", + "zh:483c8af92ae70146f2790a70c1a810251e7135aa912b66e769c934eddceebe32", + "zh:4d106d8d415d8df342f3f85e58c35418e6c55e3cb7f02897f832cefac4dca68c", + "zh:972626a6ddb31d5216606d12ab5c30fbf8d51ed2bbe0efcdd7cffa68c1141557", + "zh:a230d55ec52b1695148d40296877ee23e0b302e817154f9b838eb117c87b13fa", + "zh:c95fddfbd7f870db949da0601323e866e0f0fb0d4a93e96725ae5b88029e84d5", + "zh:ea0c7f568074f835f22273c8e7e61e87f5277e32004c72122915fd3c8df49ccc", + "zh:f96d25887e6e2d2ae47659e2c586efea2167995b59a479ae65a02b097da86474", + "zh:fe7502d8e52d3b5ccb2b3c178e7ea894344783093aa71ffb20e978914c976182", + ] +} diff --git a/infra/src/cloudfront.tf b/infra/src/cloudfront.tf new file mode 100644 index 000000000..1e130f8e9 --- /dev/null +++ b/infra/src/cloudfront.tf @@ -0,0 +1,169 @@ +# Shared cache behaviors for both main and preview distributions +locals { + shared_cache_behaviors = [ + { + path_pattern = "/business-operations-framework-docs/*" + target_origin_id = "mojaloop.github.io" + }, + { + path_pattern = "/business-operations-framework-docs" + target_origin_id = "mojaloop.github.io" + }, + { + path_pattern = "/mojaloop-business-docs/*" + target_origin_id = "mojaloop.github.io" + }, + { + path_pattern = "/mojaloop-business-docs" + target_origin_id = "mojaloop.github.io" + }, + { + path_pattern = "/reference-architecture-doc/*" + target_origin_id = "mojaloop.github.io" + }, + { + path_pattern = "/reference-architecture-doc" + target_origin_id = "mojaloop.github.io" + }, + { + path_pattern = "/charts/*" + target_origin_id = "mojaloop.github.io" + }, + { + path_pattern = "/helm/*" + target_origin_id = "mojaloop.github.io" + }, + { + path_pattern = "/wso2-helm-charts-simple/*" + target_origin_id = "mojaloop.github.io" + }, + { + path_pattern = "/finance-portal-v2-ui/*" + target_origin_id = "mojaloop.github.io" + } + ] +} + +# CloudFront +# Creates the CloudFront distribution to serve the static website +resource "aws_cloudfront_distribution" "website_cdn_root" { + provider = aws.custom + enabled = true + price_class = "PriceClass_All" + + depends_on = [ + aws_s3_bucket.website_root + ] + + aliases = [var.website-domain-main] + + // base docs.mojaloop.io origin + origin { + origin_id = "origin-bucket-${aws_s3_bucket.website_root.id}" + domain_name = aws_s3_bucket.website_root.website_endpoint + + custom_origin_config { + origin_protocol_policy = "http-only" + http_port = 80 + https_port = 443 + origin_ssl_protocols = ["TLSv1.2", "TLSv1.1", "TLSv1"] + } + } + + // other origins for sites hosted at docs.mojaloop.io/ + origin { + origin_id = "mojaloop.github.io" + domain_name = "mojaloop.github.io" + custom_origin_config { + origin_protocol_policy = "match-viewer" + http_port = 80 + https_port = 443 + origin_ssl_protocols = ["TLSv1.2", "TLSv1.1", "TLSv1"] + } + } + + default_root_object = "index.html" + + logging_config { + bucket = aws_s3_bucket.website_logs.bucket_domain_name + prefix = "${var.website-domain-main}/" + } + + # Shared cache behaviors for main distribution + dynamic "ordered_cache_behavior" { + for_each = local.shared_cache_behaviors + content { + path_pattern = ordered_cache_behavior.value.path_pattern + target_origin_id = ordered_cache_behavior.value.target_origin_id + allowed_methods = ["GET", "HEAD", "OPTIONS"] + cached_methods = ["GET", "HEAD", "OPTIONS"] + viewer_protocol_policy = "allow-all" + forwarded_values { + query_string = false + cookies { + forward = "none" + } + } + } + } + + default_cache_behavior { + allowed_methods = ["GET", "HEAD", "OPTIONS"] + cached_methods = ["GET", "HEAD", "OPTIONS"] + target_origin_id = "origin-bucket-${aws_s3_bucket.website_root.id}" + min_ttl = "0" + default_ttl = "300" + max_ttl = "1200" + + viewer_protocol_policy = "redirect-to-https" + compress = true + forwarded_values { + query_string = false + cookies { + forward = "none" + } + } + + function_association { + event_type = "viewer-request" + function_arn = aws_cloudfront_function.docs-redirects.arn + } + } + + restrictions { + geo_restriction { + restriction_type = "none" + } + } + viewer_certificate { + acm_certificate_arn = var.cloudfront-certificate-arn + ssl_support_method = "sni-only" + } + custom_error_response { + error_caching_min_ttl = 300 + error_code = 404 + response_page_path = "/404.html" + response_code = 404 + } + + tags = merge(var.tags, { + ManagedBy = "terraform" + Changed = formatdate("YYYY-MM-DD hh:mm ZZZ", timestamp()) + }) + + lifecycle { + ignore_changes = [ + tags["Changed"], + viewer_certificate, + ] + } +} + +resource "aws_cloudfront_function" "docs-redirects" { + provider = aws.custom + name = "${replace(var.website-domain-main, ".", "-")}-docs-redirects" + runtime = "cloudfront-js-1.0" + comment = "main" + publish = true + code = file("${path.module}/redirect/index.js") +} diff --git a/infra/src/iam.tf b/infra/src/iam.tf new file mode 100644 index 000000000..7493166a6 --- /dev/null +++ b/infra/src/iam.tf @@ -0,0 +1,52 @@ + +resource "aws_iam_group_policy" "infa_group_policy" { + provider = aws.custom + name = "${var.website-domain-main}-infra" + group = aws_iam_group.infra_group.name + policy = < { + if (uri.endsWith(m.from)) { + var newurl = uri.replace(m.from, m.to) + response = { + statusCode: 301, + statusDescription: 'Moved Permanently', + headers: { "location": { "value": newurl } } + } + } + }) + if (response) { + return response + } + + // fallthrough + return request +} diff --git a/infra/src/redirect/link_list.md b/infra/src/redirect/link_list.md new file mode 100644 index 000000000..9989f4c52 --- /dev/null +++ b/infra/src/redirect/link_list.md @@ -0,0 +1,196 @@ + + +## migrated already - has a new location +/mojaloop-specification/;/api/ +/mojaloop-specification/fspiop-api/documents/Logical-Data-Model.html;/api/fspiop/logical-data-model.html +/mojaloop-specification/fspiop-api/documents/Generic-Transaction-Patterns.html;/api/fspiop/generic-transaction-patterns.html +/mojaloop-specification/fspiop-api/documents/Use-Cases.html;/api/fspiop/use-cases.html +/mojaloop-specification/admin-api/admin-api-specification-v1.0.html;/api/administration/ +/mojaloop-specification/fspiop-api/documents/Scheme-Rules.html;/api/fspiop/scheme-rules.html +/mojaloop-specification/fspiop-api/documents/JSON-Binding-Rules.html;/api/fspiop/json-binding-rules.html +/mojaloop-specification/fspiop-api/documents/PKI-Best-Practices.html;/api/fspiop/pki-best-practices.html +/mojaloop-specification/fspiop-api/documents/Signature_v1.1.html;/api/fspiop/v1.1/signature.html +/mojaloop-specification/fspiop-api/documents/Encryption_v1.1.html;/api/fspiop/v1.1/encryption.html +/mojaloop-specification/ccb-meetings/;https://github.com/mojaloop/mojaloop-specification/tree/master/ccb-meetings +/mojaloop-specification/ccb-meetings/Issue-and-Decision-Log.html;https://github.com/mojaloop/mojaloop-specification/issues +/documentation/;/ +/documentation/mojaloop-background/;/not_found.html +/documentation/mojaloop-background/core-scenarios.html;/not_found.html +/documentation/mojaloop-background/level-one-principles.html;/not_found.html +/documentation/onboarding.html;/not_found.html +/documentation/deployment-guide/;/legacy/deployment-guide/ +/documentation/deployment-guide/releases.html;/legacy/deployment-guide/releases.html +/documentation/deployment-guide/local-setup-linux.html;/legacy/deployment-guide/local-setup-linux.html +/documentation/deployment-guide/local-setup-mac.html;/legacy/deployment-guide/local-setup-mac.html +/documentation/deployment-guide/local-setup-windows.html;/legacy/deployment-guide/local-setup-windows.html +/documentation/deployment-guide/deployment-troubleshooting.html;/legacy/deployment-guide/deployment-troubleshooting.html +/documentation/deployment-guide/upgrade-strategy-guide.html;/legacy/deployment-guide/upgrade-strategy-guide.html +/documentation/deployment-guide/helm-legacy-migration.html;/legacy/deployment-guide/helm-legacy-migration.html +/documentation/deployment-guide/helm-legacy-deployment.html;/legacy/deployment-guide/helm-legacy-deployment.html +/documentation/contributors-guide/;/community/contributing/contributors-guide.html +/documentation/contributors-guide/new-contributor-checklist.html;/community/contributing/new-contributor-checklist.html +/documentation/contributors-guide/code-of-conduct.html;/community/contributing/code-of-conduct.html +/documentation/contributors-guide/signing-the-cla.html;/community/contributing/signing-the-cla.html +/documentation/contributors-guide/frequently-asked-questions.html;/getting-started/faqs.html +/documentation/contributors-guide/standards/;/community/standards/guide.html +/documentation/contributors-guide/standards/versioning.html;/community/standards/versioning.html +/documentation/contributors-guide/standards/creating-new-features.html;/community/standards/creating-new-features.html +/documentation/contributors-guide/standards/triaging-ml-oss-bugs.html;/community/standards/triaging-bugs.html +/documentation/contributors-guide/tools-and-technologies/;/community/tools/tools-and-technologies.html +/documentation/contributors-guide/tools-and-technologies/pragmatic-rest.html;/community/tools/pragmatic-rest.html +/documentation/contributors-guide/tools-and-technologies/code-quality-metrics.html;/community/tools/code-quality-metrics.html +/documentation/contributors-guide/tools-and-technologies/automated-testing.html;/community/tools/automated-testing.html +/documentation/contributors-guide/documentation/;/community/documentation/standards.html +/documentation/contributors-guide/documentation/api-documentation.html;/community/documentation/api-documentation.html +/documentation/contributors-guide/documentation/documentation-style-guide.html;/community/documentation/style-guide.html +/documentation/mojaloop-roadmap.html;/community/mojaloop-roadmap.html +/documentation/mojaloop-publications.html;/community/mojaloop-publications.html +/documentation/discussions/readme.html;/community/archive/discussion-docs/ +/documentation/discussions/ISO_Integration.html;/community/archive/discussion-docs/ +/documentation/discussions/decimal.html;/community/archive/discussion-docs/ +/documentation/discussions/workbench.html;/community/archive/discussion-docs/ +/documentation/discussions/cross_border_day_1.html;/community/archive/discussion-docs/ +/documentation/discussions/cross_border_day_2.html;/community/archive/discussion-docs/ +/documentation/meeting-notes/readme.html;/not_found.html +/documentation/meeting-notes/scrum-of-scrum-notes.html;/not_found.html +/documentation/meeting-notes/da-notes.html;/not_found.html +/documentation/meeting-notes/ccb-notes.html;/not_found.html +/documentation/quality-security/readme.html;/legacy/quality-security/readme.html +/documentation/quality-security/program-management/readme.html;/legacy/quality-security/program-management/readme.html +/documentation/quality-security/program-management/vulnerability-disclosure-procedure.html;/legacy/quality-security/program-management/vulnerability-disclosure-procedure.html +/documentation/quality-security/program-management/scheme-rules-guidelines.html;/legacy/quality-security/program-management/scheme-rules-guidelines.html +/documentation/quality-security/standards-guidelines/readme.html;/legacy/quality-security/standards-guidelines/readme.html +/documentation/quality-security/reference-implementation.html;/legacy/quality-security/reference-implementation.html +/documentation/api/;/api/ +/documentation/api/central-ledger-api-specification.html;/api/administration/ +/documentation/api/central-settlements-api-specification.html;/api/settlement/ +/documentation/api/als-oracle-api-specification.html;/legacy/api/als-oracle-api-specification.html +/documentation/mojaloop-technical-overview/;/legacy/mojaloop-technical-overview/ +/documentation/mojaloop-technical-overview/overview/;/legacy/mojaloop-technical-overview/overview/ +/documentation/mojaloop-technical-overview/overview/components-PI14.html;/legacy/mojaloop-technical-overview/overview/components-PI14.html +/documentation/mojaloop-technical-overview/overview/components-PI12.html;/legacy/mojaloop-technical-overview/overview/components-PI12.html +/documentation/mojaloop-technical-overview/overview/components-PI11.html;/legacy/mojaloop-technical-overview/overview/components-PI11.html +/documentation/mojaloop-technical-overview/overview/components-PI8.html;/legacy/mojaloop-technical-overview/overview/components-PI8.html +/documentation/mojaloop-technical-overview/overview/components-PI7.html;/legacy/mojaloop-technical-overview/overview/components-PI7.html +/documentation/mojaloop-technical-overview/overview/components-PI6.html;/legacy/mojaloop-technical-overview/overview/components-PI6.html +/documentation/mojaloop-technical-overview/overview/components-PI5.html;/legacy/mojaloop-technical-overview/overview/components-PI5.html +/documentation/mojaloop-technical-overview/overview/components-PI3.html;/legacy/mojaloop-technical-overview/overview/components-PI3.html +/documentation/mojaloop-technical-overview/account-lookup-service/;/legacy/mojaloop-technical-overview/account-lookup-service/ +/documentation/mojaloop-technical-overview/account-lookup-service/als-get-participants.html;/legacy/mojaloop-technical-overview/account-lookup-service/als-get-participants.html +/documentation/mojaloop-technical-overview/account-lookup-service/als-post-participants.html;/legacy/mojaloop-technical-overview/account-lookup-service/als-post-participants.html +/documentation/mojaloop-technical-overview/account-lookup-service/als-post-participants-batch.html;/legacy/mojaloop-technical-overview/account-lookup-service/als-post-participants-batch.html +/documentation/mojaloop-technical-overview/account-lookup-service/als-del-participants.html;/legacy/mojaloop-technical-overview/account-lookup-service/als-del-participants.html +/documentation/mojaloop-technical-overview/account-lookup-service/als-get-parties.html;/legacy/mojaloop-technical-overview/account-lookup-service/als-get-parties.html +/documentation/mojaloop-technical-overview/quoting-service/;/legacy/mojaloop-technical-overview/quoting-service/ +/documentation/mojaloop-technical-overview/quoting-service/qs-get-quotes.html;/legacy/mojaloop-technical-overview/quoting-service/qs-get-quotes.html +/documentation/mojaloop-technical-overview/quoting-service/qs-post-quotes.html;/legacy/mojaloop-technical-overview/quoting-service/qs-post-quotes.html +/documentation/mojaloop-technical-overview/quoting-service/qs-get-bulk-quotes.html;/legacy/mojaloop-technical-overview/quoting-service/qs-get-bulk-quotes.html +/documentation/mojaloop-technical-overview/quoting-service/qs-post-bulk-quotes.html;/legacy/mojaloop-technical-overview/quoting-service/qs-post-bulk-quotes.html +/documentation/mojaloop-technical-overview/central-ledger/;/legacy/mojaloop-technical-overview/central-ledger/ +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/ +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-post-participant-position-limit.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-post-participant-position-limit.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-get-participant-limit-details.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-get-participant-limit-details.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-post-participant-limits.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-post-participant-limits.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/1.1.5-get-transfer-status.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.5-get-transfer-status.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-post-participant-callback-details.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-post-participant-callback-details.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-get-participant-callback-details.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-get-participant-callback-details.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/4.1.0-get-participant-position-details.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/4.1.0-get-participant-position-details.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/;/legacy/mojaloop-technical-overview/central-ledger/transfers/ +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.1.0-prepare-transfer-request.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.0-prepare-transfer-request.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.1.1.a-prepare-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.1.a-prepare-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.3.1-prepare-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.1-prepare-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.1.2.a-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.2.a-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.3.3-abort-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.3-abort-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.3.0-transfer-timeout.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.3.0-transfer-timeout.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.3.1-timeout-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.3.1-timeout-handler-consume.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/;/legacy/mojaloop-technical-overview/central-bulk-transfers/ +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.2-position-consume-abort.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.2-position-consume-abort.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.html +/documentation/mojaloop-technical-overview/central-settlements/;/legacy/mojaloop-technical-overview/central-settlements/ +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/ +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-windows-by-params.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-windows-by-params.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-window-by-id.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-window-by-id.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/post-close-settlement-window.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/post-close-settlement-window.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/post-create-settlement.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/post-create-settlement.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-id.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-id.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-transfer-ack.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-transfer-ack.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-abort.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-abort.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-spa.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-spa.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/get-settlements-by-params.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlements-by-params.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/gross-settlement-handler-consume.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/gross-settlement-handler-consume.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/rules-handler-consume.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/rules-handler-consume.html +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/ +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/reconciliation-transfer-prepare.html;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/reconciliation-transfer-prepare.html +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/transfer-state-and-position-change.html;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/transfer-state-and-position-change.html +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/funds-in-prepare-reserve-commit.html;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-in-prepare-reserve-commit.html +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-prepare-reserve.html;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-prepare-reserve.html +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-commit.html;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-commit.html +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-abort.html;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-abort.html +/documentation/mojaloop-technical-overview/central-settlements/oss-settlement-fsd.html;/legacy/mojaloop-technical-overview/central-settlements/oss-settlement-fsd.html +/documentation/mojaloop-technical-overview/transaction-requests-service/;/legacy/mojaloop-technical-overview/transaction-requests-service/ +/documentation/mojaloop-technical-overview/transaction-requests-service/transaction-requests-post.html;/legacy/mojaloop-technical-overview/transaction-requests-service/transaction-requests-post.html +/documentation/mojaloop-technical-overview/transaction-requests-service/transaction-requests-get.html;/legacy/mojaloop-technical-overview/transaction-requests-service/transaction-requests-get.html +/documentation/mojaloop-technical-overview/transaction-requests-service/authorizations.html;/legacy/mojaloop-technical-overview/transaction-requests-service/authorizations.html +/documentation/mojaloop-technical-overview/central-event-processor/;/legacy/mojaloop-technical-overview/central-event-processor/ +/documentation/mojaloop-technical-overview/central-event-processor/9.1.0-event-handler-placeholder.html;/legacy/mojaloop-technical-overview/central-event-processor/9.1.0-event-handler-placeholder.html +/documentation/mojaloop-technical-overview/central-event-processor/5.1.1-notification-handler-for-rejections.html;/legacy/mojaloop-technical-overview/central-event-processor/5.1.1-notification-handler-for-rejections.html +/documentation/mojaloop-technical-overview/central-event-processor/signature-validation.html;/legacy/mojaloop-technical-overview/central-event-processor/signature-validation.html +/documentation/mojaloop-technical-overview/event-framework/;/legacy/mojaloop-technical-overview/event-framework/ +/documentation/mojaloop-technical-overview/event-stream-processor/;/legacy/mojaloop-technical-overview/event-stream-processor/ +/documentation/mojaloop-technical-overview/fraud-services/;/legacy/mojaloop-technical-overview/fraud-services/ +/documentation/mojaloop-technical-overview/fraud-services/related-documents/documentation.html;/legacy/mojaloop-technical-overview/fraud-services/related-documents/documentation.html +/documentation/mojaloop-technical-overview/sdk-scheme-adapter/;/legacy/mojaloop-technical-overview/sdk-scheme-adapter/ +/documentation/mojaloop-technical-overview/sdk-scheme-adapter/usage/;/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/ +/documentation/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/;/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/ +/documentation/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/;/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/ +/documentation/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/;/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/ +/documentation/mojaloop-technical-overview/ml-testing-toolkit/;/legacy/mojaloop-technical-overview/ml-testing-toolkit/ +/documentation/repositories/;/legacy/repositories/ +/documentation/repositories/helm.html;/legacy/repositories/helm.html +/documentation/repositories/project.html;/legacy/repositories/project.html +/documentation/glossary.html;/legacy/glossary.html +/documentation/discussions/Mojaloop%20Performance%202020.pdf;/legacy/discussions/Mojaloop%20Performance%202020.pdf + + + + +## not yet migrated + +/mojaloop-specification/fspiop-api/documents/Glossary.html +/mojaloop-specification/fspiop-api/documents/API-Definition_v1.1.html +/documentation/api/mojaloop-api-specification.html + + diff --git a/infra/src/redirect/link_list.txt b/infra/src/redirect/link_list.txt new file mode 100644 index 000000000..e92fb9247 --- /dev/null +++ b/infra/src/redirect/link_list.txt @@ -0,0 +1,182 @@ +/mojaloop-specification/;/api/ +/mojaloop-specification/fspiop-api/documents/Logical-Data-Model.html;/api/fspiop/logical-data-model.html +/mojaloop-specification/fspiop-api/documents/Generic-Transaction-Patterns.html;/api/fspiop/generic-transaction-patterns.html +/mojaloop-specification/fspiop-api/documents/Use-Cases.html;/api/fspiop/use-cases.html +/mojaloop-specification/admin-api/admin-api-specification-v1.0.html;/api/administration/ +/mojaloop-specification/fspiop-api/documents/Scheme-Rules.html;/api/fspiop/scheme-rules.html +/mojaloop-specification/fspiop-api/documents/JSON-Binding-Rules.html;/api/fspiop/json-binding-rules.html +/mojaloop-specification/fspiop-api/documents/PKI-Best-Practices.html;/api/fspiop/pki-best-practices.html +/mojaloop-specification/fspiop-api/documents/Signature_v1.1.html;/api/fspiop/v1.1/signature.html +/mojaloop-specification/fspiop-api/documents/Encryption_v1.1.html;/api/fspiop/v1.1/encryption.html +/mojaloop-specification/ccb-meetings/;https://github.com/mojaloop/mojaloop-specification/tree/master/ccb-meetings +/mojaloop-specification/ccb-meetings/Issue-and-Decision-Log.html;https://github.com/mojaloop/mojaloop-specification/issues +/documentation/;/ +/documentation/mojaloop-background/;/not_found.html +/documentation/mojaloop-background/core-scenarios.html;/not_found.html +/documentation/mojaloop-background/level-one-principles.html;/not_found.html +/documentation/onboarding.html;/not_found.html +/documentation/deployment-guide/;/legacy/deployment-guide/ +/documentation/deployment-guide/releases.html;/legacy/deployment-guide/releases.html +/documentation/deployment-guide/local-setup-linux.html;/legacy/deployment-guide/local-setup-linux.html +/documentation/deployment-guide/local-setup-mac.html;/legacy/deployment-guide/local-setup-mac.html +/documentation/deployment-guide/local-setup-windows.html;/legacy/deployment-guide/local-setup-windows.html +/documentation/deployment-guide/deployment-troubleshooting.html;/legacy/deployment-guide/deployment-troubleshooting.html +/documentation/deployment-guide/upgrade-strategy-guide.html;/legacy/deployment-guide/upgrade-strategy-guide.html +/documentation/deployment-guide/helm-legacy-migration.html;/legacy/deployment-guide/helm-legacy-migration.html +/documentation/deployment-guide/helm-legacy-deployment.html;/legacy/deployment-guide/helm-legacy-deployment.html +/documentation/contributors-guide/;/community/contributing/contributors-guide.html +/documentation/contributors-guide/new-contributor-checklist.html;/community/contributing/new-contributor-checklist.html +/documentation/contributors-guide/code-of-conduct.html;/community/contributing/code-of-conduct.html +/documentation/contributors-guide/signing-the-cla.html;/community/contributing/signing-the-cla.html +/documentation/contributors-guide/frequently-asked-questions.html;/getting-started/faqs.html +/documentation/contributors-guide/standards/;/community/standards/guide.html +/documentation/contributors-guide/standards/versioning.html;/community/standards/versioning.html +/documentation/contributors-guide/standards/creating-new-features.html;/community/standards/creating-new-features.html +/documentation/contributors-guide/standards/triaging-ml-oss-bugs.html;/community/standards/triaging-bugs.html +/documentation/contributors-guide/tools-and-technologies/;/community/tools/tools-and-technologies.html +/documentation/contributors-guide/tools-and-technologies/pragmatic-rest.html;/community/tools/pragmatic-rest.html +/documentation/contributors-guide/tools-and-technologies/code-quality-metrics.html;/community/tools/code-quality-metrics.html +/documentation/contributors-guide/tools-and-technologies/automated-testing.html;/community/tools/automated-testing.html +/documentation/contributors-guide/documentation/;/community/documentation/standards.html +/documentation/contributors-guide/documentation/api-documentation.html;/community/documentation/api-documentation.html +/documentation/contributors-guide/documentation/documentation-style-guide.html;/community/documentation/style-guide.html +/documentation/mojaloop-roadmap.html;/community/mojaloop-roadmap.html +/documentation/mojaloop-publications.html;/community/mojaloop-publications.html +/documentation/discussions/readme.html;/community/archive/discussion-docs/ +/documentation/discussions/ISO_Integration.html;/community/archive/discussion-docs/ +/documentation/discussions/decimal.html;/community/archive/discussion-docs/ +/documentation/discussions/workbench.html;/community/archive/discussion-docs/ +/documentation/discussions/cross_border_day_1.html;/community/archive/discussion-docs/ +/documentation/discussions/cross_border_day_2.html;/community/archive/discussion-docs/ +/documentation/meeting-notes/readme.html;/not_found.html +/documentation/meeting-notes/scrum-of-scrum-notes.html;/not_found.html +/documentation/meeting-notes/da-notes.html;/not_found.html +/documentation/meeting-notes/ccb-notes.html;/not_found.html +/documentation/quality-security/readme.html;/legacy/quality-security/readme.html +/documentation/quality-security/program-management/readme.html;/legacy/quality-security/program-management/readme.html +/documentation/quality-security/program-management/vulnerability-disclosure-procedure.html;/legacy/quality-security/program-management/vulnerability-disclosure-procedure.html +/documentation/quality-security/program-management/scheme-rules-guidelines.html;/legacy/quality-security/program-management/scheme-rules-guidelines.html +/documentation/quality-security/standards-guidelines/readme.html;/legacy/quality-security/standards-guidelines/readme.html +/documentation/quality-security/reference-implementation.html;/legacy/quality-security/reference-implementation.html +/documentation/api/;/api/ +/documentation/api/central-ledger-api-specification.html;/api/administration/ +/documentation/api/central-settlements-api-specification.html;/api/settlement/ +/documentation/api/als-oracle-api-specification.html;/legacy/api/als-oracle-api-specification.html +/documentation/mojaloop-technical-overview/;/legacy/mojaloop-technical-overview/ +/documentation/mojaloop-technical-overview/overview/;/legacy/mojaloop-technical-overview/overview/ +/documentation/mojaloop-technical-overview/overview/components-PI14.html;/legacy/mojaloop-technical-overview/overview/components-PI14.html +/documentation/mojaloop-technical-overview/overview/components-PI12.html;/legacy/mojaloop-technical-overview/overview/components-PI12.html +/documentation/mojaloop-technical-overview/overview/components-PI11.html;/legacy/mojaloop-technical-overview/overview/components-PI11.html +/documentation/mojaloop-technical-overview/overview/components-PI8.html;/legacy/mojaloop-technical-overview/overview/components-PI8.html +/documentation/mojaloop-technical-overview/overview/components-PI7.html;/legacy/mojaloop-technical-overview/overview/components-PI7.html +/documentation/mojaloop-technical-overview/overview/components-PI6.html;/legacy/mojaloop-technical-overview/overview/components-PI6.html +/documentation/mojaloop-technical-overview/overview/components-PI5.html;/legacy/mojaloop-technical-overview/overview/components-PI5.html +/documentation/mojaloop-technical-overview/overview/components-PI3.html;/legacy/mojaloop-technical-overview/overview/components-PI3.html +/documentation/mojaloop-technical-overview/account-lookup-service/;/legacy/mojaloop-technical-overview/account-lookup-service/ +/documentation/mojaloop-technical-overview/account-lookup-service/als-get-participants.html;/legacy/mojaloop-technical-overview/account-lookup-service/als-get-participants.html +/documentation/mojaloop-technical-overview/account-lookup-service/als-post-participants.html;/legacy/mojaloop-technical-overview/account-lookup-service/als-post-participants.html +/documentation/mojaloop-technical-overview/account-lookup-service/als-post-participants-batch.html;/legacy/mojaloop-technical-overview/account-lookup-service/als-post-participants-batch.html +/documentation/mojaloop-technical-overview/account-lookup-service/als-del-participants.html;/legacy/mojaloop-technical-overview/account-lookup-service/als-del-participants.html +/documentation/mojaloop-technical-overview/account-lookup-service/als-get-parties.html;/legacy/mojaloop-technical-overview/account-lookup-service/als-get-parties.html +/documentation/mojaloop-technical-overview/quoting-service/;/legacy/mojaloop-technical-overview/quoting-service/ +/documentation/mojaloop-technical-overview/quoting-service/qs-get-quotes.html;/legacy/mojaloop-technical-overview/quoting-service/qs-get-quotes.html +/documentation/mojaloop-technical-overview/quoting-service/qs-post-quotes.html;/legacy/mojaloop-technical-overview/quoting-service/qs-post-quotes.html +/documentation/mojaloop-technical-overview/quoting-service/qs-get-bulk-quotes.html;/legacy/mojaloop-technical-overview/quoting-service/qs-get-bulk-quotes.html +/documentation/mojaloop-technical-overview/quoting-service/qs-post-bulk-quotes.html;/legacy/mojaloop-technical-overview/quoting-service/qs-post-bulk-quotes.html +/documentation/mojaloop-technical-overview/central-ledger/;/legacy/mojaloop-technical-overview/central-ledger/ +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/ +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-post-participant-position-limit.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-post-participant-position-limit.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-get-participant-limit-details.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-get-participant-limit-details.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-post-participant-limits.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-post-participant-limits.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/1.1.5-get-transfer-status.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.5-get-transfer-status.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-post-participant-callback-details.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-post-participant-callback-details.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-get-participant-callback-details.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-get-participant-callback-details.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/4.1.0-get-participant-position-details.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/4.1.0-get-participant-position-details.html +/documentation/mojaloop-technical-overview/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.html;/legacy/mojaloop-technical-overview/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/;/legacy/mojaloop-technical-overview/central-ledger/transfers/ +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.1.0-prepare-transfer-request.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.0-prepare-transfer-request.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.1.1.a-prepare-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.1.a-prepare-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.3.1-prepare-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.1-prepare-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.1.2.a-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.2.a-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/1.3.3-abort-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.3-abort-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.3.0-transfer-timeout.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.3.0-transfer-timeout.html +/documentation/mojaloop-technical-overview/central-ledger/transfers/2.3.1-timeout-handler-consume.html;/legacy/mojaloop-technical-overview/central-ledger/transfers/2.3.1-timeout-handler-consume.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/;/legacy/mojaloop-technical-overview/central-bulk-transfers/ +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.2-position-consume-abort.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.2-position-consume-abort.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.html +/documentation/mojaloop-technical-overview/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.html;/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.html +/documentation/mojaloop-technical-overview/central-settlements/;/legacy/mojaloop-technical-overview/central-settlements/ +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/ +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-windows-by-params.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-windows-by-params.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-window-by-id.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-window-by-id.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/post-close-settlement-window.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/post-close-settlement-window.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/post-create-settlement.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/post-create-settlement.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-id.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-id.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-transfer-ack.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-transfer-ack.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-abort.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-abort.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-spa.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-spa.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/get-settlements-by-params.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlements-by-params.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/gross-settlement-handler-consume.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/gross-settlement-handler-consume.html +/documentation/mojaloop-technical-overview/central-settlements/settlement-process/rules-handler-consume.html;/legacy/mojaloop-technical-overview/central-settlements/settlement-process/rules-handler-consume.html +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/ +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/reconciliation-transfer-prepare.html;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/reconciliation-transfer-prepare.html +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/transfer-state-and-position-change.html;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/transfer-state-and-position-change.html +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/funds-in-prepare-reserve-commit.html;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-in-prepare-reserve-commit.html +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-prepare-reserve.html;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-prepare-reserve.html +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-commit.html;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-commit.html +/documentation/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-abort.html;/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-abort.html +/documentation/mojaloop-technical-overview/central-settlements/oss-settlement-fsd.html;/legacy/mojaloop-technical-overview/central-settlements/oss-settlement-fsd.html +/documentation/mojaloop-technical-overview/transaction-requests-service/;/legacy/mojaloop-technical-overview/transaction-requests-service/ +/documentation/mojaloop-technical-overview/transaction-requests-service/transaction-requests-post.html;/legacy/mojaloop-technical-overview/transaction-requests-service/transaction-requests-post.html +/documentation/mojaloop-technical-overview/transaction-requests-service/transaction-requests-get.html;/legacy/mojaloop-technical-overview/transaction-requests-service/transaction-requests-get.html +/documentation/mojaloop-technical-overview/transaction-requests-service/authorizations.html;/legacy/mojaloop-technical-overview/transaction-requests-service/authorizations.html +/documentation/mojaloop-technical-overview/central-event-processor/;/legacy/mojaloop-technical-overview/central-event-processor/ +/documentation/mojaloop-technical-overview/central-event-processor/9.1.0-event-handler-placeholder.html;/legacy/mojaloop-technical-overview/central-event-processor/9.1.0-event-handler-placeholder.html +/documentation/mojaloop-technical-overview/central-event-processor/5.1.1-notification-handler-for-rejections.html;/legacy/mojaloop-technical-overview/central-event-processor/5.1.1-notification-handler-for-rejections.html +/documentation/mojaloop-technical-overview/central-event-processor/signature-validation.html;/legacy/mojaloop-technical-overview/central-event-processor/signature-validation.html +/documentation/mojaloop-technical-overview/event-framework/;/legacy/mojaloop-technical-overview/event-framework/ +/documentation/mojaloop-technical-overview/event-stream-processor/;/legacy/mojaloop-technical-overview/event-stream-processor/ +/documentation/mojaloop-technical-overview/fraud-services/;/legacy/mojaloop-technical-overview/fraud-services/ +/documentation/mojaloop-technical-overview/fraud-services/related-documents/documentation.html;/legacy/mojaloop-technical-overview/fraud-services/related-documents/documentation.html +/documentation/mojaloop-technical-overview/sdk-scheme-adapter/;/legacy/mojaloop-technical-overview/sdk-scheme-adapter/ +/documentation/mojaloop-technical-overview/sdk-scheme-adapter/usage/;/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/ +/documentation/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/;/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/ +/documentation/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/;/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/ +/documentation/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/;/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/ +/documentation/mojaloop-technical-overview/ml-testing-toolkit/;/legacy/mojaloop-technical-overview/ml-testing-toolkit/ +/documentation/repositories/;/legacy/repositories/ +/documentation/repositories/helm.html;/legacy/repositories/helm.html +/documentation/repositories/project.html;/legacy/repositories/project.html +/documentation/glossary.html;/legacy/glossary.html +/documentation/discussions/Mojaloop%20Performance%202020.pdf;/legacy/discussions/Mojaloop%20Performance%202020.pdf \ No newline at end of file diff --git a/infra/src/s3.tf b/infra/src/s3.tf new file mode 100644 index 000000000..4221a5704 --- /dev/null +++ b/infra/src/s3.tf @@ -0,0 +1,74 @@ +# Creates bucket to store logs +resource "aws_s3_bucket" "website_logs" { + provider = aws.custom + bucket = "${var.website-domain-main}-logs" + acl = "log-delivery-write" + + # Comment the following line if you are uncomfortable with Terraform destroying the bucket even if this one is not empty + force_destroy = true + + tags = merge(var.tags, { + ManagedBy = "terraform" + Changed = formatdate("YYYY-MM-DD hh:mm ZZZ", timestamp()) + }) + + lifecycle { + ignore_changes = [tags["Changed"]] + } +} + +# Creates bucket to store the static website +resource "aws_s3_bucket" "website_root" { + provider = aws.custom + bucket = "${var.website-domain-main}-root" + acl = "public-read" + + # Comment the following line if you are uncomfortable with Terraform destroying the bucket even if not empty + force_destroy = true + + logging { + target_bucket = aws_s3_bucket.website_logs.bucket + target_prefix = "${var.website-domain-main}/" + } + + website { + index_document = "index.html" + error_document = "404.html" + } + + tags = merge(var.tags, { + ManagedBy = "mojaloop/documentation" + Changed = formatdate("YYYY-MM-DD hh:mm ZZZ", timestamp()) + }) + + lifecycle { + ignore_changes = [tags["Changed"]] + } +} + +# Creates policy to allow public access to the S3 bucket +resource "aws_s3_bucket_policy" "update_website_root_bucket_policy" { + provider = aws.custom + bucket = aws_s3_bucket.website_root.id + policy = < git.log + + echo "Checking out $GITBOOK_TARGET_BRANCH" + git checkout -b $GITBOOK_TARGET_BRANCH $GITHUB_PROJECT_USERNAME/$GITBOOK_TARGET_BRANCH &> git.log + + echo "Pulling latest code from $GITBOOK_TARGET_BRANCH branch..." + git pull -q $GITHUB_PROJECT_USERNAME $GITBOOK_TARGET_BRANCH --rebase &> git.log + + echo "Copying contents of _book to root..." + cp -R _book/* . + + echo "Staging general changes..." + git add . + + echo "Staging generated UML..." + git add -f assets/images/uml/*.* + + echo "Commiting changes..." + git commit -a -m "Updating release to $GITHUB_TAG" + + echo "Publishing $GITHUB_TAG release to $GITBOOK_TARGET_BRANCH on github..." + git push -q $GITHUB_PROJECT_USERNAME $GITBOOK_TARGET_BRANCH &> git.log +## +# Executors +# +# CircleCI Executors +## +executors: + default-docker: + working_directory: /home/circleci/project + docker: + - image: node:10.15-alpine + + default-machine: + machine: + image: ubuntu-1604:201903-01 + +## +# Jobs +# +# A map of CircleCI jobs +## +jobs: + setup: + executor: default-docker + steps: + - checkout + - run: + <<: *defaults_Dependencies + - run: + name: Access npm folder as root + command: cd $(npm root -g)/npm + - run: + name: Update NPM install + command: npm ci + - run: + name: Delete build dependencies + command: apk del build-dependencies + - save_cache: + key: dependency-cache-{{ checksum "package-lock.json" }} + paths: + - node_modules + + build: + executor: default-docker + steps: + - checkout + - run: + <<: *defaults_Dependencies + - run: + name: Installing build dependencies + command: | + echo 'Installing build dependencies via APK' + apk add --no-cache -t gitbook-build-dependencies openjdk8-jre graphviz ttf-droid ttf-droid-nonlatin + + echo 'Setting env vars' + echo 'export PLANTUML_VERSION=$PLANTUML_VERSION' >> $BASH_ENV + echo 'export LANG=$PLANTUML_LANG' >> $BASH_ENV + + echo 'Downloading plantuml jar' + curl -L https://sourceforge.net/projects/plantuml/files/plantuml.${PLANTUML_VERSION}.jar/download -o plantuml.jar + - restore_cache: + keys: + - dependency-cache-{{ checksum "package-lock.json" }} + - run: + name: Build Gitbooks + command: | + npm run gitbook:build + - save_cache: + key: build-cache-{{ checksum "package-lock.json" }} + paths: + - _book + + test-svg: + executor: default-machine + steps: + - checkout + - run: + name: Set up NVM + command: | + echo ${NVM_DIR} + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + nvm install v10.15.3 + nvm alias default v10.15.3 + node --version + npm ci + - run: + name: Check if plantuml has been updated correctly + command: | + set +o pipefail + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + npm run build:plantuml:all + FILE_COUNT=$(git diff --name-only | grep .svg | wc -l) + if [ ${FILE_COUNT} -ne "0" ]; then + echo "${FILE_COUNT} plantuml files are out of sync. Please run npm run build:plantuml and try again."; + exit 1; + else + echo 'Plantuml files are up to date'; + fi + + deploy: + executor: default-docker + steps: + - checkout + - run: + <<: *defaults_Dependencies + - run: + name: setup environment vars + command: | + echo 'export GITBOOK_TARGET_BRANCH=$GITBOOK_TARGET_BRANCH' >> $BASH_ENV + echo 'export GITHUB_TOKEN=$GITHUB_TOKEN' >> $BASH_ENV + echo 'export GITHUB_PROJECT_USERNAME=$CIRCLE_PROJECT_USERNAME' >> $BASH_ENV + echo 'export GITHUB_PROJECT_REPONAME=$CIRCLE_PROJECT_REPONAME' >> $BASH_ENV + echo 'export GITHUB_TAG=$CIRCLE_TAG' >> $BASH_ENV + echo 'export GIT_CI_USER=$GIT_CI_USER' >> $BASH_ENV + echo 'export GIT_CI_EMAIL=$GIT_CI_EMAIL' >> $BASH_ENV + - restore_cache: + keys: + - build-cache-{{ checksum "package-lock.json" }} + - run: + <<: *defaults_git_identity_setup + - run: + <<: *defaults_publish_to_gh_pages + - run: + <<: *defaults_slack_announcement + +## +# Workflows +# +# CircleCI Workflow config +## +workflows: + version: 2 + build_and_test: + jobs: + - pr-tools/pr-title-check: + context: org-global + - setup: + context: org-global + filters: + tags: + only: /.*/ + branches: + ignore: + - /feature.*/ + - /bugfix.*/ + - gh-pages + - test-svg: + context: org-global + requires: + - setup + filters: + tags: + only: /.*/ + branches: + ignore: + - /feature*/ + - /bugfix*/ + - build: + context: org-global + requires: + - setup + filters: + tags: + only: /.*/ + branches: + ignore: + - /feature.*/ + - /bugfix.*/ + - gh-pages + - deploy: + context: org-global + requires: + - build + filters: + tags: + only: /v[0-9]+(\.[0-9]+)*/ + branches: + ignore: + - /.*/ diff --git a/.dockerignore b/legacy/.dockerignore similarity index 100% rename from .dockerignore rename to legacy/.dockerignore diff --git a/.gitbook.md b/legacy/.gitbook.md similarity index 100% rename from .gitbook.md rename to legacy/.gitbook.md diff --git a/legacy/.gitignore b/legacy/.gitignore new file mode 100644 index 000000000..5f1920278 --- /dev/null +++ b/legacy/.gitignore @@ -0,0 +1,24 @@ +# --------------- # +# IntelliJ # +# --------------- # +.idea/ +**/*.iml + +# VSCode directory +.vscode + +# Node +node_modules + +# Gitbook +_book + +# Gitbook UML +**/uml + +# MacOs +.DS_Store + +*.log + +*.jar diff --git a/.ncurc.json b/legacy/.ncurc.json similarity index 100% rename from .ncurc.json rename to legacy/.ncurc.json diff --git a/legacy/.nvmrc b/legacy/.nvmrc new file mode 100644 index 000000000..95abd2ac4 --- /dev/null +++ b/legacy/.nvmrc @@ -0,0 +1 @@ +10.15.2 diff --git a/legacy/CODEOWNERS b/legacy/CODEOWNERS new file mode 100644 index 000000000..8d2572104 --- /dev/null +++ b/legacy/CODEOWNERS @@ -0,0 +1,38 @@ +# This is a comment. +# Each line is a file pattern followed by one or more owners. + +## These owners will be the default owners for everything in +## the repo. Unless a later match takes precedence, +## @global-owner1 and @global-owner2 will be requested for +## review when someone opens a pull request. +#* @global-owner1 @global-owner2 +* @millerabel @mdebarros @kjw000 @elnyry-sam-k @lewisdaly @simeonoriko + +## Order is important; the last matching pattern takes the most +## precedence. When someone opens a pull request that only +## modifies JS files, only @js-owner and not the global +## owner(s) will be requested for a review. +# *.js @js-owner + +## You can also use email addresses if you prefer. They'll be +## used to look up users just like we do for commit author +## emails. +#*.go docs@example.com + +# In this example, @doctocat owns any files in the build/logs +# directory at the root of the repository and any of its +# subdirectories. +# /build/logs/ @doctocat + +## The `docs/*` pattern will match files like +## `docs/getting-started.md` but not further nested files like +## `docs/build-app/troubleshooting.md`. +# docs/* docs@example.com + +## In this example, @octocat owns any file in an apps directory +## anywhere in your repository. +#apps/ @octocat + +## In this example, @doctocat owns any file in the `/docs` +## directory in the root of your repository. +#/docs/ @doctocat diff --git a/Dockerfile b/legacy/Dockerfile similarity index 100% rename from Dockerfile rename to legacy/Dockerfile diff --git a/legacy/LICENSE.md b/legacy/LICENSE.md new file mode 100644 index 000000000..40350591c --- /dev/null +++ b/legacy/LICENSE.md @@ -0,0 +1,10 @@ +# LICENSE + +Copyright © 2020 Mojaloop Foundation + +The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 +(the "License") and you may not use these files except in compliance with the [License](http://www.apache.org/licenses/LICENSE-2.0). + +You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) + +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the [License](http://www.apache.org/licenses/LICENSE-2.0). diff --git a/legacy/NOTES.md b/legacy/NOTES.md new file mode 100644 index 000000000..5f37bea56 --- /dev/null +++ b/legacy/NOTES.md @@ -0,0 +1,51 @@ +# Documentation Notes + +Helpers and notes for building and working on these docs. + + +## Building `.svg`s from plantuml sources + +We use a git commit hook to automatically rebuild `.svg` files from plantuml +sources. The magic of git hooks means that no extra work is required by you +after creating or editing a `.puml` file + +Behind the scenes, this hook spins up a docker container to run the PUML server +and calls `./scripts/_render_svg.mjs` for each file that has changed. We use the +docker version instead of the public puml server to (1) get around rate limits, and +(2) ensure deterministic SVG output that is git diffable. + +### Creating a new PUML + +1. Create a new `*.puml/plantuml` file +2. Add the file and generate the `.svg` + +```bash +git add . #(or the specific file you are working on) +npm run build:plantuml:diff +``` +3. Update your `.md` file to refer to the newly created `.svg` file +4. Git add/commit +### Updating an existing PUML + +1. Make changes to an existing `*.puml/plantuml` file +2. `git add` + `git commit` +3. The pre-commit hook rebuilds the changed SVG files, and adds them before the commit + +### Building all `.puml` sources manually + +You can also force a complete rebuild of all `.puml` and `.plantuml` sources like so: + +```bash +npm install +npm run build:plantuml:all +``` + +### `test-svg` CI/CD Step + +This is a ci/cd step that ensures that the `.svg` files have been updated +correctly, just in case something got out of sync on your branch before +merging a pull request. + +It runs `npm run build:plantuml:all` to build all of the plantuml sources +and if it detects file changes, it means something went wrong with the +commit hook (or you skipped it with `git commit -n`). diff --git a/legacy/README.md b/legacy/README.md new file mode 100644 index 000000000..a7a7247cb --- /dev/null +++ b/legacy/README.md @@ -0,0 +1,18 @@ +# Mojaloop Overview +[![Git Commit](https://img.shields.io/github/last-commit/mojaloop/documentation.svg?style=flat)](https://github.com/mojaloop/documentation/commits/master) +[![Git Releases](https://img.shields.io/github/release/mojaloop/documentation.svg?style=flat)](https://github.com/mojaloop/documentation/releases) +[![CircleCI](https://circleci.com/gh/mojaloop/documentation.svg?style=svg)](https://circleci.com/gh/mojaloop/documentation) + +Mojaloop is open source software for creating digital payments platforms that connect all customers, merchants, banks, and other financial providers in a country's economy. Rather than a financial product or application in itself, Mojaloop establishes a blueprint for technology that bridges all the financial products and applications in any given market. + +The basic idea behind Mojaloop is that we need to connect multiple Digital Financial Services Providers \(DFSPs\) together into a competitive and interoperable network in order to maximize opportunities for poor people to get access to financial services with low or no fees. We don't want a single monopoly power in control of all payments in a country, or a system that shuts out new players. It also doesn't help if there are too many isolated subnetworks. + +![Mojaloop Solution](./mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-simple.svg) + +Our model addresses these issues in several key ways: + +* A set of central services provides a hub through which money can flow from one DFSP to another. This is similar to how money moves through a central bank or clearing house in developed countries. Besides a central ledger, central services can provide identity lookup, fraud management, and enforce scheme rules. +* A standard set of interfaces a DFSP can implement to connect to the system, and example code that shows how to use the system. A DFSP that wants to connect up can adapt our example code or implement the standard interfaces into their own software. The goal is for it to be as straightforward as possible for a DFSP to connect to the interoperable network. +* Complete working open-source implementations of both sides of the interfaces - an example DFSP that can send and receive payments and the client that an existing DFSP could host to connect to the network. + +The intention for the Mojaloop project is for financial institutions and commercial providers to use the open-source software to help build digital, interoperable payments platforms that drive financial inclusion on a national scale. Specifically, the platforms will enable seamless, low-cost transactions between individual users, merchants, banks, providers, and even government offices - helping connect poor customers with everyone else in the digital economy. diff --git a/legacy/SUMMARY.md b/legacy/SUMMARY.md new file mode 100644 index 000000000..dbe3f67d4 --- /dev/null +++ b/legacy/SUMMARY.md @@ -0,0 +1,181 @@ +# Table of contents + +* [Mojaloop Overview](README.md) +* [Mojaloop Background](mojaloop-background/README.md) + * [Core Scenarios](mojaloop-background/core-scenarios.md) + * [Level One Principles](mojaloop-background/level-one-principles.md) +* [Onboarding](onboarding.md) +* [Deployment Guide](deployment-guide/README.md) + * [Releases](deployment-guide/releases.md) + * [Local Setup Linux](deployment-guide/local-setup-linux.md) + * [Local Setup Mac](deployment-guide/local-setup-mac.md) + * [Local Setup Windows](deployment-guide/local-setup-windows.md) + * [Troubleshooting](deployment-guide/deployment-troubleshooting.md) + * [Upgrade Strategy Guide](deployment-guide/upgrade-strategy-guide.md) + * [Helm v2 to v3 Migration Guide](deployment-guide/helm-legacy-migration.md) + * [Deployment with (Deprecated) Helm v2](deployment-guide/helm-legacy-deployment.md) +* [Contributors Guide](contributors-guide/README.md) + * [New Contributor Checklist](contributors-guide/new-contributor-checklist.md) + * [Code Of Conduct](contributors-guide/code-of-conduct.md) + * [Signing the CLA](contributors-guide/signing-the-cla.md) + * [FAQ](contributors-guide/frequently-asked-questions.md) + * [Standards](contributors-guide/standards/README.md) + * [Versioning](contributors-guide/standards/versioning.md) + * [Creating new Features](contributors-guide/standards/creating-new-features.md) + * [ML OSS Bug Triage](contributors-guide/standards/triaging-ml-oss-bugs.md) + * [Tools and Technologies](contributors-guide/tools-and-technologies/README.md) + * [Pragmatic REST](contributors-guide/tools-and-technologies/pragmatic-rest.md) + * [Code Quality Metrics](contributors-guide/tools-and-technologies/code-quality-metrics.md) + * [Automated Testing](contributors-guide/tools-and-technologies/automated-testing.md) + * [Documentation](contributors-guide/documentation/README.md) + * [API Documentation](contributors-guide/documentation/api-documentation.md) + * [Documentation Style Guide](contributors-guide/documentation/documentation-style-guide.md) +* [Mojaloop Technical Overview](mojaloop-technical-overview/README.md) + * [Mojaloop Hub](mojaloop-technical-overview/overview/README.md) + * [Current Architecture - PI14](mojaloop-technical-overview/overview/components-PI14.md) + * [Current Architecture - PI12](mojaloop-technical-overview/overview/components-PI12.md) + * [Legacy Architecture - PI11](mojaloop-technical-overview/overview/components-PI11.md) + * [Legacy Architecture - PI8](mojaloop-technical-overview/overview/components-PI8.md) + * [Legacy Architecture - PI7](mojaloop-technical-overview/overview/components-PI7.md) + * [Legacy Architecture - PI6](mojaloop-technical-overview/overview/components-PI6.md) + * [Legacy Architecture - PI5](mojaloop-technical-overview/overview/components-PI5.md) + * [Legacy Architecture - PI3](mojaloop-technical-overview/overview/components-PI3.md) + * [Account-Lookup Service](mojaloop-technical-overview/account-lookup-service/README.md) + * [GET Participants](mojaloop-technical-overview/account-lookup-service/als-get-participants.md) + * [POST Participants](mojaloop-technical-overview/account-lookup-service/als-post-participants.md) + * [POST Participants (batch)](mojaloop-technical-overview/account-lookup-service/als-post-participants-batch.md) + * [DEL Participants](mojaloop-technical-overview/account-lookup-service/als-del-participants.md) + * [GET Parties](mojaloop-technical-overview/account-lookup-service/als-get-parties.md) + * [Quoting Service Overview](mojaloop-technical-overview/quoting-service/README.md) + * [GET Quote](mojaloop-technical-overview/quoting-service/qs-get-quotes.md) + * [POST Quote](mojaloop-technical-overview/quoting-service/qs-post-quotes.md) + * [GET Bulk Quote](mojaloop-technical-overview/quoting-service/qs-get-bulk-quotes.md) + * [POST Bulk Quote](mojaloop-technical-overview/quoting-service/qs-post-bulk-quotes.md) + * [Central-Ledger Services](mojaloop-technical-overview/central-ledger/README.md) + * [Admin Operations](mojaloop-technical-overview/central-ledger/admin-operations/README.md) + * [POST Participant Limit](mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md) + * [GET Participant Limit Details](mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md) + * [GET All Participant Limits](mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md) + * [POST Participant limits](mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-post-participant-limits.md) + * [GET Transfer Status](mojaloop-technical-overview/central-ledger/admin-operations/1.1.5-get-transfer-status.md) + * [POST Participant Callback](mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md) + * [GET Participant Callback](mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md) + * [GET Participant Position](mojaloop-technical-overview/central-ledger/admin-operations/4.1.0-get-participant-position-details.md) + * [GET All Participants Positions](mojaloop-technical-overview/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md) + * [Transfer Operations](mojaloop-technical-overview/central-ledger/transfers/README.md) + * [Prepare Handler](mojaloop-technical-overview/central-ledger/transfers/1.1.0-prepare-transfer-request.md) + * [Prepare Handler Consume](mojaloop-technical-overview/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md) + * [Prepare Position Handler](mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.md) + * [Prepare Position Handler v1.1](mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.md) + * [Prepare Position Handler](mojaloop-technical-overview/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md) + * [Position Handler Consume](mojaloop-technical-overview/central-ledger/transfers/1.1.2.a-position-handler-consume.md) + * [Fulfil Handler](mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request.md) + * [Fulfil Handler v1.1](mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.md) + * [Fulfil Handler Consume](mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume.md) + * [Fulfil Handler Consume v1.1](mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.md) + * [Fulfil Position Handler](mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.md) + * [Fulfil Position Handler](mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md) + * [Fulfil Position Handler v1.1](mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.md) + * [Fulfil Reject Transfer](mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md) + * [Fulfil Reject Transfer (a)](mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md) + * [Fulfil Handler (Reject-Abort)](mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler.md) + * [Fulfil Reject Transfer v1.1](mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.md) + * [Fulfil Reject Transfer (a) v1.1](mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.md) + * [Fulfil Handler (Reject-Abort) v1.1](mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.md) + * [Notifications]() + * [Notification to Participant (a)](mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md) + * [Notification to Participant (a) - v1.1](mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.md) + * [Notification to Participant (b)](mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md) + * [Reject/Abort]() + * [Abort Position Handler](mojaloop-technical-overview/central-ledger/transfers/1.3.3-abort-position-handler-consume.md) + * [Timeout]() + * [Transfer Timeout](mojaloop-technical-overview/central-ledger/transfers/2.3.0-transfer-timeout.md) + * [Timeout Handler Consume](mojaloop-technical-overview/central-ledger/transfers/2.3.1-timeout-handler-consume.md) + * [Bulk Transfer Operations](mojaloop-technical-overview/central-bulk-transfers/README.md) + * [Bulk Prepare Overview](mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md) + * [Bulk Prepare Handler](mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md) + * [Prepare Handler](mojaloop-technical-overview/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md) + * [Position Handler Overview](mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md) + * [Prepare Position Handler Consume](mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md) + * [Fulfil Position Handler Consume](mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md) + * [Fulfil Abort Position Handler Consume](mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md) + * [Bulk Fulfil Handler Overview](mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md) + * [Bulk Fulfil Handler Consume](mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md) + * [Fulfil Handler - Commit](mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md) + * [Fulfil Handler - Reject/Abort](mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md) + * [Bulk Processing Handler](mojaloop-technical-overview/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md) + * [Notifications]() + * [Notification to Participant (a)](mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md) + * [Notification to Participant (b)](mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md) + * [Timeout Overview](mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md) + * [Timeout Handler Consume](mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md) + * [Bulk Abort Overview](mojaloop-technical-overview/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.md) + * [Get Bulk Transfer Overview](mojaloop-technical-overview/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.md) + * [Central-Settlements Service](mojaloop-technical-overview/central-settlements/README.md) + * [Settlement Process](mojaloop-technical-overview/central-settlements/settlement-process/README.md) + * [Settlement Windows By Params](mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-windows-by-params.md) + * [Request Settlement Window](mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-window-by-id.md) + * [Close Settlement Window](mojaloop-technical-overview/central-settlements/settlement-process/post-close-settlement-window.md) + * [Create Settlement](mojaloop-technical-overview/central-settlements/settlement-process/post-create-settlement.md) + * [Request Settlement](mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-id.md) + * [Settlement Transfer Acknowledgement](mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-transfer-ack.md) + * [Settlement Abort](mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-abort.md) + * [Request Settlement By SPA](mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-spa.md) + * [Request Settlements By Params](mojaloop-technical-overview/central-settlements/settlement-process/get-settlements-by-params.md) + * [Gross Settlement Handler](mojaloop-technical-overview/central-settlements/settlement-process/gross-settlement-handler-consume.md) + * [Rules Handler](mojaloop-technical-overview/central-settlements/settlement-process/rules-handler-consume.md) + * [Funds In/Out](mojaloop-technical-overview/central-settlements/funds-in-out/README.md) + * [Reconciliation Transfer Prepare](mojaloop-technical-overview/central-settlements/funds-in-out/reconciliation-transfer-prepare.md) + * [Transfer State and Position Change](mojaloop-technical-overview/central-settlements/funds-in-out/transfer-state-and-position-change.md) + * [Funds In](mojaloop-technical-overview/central-settlements/funds-in-out/funds-in-prepare-reserve-commit.md) + * [Funds Out - Prepare & Reserve](mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-prepare-reserve.md) + * [Funds Out - Commit](mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-commit.md) + * [Funds Out - Abort](mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-abort.md) + * [OSS Settlement FSD](mojaloop-technical-overview/central-settlements/oss-settlement-fsd.md) + * [Transaction-requests-service Service](mojaloop-technical-overview/transaction-requests-service/README.md) + * [Transaction Requests Create](mojaloop-technical-overview/transaction-requests-service/transaction-requests-post.md) + * [Transaction Requests Query](mojaloop-technical-overview/transaction-requests-service/transaction-requests-get.md) + * [Authorizations](mojaloop-technical-overview/transaction-requests-service/authorizations.md) + * [Central-Event-Processor Services](mojaloop-technical-overview/central-event-processor/README.md) + * [Event Handler (Placeholder)](mojaloop-technical-overview/central-event-processor/9.1.0-event-handler-placeholder.md) + * [Notification Handler For Rejections](mojaloop-technical-overview/central-event-processor/5.1.1-notification-handler-for-rejections.md) + * [Signature Validation](mojaloop-technical-overview/central-event-processor/signature-validation.md) + * [Event Framework](mojaloop-technical-overview/event-framework/README.md) + * [Event Stream Processor](mojaloop-technical-overview/event-stream-processor/README.md) + * [Fraud Services](mojaloop-technical-overview/fraud-services/README.md) + * [Ecosystem Fraud Documentation](mojaloop-technical-overview/fraud-services/related-documents/documentation.md) + * [SDK Scheme Adapter](mojaloop-technical-overview/sdk-scheme-adapter/README.md) + * [Usage](mojaloop-technical-overview/sdk-scheme-adapter/usage/README.md) + * [Scheme Adapter to Scheme Adapter](mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/README.md) + * [Scheme Adapter to Local ML Cluster](mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/README.md) + * [Scheme Adapter to WSO2 API Gateway](mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/README.md) + * [ML Testing Toolkit](mojaloop-technical-overview/ml-testing-toolkit/README.md) +* [API Specifications](api/README.md) + * [Mojaloop](api/mojaloop-api-specification.md) + * [Central Ledger API](api/central-ledger-api-specification.md) + * [Central Settlements](api/central-settlements-api-specification.md) + * [ALS Oracle](api/als-oracle-api-specification.md) +* [Repo Details](repositories/README.md) + * [Helm](repositories/helm.md) + * [Project](repositories/project.md) +* [Mojaloop Roadmap](mojaloop-roadmap.md) +* [Mojaloop Publications](mojaloop-publications.md) +* [Discussion Documents](discussions/readme.md) + * [ISO integration Overivew](discussions/ISO_Integration.md) + * [Mojaloop Decimal Type; Based on XML Schema Decimal Type](discussions/decimal.md) + * [Workbench Workstream](discussions/workbench.md) + * [Cross Border Meeting Notes Day 1](discussions/cross_border_day_1.md) + * [Cross Border Meeting Notes Day 2](discussions/cross_border_day_2.md) +* [Mojaloop DA, CCB, Scrum-of-scrum Notes](meeting-notes/readme.md) + * [Scrum-of-scrum meeting notes](meeting-notes/scrum-of-scrum-notes.md) + * [DA meeting notes](meeting-notes/da-notes.md) + * [CCB Notes](meeting-notes/ccb-notes.md) +* [Code Quality and Security](quality-security/readme.md) + * [Program Management](quality-security/program-management/readme.md) + * [Vulnerability Reporting](quality-security/program-management/vulnerability-disclosure-procedure.md) + * [Scheme Rules Guidelines](quality-security/program-management/scheme-rules-guidelines.md) + * [Standards + Guidelines](quality-security/standards-guidelines/readme.md) + * [Reference Implementation](quality-security/reference-implementation.md) +* [Frequently Asked Questions](contributors-guide/frequently-asked-questions.md) +* [Glossary of Terms](glossary.md) + diff --git a/api/README.md b/legacy/api/README.md similarity index 100% rename from api/README.md rename to legacy/api/README.md diff --git a/api/als-oracle-api-specification.md b/legacy/api/als-oracle-api-specification.md similarity index 100% rename from api/als-oracle-api-specification.md rename to legacy/api/als-oracle-api-specification.md diff --git a/legacy/api/assets/interface-contracts/oracle-service-swagger-v1.yaml b/legacy/api/assets/interface-contracts/oracle-service-swagger-v1.yaml new file mode 100644 index 000000000..6851ebcc1 --- /dev/null +++ b/legacy/api/assets/interface-contracts/oracle-service-swagger-v1.yaml @@ -0,0 +1,1131 @@ +openapi: 3.0.0 +info: + version: '1.0' + title: >- + Interface for interaction between Mojaloop's Account Lookup Service(ALS) and + an Oracle Registry Service + description: >- + Based on Mojaloop [API + Definition](https://github.com/mojaloop/mojaloop-specification/blob/main/API%20Definition%20v1.1.pdf). + More information can be found at [mojaloop.io](http://mojaloop.io/) + contact: {} +paths: + /health: + get: + tags: + - health + responses: + '200': + $ref: '#/components/responses/200' + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '403': + $ref: '#/components/responses/403' + '404': + $ref: '#/components/responses/404' + '405': + $ref: '#/components/responses/405' + '406': + $ref: '#/components/responses/406' + '501': + $ref: '#/components/responses/501' + '503': + $ref: '#/components/responses/503' + operationId: HealthGet + summary: Get Server + description: >- + The HTTP request GET /health is used to return the current status of the + API. + /metrics: + get: + tags: + - metrics + responses: + '200': + $ref: '#/components/responses/200' + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '403': + $ref: '#/components/responses/403' + '404': + $ref: '#/components/responses/404' + '405': + $ref: '#/components/responses/405' + '406': + $ref: '#/components/responses/406' + '501': + $ref: '#/components/responses/501' + '503': + $ref: '#/components/responses/503' + operationId: MetricsGet + summary: Prometheus metrics endpoint + description: The HTTP request GET /metrics is used to return metrics for the API. + /participants/{Type}/{ID}: + parameters: + - $ref: '#/components/parameters/Type' + - $ref: '#/components/parameters/ID' + post: + description: > + The HTTP request `POST /participants/{Type}/{ID}` + + (or `POST /participants/{Type}/{ID}/{SubId}`) + + is used to create information in the server regarding the provided + identity, + + defined by `{Type}`, `{ID}`, and optionally `{SubId}` + + (for example, `POST /participants/MSISDN/123456789` or + + `POST /participants/BUSINESS/shoecompany/employee1`). + + An ExtensionList element has been added to this request in version v1.1 + summary: Create participant information + tags: + - participants + operationId: ParticipantsByTypeAndIDPost + requestBody: + description: Participant information to be created. + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ParticipantsTypeIDPostPutRequest' + responses: + '201': + description: Created + headers: {} + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '403': + $ref: '#/components/responses/403' + '404': + $ref: '#/components/responses/404' + '405': + $ref: '#/components/responses/405' + '406': + $ref: '#/components/responses/406' + '501': + $ref: '#/components/responses/501' + '503': + $ref: '#/components/responses/503' + get: + description: > + The HTTP request `GET /participants/{Type}/{ID}` (or `GET + /participants/{Type}/{ID}/{SubId}`) + + is used to find out in which FSP the requested Party, defined by + `{Type}`, `{ID}` and optionally `{SubId}`, + is located (for example, `GET /participants/MSISDN/123456789`, or + `GET /participants/BUSINESS/shoecompany/employee1`). + This HTTP request should support a query string for filtering of currency. + To use filtering of currency, the HTTP request `GET /participants/{Type}/{ID}?currency=XYZ` + should be used, where `XYZ` is the requested currency. + summary: Look up participant information + tags: + - participants + operationId: ParticipantsByTypeAndIDGet + parameters: + - $ref: '#/components/parameters/partySubIdOrType' + responses: + '200': + description: OK + headers: + Content-Length: + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ParticipantsTypeIDGetResponse' + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '403': + $ref: '#/components/responses/403' + '404': + $ref: '#/components/responses/404' + '405': + $ref: '#/components/responses/405' + '406': + $ref: '#/components/responses/406' + '501': + $ref: '#/components/responses/501' + '503': + $ref: '#/components/responses/503' + put: + description: | + The PUT /participants/{Type}/{ID} is used to update information in the + server regarding the provided identity, defined by {Type} and {ID} + (for example, PUT /participants/MSISDN/123456789). + summary: Update participant information + tags: + - participants + operationId: ParticipantsByTypeAndIDPut + requestBody: + description: Participant information returned. + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ParticipantsTypeIDPostPutRequest' + responses: + '200': + $ref: '#/components/responses/200' + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '403': + $ref: '#/components/responses/403' + '404': + $ref: '#/components/responses/404' + '405': + $ref: '#/components/responses/405' + '406': + $ref: '#/components/responses/406' + '501': + $ref: '#/components/responses/501' + '503': + $ref: '#/components/responses/503' + delete: + description: > + The HTTP request `DELETE /participants/{Type}/{ID}` + + (or `DELETE /participants/{Type}/{ID}/{SubId}`) is used to delete + + information in the server regarding the provided identity, + + defined by `{Type}` and `{ID}`) (for example, `DELETE + /participants/MSISDN/123456789`), + + and optionally `{SubId}`. This HTTP request should support a query + + string to delete FSP information regarding a specific currency only. + + To delete a specific currency only, the HTTP request + + `DELETE /participants/{Type}/{ID}?currency=XYZ` + + should be used, where `XYZ` is the requested currency. + + + + **Note:** The Account Lookup System should verify that it is the Party’s + current FSP that is deleting the FSP information. + summary: Delete participant information + tags: + - participants + operationId: ParticipantsByTypeAndIDDelete + responses: + '204': + description: No Content + headers: {} + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '403': + $ref: '#/components/responses/403' + '404': + $ref: '#/components/responses/404' + '405': + $ref: '#/components/responses/405' + '406': + $ref: '#/components/responses/406' + '501': + $ref: '#/components/responses/501' + '503': + $ref: '#/components/responses/503' + /participants/{Type}/{ID}/{SubId}: + parameters: + - $ref: '#/components/parameters/Type' + - $ref: '#/components/parameters/ID' + - $ref: '#/components/parameters/SubId' + post: + description: > + The HTTP request `POST /participants/{Type}/{ID}` + + (or `POST /participants/{Type}/{ID}/{SubId}`) + + is used to create information in the server regarding the provided + identity, + + defined by `{Type}`, `{ID}`, and optionally `{SubId}` + + (for example, `POST /participants/MSISDN/123456789` or + + `POST /participants/BUSINESS/shoecompany/employee1`). + + An ExtensionList element has been added to this request in version v1.1 + summary: Create participant information + tags: + - participants + operationId: ParticipantsSubIdByTypeAndIDPost + requestBody: + description: Participant information to be created. + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ParticipantsTypeIDSubIDPostRequest' + responses: + '201': + description: Created + headers: {} + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '403': + $ref: '#/components/responses/403' + '404': + $ref: '#/components/responses/404' + '405': + $ref: '#/components/responses/405' + '406': + $ref: '#/components/responses/406' + '501': + $ref: '#/components/responses/501' + '503': + $ref: '#/components/responses/503' + get: + description: > + The HTTP request `GET /participants/{Type}/{ID}` (or `GET + /participants/{Type}/{ID}/{SubId}`) + + is used to find out in which FSP the requested Party, defined by + `{Type}`, `{ID}` and optionally `{SubId}`, + is located (for example, `GET /participants/MSISDN/123456789`, or + `GET /participants/BUSINESS/shoecompany/employee1`). + This HTTP request should support a query string for filtering of currency. + To use filtering of currency, the HTTP request `GET /participants/{Type}/{ID}?currency=XYZ` + should be used, where `XYZ` is the requested currency. + summary: Look up participant information + tags: + - participants + operationId: ParticipantsSubIdByTypeAndIDGet + responses: + '200': + description: OK + headers: + Content-Length: + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ParticipantsTypeIDGetResponse' + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '403': + $ref: '#/components/responses/403' + '404': + $ref: '#/components/responses/404' + '405': + $ref: '#/components/responses/405' + '406': + $ref: '#/components/responses/406' + '501': + $ref: '#/components/responses/501' + '503': + $ref: '#/components/responses/503' + put: + description: > + The PUT /participants/{Type}/{ID}/{SubId} is used to update information + in the + + server regarding the provided identity, defined by {Type}, {ID} and + {SubId} + + (for example, PUT /participants/MSISDN/123456789/PERSONAL). + summary: Update participant information + tags: + - participants + operationId: ParticipantsSubIdByTypeAndIDPut + requestBody: + description: Participant information returned. + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ParticipantsTypeIDPostPutRequest' + responses: + '200': + $ref: '#/components/responses/200' + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '403': + $ref: '#/components/responses/403' + '404': + $ref: '#/components/responses/404' + '405': + $ref: '#/components/responses/405' + '406': + $ref: '#/components/responses/406' + '501': + $ref: '#/components/responses/501' + '503': + $ref: '#/components/responses/503' + delete: + description: > + The HTTP request `DELETE /participants/{Type}/{ID}` + + (or `DELETE /participants/{Type}/{ID}/{SubId}`) is used to delete + + information in the server regarding the provided identity, + + defined by `{Type}` and `{ID}`) (for example, `DELETE + /participants/MSISDN/123456789`), + + and optionally `{SubId}`. This HTTP request should support a query + + string to delete FSP information regarding a specific currency only. + + To delete a specific currency only, the HTTP request + + `DELETE /participants/{Type}/{ID}?currency=XYZ` + + should be used, where `XYZ` is the requested currency. + + + + **Note:** The Account Lookup System should verify that it is the Party’s + current FSP that is deleting the FSP information. + summary: Delete participant information + tags: + - participants + operationId: ParticipantsSubIdByTypeAndIDDelete + responses: + '204': + description: No Content + headers: {} + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '403': + $ref: '#/components/responses/403' + '404': + $ref: '#/components/responses/404' + '405': + $ref: '#/components/responses/405' + '406': + $ref: '#/components/responses/406' + '501': + $ref: '#/components/responses/501' + '503': + $ref: '#/components/responses/503' + /participants: + post: + description: >- + The HTTP request `POST /participants` is used to create information in + the server regarding the provided list of identities. This request + should be used for bulk creation of FSP information for more than one + Party. The optional currency parameter should indicate that each + provided Party supports the currency. + summary: Create bulk participant information + tags: + - participants + operationId: ParticipantsPost + requestBody: + description: Participant information to be created. + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ParticipantsPostRequest' + responses: + '201': + description: Created + headers: {} + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '403': + $ref: '#/components/responses/403' + '404': + $ref: '#/components/responses/404' + '405': + $ref: '#/components/responses/405' + '406': + $ref: '#/components/responses/406' + '501': + $ref: '#/components/responses/501' + '503': + $ref: '#/components/responses/503' +tags: + - name: participants + description: '' +servers: + - url: / +components: + parameters: + partySubIdOrType: + name: partySubIdOrType + in: query + required: false + schema: + type: string + description: >- + A sub-identifier of the party identifier, or a sub-type of the party + identifier's type. For example, `PASSPORT`, `DRIVING_LICENSE`. + Type: + name: Type + in: path + required: true + schema: + type: string + description: The type of the party identifier. For example, `MSISDN`, `PERSONAL_ID`. + ID: + name: ID + in: path + required: true + schema: + type: string + description: The identifier value. + SubId: + name: SubId + in: path + required: true + schema: + type: string + description: >- + A sub-identifier of the party identifier, or a sub-type of the party + identifier's type. For example, `PASSPORT`, `DRIVING_LICENSE`. + schemas: + ParticipantsTypeIDPostPutRequest: + title: ParticipantsTypeIDPostPutRequest + description: PUT /participants/{Type}/{ID} object + type: object + properties: + fspId: + description: FSP Identifier that the Party belongs to. + type: string + currency: + description: >- + Indicate that the provided Currency was set to be supported by each + successfully added PartyIdInfo. + type: string + partySubIdOrType: + description: A sub-identifier or sub-type for the Party. + type: string + required: + - fspId + ParticipantsTypeIDGetResponse: + title: ParticipantsTypeIDGetResponse + description: OK + type: object + properties: + partyList: + description: >- + List of PartyTypeIdInfo elements that were either created or failed + to be created. + type: array + items: + $ref: '#/components/schemas/PartyTypeIdInfo' + minItems: 1 + maxItems: 10000 + PartyTypeIdInfo: + title: PartyTypeIdInfo + description: Data model for the complex type PartyIdInfo. + type: object + properties: + fspId: + $ref: '#/components/schemas/FspId' + partySubIdOrType: + $ref: '#/components/schemas/PartySubIdOrType' + required: + - fspId + ErrorCode: + title: ErrorCode + type: string + pattern: ^[1-9]\d{3}$ + description: >- + The API data type ErrorCode is a JSON String of four characters, + consisting of digits only. Negative numbers are not allowed. A leading + zero is not allowed. Each error code in the API is a four-digit number, + for example, 1234, where the first number (1 in the example) represents + the high-level error category, the second number (2 in the example) + represents the low-level error category, and the last two numbers (34 in + the example) represent the specific error. + example: '5100' + ErrorDescription: + title: ErrorDescription + type: string + minLength: 1 + maxLength: 128 + description: Error description string. + ExtensionKey: + title: ExtensionKey + type: string + minLength: 1 + maxLength: 32 + description: Extension key. + ExtensionValue: + title: ExtensionValue + type: string + minLength: 1 + maxLength: 128 + description: Extension value. + Extension: + title: Extension + type: object + description: Data model for the complex type Extension. + properties: + key: + $ref: '#/components/schemas/ExtensionKey' + value: + $ref: '#/components/schemas/ExtensionValue' + required: + - key + - value + ExtensionList: + title: ExtensionList + type: object + description: >- + Data model for the complex type ExtensionList. An optional list of + extensions, specific to deployment. + properties: + extension: + type: array + items: + $ref: '#/components/schemas/Extension' + minItems: 1 + maxItems: 16 + description: Number of Extension elements. + required: + - extension + ErrorInformation: + title: ErrorInformation + type: object + description: Data model for the complex type ErrorInformation. + properties: + errorCode: + $ref: '#/components/schemas/ErrorCode' + errorDescription: + $ref: '#/components/schemas/ErrorDescription' + extensionList: + $ref: '#/components/schemas/ExtensionList' + required: + - errorCode + - errorDescription + ErrorInformationResponse: + title: ErrorInformationResponse + type: object + description: >- + Data model for the complex type object that contains an optional element + ErrorInformation used along with 4xx and 5xx responses. + properties: + errorInformation: + $ref: '#/components/schemas/ErrorInformation' + FspId: + title: FspId + type: string + minLength: 1 + maxLength: 32 + description: FSP identifier. + PartySubIdOrType: + title: PartySubIdOrType + type: string + minLength: 1 + maxLength: 128 + description: >- + Either a sub-identifier of a PartyIdentifier, or a sub-type of the + PartyIdType, normally a PersonalIdentifierType. + Currency: + title: Currency + description: >- + The currency codes defined in [ISO + 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter + alphabetic codes are used as the standard naming representation for + currencies. + type: string + minLength: 3 + maxLength: 3 + enum: + - AED + - AFN + - ALL + - AMD + - ANG + - AOA + - ARS + - AUD + - AWG + - AZN + - BAM + - BBD + - BDT + - BGN + - BHD + - BIF + - BMD + - BND + - BOB + - BRL + - BSD + - BTN + - BWP + - BYN + - BZD + - CAD + - CDF + - CHF + - CLP + - CNY + - COP + - CRC + - CUC + - CUP + - CVE + - CZK + - DJF + - DKK + - DOP + - DZD + - EGP + - ERN + - ETB + - EUR + - FJD + - FKP + - GBP + - GEL + - GGP + - GHS + - GIP + - GMD + - GNF + - GTQ + - GYD + - HKD + - HNL + - HRK + - HTG + - HUF + - IDR + - ILS + - IMP + - INR + - IQD + - IRR + - ISK + - JEP + - JMD + - JOD + - JPY + - KES + - KGS + - KHR + - KMF + - KPW + - KRW + - KWD + - KYD + - KZT + - LAK + - LBP + - LKR + - LRD + - LSL + - LYD + - MAD + - MDL + - MGA + - MKD + - MMK + - MNT + - MOP + - MRO + - MUR + - MVR + - MWK + - MXN + - MYR + - MZN + - NAD + - NGN + - NIO + - NOK + - NPR + - NZD + - OMR + - PAB + - PEN + - PGK + - PHP + - PKR + - PLN + - PYG + - QAR + - RON + - RSD + - RUB + - RWF + - SAR + - SBD + - SCR + - SDG + - SEK + - SGD + - SHP + - SLL + - SOS + - SPL + - SRD + - STD + - SVC + - SYP + - SZL + - THB + - TJS + - TMT + - TND + - TOP + - TRY + - TTD + - TVD + - TWD + - TZS + - UAH + - UGX + - USD + - UYU + - UZS + - VEF + - VND + - VUV + - WST + - XAF + - XCD + - XDR + - XOF + - XPF + - XTS + - XXX + - YER + - ZAR + - ZMW + - ZWD + ParticipantsTypeIDSubIDPostRequest: + title: ParticipantsTypeIDSubIDPostRequest + type: object + description: >- + The object sent in the POST /participants/{Type}/{ID}/{SubId} and + /participants/{Type}/{ID} requests. An additional optional ExtensionList + element has been added as part of v1.1 changes. + properties: + fspId: + $ref: '#/components/schemas/FspId' + currency: + $ref: '#/components/schemas/Currency' + extensionList: + $ref: '#/components/schemas/ExtensionList' + required: + - fspId + CorrelationId: + title: CorrelationId + type: string + pattern: >- + ^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ + description: >- + Identifier that correlates all messages of the same sequence. The API + data type UUID (Universally Unique Identifier) is a JSON String in + canonical format, conforming to [RFC + 4122](https://tools.ietf.org/html/rfc4122), that is restricted by a + regular expression for interoperability reasons. A UUID is always 36 + characters long, 32 hexadecimal symbols and 4 dashes (‘-‘). + example: b51ec534-ee48-4575-b6a9-ead2955b8069 + PartyIdType: + title: PartyIdType + type: string + enum: + - MSISDN + - EMAIL + - PERSONAL_ID + - BUSINESS + - DEVICE + - ACCOUNT_ID + - IBAN + - ALIAS + - CONSENT + - THIRD_PARTY_LINK + description: > + Below are the allowed values for the enumeration. + + - MSISDN - An MSISDN (Mobile Station International Subscriber Directory + + Number, that is, the phone number) is used as reference to a + participant. + + The MSISDN identifier should be in international format according to the + + [ITU-T E.164 standard](https://www.itu.int/rec/T-REC-E.164/en). + + Optionally, the MSISDN may be prefixed by a single plus sign, indicating + the + + international prefix. + + - EMAIL - An email is used as reference to a + + participant. The format of the email should be according to the + informational + + [RFC 3696](https://tools.ietf.org/html/rfc3696). + + - PERSONAL_ID - A personal identifier is used as reference to a + participant. + + Examples of personal identification are passport number, birth + certificate + + number, and national registration number. The identifier number is added + in + + the PartyIdentifier element. The personal identifier type is added in + the + + PartySubIdOrType element. + + - BUSINESS - A specific Business (for example, an organization or a + company) + + is used as reference to a participant. The BUSINESS identifier can be in + any + + format. To make a transaction connected to a specific username or bill + number + + in a Business, the PartySubIdOrType element should be used. + + - DEVICE - A specific device (for example, a POS or ATM) ID connected to + a + + specific business or organization is used as reference to a Party. + + For referencing a specific device under a specific business or + organization, + + use the PartySubIdOrType element. + + - ACCOUNT_ID - A bank account number or FSP account ID should be used as + + reference to a participant. The ACCOUNT_ID identifier can be in any + format, + + as formats can greatly differ depending on country and FSP. + + - IBAN - A bank account number or FSP account ID is used as reference to + a + + participant. The IBAN identifier can consist of up to 34 alphanumeric + + characters and should be entered without whitespace. + + - ALIAS An alias is used as reference to a participant. The alias should + be + + created in the FSP as an alternative reference to an account owner. + + Another example of an alias is a username in the FSP system. + + The ALIAS identifier can be in any format. It is also possible to use + the + + PartySubIdOrType element for identifying an account under an Alias + defined + + by the PartyIdentifier. + + - CONSENT - A Consent represents an agreement between a PISP, a Customer + and + + a DFSP which allows the PISP permission to perform actions on behalf of + the + + customer. A Consent has an authoritative source: either the DFSP who + issued + + the Consent, or an Auth Service which administers the Consent. + + - THIRD_PARTY_LINK - A Third Party Link represents an agreement between + a PISP, + + a DFSP, and a specific Customer's account at the DFSP. The content of + the link + + is created by the DFSP at the time when it gives permission to the PISP + for + + specific access to a given account. + example: PERSONAL_ID + PartyIdentifier: + title: PartyIdentifier + type: string + minLength: 1 + maxLength: 128 + description: Identifier of the Party. + example: '16135551212' + PartyIdInfo: + title: PartyIdInfo + type: object + description: Data model for the complex type PartyIdInfo. + properties: + partyIdType: + $ref: '#/components/schemas/PartyIdType' + partyIdentifier: + $ref: '#/components/schemas/PartyIdentifier' + partySubIdOrType: + $ref: '#/components/schemas/PartySubIdOrType' + fspId: + $ref: '#/components/schemas/FspId' + extensionList: + $ref: '#/components/schemas/ExtensionList' + required: + - partyIdType + - partyIdentifier + ParticipantsPostRequest: + title: ParticipantsPostRequest + type: object + description: The object sent in the POST /participants request. + properties: + requestId: + $ref: '#/components/schemas/CorrelationId' + partyList: + type: array + items: + $ref: '#/components/schemas/PartyIdInfo' + minItems: 1 + maxItems: 10000 + description: | + List of PartyIdInfo elements that the client would like to update + or create FSP information about. + currency: + $ref: '#/components/schemas/Currency' + required: + - requestId + - partyList + responses: + '200': + description: OK + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorInformationResponse' + headers: + Content-Length: + $ref: '#/components/headers/Content-Length' + Content-Type: + $ref: '#/components/headers/Content-Type' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorInformationResponse' + headers: + Content-Length: + $ref: '#/components/headers/Content-Length' + Content-Type: + $ref: '#/components/headers/Content-Type' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorInformationResponse' + headers: + Content-Length: + $ref: '#/components/headers/Content-Length' + Content-Type: + $ref: '#/components/headers/Content-Type' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorInformationResponse' + headers: + Content-Length: + $ref: '#/components/headers/Content-Length' + Content-Type: + $ref: '#/components/headers/Content-Type' + '405': + description: Method Not Allowed + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorInformationResponse' + headers: + Content-Length: + $ref: '#/components/headers/Content-Length' + Content-Type: + $ref: '#/components/headers/Content-Type' + '406': + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorInformationResponse' + headers: + Content-Length: + $ref: '#/components/headers/Content-Length' + Content-Type: + $ref: '#/components/headers/Content-Type' + '501': + description: Not Implemented + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorInformationResponse' + headers: + Content-Length: + $ref: '#/components/headers/Content-Length' + Content-Type: + $ref: '#/components/headers/Content-Type' + '503': + description: Service Unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorInformationResponse' + headers: + Content-Length: + $ref: '#/components/headers/Content-Length' + Content-Type: + $ref: '#/components/headers/Content-Type' + headers: + Content-Length: + required: false + schema: + type: integer + description: >- + The `Content-Length` header field indicates the anticipated size of the + payload body. Only sent if there is a body. + + + **Note:** The API supports a maximum size of 5242880 bytes (5 + Megabytes). + Content-Type: + schema: + type: string + required: true + description: >- + The `Content-Type` header indicates the specific version of the API used + to send the payload body. diff --git a/api/central-ledger-api-specification.md b/legacy/api/central-ledger-api-specification.md similarity index 100% rename from api/central-ledger-api-specification.md rename to legacy/api/central-ledger-api-specification.md diff --git a/api/central-settlements-api-specification.md b/legacy/api/central-settlements-api-specification.md similarity index 100% rename from api/central-settlements-api-specification.md rename to legacy/api/central-settlements-api-specification.md diff --git a/legacy/api/mojaloop-api-specification.md b/legacy/api/mojaloop-api-specification.md new file mode 100644 index 000000000..96cef71e4 --- /dev/null +++ b/legacy/api/mojaloop-api-specification.md @@ -0,0 +1,4 @@ +--- +showToc: false +--- +https://raw.githubusercontent.com/mojaloop/mojaloop-specification/master/fspiop-api/documents/v1.0-document-set/fspiop-rest-v1.0-OpenAPI-implementation.yaml \ No newline at end of file diff --git a/mojaloop-technical-overview/account-lookup-service/assets/.gitkeep b/legacy/assets/.gitkeep similarity index 100% rename from mojaloop-technical-overview/account-lookup-service/assets/.gitkeep rename to legacy/assets/.gitkeep diff --git a/mojaloop-technical-overview/central-ledger/.gitkeep b/legacy/assets/diagrams/.gitkeep similarity index 100% rename from mojaloop-technical-overview/central-ledger/.gitkeep rename to legacy/assets/diagrams/.gitkeep diff --git a/book.json b/legacy/book.json similarity index 84% rename from book.json rename to legacy/book.json index 6a11e685e..0028a0338 100644 --- a/book.json +++ b/legacy/book.json @@ -3,8 +3,8 @@ "plugins": ["swagger", "editlink", "include", "insert-logo", "plantuml-svg", "collapsible-chapters", "back-to-top-button", "theme-api", "variables", "changelog", "page-toc" ], "pluginsConfig": { "theme-gestalt": { - "logo": "https://mojaloop.io/images/logo.png", - "favicon": "https://mojaloop.io/images/logo.png", + "logo": "https://docs.mojaloop.io/mojaloop_logo_med.png", + "favicon": "https://docs.mojaloop.io/mojaloop_logo_med.png", "baseUrl": null, "excludeDefaultStyles": false, "doNotHideChildrenChapters" : false @@ -15,7 +15,7 @@ "multilingual": true }, "insert-logo": { - "url": "https://mojaloop.io/images/logo.png", + "url": "https://docs.mojaloop.io/mojaloop_logo_med.png", "style": "background: none; max-height: 140px; max-width: 140px;" }, "theme-api": { diff --git a/book_variables.yml b/legacy/book_variables.yml similarity index 85% rename from book_variables.yml rename to legacy/book_variables.yml index 7e4ca6a02..9b232a7ba 100644 --- a/book_variables.yml +++ b/legacy/book_variables.yml @@ -12,8 +12,8 @@ mojaloop: spec: version: v1.0 uri: - doc: https://github.com/mojaloop/mojaloop-specification/blob/master/API%20Definition%20v1.0.pdf - api: https://github.com/mojaloop/mojaloop-specification/blob/master/Supporting%20Files/fspiop-rest-v1.0-OpenAPI-implementation.yaml + doc: https://mojaloop.io/mojaloop-specification/ + api: https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.0-document-set/fspiop-rest-v1.0-OpenAPI-implementation.yaml central_ledger: spec: version: v2.0 diff --git a/changelog.md b/legacy/changelog.md similarity index 100% rename from changelog.md rename to legacy/changelog.md diff --git a/legacy/contributors-guide/README.md b/legacy/contributors-guide/README.md new file mode 100644 index 000000000..c22389122 --- /dev/null +++ b/legacy/contributors-guide/README.md @@ -0,0 +1,63 @@ +# Contributors Guide + +## How do I contribute? + +* Review the [Mojaloop Deployment](../deployment-guide/) Guide and the [Onboarding Guide](https://github.com/mojaloop/mojaloop/blob/master/onboarding.md) +* Browse through the [Repository Overview](../repositories/) to understand how the Mojaloop code is managed across multiple Github Repositories +* Get familiar with our [Standards](standards/) on contributing to this project +* Go through the [New Contributor Checklist](./new-contributor-checklist.md), and browse through the project board and work on your [good first issue](https://github.com/mojaloop/project/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) +* Review the [Roadmap](../mojaloop-roadmap.md) and contribute to future opportunities +* Familiarize yourself with our Community [Code of Conduct](../code-of-conduct.md) + +## What work is needed? + +Work is tracked as issues in the [mojaloop/project](https://github.com/mojaloop/project) repository GitHub. You'll see issues there that are open and marked as bugs, stories, or epics. An epic is larger work that contains multiple stories. Start with any stories that are marked with "[good first issue](https://github.com/mojaloop/project/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)". In addition, anything that is in the backlog and not assigned to someone are things we could use help with. Stories that have owners are in someone's backlog already, though you can always ask about them in the issue or on Slack. + +There's a [roadmap](../mojaloop-roadmap.md) that shows larger work that people could do or are working on. It has some main initiatives and epics and the order, but lacks dates as this work is community driven. Work is broken down from there into issues in GitHub. + +In general, we are looking for example implementations and bug fixes, and project enhancements. + +### Where do I get help? + +Join the [Mojaloop Slack Discussions](https://mojaloop-slack.herokuapp.com/) to connect with other developers. + +Also checkout the [FAQ](https://github.com/mojaloop/documentation/blob/master/contributors-guide/frequently-asked-questions.md) + +### What is the current release? + +See the [Mojaloop Slack Announcements](https://mojaloop.slack.com/messages/CG3MAJZ5J) to find out information on the latest release. + +### What's here and what's not? + +This is free code provided under an [Apache 2.0 license](https://github.com/mojaloop/mojaloop/blob/master/LICENSE.md). + +The code is released with an Apache 2.0 license but the Specification documents under the 'mojaloop-specification' documents are published with CC BY-ND 4.0 License + +We don't provide production servers to run it on. That's up to you. You are free \(and encouraged!\) to clone these repositories, participate in the community of developers, and contribute back to the code. + +We are not trying to replace any mobile wallet or financial providers. We provide code to link together new and existing financial providers using a common scheme. There are central services for identifying a customer's provider, quoting, fulfillment, deferred net settlement, and shared fraud management. Each provider can take advantage of these services to send and receive money with others on the system and there's no cost to them to onboard new providers. We provide code for a simple example mobile money provider to show how integration can be done, but our example DFSP is not meant to be a production mobile money provider. + +## Where do I send bugs, questions, and feedback? + +For bugs, see [Reporting bugs](https://github.com/mojaloop/mojaloop/blob/master/contribute/Reporting-Bugs.md). + +### Related Projects + +The [Interledger Protocol Suite](https://interledger.org/) \(ILP\) is an open and secure standard that enables DFSPs to settle payments with minimal _counter-party risk_ \(the risk you incur when someone else is holding your money\). With ILP, you can transact across different systems with no chance that someone in the middle disappears with your money. Mojaloop uses the Interledger Protocol Suite for the clearing layer. + +## Types of Contributors + +There are three types of contributors that we are targeting for this phase of the Mojaloop project. + +### Developers or General Contributors + +These individuals are those that want to start contributing to the Mojaloop community. This could be a developer or quality assurance person that wants to write new code or fix a bug. This could also be a business, compliance or risk specialist that wants to help provide rules, write documentation or participate in requirements gathering. + +### Hub Operators + +Typically these or organizations or individuals or government agencies that are interested in setting up their own Mojaloop Switch to become part of the ecosystem. + +### Implementation Teams + +Implementation teams can assist banks, government offices, mobile operators or credit unions in deploying Mojaloop. + diff --git a/legacy/contributors-guide/code-of-conduct.md b/legacy/contributors-guide/code-of-conduct.md new file mode 100644 index 000000000..641649471 --- /dev/null +++ b/legacy/contributors-guide/code-of-conduct.md @@ -0,0 +1,94 @@ +# Mojaloop Code of Conduct + + +## Vision and Mission + +Mojaloop is a portmanteau derived from the Swahili word "Moja" meaning "one" and the English word loop. Mojaloop's vision is to loop digital financial providers and customers together in one inclusive ecosystem. + +The Mojaloop open source project mission is to increase financial inclusion by empowering organizations creating trusted and interoperable payments systems to enable digital financial services for all. We believe an economy that includes everyone, benefits everyone and we are building software that will accelerate full financial inclusion. Succeeding in our mission will require diverse opinions and contributions from people reflecting differing experiences and who come from culturally diverse backgrounds. + +## Community Foundation and Values + +Our goal is a strong and diverse community that welcomes new ideas in a complex field and fosters collaboration between groups and individuals with very different needs, interests, and skills. + +We build a strong and diverse community by actively seeking participation from those who add value to it. + +We treat each other openly and respectfully, we evaluate contributions with fairness and equity, and we seek to create a project that includes everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, and orientation. + +*This code of conduct exists to ensure that diverse groups collaborate to mutual advantage and enjoyment.* + +The Code of Conduct governs how we behave in public or in private, virtually or in person. We expect it to be honoured by everyone who represents the project officially or informally, claims affiliation with the project, or participates directly. + +### We strive to: + +- **Be Considerate**\ + Our work will be used by other people, and we in turn will depend on the work of others. Any decision we take will affect everyone involved in our ecosystem, and we should consider all relevant aspects when making decisions. + +- **Be Respectful**\ + We work together to resolve conflict, assume good intentions, and do our best to act in an empathic fashion. We believe a community where people are respected and feel comfortable is a productive one. + +- **Be Accountable**\ + We are accountable for our words and actions. We all can make mistakes; when we do, we take responsibility for them. If someone has been harmed or offended, we listen carefully and respectfully and work to right the wrong. + +- **Be Collaborative**\ + What we produce is a complex whole made of many parts. Collaboration between teams that each have their own goal and vision is essential; for the whole to be more than the sum of its parts, each part must make an effort to understand the whole.\ + Collaboration reduces redundancy and improves the quality of our work. Internally and externally, we celebrate good collaboration. Wherever possible, we work closely with upstream projects and others in the open-source software community to coordinate our efforts. We prefer to work transparently and involve interested parties as early as possible. + +- **Value Decisiveness, Clarity, and Consensus**\ + Disagreements, social and technical, are normal, but we do not allow them to persist and fester leaving others uncertain of the agreed direction.\ + We expect community members to resolve disagreements constructively. When they face obstacles in doing so, we escalate the matter to structures with designated leaders to arbitrate and provide clarity and direction. + +- **Ask for help when unsure**\ + Nobody is expected to be perfect in this community. Asking questions early avoids many problems later, so questions are encouraged, though they may be directed to the appropriate forum. Those who are asked should be responsive and helpful. + +- **Step Down Considerately**\ + When somebody leaves or disengages from the project, we ask that they do so in a way that minimises disruption to the project. They should tell people they are leaving and take the proper steps to ensure that others can pick up where they left off. + +- **Open Meritocracy**\ +We invite anybody, from any company or organization, to participate in any aspect of the project. Our community is open, and any responsibility can be carried by any contributor who demonstrates the required capacity and competence. + +- **Value Diversity and Inclusion**\ +This is a community that wants to make a real difference to people's lives across the globe; and, in particular, in developing societies and economies. We value our members, first of all, for themselves; and, second, for the help they can give each of us as we work together to transform the world. Each of us will strive never to allow any other considerations to weigh with us, either consciously or unconsciously. In particular, considerations of gender identity or expression, sexual orientation, religion, ethnicity, age, neurodiversity, disability status, language, and citizenship have no place in our collaboration and we will work to eradicate them where we find them: first of all, in ourselves; but after that, and with respect and affection, in those we work with. + +- **Be Transparent**\ +We believe community members will have personal and professional interests in the development of the Mojaloop Open Source Software. These interests will, directly and indirectly, influence perceptions about the best direction of the community. Community members should make every reasonable effort to be transparent about their interests within the limits of confidentiality.  Community members who hold permanent or temporary governance roles should not use those roles in the advancement of personal or professional interests but should base their influence on the best interests of the success of the community. + +This Code of Conduct is not exhaustive or complete. It is not a rulebook; it serves to distill our common understanding of a collaborative, shared environment, and goals. We expect it to be followed in spirit as much as in the letter. + +### Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +- Using welcoming and inclusive language + +- Being respectful of differing viewpoints and experiences + +- Gracefully accepting constructive criticism + +- Focusing on what is best for the community + +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and unwelcome sexual attention or advances + +- Trolling, insulting/derogatory comments, and personal or political attacks + +- Public or private harassment + +- Publishing others' private information, such as a physical or electronic address, without explicit permission + +- Other conduct which could reasonably be considered inappropriate in a professional setting + +### Reporting and Resolution + +If you see someone violating the code of conduct, you are encouraged to address the behavior directly with those involved. Many issues can be resolved quickly and easily, and this gives people more control over the outcome of their dispute. If you are unable to resolve the matter for any reason, or if the behavior is threatening or harassing, report it. We are dedicated to providing an environment where participants feel welcome and safe. + +Reports should be directed to the Community Leadership Committee via an email sent to . This email goes to the Mojaloop Foundation Community Manager whose duty it is to receive and address reported violations of the code of conduct. They will then work with the Community Leadership Committee to address and resolve the report. + +We will investigate every complaint, but you may not receive a direct response. Whether we respond to you directly or not, you will always be able to enquire after the status of a complaint by contacting a member of the Community Leadership Committee. We will use our discretion in determining when and how to follow up on reported incidents, which may range from not taking action to permanent expulsion from the community and foundation-sponsored spaces. We will notify the accused of the report and provide them an opportunity to discuss it before any action is taken. The identity of the reporter will be omitted from the details of the report supplied to the accused. In potentially harmful situations, such as ongoing harassment or threats to anyone's safety, we may take action without notice. + +### Attribution + +This Code of Conduct is adapted from the Ubuntu Code of Conduct v2.0, available at diff --git a/contributors-guide/documentation/README.md b/legacy/contributors-guide/documentation/README.md similarity index 100% rename from contributors-guide/documentation/README.md rename to legacy/contributors-guide/documentation/README.md diff --git a/legacy/contributors-guide/documentation/api-documentation.md b/legacy/contributors-guide/documentation/api-documentation.md new file mode 100644 index 000000000..c1c8f8174 --- /dev/null +++ b/legacy/contributors-guide/documentation/api-documentation.md @@ -0,0 +1,29 @@ +# API Documentation + +All APIs should be documented in RAML or Swagger, see Architecture-Documentation-Guidelines\]\(Architecture-Documentation-Guidelines.md\) + + + +**Section Headings** + +* Do not number headings - for example, "Prepare and Fulfill", not "C - Prepare and Fulfill" +* Make sure section headings \(\# \) match the heading to which they correspond in the comprehensive PDF \(built from the [dactyl config file](https://github.com/Mojaloop/Docs/blob/master/ExportDocs/dactyl-config.yml)\) +* Do not include the word "documentation" in headings + +#### Retrievability + +* For sections that contain many subsections of endpoints or methods, provide a table of contents at the beginning of the section +* Don't say the word project; use component, microservice, interfaces, etc + +#### Language + +Instead of the word "project," use a specific noun such as component, microservice, or interface. + +#### Procedures + +* Introduce procedures with H3 \(\#\#\#\) or H4 \(\#\#\#\#\) headers \(not H2 \(\#\#\)\). +* Do not use numbers in procedure section headings. +* Use ordered-list tagging for procedure steps. For example: +* Step 1 +* Step 2 +* Step 2 diff --git a/legacy/contributors-guide/documentation/documentation-style-guide.md b/legacy/contributors-guide/documentation/documentation-style-guide.md new file mode 100644 index 000000000..2d927651f --- /dev/null +++ b/legacy/contributors-guide/documentation/documentation-style-guide.md @@ -0,0 +1,229 @@ +# Documentation Style Guide + +In most cases, Mojaloop follows the latest edition of the Associated Press Stylebook. The following are foundation-specific guidelines which have been updated and slightly modified. + +#### Acronyms + +Spell out all acronyms on first reference. Include the acronym in parentheses immediately after the full spelling only if you refer to it again in the document. Example: _Kofi Annan, chairman of the board of the Alliance for a Green Revolution in Africa \(AGRA\), traveled to Nairobi this month. It was his first visit to the AGRA office._ + +#### Ampersand + +Only use an ampersand \(&\) when it's part of a formal name like the Bill & Melinda Gates Foundation. In all other cases, spell out and. + +#### Bill & Melinda Gates Foundation + +Our formal legal name is the Bill & Melinda Gates Foundation. Use it on first reference. Always use the ampersand \(&\) and always capitalize Foundation when Bill & Melinda Gates comes before it. + +Never abbreviate the foundation's name as _BMGF_. + +Never translate the foundation name into other languages, as it is a proper noun. The one exception to this is when translating the foundation's name into Chinese, in which case translation is acceptable. + +Do not capitalize foundation when the word stands alone. Example: _The foundation's new headquarters will be built near Seattle Center._ + +Use Gates Foundation only if you are sure the context makes the foundation's identity clear. There is a Gates Family Foundation in Colorado, so we need to be careful. Example: _The Bill & Melinda Gates Foundation and the Ford Foundation co-sponsored the event. A Gates Foundation staff member gave closing remarks._ + +The entity that manages the endowment is formally and legally known as the Bill & Melinda Gates Foundation Trust. You will not need to refer to this entity often, but when you do, write it out on first reference and refer to it as the asset trust thereafter. + +#### Bold and colons + +Frequently I see structures \(like in this very comment!\) where you have introductory terms or phrases that are bolded and set apart from the contents with a colon. Should the colon also be bolded, or not? \(I frequently see it done both ways.\) + +#### Buffett + +Note the spelling: two fs and two ts \(_i.e., Warren Buffett_\). + +#### Bulleted lists + +Introduce bulleted lists with a colon when the listed items complete the lead-in sentence or phrase. Exception: never use colons in headings or subheadings to introduce bulleted lists. + +Capitalize the first words of and use periods with listed items only if they are full sentences. Examples: + +* _This is a complete sentence._ +* _not a complete sentence_ + +Never link items in a bulleted list with coordinating conjunctions and punctuation \(semicolons or commas\) as you would in a sentence-style list. In other words, never do: + +* _this,_ +* _that, or_ +* _the other thing._ + +#### Captions + +Caption photos whenever possible. It helps people understand our work. + +Write captions as single gerund \(_ing verb_\) phrases, followed by the city, state or country, and year the photo was taken in parentheses. Example: _A doctor preparing a vaccine for delivery_ \(Brazzaville, Congo, 2007\).\_ + +When writing a caption, be sure to introduce the people featured and explain what's happening in the image as it relates to our areas of focus. Be as brief as possible so you don't distract from the image or layout. Avoid verbs that state the obvious about what the photo's subject is doing _\(e.g., smiling, standing, and so on\)._ + +If one of the co-chairs appears in a photo with other people, be sure to identify the co-chair in the caption. Don't assume everyone knows what our co-chairs look like. + +#### Citations + +Most fields have their own citation conventions. Adopt those used by the field in question. When citation conventions are unavailable or uncertain, follow The Chicago Manual of Style. + +When a document uses both footnotes and endnotes, for the footnotes, use the following symbols: + +* 1st note = \* \(asterisk\) +* 2nd note = † \(dagger\) +* 3rd note = ‡ \(double dagger\) +* 4th note = § \(section sign\) +* 5th note = \*\* \(2 asterisks\) +* 6th note = †† \(2 daggers\) +* 7th note = ‡‡ \(2 double daggers\) +* 8th note = §§ \(2 section signs\) + +Separate multiple superscript references \(footnotes, endnotes\) with commas, not semicolons. + +#### Clinical trials + +Use Roman numerals when referring to clinical trial phases and always capitalize Phase. Example: The company will begin Phase III trials on the new drug this spring. + +#### Contact information + +Use periods to separate parts of phone numbers, and begin each number with a plus sign. + +Because we work with people throughout the world, omit the international access code, which differs from country to country \(it's 011 in the United States\). Examples: _+1.206.709.3100 \(United States\)_ _+91.11.4100.3100 \(India\)_ + +#### Copyright and trademark notice + +All publications, media, and materials produced by or for the foundation should contain the notice shown below. The Legal team must approve all exceptions. + + _© \(year\) Bill & Melinda Gates Foundation. All Rights Reserved._ Bill & Melinda Gates Foundation is a registered trademark in the United States and other countries. + +When possible, begin the trademark portion of the notice on a separate line. + +#### Dashes + +Use dashes—those the width of a capital M—to indicate asides or abrupt changes in thought. Use en dashes—those the width of a capital N—with numerical ranges. + +Do not include a space before or after a dash. + +Examples: _We work to make safe, affordable financial services—particularly savings accounts—more widely available to people in developing countries._ + +_In the 2004 presidential election, 76 percent of U.S. college graduates ages 25-44 voted._ + +#### Dollars \($\) + +In Global Health and Global Development materials, because more than a dozen countries use dollars, specify U.S. dollars in parentheses on first mention in a document. Example: _$100,000 \(U.S.\)_. Omit the parenthetical U.S. in subsequent references to dollar amounts in the same document. + +#### Foundation program names + +We have three programs: Global Development Program, Global Health Program, and United States Program. + +_Program_ is capitalized when used with the full name \(Global Development Program\), but not when used alone \(The program makes grants in several areas.\). + +Use periods when abbreviating the name of the United States Program: U.S. Program. + +GH, GD, and USP are fine for internal use, but inappropriate for external publications. + +#### Gates family + +William Gates III is formally referred to as Bill Gates. In internal documents, use Bill—not a nickname or abbreviation. + +Use Melinda Gates when formally referring to Melinda. + +Use William H. Gates Sr. when formally referring to Bill Gates Sr. There is no comma between Gates and Sr. Bill Sr. is acceptable in internal documents. + +Plural: Gateses. Do not use an apostrophe to form the plural of the family's name. Example: The Gateses attended the opening of the new University of Washington law building. + +Possessive: The apostrophe follows Gates when you refer to something owned by either Bill or Melinda. Example: Melinda Gates' speech was well received. The apostrophe follows Gateses when you refer to something Bill and Melinda own jointly. Example: _The Gateses' decision to provide free Internet access in U.S. public libraries has increased library usage and circulation overall._ + +You may also phrase it this way: Bill and Melinda Gates' decision to provide free Internet access … + +See the Titles of people entry for the formal titles of Bill, Melinda, Bill Sr., and other leaders of the foundation. + +#### Hyphens + +There are few hard-and-fast rules when it comes to hyphens. Generally we use them to enhance the reader's understanding. + +Examples: _When writing for the Bill & Melinda Gates Foundation, use real-world poverty examples to illustrate your point._ _When writing for the Bill & Melinda Gates Foundation, use real world-poverty examples to illustrate your point._ + +In the first example, the hyphen in real-world connects real and world to form a single adjective describing poverty. In the second example, the hyphen in world-poverty connects world and poverty to form a single adjective describing examples. + +The meaning changes depending on the placement of the hyphen. In instances where a series of adjectives creates ambiguity about what they refer to, use a hyphen to clarify the intended meaning. + +When capitalizing hyphenated words, only capitalize the first part. Example: _Co-chairs Bill and Melinda Gates._ + +For other uses of hyphens—compound modifiers, prefixes and suffixes, fractions—refer to the Associated Press Stylebook. + +#### Numerals + +When referring to dollar figures, spell out million and billion. Use figures and decimals \(not fractions\). Do not go beyond two decimal places. Example: _The foundation granted .45 million to United Way._ + +When using numbers that have nothing to do with dollar figures or percentages, write them out if they are under 10, and use numerals if they are 10 or over. Example: Four program officers went on 13 site visits. + +In cases of grammatical parallelism, parallel construction always trumps this rule. For instance: Mr. Johnson has two children, 5-year-old Kyle and 13-year-old Frances. + +Never begin a sentence with a numeral. Either spell the number out or revise the sentence so it doesn't begin with a number. + +#### Percentages + +When using percentages, write out percent \(don't use %\). Use numerals instead of writing numbers out, even if they're less than 10. + +Example: _This program accounts for 6 percent of our grantmaking._ + +#### Photographer credits + +If the foundation owns the image you are using, you don't need to credit the photographer. All images in our media asset management system are foundation-owned. If the foundation has purchased a license to use the image, you may need to credit the photographer. If you have questions about photo credit requirements, contact the Foundation Communications Service Desk. + +#### Plain language + +We could call out a few specific constructions that are needlessly wordy. One that we frequently catch at Ripple is "in order to" instead of just "to." + +#### Quotation marks + +Use double quotation marks for dialogue and the citation of printed sources. Limit use of scare quotes—quotation marks meant to call attention to a quoted word or phrase and distance the author from its meaning, typically because the language is specialized, idiomatic, ironic, or misused. Example: _The foundation has increasingly used “program-related investments” in recent years._ + +#### Quoted strings and punctuation + +When describing exact strings in technical documentation, should punctuation \(not part of the literal strings\) be included in the quotation marks? For example, valid states include "pending," "in progress," and "completed." + +#### Scientific names + +Capitalize and italicize scientific names in accordance with conventions in the scientific community. Use the full version of a scientific name on first mention and the abbreviated form thereafter. For example, _use Salmonella typhi first and S. typhi for each additional reference._ + +#### Serial commas + +With lists of three or more items in a sentence, add a final comma before the coordinating conjunction and or or. Example: _The foundation's three program areas are Global Development, Global Health, and the United States._ + +#### Spacing after punctuation + +Use only one space after punctuation, including periods, colons, and semicolons. + +#### Spelling and capitalization conventions + +_bed net:_ two words, no hyphen. + +_email:_ one word, no hyphen, lowercase. + +_foundation:_ lowercase, except as part of the full foundation name. + +_grantmaking:_ one word, no hyphen. + +_nongovernmental:_ one word, no hyphen. + +_nonprofit:_ one word, no hyphen. + +_postsecondary:_ one word, no hyphen. + +_Washington state:_ lowercase state \(unless you're referring to Washington State University, the Washington State Legislature, or something similar\). + +_website:_ one word, lowercase + +#### Titles of people + +Formal titles should not be capitalized unless the title precedes a person's name or appears in a headline. Example: _Co-chair Melinda Gates will speak at the Washington Economic Club this year._ + +Lowercase and spell out titles when they are not used with an individual's name. Example: _The foundation co-chair issued a statement._ + +Lowercase and spell out titles in constructions that use commas to set them off from a name. Example: _Bill Gates, co-chair of the foundation, commented on the grant._ + +#### United States + +Spell out United States when using it as a noun. Abbreviate it as U.S. \(including periods\) when using it as an adjective. In certain cases, as when referring to a person from the United States, it's acceptable to use American. + +Examples: _The U.S. State Department is in the United States._ _The foundation's U.S. Program…_ + +#### URL + +Reference web addresses without the http:// as follows: _www.gatesfoundation.org_ diff --git a/contributors-guide/frequently-asked-questions.md b/legacy/contributors-guide/frequently-asked-questions.md similarity index 77% rename from contributors-guide/frequently-asked-questions.md rename to legacy/contributors-guide/frequently-asked-questions.md index edf79bc54..58ac80757 100644 --- a/contributors-guide/frequently-asked-questions.md +++ b/legacy/contributors-guide/frequently-asked-questions.md @@ -8,43 +8,46 @@ This document contains some of the most frequently asked questions from the comm ### Table of Content -* [What is Mojaloop](#1-what-is-mojaloop) -* [How does it work](#2-how-does-it-work) -* [Who is it for](#3-who-is-it-for) -* [Why does it exist](#4-why-does-it-exist) -* [Who's behind it](#5-whos-behind-it) -* [What platforms does Mojaloop run on](#6-what-platforms-does-mojaloop-run-on) -* [Is it really open-source](#7-is-it-really-open-source) -* [How can I contribute to Mojaloop](#8-how-can-i-contribute-to-mojaloop) -* [What is supported](#9-what-is-supported) -* [Can we connect directly to Pathfinder in a development environment](#10-can-we-connect-directly-to-pathfinder-in-a-development-environment) -* [Should i register DFSP via url or update configuration in default.json](#11-should-i-register-dfsp-via-urlhttpcentral-directorycommandsregisteror-i-need-to-update-configuration-in-defaultjson) -* [Status of the pod pi3-kafka-0 is still on CrashLoopBackOff](#12-status-of-the-pod-pi3-kafka-0-is-still-on-crashloopbackoff) -* [Why am I getting an error when we try to create new DFSP using Admin](#13-why-am-i-getting-an-error-when-we-try-to-create-new-dfsp-using-admin) -* [Using Mojaloop to do payment using crypto-currency](#14-using-mojaloop-to-do-payment-using-crypto-currency) -* [Can I spread Mojaloop components over different physical machines and VM's](#15--can-i-spread-mojaloop-components-over-different-physical-machines-and-vms) -* [Can we expect all the endpoints defined in the API document are implemented in Mojaloop](#16-can-we-expect-all-the-endpoints-defined-in-the-api-document-are-implemented-in-mojaloop) -* [Does Mojaloop store the payment initiator FSP’s quote/status info](#17-does-mojaloop-store-the-payment-initiator-fsps-quotestatus-info) -* [Does Mojaloop handle workflow validation](#18-does-mojaloop-handle-workflow-validation) -* [How is the Mojaloop source accessible](#19-how-is-the-mojaloop-source-accessible) -* [How to register a new party in Mojaloop](#20-how-to-register-a-new-party-in-mojaloop) -* [Does the participant represent an account of a customer in a bank](#21-does-the-participant-represent-an-account-of-a-customer-in-a-bank) -* [How to register _trusted_ payee to a payer, to skip OTP](#22-how-to-register-trusted-payee-to-a-payer-to-skip-otp) -* [Receiving a 404 error when attempting to access or load kubernetes-dashboard.yaml file](#23-receiving-a-404-error-when-attempting-to-access-or-load-kubernetes-dashboardyaml-file) -* [When installing nginx-ingress for load balancing & external access - Error: no available release name found](#24-when-installing-nginx-ingress-for-load-balancing--external-access---error-no-available-release-name-found) -* [Received "ImportError: librdkafka.so.1: cannot open shared object file: No such file or directory" when running `npm start' command](#25-received-importerror-librdkafkaso1-cannot-open-shared-object-file-no-such-file-or-directory-when-running-npm-start-command) -* [Can we use mojaloop as open-source mobile wallet software or mojaloop does interoperability only](#26-can-we-use-mojaloop-as-open-source-mobile-wallet-software-or-mojaloop-does-interoperability-only) -* [Describe companies that helps to deploy & support for mojaloop](#27-describe-companies-that-helps-to-deploy--support-for-mojaloop) -* [Can you say something about mojaloop & security](#28-can-you-say-something-about-mojaloop--security) -* [What are the benefit(s) from using mojaloop as interoperabilty platform](#29-what-are-the-benefits-from-using-mojaloop-as-interoperabilty-platform) -* [What are the main challenges that companies face using mojaloop](#30-what-are-the-main-challenges-that-companies-face-using-mojaloop) -* [Is forensic logging/audit in mojaloop , is it related with securing the inter-operability platform](#31-is-forensic-loggingaudit-in-mojaloop--is-it-related-with-securing-the-inter-operability-platform) -* [How do the financial service providers connect with mojaloop](#32-how-do-the-financial-service-providers-connect-with-mojaloop) -* [Is there any open source ISO8583-OpenAPI converter/connector available](#33-is-there-any-open-source-iso8583-openapi-converterconnector-available) -* [How do I know the end points to setup postman for testing the deployment](#34-how-do-i-know-the-end-points-to-setup-postman-for-testing-the-deployment) -* [Why are there no reversals allowed on a Mojaloop](#35-why-are-there-no-reversals-allowed-on-a-mojaloop) -* [ffg. error with microk8s installation "MountVolume.SetUp failed"](#36-ffg-error-with-microk8s-installation-mountvolumesetup-failed) -* [Why am I getting this error when trying to create a participant: "Hub reconciliation account for the specified currency does not exist"?](#37-why-am-i-getting-this-error-when-trying-to-create-a-participant-hub-reconciliation-account-for-the-specified-currency-does-not-exist) +- [Frequently Asked Questions](#frequently-asked-questions) + - [Table of Content](#table-of-content) + - [1. What is Mojaloop?](#1-what-is-mojaloop) + - [2. How does it work?](#2-how-does-it-work) + - [3. Who is it for?](#3-who-is-it-for) + - [4. Why does it exist?](#4-why-does-it-exist) + - [5. Who's behind it?](#5-whos-behind-it) + - [6. What platforms does Mojaloop run on?](#6-what-platforms-does-mojaloop-run-on) + - [7. Is it really open-source?](#7-is-it-really-open-source) + - [8. How can I contribute to Mojaloop?](#8-how-can-i-contribute-to-mojaloop) + - [9. What is supported?](#9-what-is-supported) + - [10. Can we connect directly to Pathfinder in a development environment?](#10-can-we-connect-directly-to-pathfinder-in-a-development-environment) + - [11. Should i register DFSP via url http://central-directory/commands/register or i need to update configuration in default.json?](#11-should-i-register-dfsp-via-urlhttpcentral-directorycommandsregisteror-i-need-to-update-configuration-in-defaultjson) + - [12. Status of the pod pi3-kafka-0 is still on CrashLoopBackOff?](#12-status-of-the-pod-pi3-kafka-0-is-still-on-crashloopbackoff) + - [13. Why am I getting an error when we try to create new DFSP using Admin?](#13-why-am-i-getting-an-error-when-we-try-to-create-new-dfsp-using-admin) + - [14. Using Mojaloop to do payment using crypto-currency?](#14-using-mojaloop-to-do-payment-using-crypto-currency) + - [15. Can I spread Mojaloop components over different physical machines and VM's?](#15--can-i-spread-mojaloop-components-over-different-physical-machines-and-vms) + - [16. Can we expect all the endpoints defined in the API document are implemented in Mojaloop?](#16-can-we-expect-all-the-endpoints-defined-in-the-api-document-are-implemented-in-mojaloop) + - [17. Does Mojaloop store the payment initiator FSP’s quote/status info?](#17-does-mojaloop-store-the-payment-initiator-fsps-quotestatus-info) + - [18. Does Mojaloop handle workflow validation?](#18-does-mojaloop-handle-workflow-validation) + - [19. How is the Mojaloop source accessible?](#19-how-is-the-mojaloop-source-accessible) + - [20. How to register a new party in Mojaloop?](#20-how-to-register-a-new-party-in-mojaloop) + - [21. Does the participant represent an account of a customer in a bank?](#21-does-the-participant-represent-an-account-of-a-customer-in-a-bank) + - [22. How to register _trusted_ payee to a payer, to skip OTP?](#22-how-to-register-trusted-payee-to-a-payer-to-skip-otp) + - [23. Receiving a 404 error when attempting to access or load kubernetes-dashboard.yaml file?](#23-receiving-a-404-error-when-attempting-to-access-or-load-kubernetes-dashboardyaml-file) + - [24. When installing nginx-ingress for load balancing & external access - Error: no available release name found?](#24-when-installing-nginx-ingress-for-load-balancing--external-access---error-no-available-release-name-found) + - [25. Received "ImportError: librdkafka.so.1: cannot open shared object file: No such file or directory" when running `npm start' command.](#25-received-importerror-librdkafkaso1-cannot-open-shared-object-file-no-such-file-or-directory-when-running-npm-start-command) + - [26. Can we use mojaloop as open-source mobile wallet software or mojaloop does interoperability only?](#26-can-we-use-mojaloop-as-open-source-mobile-wallet-software-or-mojaloop-does-interoperability-only) + - [27. Describe companies that helps to deploy & support for mojaloop?](#27-describe-companies-that-helps-to-deploy--support-for-mojaloop) + - [28. Can you say something about mojaloop & security?](#28-can-you-say-something-about-mojaloop--security) + - [29. What are the benefit(s) from using mojaloop as interoperabilty platform?](#29-what-are-the-benefits-from-using-mojaloop-as-interoperabilty-platform) + - [30. What are the main challenges that companies face using mojaloop?](#30-what-are-the-main-challenges-that-companies-face-using-mojaloop) + - [31. Is forensic logging/audit in mojaloop , is it related with securing the inter-operability platform?](#31-is-forensic-loggingaudit-in-mojaloop--is-it-related-with-securing-the-inter-operability-platform) + - [32. How do the financial service providers connect with mojaloop?](#32-how-do-the-financial-service-providers-connect-with-mojaloop) + - [33. Is there any open source ISO8583-OpenAPI converter/connector available?](#33-is-there-any-open-source-iso8583-openapi-converterconnector-available) + - [34. How do I know the end points to setup postman for testing the deployment?](#34-how-do-i-know-the-end-points-to-setup-postman-for-testing-the-deployment) + - [35. Why are there no reversals allowed on a Mojaloop?](#35-why-are-there-no-reversals-allowed-on-a-mojaloop) + - [36. ffg. error with microk8s installation "MountVolume.SetUp failed"?](#36-ffg-error-with-microk8s-installation-mountvolumesetup-failed) + - [37. Why am I getting this error when trying to create a participant: "Hub reconciliation account for the specified currency does not exist"?](#37-why-am-i-getting-this-error-when-trying-to-create-a-participant-hub-reconciliation-account-for-the-specified-currency-does-not-exist) + - [38. Resolve problems with VSCode and kafka on ubuntu 18.04. To make the code work with VSCode debugger, added the following into the launch.json](#38-resolve-problems-with-vscode-and-kafka-on-ubuntu-1804-to-make-the-code-work-with-vscode-debugger-added-the-following-into-the-launchjson) #### 1. What is Mojaloop? @@ -139,7 +142,7 @@ Not at the moment, but this may happen in the future. Regarding correlating requ #### 19. How is the Mojaloop source accessible? Here are some resources to start with: -1. Docs: https://github.com/mojaloop/documents. Note we are in the process to migrate from https://github.com/mojaloop/docs to https://github.com/mojaloop/documents. +1. Docs: https://github.com/mojaloop/documentation. 2. Look at the repos that have “CORE COMPONENT (Mojaloop)” in the description and these are core components. “CORE RELATED (Mojaloop)” repos are the ones that are needed to support the current Mojaloop Switch implementation/deployment. 3. As a generic point of note, for latest code, please use the ‘develop’ branch for the time-being. 4. Current architecture: https://github.com/mojaloop/docs/tree/master/Diagrams/ArchitectureDiagrams. Please note that these are currently being migrated to https://github.com/mojaloop/documents. @@ -252,3 +255,12 @@ You need to create the corresponding Hub accounts (HUB_MULTILATERAL_SETTLEMENT a In this Postman collection you can find the requests to perform the operation in the "Hub Account" folder: https://github.com/mojaloop/postman/blob/master/OSS-New-Deployment-FSP-Setup.postman_collection.json Find also the related environments in the Postman repo: https://github.com/mojaloop/postman + +#### 38. Resolve problems with VSCode and kafka on ubuntu 18.04. To make the code work with VSCode debugger, added the following into the launch.json + + ```json + "env": { + "LD_LIBRARY_PATH": "${workspaceFolder}/node_modules/node-rdkafka/build/deps", + "WITH_SASL": 0 + } + ``` diff --git a/legacy/contributors-guide/images/cla/admin_configure.png b/legacy/contributors-guide/images/cla/admin_configure.png new file mode 100644 index 000000000..1d8281bb4 Binary files /dev/null and b/legacy/contributors-guide/images/cla/admin_configure.png differ diff --git a/legacy/contributors-guide/images/cla/admin_sign_in.png b/legacy/contributors-guide/images/cla/admin_sign_in.png new file mode 100644 index 000000000..a960e2dcd Binary files /dev/null and b/legacy/contributors-guide/images/cla/admin_sign_in.png differ diff --git a/legacy/contributors-guide/images/cla/cla_1.png b/legacy/contributors-guide/images/cla/cla_1.png new file mode 100644 index 000000000..46718fc66 Binary files /dev/null and b/legacy/contributors-guide/images/cla/cla_1.png differ diff --git a/legacy/contributors-guide/images/cla/cla_2_1.png b/legacy/contributors-guide/images/cla/cla_2_1.png new file mode 100644 index 000000000..18ae1809c Binary files /dev/null and b/legacy/contributors-guide/images/cla/cla_2_1.png differ diff --git a/legacy/contributors-guide/images/cla/cla_2_2.png b/legacy/contributors-guide/images/cla/cla_2_2.png new file mode 100644 index 000000000..2e60fb762 Binary files /dev/null and b/legacy/contributors-guide/images/cla/cla_2_2.png differ diff --git a/legacy/contributors-guide/images/cla/cla_3.png b/legacy/contributors-guide/images/cla/cla_3.png new file mode 100644 index 000000000..5e2ddc46d Binary files /dev/null and b/legacy/contributors-guide/images/cla/cla_3.png differ diff --git a/legacy/contributors-guide/new-contributor-checklist.md b/legacy/contributors-guide/new-contributor-checklist.md new file mode 100644 index 000000000..b189457d2 --- /dev/null +++ b/legacy/contributors-guide/new-contributor-checklist.md @@ -0,0 +1,67 @@ +# New Contributor Checklist + +This guide summarizes the steps needed to get up and running as a contributor to Mojaloop. They needn't be completed all in one sitting, but by the end of the checklist, you should have learned a good deal about Mojaloop, and be prepared to contribute to the community. + + +## 1. Tools & Documentation + +- Make sure you have a GitHub account already, or sign up for an account [here](https://github.com/join) + +- Join the slack community at the [self-invite link](https://mojaloop-slack.herokuapp.com/), and join the following channels: + - `#announcements` - Announcements for new Releases and QA Status + - `#design-authority` - Questions + Discussion around Mojaloop Design + - `#general` - General discussion about Mojaloop + - `#help-mojaloop` - Ask for help with installing or running Mojaloop + - `#ml-oss-bug-triage` - Discussion and triage for new bugs and issues + +- Say hi! Feel free to give a short introduction of yourself to the community on the `#general` channel. + +- Review the [Git workflow guide](https://mojaloop.io/documentation/contributors-guide/standards/creating-new-features.html) and ensure you are familiar with git. + - Further reading: [Introduction to Github workflow](https://www.atlassian.com/git/tutorials/comparing-workflows) + +- Familiarize yourself with our standard coding style: https://standardjs.com/ + +- Browse through the [Mojaloop Documentation](https://mojaloop.io/documentation/) and get a basic understanding of how the technology works. + +- Go through the [Developer Tools Guide](https://github.com/mojaloop/mojaloop/blob/master/onboarding.md) to get the necessary developer tools up and running on your local environment. + +- (Optional) Get the Central-Ledger up and running on local machines: + - https://github.com/mojaloop/central-ledger/blob/master/Onboarding.md + - https://github.com/mojaloop/ml-api-adapter/blob/master/Onboarding.md + +- (Optional:) Run an entire switch yourself with Kubernetes https://mojaloop.io/documentation/deployment-guide/ _(note: if running locally, your Kubernetes cluster will need 8gb or more of RAM)_ + +## 2. Finding an Issue + +- Review the [good-first-issue](https://github.com/mojaloop/project/labels/good%20first%20issue) list on [`mojaloop/project`](https://github.com/mojaloop/project), to find a good issue to start working on. Alternatively, reach out to the community on Slack at `#general` to ask for help to find an issue. + +- Leave a comment on the issue asking for it to be assigned to you -- this helps make sure we don't duplicate work. As always, reach out to us on Slack if you have any questions or concerns. + +- Fork the relevant repos for the issue, clone and create a new branch for the issue + - Refer to our [git user guide](https://mojaloop.io/documentation/contributors-guide/standards/creating-new-features.html) if you get lost + + +## 3. Opening your First PR + +> _Complete this part of the guide once you have been added to the Mojaloop GitHub organization. If you don't have access, reach out to us on the `#general` or `#help-mojaloop` + +- Sign up for [Zenhub](https://www.zenhub.com/), and connect it to the Mojaloop Organisation, Search for the _'project'_ workspace +- Install the [Zenhub Browser extension](https://www.zenhub.com/extension) for Chrome or Firefox, and browse the (Mojaloop Project Kanban board](https://github.com/mojaloop/project#zenhub) + +- When your branch is ready for review, open a new pull request from your repository back into the mojaloop project. + >_Note: if the CI/CD pipelines don't run, this may be because your Github account isn't added to the Mojaloop repo_ +- Ensure the following: + - A good description of the feature/bugfix you implemented + - The PR is _assigned_ to yourself + - You have assigned two or more _reviewers_. GitHub often has suggested reviewers, but if you don't know who to assign, feel free to ask whoever created the issue. + +- (Optional) Post a link to your PR on the `#ml-oss-devs` channel in Slack so everyone can share in the fun + + +## 4. Signing the CLA + +After you open your first PR, our CI/CD pipelines will ask you to sign the CLA. For more information on what the CLA is and how to sign it, see [signing the cla](./signing-the-cla.html) + +## FAQs: + +> None as of yet. If you have problems getting through this list, or need more help, reach out to us on Slack! diff --git a/legacy/contributors-guide/personas.md b/legacy/contributors-guide/personas.md new file mode 100644 index 000000000..5443d3ec9 --- /dev/null +++ b/legacy/contributors-guide/personas.md @@ -0,0 +1,46 @@ +# Mojaloop OSS/Community Personas + +# Document Purpose + +To specify the different types of personas/roles that will need access to the Mojaloop portal and documentation. + +## Contributor + +A contributor is someone that is actively involved in contributing to the Mojaloop project code, tests, and documentation. Some scenarios could include a developer, technical writer, or product manager. These people might be brand new to the project or someone that is well versed with the project. + +## Hub Operator + +A hub operator is someone who would be responsible for deploying a Mojaloop hub; they might already have a payments hub. A payment hub operator would need to know how the technical components work (ex how payments and messaging work, API flows, etc). They would also have to have operational control and participate in regulatory forums. + +## Digital Financial Service Provider (DFSP) + +A digital financial service provider, bank, mobile money operator is anyone that will have to talk/communicate directly with a Mojaloop hub. They will need to be familiar with the Mojaloop APIs and participate in scheme agreements with the other Mojaloop hub participants. + +## Systems Integrator + +This person would be responsible for deploying and customizing the Mojaloop components to work with an existing or new payment hub, DFSP or banking system. They would need equal access as the contributor but not necessarily have the system's full details, just those required for integration. + +## Business Owner, Decision Maker or Stakeholder + +A stakeholder is typically someone evaluating Mojaloop, potentially a new pilot customer or collaborator. Documentation for this individual needs to be at a higher level and explain the systems' value proposition, overview, integration points and technology drill-downs. + +## End-User (USSD user) + +The end-user documentation would be minimal for someone using the USSD interface to interact on their flip phone. Some issues that might arise for the end-user would be pin reset and trouble adding new accounts. + +## Customer Service + +Customer service or support personnel included in this category needs to understand the system's user interfaces and operational hubs. Advanced (tier 2 or 3) personnel might also need access to the network overview, API's and logs to help troubleshoot issues. + +End-User (merchant/bulk payment) + +The documentation required for an end-user in using the bulk payment system would need to include an onboarding guide, have some integration information to potentially contact to a merchant's accounts payable system, and have some info regarding bulk payment status accounts. This documentation would also need to include the ability to set different thresholds. + +## Auditor + +The auditor role represents the board of directors and shareholders of a given institution. An example would be an auditor for a financial provider. This role will require a high-level knowledge of the system and access to foresic logs. This role might have access to the different operational hubs and might represent a specific function, and have different access levels for the various components. + +## Regulator + +The regulator ensures the safety and soundness of the financial systems. Like the auditor role, will require a high level of knowledge of the system and access to forensic logs. This role might have access to the different operational hubs and might represent a specific function, and have different access levels for the various components. + diff --git a/legacy/contributors-guide/signing-the-cla.md b/legacy/contributors-guide/signing-the-cla.md new file mode 100644 index 000000000..edb75e520 --- /dev/null +++ b/legacy/contributors-guide/signing-the-cla.md @@ -0,0 +1,99 @@ +# Signing the CLA + +Mojaloop has a [Contributor License Agreement (CLA)](https://github.com/mojaloop/mojaloop/blob/master/CONTRIBUTOR_LICENSE_AGREEMENT.md) which clarifies the intellectual property rights for contributions from individuals or entities. + +To ensure every developer has signed the CLA, we use [CLA Assistant](https://cla-assistant.io/), a well maintained, open source tool which checks to make sure that a contributor has signed the CLA before allowing a pull request to be merged. + +## How to sign the CLA + +1. Open a pull request to any Mojaloop repository +2. When the pull request performs the standard checks, you will see the `license/cla` check has run, and requests users to sign the CLA: + + + + + +3. Click 'Details', and you will be directed to the CLA Assistant tool, where you can read the CLA, fill out some personal details, and sign it. + + +
    + + + +4. Once you have clicked "I agree", navigate back to the Pull request, and see that the CLA Assistant check has passed. + + + + + +### Signing For A Company + +Section 3 of the [Mojaloop CLA](https://github.com/mojaloop/mojaloop/blob/master/CONTRIBUTOR_LICENSE_AGREEMENT.md) covers contributions both from individuals and contributions made by individuals on behalf of their employer. If you are contributing to the Mojaloop Community on behalf of your employer, please enter your employer's name in the "Company or Organization" field. If not, feel free to write "OSS Contributor" and leave the "role" field blank. + + +## Administering the CLA tool + +The CLA Tool is easy to install, any GitHub admin can link it with the Mojaloop organization. + +1. Create a new GitHub Gist and enter in the text of the CLA in a new file. +> Since Github doesn't allow Gists to be owned my organizations, [our gist](https://gist.github.com/mojaloopci/9b7133e1ac153a097ae4ff893add8974) is owned by the 'mojaloopci' user. + +2. Go to [CLA Assistant](https://cla-assistant.io/) and click "Sign in with GitHub" + + + +3. You can add a CLA to either a Repo or Organization. Select "Mojaloop", and then select the gist you just created + + + +4. Hit "Link" and that's it! + + +### Requesting Additional Information: + +> Reference: [request-more-information-from-the-cla-signer](https://github.com/cla-assistant/cla-assistant#request-more-information-from-the-cla-signer) + +You can also add a `metadata` file to the CLA gist, to build a custom form for the CLA tool: + +```json +{ + "name": { + "title": "Full Name", + "type": "string", + "githubKey": "name" + }, + "email": { + "title": "E-Mail", + "type": "string", + "githubKey": "email", + "required": true + }, + "country": { + "title": "Country you are based in", + "type": "string", + "required": true + }, + "company": { + "title": "Company or Organization", + "description": "If you're not affiliated with any, please write 'OSS Contributor'", + "type": "string", + "required": true + }, + "role": { + "title": "Your Role", + "description": "What is your role in your company/organization? Skip this if you're not affiliated with any", + "type": "string", + "required": false + }, + "agreement": { + "title": "I have read and agree to the CLA", + "type": "boolean", + "required": true + } +} +``` + +Produces the following form: + + + diff --git a/legacy/contributors-guide/standards/README.md b/legacy/contributors-guide/standards/README.md new file mode 100644 index 000000000..34723d218 --- /dev/null +++ b/legacy/contributors-guide/standards/README.md @@ -0,0 +1,355 @@ +# Standards + +> *Note:* These standards are by no means set in stone, and as a community, we always want to be iterating and improving Mojaloop. If you want to propose a change to these standards, or suggest further improvements, please reach out to the Design Authority Channel on the Mojaloop Slack (#design-authority) + +## Style Guide + +The Mojaloop Community provides a set of guidelines for the style of code we write. These standards help ensure that the Mojaloop codebase remains high quality, maintainable and consistent. + +These style guides are chosen because they can be easily enforced and checked using popular tools with minimal customisation. While we recognise that developers will have personal preferences that may conflict with these guidelines we favour consistency over [bike-shedding](https://en.wikipedia.org/wiki/Law_of_triviality) these rules. + +The goal of these guides is to ensure an easy developer workflow and reduce code commits that contain changes for the sake of style over content. By reducing the noise in diffs we make the job of reviewers easier. + +### Code Style + +#### Javascript + +Mojaloop uses the Javascript code style dictated by [StandardJS](https://standardjs.com/). For a full set of rules, refer to the [Standard Rules](https://standardjs.com/rules.html), but as a brief set of highlights: + +- Use *2 spaces* for indentation + +```js +function helloWorld (name) { + console.log('hi', name) +} +``` + +- Use *single quotes* for strings except to avoid escaping. + +```js +console.log('hello there') // ✓ ok +console.log("hello there") // ✗ avoid +console.log(`hello there`) // ✗ avoid +``` + +- No semicolons. (see: 1, 2, 3) + +```js +window.alert('hi') // ✓ ok +window.alert('hi'); // ✗ avoid +``` + +#### Typescript + +>*Note: Standard and Typescript* +> +>As we start to introduce more Typescript into the codebase, Standard becomes less useful, and can even be detrimental +>to our development workflow if we try to run standard across the Javascript compiled from Typescript. +>We need to evaluate other options for Standard in Typescript, such as a combination of Prettier + ESLint + +Refer to the [template-typescript-public](https://github.com/mojaloop/template-typescript-public) for the standard typescript configuration. + + +#### YAML + +While YAML deserializers can vary from one to another, we follow the following rules when writing YAML: +> Credit: these examples were taken from the [flathub style guide](https://github.com/flathub/flathub/wiki/YAML-Style-Guide) + +- 2 space indents +- Always indent child elements + +```yaml +# GOOD: +modules: + - name: foo + sources: + - type: bar + +# BAD: +modules: +- name: foo + sources: + - type: bar +``` + +- Do not align values + +```yaml +# BAD: +id: org.example.Foo +modules: + - name: foo + sources: + - type: git +``` +#### sh + bash + +- The Shebang should respect the user's local environment: + +```bash +#!/usr/bin/env bash +``` + +This ensures that the script will match the `bash` that is defined in the user's environment, instead of hardcoding to a specific bash at `/usr/bin/bash`. + +- When referring to other files, don't use relative paths: + +This is because your script will likely break if somebody runs it from a different directory from where the script is located + +```bash +# BAD: +cat ../Dockerfile | wc -l + +# GOOD: +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cat ${DIR}/../Dockerfile | wc -l +``` + +For other recommended bash conventions, refer to this blog post: [Best Practices for Writing Shell Scripts](https://kvz.io/bash-best-practices.html) + +### Documentation + +Documentation should be written in Mark Down format. +All discusison documents should be placed in /documentation/discussions +The use of Google Docs and other tools should not be used. + +### Directory Structure + +Along with guidelines for coding styles, the Mojaloop Community recommends the following directory structure. This ensures that developers can easily switch from one project to another, and also ensures that our tools and configs (such as `.circleci/config.yml` and `Dockerfile`s) can be ported easily from one project to another with minor changes. + +The directory structure guide requires: + +```bash +├── package.json # at the root of the project +├── src # directory containing project source files +├── dist # directory containing compiled javascript files (see tsconfig below) +├── test # directory for tests, containing at least: +│  ├── unit # unit tests, matching the directory structure in `./src` +│  └── integration # integration tests, matching the directory structure in `./src` +└── config + └── default.json # RC config file +``` + +### Config Files + +The following Config files help to enforce the code styles outlined above: + + +#### EditorConfig +> EditorConfig is supported out of the box in many IDEs and Text editors. For more information, refer to the [EditorConfig guide](https://editorconfig.org/). + +`.editorconfig` +```ini +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 + +[{*.js,*.ts,package.json,*.yml,*.cjson}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false +``` + +#### NYC (code coverage tool) + +`.nycrc.yml` +```yml +temp-directory: "./.nyc_output" +check-coverage: true +per-file: true +lines: 90 +statements: 90 +functions: 90 +branches: 90 +all: true +include: [ + "src/**/*.js" +] +reporter: [ + "lcov", + "text-summary" +] +exclude: [ + "**/node_modules/**", + '**/migrations/**' +] +``` + +### Typescript + +`.tsconfig.json` +```json +{ + "include": [ + "src" + ], + "exclude": [ + "node_modules", + "**/*.spec.ts", + "test", + "lib", + "coverage" + ], + "compilerOptions": { + "target": "es2018", + "module": "commonjs", + "lib": [ + "esnext" + ], + "importHelpers": true, + "declaration": true, + "sourceMap": true, + "rootDir": "./src", + "outDir": "./dist", + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "moduleResolution": "node", + "baseUrl": "./", + "paths": { + "*": [ + "src/*", + "node_modules/*" + ] + }, + "esModuleInterop": true + } +} +``` + +`.eslintrc.js` +```js +module.exports = { + parser: '@typescript-eslint/parser', // Specifies the ESLint parser + extends: [ + 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin + 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier + 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. + // Enforces ES6+ import/export syntax + 'plugin:import/errors', + 'plugin:import/warnings', + 'plugin:import/typescript', + ], + parserOptions: { + ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features + sourceType: 'module', // Allows for the use of imports + }, + rules: { + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off' + }, + overrides: [ + { + // Disable some rules that we abuse in unit tests. + files: ['test/**/*.ts'], + rules: { + '@typescript-eslint/explicit-function-return-type': 'off', + }, + }, + ], +}; +``` + +For a more detailed list of the recommended typescript configuration, including `package.json`, `jest.config.js` and more, refer to the [Typescript Template Project](https://github.com/mojaloop/template-typescript-public) + +### Design + Implementation Guidelines + +These guidelines are meant as recommendations for writing code in the Mojaloop community (or code that will be adopted into the community). If you are writing code that you wish to donate code to the community, we ask that you follow these guidelines as much as possible to aid with the consistency and maintainability of the codebase. Donations that adhere to these guidelines will be adopted more easily and swiftly. + +For more information, refer to the FAQ [below](#faqs). + +#### Tools + Frameworks + +In the Mojaloop OSS Community, we are prefer the following tools and frameworks: + +- **Web Server:** [`HapiJS`](https://github.com/hapijs/hapi) +- **Web UI Framework:** [`ReactJS`](https://reactjs.org/) +- **Runtime Configuration:** [`rc`](https://www.npmjs.com/package/rc) (both from env variables and config files) +- **Package Management:** `npm` +- **Logging:** [`@mojaloop/central-services-logger`](https://github.com/mojaloop/central-services-logger#readme) library, built on top of Winston +- **Containers and Orchestration:** [`docker`](https://www.docker.com/) and [`kubernetes`](https://kubernetes.io/) +- **Unit Testing:** For existing tests, [`Tape`](https://github.com/substack/tape), but we are currently moving over to [`Jest`](https://jestjs.io/) for new codebases. +- **Test Coverage:** [`nyc`](https://github.com/istanbuljs/nyc) +- **CI:** [`CircleCI`](https://circleci.com/) + +By using these tools and frameworks, we maintain a high level of consistency and maintainability across the codebase, which keeps our developers productive and happy. While we don't mandate that donated codebases use these same tools and frameworks, we would like to stress that adoptions that use different tools could create an undue maintenance burden on the Community. + +### Adopting Open Source Contributions into Mojaloop + +This section provides guidelines regarding the adoption of a contribution to the Mojaloop Open Source repositories. Adoption is the process where we as the community work with a contributor to bring a contribution into alignment with our standards and guidelines to be a part of the Mojaloop OSS Codebase. + +>*Note:* Code Contributions are evaluated on a **case-by-case** basis. Contributions that don't align to these guidelines will need to go through the incubation phase as described below. Other misalignments to these standards (for example, framework choices) may be added to a roadmap for further improvement and OSS Standardization in the future. + +#### Step 0: Prerequisites + +Before a contribution is to be considered for adoption, it: + +1. Should be in-line with the [Level One Project Principles](https://leveloneproject.org/) +1. Should adhere to the above Style and Design + Implementation Guides +1. Should contain documentation to get started: the more, the better +1. Contain tests with a high level of coverage. At a minimum, a contribution should contain unit tests, but a test suite with unit, integration and functional tests is preferred. Refer to the [contributors guide](./tools-and-technologies/automated-testing) for more information. + +#### Step 1: Incubation + +1. Create a private repo within the Mojaloop GitHub organization for the adopted code +1. Have a sub-team of the DA take a look to make sure its portable \(to OSS\) - aligns with L1P principles, etc, and ensure design is in line with standards +1. Check Licensing of the contribution and any new dependencies it requires, and add the standard Mojaloop License with attribution to donor/contributors +1. Assess the current state of the codebase, including documentation, tests, code quality, and address any shortfalls +1. Assess Performance impact +1. Create action items \(stories\) to update naming, remove/sanitize any items that are not generic +1. Inspect and discuss any framework and tooling choices. + - If a decision is made to make any changes, add them to the roadmap + +#### Step 2: Public Adoption + +1. Make the project public on Mojaloop GitHub +1. Announce on the slack `#announcements` channel +1. Enable CI/CD Pipelines and publish any relevant artifacts, such as Docker Images or npm modules +1. Review and recommend a module or course for the Mojaloop Training Program if needed and relevant for this contribution. + +### Versioning + +Review the information on [versioning](versioning.md) for Mojaloop. + +### Creating new Features + +Process for creating new [features and branches](creating-new-features.md) in Mojaloop. + +### Pull Request Process + +It's a good idea to ask about major changes on [Slack](https://mojaloop.slack.com). Submit pull requests which include both the change and the reason for the change. Feel free to use GitHub's "Draft Pull Request" feature to open up your changes for comments and review from the community. + +Pull requests will be denied if they violate the [Level One Principles](https://leveloneproject.org/wp-content/uploads/2016/03/L1P_Level-One-Principles-and-Perspective.pdf) + +### Code of conduct + +We use the [Mojaloop Foundation Code of Conduct](https://github.com/mojaloop/mojaloop/blob/master/CODE_OF_CONDUCT.md) + +### Licensing + +See [License](https://github.com/mojaloop/mojaloop/blob/master/contribute/License.md) policy + +### FAQs + +__1. What if I want to contribute code, but it doesn't align with the code style and framework/tool recommendations in this guide?__ + +Contributions are accepted on a _case by case_ basis. If your contribution is not yet ready to be fully adopted, we can go through the incubation phase described above, where the code is refactored with our help and brought into alignment with the code and documentation requirements. + + +__2. These standards are outdated, and a newer, cooler tool (or framework, method or language) has come along that will solve problem _x_ for us. How can I update the standards?__ + +Writing high quality, functional code is a moving target, and we always want to be on the lookout for new tools that will improve the Mojaloop OSS codebase. So please talk to us in the design authority slack channel (`#design-authority`) if you have a recommendation. diff --git a/legacy/contributors-guide/standards/creating-new-features.md b/legacy/contributors-guide/standards/creating-new-features.md new file mode 100644 index 000000000..a5a3ea3af --- /dev/null +++ b/legacy/contributors-guide/standards/creating-new-features.md @@ -0,0 +1,63 @@ +# Creating new Features + +### Fork + +Fork the Mojaloop repository into your own personal space. Ensure that you keep the `master` branch in sync. + +Refer to the following documentation for more information: [https://help.github.com/articles/fork-a-repo/](https://help.github.com/articles/fork-a-repo/) + +1. Clone repo using Git Fork button \(refer to the above documentation for more information\) +2. Clone your forked repo: `git clone https://github.com//.git` +3. Synchronise your forked repo with Mojaloop + + Add a new upstream repo for Mojaloop `$ git remote add mojaloop https://github.com/mojaloop/.git` + + You should now see that you have two remotes: + + ```bash + git remote -v + origin https://github.com//.git (fetch) + origin https://github.com//.git (push) + mojaloop https://github.com/mojaloop/.git (fetch) + mojaloop https://github.com/mojaloop/.git (push) + ``` + +4. To sync to your current branch: `git pull mojaloop ` This will merge any changes from Mojaloop's repo into your forked repo. +5. Push the changes back to your remote fork: `git push origin ` + +### Creating a Branch + +Create a new branch from the `master` branch with the following format: `/` where `issue#` can be attained from the Github issue, and the `issueDescription` is the issue description formatted in CamelCase. + +1. Create and checkout the branch: `git checkout -b /` +2. Push the branch to your remote: `git push origin /` + +Where `` can be one of the following: + +| branchType | Description | +| :--- | :--- | +| feature | Any new or maintenance features that are in active development. | +| hotfix | A hotfix branch is for any urgent fixes. | +| release | A release branch containing a snapshot of a release. | +| backup | A temporary backup branch. Used normally during repo maintenance. | + +### Open a Pull Request (PR) + +Once your feature is ready for review, create a Pull Request from you feature branch back into the `master` branch on the Mojaloop Repository. If you're new to GitHub or Pull Requests, take a look at [this guide](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests) for more information. + +#### Pull Request Titles + +Mojaloop uses [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) to help our automated tooling manage releases and deployments. Your Pull Request title _must_conform to the conventional commits specification to pass the CI/CD checks in CircleCI. + +By adopting Conventional Commits + Semantic Versioning we can automatically release a new version for a given component and increment the `MAJOR`, `MINOR` and `BUGFIX` versions based soley on the PR titles, and auto generate rich changelogs. (See [this example](https://github.com/mojaloop/thirdparty-scheme-adapter/releases/tag/v11.20.0) of an auto generated changelog) + +> **Note**: +> When merging (and squashing) a PR, GitHub uses the _title_ of the PR for the git commit message. This means that to specify a breaking change, you must use the `!` format: +> "If included in the type/scope prefix, breaking changes MUST be indicated by a ! immediately before the :. If ! is used, BREAKING CHANGE: MAY be omitted from the footer section, and the commit description SHALL be used to describe the breaking change." + +**Examples of good PR titles** +- feat(api): add ability to handle `PUT /thirdpartyRequests/trasactions/{ID}` endpoint +- fix: update outdated node modules +- feat(models)!: change database schema +- chore: tidy up readme + diff --git a/contributors-guide/standards/triaging-ml-oss-bugs.md b/legacy/contributors-guide/standards/triaging-ml-oss-bugs.md similarity index 92% rename from contributors-guide/standards/triaging-ml-oss-bugs.md rename to legacy/contributors-guide/standards/triaging-ml-oss-bugs.md index 7c8a43ff3..92d140af8 100644 --- a/contributors-guide/standards/triaging-ml-oss-bugs.md +++ b/legacy/contributors-guide/standards/triaging-ml-oss-bugs.md @@ -21,18 +21,13 @@ There is a bug [template](https://github.com/mojaloop/project/issues/new?assigne 3. Based on the discussions, a final call on the priority and severity of the issue is made by the Program Manager. 4. If you think you need a vote, please reach out to Kim or Sam. 5. Here are the voting members [14] for triaging bugs to start with. - 1. Adrian Hope-Bailie - 1. James Bush 1. Kim Walters 1. Lewis Daly 1. Miguel deBarros - 1. Matt Bohan - 1. Miller Abel - 1. Neal Donnan - 1. Nico Duvenage - 1. Rajiv Mothilal - 1. Rob Reeve 1. Sam Kummary 1. Sri Miryala 1. Warren Carew + 1. Vijay Guthi + 1. Valentin Genev + 1. Shashi Hirugade 6. The list and the process will be updated as it evolves, this is a proposal to start with do a Pilot on. diff --git a/legacy/contributors-guide/standards/versioning.md b/legacy/contributors-guide/standards/versioning.md new file mode 100644 index 000000000..8ea82358e --- /dev/null +++ b/legacy/contributors-guide/standards/versioning.md @@ -0,0 +1,126 @@ +# Versioning + +## Versioning of releases made for core Switch services + +This document provides guidelines regarding the versioning strategy used for the releases of Mojaloop Open Source repositories corresponding to the Switch services. + +### Versioning Strategy + + +#### Standard for PI-11 and beyond +1. Starting PI-11 (27th July, 2020) the Versioning guidance is to move to a versioning system that is closely aligned with Semantic versioning by removing the PI/Sprint dependency. So starting 11.x.x, the proposal is to move to pure [SemVer](https://semver.org/). +2. At a high-level, we will still follow the vX.Y.Z format, but X represents ‘Major’ version, Y represents ‘Minor’ version and Z represents ‘patch’ version. Minor fixes, patches affect increments to ‘Z’, whereas non-breaking functionality changes affect changes to ‘Y; breaking changes affect the ‘X’ version. +3. Along with these, suffixes such as “-snapshot”, “-patch”, “-hotfix” are used as relevant and on need basis (supported by CI config). +4. So starting with 11.0.0 (primarily for Helm, but for individual services as well) for PI-11, the proposal is to move to pure [SemVer](https://semver.org/). +5. This implies that for any new release of a package/service below X=11 (for existing repositories and not new ones) will first be baselined to v11.0.0 and from then on follow standard SemVer guidelines as discussed above. For new projects or repositories, versioning can start from v1.0.0 (after they reach release status) + + +#### Versioning Strategy used until PI-10 +1. The Mojaloop (up to PI-10) versioning system is inspired by the [Semantic Versioning](https://semver.org/) numbering system for releases. +2. However, this is customized to depict the timelines of the Mojaloop project, based on the Program Increment \(PI\) and Sprint numbers +3. For example, the release number v5.1.0 implies that this release was the first one made during a Sprint 5.1, where Sprint5.1 is the first Sprint in PI-5. So for a version vX.Y.Z, X.Y is the Sprint number where X is the PI number and Z represents the number of release for this specific repository. Example v4.4.4 implies that the current release is the fourth of four releases made in Sprint 4.4 \(of PI-4\) + + + +### Current Version + +The currrent version information for Mojaloop can be found [here](../../deployment-guide/releases.md). + +### Sprint schedule for PI-13 + +Below is the Sprint schedule for Program Increment 13 which ends with the PI-14 Community event in April 2021. + +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Phase-5 Kick-off On-site**|1/25/2021|1/29/2021|5 days| Virtual Zoom Webinars| +|**Sprint 13.1**|02/01/2021|02/14/2021|2 weeks | | +|**Sprint 13.2**|02/15/2021|02/28/2021|2 weeks | | +|**Sprint 13.3**|03/01/2021|03/14/2021|2 weeks | | +|**Sprint 13.4**|03/15/2021|03/28/2021|2 weeks | | +|**Sprint 13.5**|03/29/2021|04/11/2021|2 weeks | | +|**Sprint 13.6**|04/12/2021|04/25/2021|2 weeks | | +|**Phase-5 PI-14**|04/26/2021|04/30/2021|5 days| Virtual meetings | + +### Sprint schedule for PI-12 + +Below is the Sprint schedule for Program Increment 12 which ends with the PI-13 Community event in January 2021. + +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| +|**Phase-4 PI-10 Virtual**|4/21/2020|4/24/2020|4 days| Virtual Zoom Webinars| +|**Phase-4 PI-11 Virtual**|7/21/2020|7/24/2020|4 days| Virtual Zoom Webinars| +|**Phase-4 PI-12 Virtual**|10/19/2020|10/23/2020|5 days| Virtual Zoom Webinars| +|**Sprint 12.1**|10/26/2020|11/15/2020|3 weeks | | +|**Sprint 12.2**|11/16/2020|11/29/2020|2 weeks | | +|**Sprint 12.3**|11/30/2020|12/13/2020|2 weeks | | +|**Sprint 12.4**|12/14/2020|12/27/2020|2 weeks | | +|**Sprint 12.5**|12/28/2020|01/10/2021|2 weeks | | +|**Sprint 12.6**|01/11/2020|01/24/2020|2 weeks | | +|**Phase-5 Kick-off / PI-13**|01/25/2021|01/29/2021|5 days| TBD | + +### Previous Sprint Schedules: + +### Sprint schedule for PI-11 + +Below is the Sprint schedule for Program Increment 11 which ends with the PI 12 Event. + +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| +|**Phase-4 PI-10 Virtual**|4/21/2020|4/24/2020|4 days| Virtual Zoom Webinars | +|**Phase-4 PI-11 Virtual**|7/21/2020|7/24/2020|4 days| Virtual Zoom Webinars | +|**Sprint 11.1**|7/27/2020|8/9/2020|2 weeks| | +|**Sprint 11.2**|8/10/2020|8/23/2020|2 weeks| | +|**Sprint 11.3**|8/24/2020|9/6/2020|2 weeks| | +|**Sprint 11.4**|9/7/2020|9/20/2020|2 weeks| | +|**Sprint 11.5**|9/21/2020|10/4/2020|2 weeks| | +|**Sprint 11.6**|10/5/2020|10/18/2020|2 weeks | | +|**Phase-4 PI-12**|10/20/2020|10/23/2020|4 days| TBD | + +#### Sprint schedule for PI-10 + +Below is the Sprint schedule for Program Increment 10 which ends with the PI 11 Event. Please use this as guidance during the versioning and release processes. + +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Phase-3 PI6 On-site**|4/16/2019|4/18/2019|3 days| Johannesburg| +|**Phase-3 PI7 On-site**|6/25/2019|6/27/2019|3 days| Arusha| +|**Phase-3 PI8 On-site**|9/10/2019|9/12/2019|3 days| Abidjan| +|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| +|**Phase-4 PI 10 Virtual**|4/21/2020|4/24/2020|5 days| Virtual Zoom Webinars | +|**Sprint 10.1**|4/27/2020|5/10/2020|2 weeks| | +|**Sprint 10.2**|5/11/2020|5/24/2020|2 weeks| | +|**Sprint 10.3**|5/25/2020|6/7/2020|2 weeks| | +|**Sprint 10.4**|6/8/2020|6/21/2020|2 weeks| | +|**Sprint 10.5**|6/22/2020|7/5/2020|2 weeks| | +|**Sprint 10.6**|7/6/2020|7/19/2020|2 weeks | | +|**Phase-4 PI 11 On-Site**|7/21/2020|7/23/2020|3 days| Kenya (Tentative) | + +#### PI-9 +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Sprint 9.1**|2/3/2020|2/16/2020|2 weeks| | +|**Sprint 9.2**|2/17/2020|3/1/2020|2 weeks| | +|**Sprint 9.3**|3/2/2020|3/15/2020|2 weeks| | +|**Sprint 9.4**|3/16/2020|3/29/2020|2 weeks| | +|**Sprint 9.5**|3/30/2020|4/12/2020|2 weeks| | +|**Sprint 9.6**|3/13/2020|4/19/2020|1 week | | +|**Phase-4 PI 10 Virtual**|4/21/2020|4/23/2020|5 days| Virtual Zoom Webinars | + +#### PI-8 +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Sprint 8.1**|9/16/2019|9/29/2019|2 weeks| | +|**Sprint 8.2**|9/30/2019|10/13/2019|2 weeks| | +|**Sprint 8.3**|10/14/2019|10/27/2019|2 weeks| | +|**Sprint 8.4**|10/28/2019|11/10/2019|2 weeks| | +|**Sprint 8.5**|11/11/2019|11/24/2019|2 weeks| | +|**Sprint 8.6**|11/25/2019|12/8/2019|2 weeks| | +|**Sprint 8.7**|12/9/2019|1/5/2020|4 weeks| Christmas Break| +|**Sprint 8.8**|1/6/2020|1/26/2020|3 weeks| 1 week prep| +|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| + +### Notes + +1. A new release for **helm** repo is made based on the feature and configuration changes made to core services and requirements from thhe Community. diff --git a/contributors-guide/tools-and-technologies/README.md b/legacy/contributors-guide/tools-and-technologies/README.md similarity index 100% rename from contributors-guide/tools-and-technologies/README.md rename to legacy/contributors-guide/tools-and-technologies/README.md diff --git a/contributors-guide/tools-and-technologies/assets/diagrams/automated-license-scanning/audit-licenses-build.svg b/legacy/contributors-guide/tools-and-technologies/assets/diagrams/automated-license-scanning/audit-licenses-build.svg similarity index 100% rename from contributors-guide/tools-and-technologies/assets/diagrams/automated-license-scanning/audit-licenses-build.svg rename to legacy/contributors-guide/tools-and-technologies/assets/diagrams/automated-license-scanning/audit-licenses-build.svg diff --git a/contributors-guide/tools-and-technologies/assets/diagrams/automated-license-scanning/audit-licenses-pr.svg b/legacy/contributors-guide/tools-and-technologies/assets/diagrams/automated-license-scanning/audit-licenses-pr.svg similarity index 100% rename from contributors-guide/tools-and-technologies/assets/diagrams/automated-license-scanning/audit-licenses-pr.svg rename to legacy/contributors-guide/tools-and-technologies/assets/diagrams/automated-license-scanning/audit-licenses-pr.svg diff --git a/legacy/contributors-guide/tools-and-technologies/assets/diagrams/automated-testing/QARegressionTestingMojaloop-Complete.plantuml b/legacy/contributors-guide/tools-and-technologies/assets/diagrams/automated-testing/QARegressionTestingMojaloop-Complete.plantuml new file mode 100644 index 000000000..0aaf61dbe --- /dev/null +++ b/legacy/contributors-guide/tools-and-technologies/assets/diagrams/automated-testing/QARegressionTestingMojaloop-Complete.plantuml @@ -0,0 +1,70 @@ +@startuml + +skinparam TitleFontColor #819FF7 +skinparam TitleFontSize 23 + +title Regression Test Life Cycle\n(Self-contained Test Server on EC2) + +skinparam backgroundColor #353B42 +skinparam activity { + StartColor #40FF00 + EndColor #FF0000 + BackgroundColor #2E9AFE + BorderColor #A9D0F5 + LineColor #AAAAAA +} + +skinparam Arrow{ + Color #BFA350 + FontSize 10 + FontColor #6CBF50 +} + +start + +:Test is triggered; +note right: This could be a manual trigger, \nscheduler timer or \nan external action like a Pull Request \nfrom the Source Control System + +if (Validate run parameters as expected?) then (yes) + :Prepare environment for required run; + note left: Set Timestamp\nPostmanCollection to execute\nList of email recipients\nEnvironment Variables\nExecution Timestamp\nOutput FileName +else (no) + -[#red]-> + :Abort run with Note stating incorrect Run Parameters; + -[#red]-> + stop +endif + +:Create Simulator Docker Container; +:Create Regression Test Docker Container; +note left: This container has node\nNewman\email SMTP Server + +while (More Postman Requests to run?) is (Yes) + :Perform Pre-Request Script; + note right: Set up any variables for\npreparation of the request to follow + :Execute Postman Request; + :Perform Test; + :Log Results; + note right: Inspect the response \nagainst variables set previously during\nthe run to determine if expected results are obtained + if (Assertion Test Failed?) then (yes) + if (Run Parameter requested 'Abort at First Error'?) then (yes) + -[#red]-> + (A) + detach + else (no) + endif + else (no) + endif +endwhile (No) + +(A) +:Destroy Simulator Docker Container; +:Finalise Report; +:Prepare Notification(s); +:Attach Reports; +:Send out Notification(s); +note right: The Attachment (Generated Report) \nis sent as an attachment \nto the different notification channels. +:Destroy Regression Test Docker Container; +stop + +@enduml \ No newline at end of file diff --git a/legacy/contributors-guide/tools-and-technologies/assets/diagrams/automated-testing/QARegressionTestingMojaloop-Complete.svg b/legacy/contributors-guide/tools-and-technologies/assets/diagrams/automated-testing/QARegressionTestingMojaloop-Complete.svg new file mode 100644 index 000000000..c5a3bd917 --- /dev/null +++ b/legacy/contributors-guide/tools-and-technologies/assets/diagrams/automated-testing/QARegressionTestingMojaloop-Complete.svg @@ -0,0 +1,255 @@ + + + + + + + + + + + Regression Test Life Cycle + + + (Self-contained Test Server on EC2) + + + + + + This could be a manual trigger, + + + scheduler timer or + + + an external action like a Pull Request + + + from the Source Control System + + + + Test is triggered + + + + Validate run parameters as expected? + + + yes + + + no + + + + + Set Timestamp + + + PostmanCollection to execute + + + List of email recipients + + + Environment Variables + + + Execution Timestamp + + + Output FileName + + + + Prepare environment for required run + + + + Abort run with Note stating incorrect Run Parameters + + + + + + Create Simulator Docker Container + + + + + This container has node + + + Newman\email SMTP Server + + + + Create Regression Test Docker Container + + + + + Set up any variables for + + + preparation of the request to follow + + + + Perform Pre-Request Script + + + + Execute Postman Request + + + + Perform Test + + + + + Inspect the response + + + against variables set previously during + + + the run to determine if expected results are obtained + + + + Log Results + + + + no + + + Run Parameter requested 'Abort at First Error'? + + + yes + + + + + + yes + + + Assertion Test Failed? + + + no + + + + Yes + + + More Postman Requests to run? + + + No + + + + + + Destroy Simulator Docker Container + + + + Finalise Report + + + + Prepare Notification(s) + + + + Attach Reports + + + + + The Attachment (Generated Report) + + + is sent as an attachment + + + to the different notification channels. + + + + Send out Notification(s) + + + + Destroy Regression Test Docker Container + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contributors-guide/tools-and-technologies/assets/diagrams/rest/glory-of-rest.png b/legacy/contributors-guide/tools-and-technologies/assets/diagrams/rest/glory-of-rest.png similarity index 100% rename from contributors-guide/tools-and-technologies/assets/diagrams/rest/glory-of-rest.png rename to legacy/contributors-guide/tools-and-technologies/assets/diagrams/rest/glory-of-rest.png diff --git a/contributors-guide/tools-and-technologies/assets/images/automated-license-scanning/circle-pr-build.png b/legacy/contributors-guide/tools-and-technologies/assets/images/automated-license-scanning/circle-pr-build.png similarity index 100% rename from contributors-guide/tools-and-technologies/assets/images/automated-license-scanning/circle-pr-build.png rename to legacy/contributors-guide/tools-and-technologies/assets/images/automated-license-scanning/circle-pr-build.png diff --git a/contributors-guide/tools-and-technologies/assets/images/automated-license-scanning/circle-release-build.png b/legacy/contributors-guide/tools-and-technologies/assets/images/automated-license-scanning/circle-release-build.png similarity index 100% rename from contributors-guide/tools-and-technologies/assets/images/automated-license-scanning/circle-release-build.png rename to legacy/contributors-guide/tools-and-technologies/assets/images/automated-license-scanning/circle-release-build.png diff --git a/contributors-guide/tools-and-technologies/automated-license-scanning.md b/legacy/contributors-guide/tools-and-technologies/automated-license-scanning.md similarity index 89% rename from contributors-guide/tools-and-technologies/automated-license-scanning.md rename to legacy/contributors-guide/tools-and-technologies/automated-license-scanning.md index 62a958165..1640fb5bc 100644 --- a/contributors-guide/tools-and-technologies/automated-license-scanning.md +++ b/legacy/contributors-guide/tools-and-technologies/automated-license-scanning.md @@ -5,22 +5,21 @@ For Mojaloop to maintain its open source nature and compatibility with the [Moja ## Mojaloop License Scanner We have a suite of tools bundled under the [license-scanner](https://github.com/mojaloop/license-scanner) project on the Mojaloop Github account. The license-scanner allows us to: + - Perform a license scan across one to many Mojaloop github repositories - Integrate with FossaCLI to run mass license audits across the entire codebase - Run inside of a CI process - Run a license scan against a pre-built docker image - For more information, refer to the [readme](https://github.com/mojaloop/license-scanner) in the license-scanner repository. +## Blocking and Allowing Licenses -## Blacklisting and Whitelisting - -The license-scanner works by blacklisting unwanted licenses, and whitelisting packages which have been manually audited, and we are comfortable with using. +The license-scanner works by blocklisting unwanted licenses, and allowlisting packages which have been manually audited, and we are comfortable with using. In the [`config.toml`](https://github.com/mojaloop/license-scanner/blob/master/config.toml) file, we configure two arrays of strings. -__Adding a new License identifier to the blacklist:__ +__Adding a new License identifier to the blocklist:__ Edit `config.tml`, and add the license string into the `failList` array: ```toml @@ -33,14 +32,14 @@ failList = [ ] ``` -The license-scanner will pick out licenses that it finds in the `node_modules` folder, and if the license string is in the `failList` (using a fuzzy string search), the license-scanner will fail, unless the package is found in the whitelist. +The license-scanner will pick out licenses that it finds in the `node_modules` folder, and if the license string is in the `failList` (using a fuzzy string search), the license-scanner will fail, unless the package is found in the allowlist. -__Adding a new package to the whitelist:__ +__Adding a new package to the allowlist:__ -In addition to maintaining a blacklist of licenses, we whitelist packages that we have manually audited and are happy to include. +In addition to maintaining a blocklist of licenses, we allowlist packages that we have manually audited and are happy to include. The most common case for this is packages that don't have a license entry in the `package.json` file, which the npm license scan tool lists as `UNKNOWN`. -To add a package to the whitelist, simply add an entry to the `excludeList` in `config.toml`. For example: +To add a package to the allowlist, simply add an entry to the `excludeList` in `config.toml`. For example: ```toml excludeList = [ "taffydb@2.6.2", @@ -51,11 +50,11 @@ excludeList = [ ] ``` ->___FAQ:__ Why keep a whitelist?_ +>___FAQ:__ Why keep a allowlist?_ > >The license-scanner is not perfect, and sometimes there are packages that have been incorrectly identified, or contain no license entry in the `package.json` file, but do contain a valid license in the package's git repository. > ->By maintaining a whitelist of packages we have manually audited, we can get around incorrectly labelled packages. +>By maintaining a allowlist of packages we have manually audited, we can get around incorrectly labelled packages. ## Running Inside CI/CD @@ -63,7 +62,7 @@ excludeList = [ ### PR Flow When a new Pull Request is opened for a Mojaloop project, the license scanner runs as a part of the CI/CD workflow. The step in CircleCI is called 'audit-licenses' - +
    Example CircleCI Build Overview PR The license-scanner does the following: @@ -78,7 +77,7 @@ The license-scanner does the following: * 4. Uploads the results as a `.csv` artifact -Should the license scanner pass (i.e. find no licenses that are blacklisted), the build will succeed. +Should the license scanner pass (i.e. find no licenses that are blocklisted), the build will succeed. CircleCI license scanning for PR diff --git a/legacy/contributors-guide/tools-and-technologies/automated-testing.md b/legacy/contributors-guide/tools-and-technologies/automated-testing.md new file mode 100644 index 000000000..b7f005913 --- /dev/null +++ b/legacy/contributors-guide/tools-and-technologies/automated-testing.md @@ -0,0 +1,166 @@ +# QA and Regression Testing in Mojaloop + +An overview of the testing framework set up in Mojaloop + +Contents: + +- [QA and Regression Testing in Mojaloop](#qa-and-regression-testing-in-mojaloop) + - [Regression Topics](#regression-topics) + - [Developer Testing](#developer-testing) + - [The section below is deprecated. Mojaloop Releases now use test collections that run on the Mojaloop Testing Toolkit (TTK). Please use the readme page on the repository until this document is properly updated](#the-section-below-is-deprecated-mojaloop-releases-now-use-test-collections-that-run-on-the-mojaloop-testing-toolkit-ttk-please-use-the-readme-page-on-the-httpsgithubcommojalooptesting-toolkit-test-cases-repository-until-this-document-is-properly-updated) + - [[DEPRECATED] Postman and Newman Testing](#deprecated-postman-and-newman-testing) + - [Postman Collections](#postman-collections) + - [Environment Configuration](#environment-configuration) + - [Executing regression test](#executing-regression-test) + - [Steps to execute the script via Postman UI](#steps-to-execute-the-script-via-postman-ui) + - [Steps to execute the bash script to run the Newman / Postman test via CLI](#steps-to-execute-the-bash-script-to-run-the-newman--postman-test-via-cli) + - [Process flow of a typical Scheduled Test](#process-flow-of-a-typical-scheduled-test) + - [Newman Commands](#newman-commands) + +## Regression Topics + + In order for a deployed system to be robust, one of the last checkpoints is to determine if the environment it is deployed in, is in a healthy state and all exposed functionality works exactly the way as intended. + + Prior to that though, there are quite a number of disciplines one must put in place to ensure maximum control. + + To illustrate how the Mojaloop project reaches this goal, we are going to show you the various checkpoints put in place. + +### Developer Testing + + Looking at each component and module, inside the code base, you will find a folder named "*test*" which contain three types of tests. + +- Firstly, the *coverage test* which alerts one if there are unreachable or redundant code +- Unit Tests, which determines if the intended functionality works as expected +- Integration Tests, which does not test end-to-end functionality, but the immediate neighboring interaction +- Automated code-standard checks implemented by means of packages that form part of the code base + + These tests are executed by running the command line instructions, by the developer, during the coding process. Also, the tests are automatically executed every time a *check-in* is done and a Github Pull-Request issued for the code to be integrated into the project. + + The procedure described above, falls outside the realm of Quality Assurance (QA) and Regression testing, which this document addresses. + + Once a developer has written new functionality or extended existing functionality, by having to go through the above rigorous tests, one can assume the functionality in question is executing as intended. How does one then ensure that this new portion of code does not negatively affect the project or product as a whole? + + When the code has passed all of the above and is deployed as part of the CI/CD processes implemented by our workflow, the new component(s) are accepted onto the various hosts, cloud-based or on-premise implementations. These hosts ranges from development platforms through to production environments. + +### The section below is deprecated. Mojaloop Releases now use test collections that run on the Mojaloop Testing Toolkit (TTK). Please use the readme page on the repository until this document is properly updated + +### [DEPRECATED] Postman and Newman Testing + +Parallel to the deployment process is the upkeep and maintenance of the [Postman](https://github.com/mojaloop/postman.git "Postman") Collection testing Framework. When a new release is done, as part of the workflow, Release Notes are published listing all of the new and/or enhanced functionality implemented as part of the release. These notes are used by the QA team to extend and enhance the existing Postman Collections where tests are written behind the request/response scripts to test both positive as well as negative scenarios against the intended behaviour. These tests are then run in the following manner: + +- Manually to determine if the tests cover all aspects and angles of the functionality, positive to assert intended behaviour and negative tests to determine if the correct alternate flows work as intended when something unexpected goes wrong +- Scheduled - as part of the Regression regime, to do exactly the same as the manual intent, but fully automated (with the *Newman Package*) with reports and logs produced to highlight any unintended behaviour and to also warn where known behaviour changed from a previous run. + +In order to facilitate the automated and scheduled testing of a Postman Collection, there are various methods one can follow and the one implemented for Mojaloop use is explained further down in this document. + +There is a complete repository containing all of the scripts, setup procedures and anything required in order to set up an automated [QA and Regression Testing Framework](https://github.com/mojaloop/ml-qa-regression-testing.git "QA and Regression Testing Framework"). This framework allows one to target any Postman Collection, specifying your intended Environment to execute against, as well as a comma-separated list of intended email recipients to receive the generated report. This framework is in daily use by Mojaloop and exists on an EC2 instance on AWS, hosting the required components like Node, Docker, Email Server and Newman, as well as various Bash Scripts and Templates for use by the framework to automatically run the intended collections every day. Using this guide will allow anyone to set up their own Framework. + +#### Postman Collections + +There are a number of Postman collections in use throughout the different processes: + +For Mojaloop Simulator: + +- [MojaloopHub_Setup](https://github.com/mojaloop/postman/blob/master/MojaloopHub_Setup.postman_collection.json) : This collection needs to be executed once after a new deployment, normally by the Release Manager. It sets up an empty Mojaloop hub, including things such as the Hub's currency, the settlement accounts. +- [MojaloopSims_Onboarding](https://github.com/mojaloop/postman/blob/master/MojaloopSims_Onboarding.postman_collection.json) : MojaloopSims_Onboarding sets up the DFSP simulators, and configures things such as the endpoint urls so that the Mojaloop hub knows where to send request callbacks. +- [Golden_Path_Mojaloop](https://github.com/mojaloop/postman/blob/master/Golden_Path_Mojaloop.postman_collection.json) : The Golden_Path_Mojaloop collection is an end-to-end regression test pack which does a complete test of all the deployed functionality. This test can be run manually but is actually designed to be run from the start, in an automated fashion, right through to the end, as response values are being passed from one request to the next. (The core team uses this set to validate various releases and deployments) + - Notes: In some cases, there is need for a delay of `250ms` - `500ms` if executed through Postman UI Test Runner. This will ensure that tests have enough time to validate requests against the simulator. However, this is not always required. +- [Bulk_API_Transfers_MojaSims](https://github.com/mojaloop/postman/blob/master/Bulk_API_Transfers_MojaSims.postman_collection.json) : This collection can be used test the bulk transfers functionality that targets Mojaloop Simulator. + +For Legacy Simulator (encouraged to use Mojaloop Simulator, as this will not be supported starting PI-12 (Oct 2020) ): + +- [ML_OSS_Setup_LegacySim](https://github.com/mojaloop/postman/blob/master/ML_OSS_Setup_LegacySim.postman_collection.json) : This collection needs to be executed once after a new deployment (if it uses Legacy Simulator), normally by the Release Manager. It sets up the Mojaloop hub, including things such as the Hub's currency, the settlement accounts along with the Legacy Simulator(s) as FSP(s). +- [ML_OSS_Golden_Path_LegacySim](https://github.com/mojaloop/postman/blob/master/ML_OSS_Golden_Path_LegacySim.postman_collection.json) : The Golden_Path_Mojaloop collection is an end-to-end regression test pack which does a complete test of all the deployed functionality. This test can be run manually but is actually designed to be run from the start, in an automated fashion, right through to the end, as response values are being passed from one request to the next. (The core team uses this set to validate various releases and deployments) + - Notes: In some cases, there is need for a delay of `250ms` - `500ms` if executed through Postman UI Test Runner. This will ensure that tests have enough time to validate requests against the simulator. However, this is not always required. +- [Bulk API Transfers.postman_collection](https://github.com/mojaloop/postman/blob/master/Bulk%20API%20Transfers.postman_collection.json) : This collection can be used test the bulk transfers functionality that targets Legacy Simulator. + +#### Environment Configuration + +You will need to customize the following environment config file to match your deployment environment: + +- [Local Environment Config](https://github.com/mojaloop/postman/blob/master/environments/Mojaloop-Local.postman_environment.json) + +> Tips: +> +> - The host configurations will be the most likely changes required to match your environment. e.g. `HOST_CENTRAL_LEDGER: http://central-ledger.local`_ +> - Refer to the ingress hosts that have been configured in your `values.yaml` as part of your Helm deployment. +> + +### Executing regression test + +For the Mojaloop QA and Regression Testing Framework specifically, Postman regression test can be executed by going into the EC2 instance via SSH, for which you need the PEM file, and then by running a script(s). + +Following the requirements and instructions as set out in the detail in [QA and Regression Testing Framework](https://github.com/mojaloop/ml-qa-regression-testing.git "QA and Regression Testing Framework"), everyone will be able to create their own Framework and gain access to their instance to execute tests against any Postman Collection targeting any Environment they have control over. + +#### Steps to execute the script via Postman UI + +- Import the desired collection into your Postman UI. You can either download the collection from the repo or alternatively use the `RAW` link and import it directly via the **import link** option. +- Import the environment config into your Postman UI via the Environmental Config setup. Note that you will need to download the environmental config to your machine and customize it to your environment. +- Ensure that you have pre-loaded all prerequisite test data before executing transactions (party, quotes, transfers) as per the example collection [OSS-New-Deployment-FSP-Setup](https://github.com/mojaloop/postman/blob/master/OSS-New-Deployment-FSP-Setup.postman_collection.json): + - Hub Accounts + - FSP onboarding + - Add any test data to Simulator (if applicable) + - Oracle onboarding +- The `p2p_money_transfer` test cases from the [Golden_Path](https://github.com/mojaloop/postman/blob/master/Golden_Path.postman_collection.json) collection are a good place to start. + +#### Steps to execute the bash script to run the Newman / Postman test via CLI + +- To run a test via this method, you will have to be in posession of the PEM-file of the server on which the Mojaloop QA and Regression Framework was deployed on an EC2 instance on Amazon Cloud. + +- SSH into the specific EC2 instance and when running the script, it will in turn run the commands via an instantiated Docker container. + +- You will notice that by using this approach where both the URLs for the Postman-Collection and Environment File are required as input parameters (together with a comma-delimited email recipient list for the report) you have total freedom of executing any Postman Collection you choose. + +- Also, by having an Environment File, the specific Mojaloop services targeted can be on any server. This means you can execute any Postman test against any Mojaloop installation on any server of your choice. + +- The EC2 instance we execute these tests from are merely containing all the tools and processes in order to execute your required test and does not host any Mojaloop Services as such. + +```bash +./testMojaloop.sh +``` + +## Process flow of a typical Scheduled Test + +![QARegressionTestingMojaloop-Complete.svg](./assets/diagrams/automated-testing/QARegressionTestingMojaloop-Complete.svg) + +## Newman Commands + +The following section is a reference, obtained from the Newman Package site itself, highlighting the different commands that may be used in order to have access to the Postman environment by specifying some commands via the CLI. + +```bash +Example: +- newman run -e -n 1 -- + +Usage: run [options] + + URL or path to a Postman Collection. + + Options: + + -e, --environment Specify a URL or Path to a Postman Environment. + -g, --globals Specify a URL or Path to a file containing Postman Globals. + --folder Specify folder to run from a collection. Can be specified multiple times to run multiple folders (default: ) + -r, --reporters [reporters] Specify the reporters to use for this run. (default: cli) + -n, --iteration-count Define the number of iterations to run. + -d, --iteration-data Specify a data file to use for iterations (either json or csv). + --export-environment Exports the environment to a file after completing the run. + --export-globals Specify an output file to dump Globals before exiting. + --export-collection Specify an output file to save the executed collection + --postman-api-key API Key used to load the resources from the Postman API. + --delay-request [n] Specify the extent of delay between requests (milliseconds) (default: 0) + --bail [modifiers] Specify whether or not to gracefully stop a collection run on encountering an errorand whether to end the run with an error based on the optional modifier. + -x , --suppress-exit-code Specify whether or not to override the default exit code for the current run. + --silent Prevents newman from showing output to CLI. + --disable-unicode Forces unicode compliant symbols to be replaced by their plain text equivalents + --global-var Allows the specification of global variables via the command line, in a key=value format (default: ) + --color Enable/Disable colored output. (auto|on|off) (default: auto) + --timeout [n] Specify a timeout for collection run (in milliseconds) (default: 0) + --timeout-request [n] Specify a timeout for requests (in milliseconds). (default: 0) + --timeout-script [n] Specify a timeout for script (in milliseconds). (default: 0) + --ignore-redirects If present, Newman will not follow HTTP Redirects. + -k, --insecure Disables SSL validations. + --ssl-client-cert Specify the path to the Client SSL certificate. Supports .cert and .pfx files. + --ssl-client-key Specify the path to the Client SSL key (not needed for .pfx files) + --ssl-client-passphrase Specify the Client SSL passphrase (optional, needed for passphrase protected keys). + -h, --help output usage information +``` diff --git a/contributors-guide/tools-and-technologies/aws-cli.md b/legacy/contributors-guide/tools-and-technologies/aws-cli.md similarity index 100% rename from contributors-guide/tools-and-technologies/aws-cli.md rename to legacy/contributors-guide/tools-and-technologies/aws-cli.md diff --git a/contributors-guide/tools-and-technologies/code-quality-metrics.md b/legacy/contributors-guide/tools-and-technologies/code-quality-metrics.md similarity index 100% rename from contributors-guide/tools-and-technologies/code-quality-metrics.md rename to legacy/contributors-guide/tools-and-technologies/code-quality-metrics.md diff --git a/contributors-guide/tools-and-technologies/pragmatic-rest.md b/legacy/contributors-guide/tools-and-technologies/pragmatic-rest.md similarity index 100% rename from contributors-guide/tools-and-technologies/pragmatic-rest.md rename to legacy/contributors-guide/tools-and-technologies/pragmatic-rest.md diff --git a/cover.jpg b/legacy/cover.jpg similarity index 100% rename from cover.jpg rename to legacy/cover.jpg diff --git a/legacy/deployment-guide/README.md b/legacy/deployment-guide/README.md new file mode 100644 index 000000000..6eddbe3a3 --- /dev/null +++ b/legacy/deployment-guide/README.md @@ -0,0 +1,493 @@ +# Mojaloop Deployment + +The document is intended for an audience with a stable technical knowledge that would like to setup an environment for development, testing and contributing to the Mojaloop project. + +## Deployment and Setup + +- [Mojaloop Deployment](#mojaloop-deployment) + - [Deployment and Setup](#deployment-and-setup) + - [1. Pre-requisites](#1-pre-requisites) + - [2. Deployment Recommendations](#2-deployment-recommendations) + - [3. Kubernetes](#3-kubernetes) + - [3.1. Kubernetes Ingress Controller](#31-kubernetes-ingress-controller) + - [3.2. Kubernetes Admin Interfaces](#32-kubernetes-admin-interfaces) + - [4. Helm](#4-helm) + - [4.1. Helm configuration](#41-helm-configuration) + - [5. Mojaloop](#5-mojaloop) + - [5.1. Mojaloop Helm Deployment](#51-mojaloop-helm-deployment) + - [5.2. Verifying Ingress Rules](#52-verifying-ingress-rules) + - [5.3. Testing Mojaloop](#53-testing-mojaloop) + - [5.4. Testing Mojaloop with Postman](#54-testing-mojaloop-with-postman) + - [6. Overlay Services/3PPI](#6-overlay-services3ppi) + - [6.1 Configuring a deployment for Third Party API support](#61-configuring-a-deployment-for-third-party-api-support) + - [6.2 Validating and Testing the Third Party API](#62-validating-and-testing-the-third-party-api) + - [6.2.1 Deploying the Simulators](#621-deploying-the-simulators) + - [6.2.2 Provisioning the Environment](#622-provisioning-the-environment) + - [6.2.3 Run the Third Party API Test Collection](#623-run-the-third-party-api-test-collection) +### 1. Pre-requisites + +Versions numbers below are hard requirements, not just recommendations (more recent versions are known not to work). + +A list of the pre-requisite tool set required for the deployment of Mojaloop: + +- **Kubernetes** An open-source system for automating deployment, scaling, and management of containerized applications. Find out more about [Kubernetes](https://kubernetes.io). + - Recommended Versions: + > + > **Mojaloop Helm Chart release v14.1.x** supports **Kubernetes v1.20 - v1.24**. + > + > **Mojaloop Helm Chart release v14.0.x** supports **Kubernetes v1.20 - v1.21**. + > + > **Mojaloop Helm Chart release v13.x** supports **Kubernetes v1.13 - v1.21**. + > + > **Mojaloop Helm Chart release v12.x** supports **Kubernetes v1.13 - v1.20**. + > + > **Mojaloop Helm Chart release v11.x** supports **Kubernetes v1.13 - v1.17**. + > + > **Mojaloop Helm Chart release v10.x** supports **Kubernetes v1.13 - v1.15**, it will fail on Kubernetes v1.16+ onwards due deprecated APIs ([ref: Helm Issue #219](https://github.com/mojaloop/helm/issues/219)). + > + + - kubectl - Kubernetes CLI for Kubernetes Management is required. Find out more about [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/): + - [Install-kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/), + - microk8s - MicroK8s installs a barebones upstream Kubernetes for a single node deployment generally used for local development. We recommend this installation on Linux (ubuntu) OS. Find out more about [microk8s](https://microk8s.io/) and [microk8s documents](https://microk8s.io/docs/): + - [Install-microk8s](https://microk8s.io/docs/), + - kubectx - Not required but useful. Find out more about [kubectx](https://github.com/ahmetb/kubectx), + - kubetail - Not required but useful. Bash script that enables you to aggregate (tail/follow) logs from multiple pods into one stream. Find out more about [kubetail](https://github.com/johanhaleby/kubetail), +- **Docker** Provides containerized environment to host the application. Find out more about [Docker](https://docker.com), +- **Helm** A package manager for Kubernetes. Find out more about [Helm](https://helm.sh), +
    _Recommended Versions:_ +
        _**Helm v3.x** ([ref: Design Auth Issue #52](https://github.com/mojaloop/design-authority/issues/52))._ +- **Postman** Postman is a Google Chrome application for the interacting with HTTP API's. It presents you with a friendly GUI for the construction requests and reading responces. . Find out more about [Postman](https://postman.com). + +For **local guides** on how to setup the pre-requisites on your laptop or desktop, refer to the appropriate link document below; + +- [Local Setup for Mac](local-setup-mac.md) +- [Local Setup for Linux](local-setup-linux.md) +- [Local Setup for Windows](local-setup-windows.md) + +### 2. Deployment Recommendations + +This provides environment resource recommendations with a view of the infrastructure architecture. + +**Resources Requirements:** + +- Control Plane (i.e. Master Node) + + [https://kubernetes.io/docs/setup/cluster-large/#size-of-master-and-master-components](https://kubernetes.io/docs/setup/cluster-large/#size-of-master-and-master-components) + + - 3x Master Nodes for future node scaling and HA (High Availability) + +- ETCd Plane: + + [https://etcd.io/docs/v3.3.12/op-guide/hardware](https://etcd.io/docs/v3.3.12/op-guide/hardware) + + - 3x ETCd nodes for HA (High Availability) + +- Compute Plane (i.e. Worker Node): + + TBC once load testing has been concluded. However the current general recommended size: + + - 3x Worker nodes, each being: + - 4x vCPUs, 16GB of RAM, and 40gb storage + + **Note** that this would also depend on your underlying infrastructure, and it does NOT include requirements for persistent volumes/storage. + +![Mojaloop Deployment Recommendations - Infrastructure Architecture](./assets/diagrams/deployment/KubeInfrastructureArch.svg) + +### 3. Kubernetes + +This section will guide the reader through the deployment process to setup Kubernetes. + +If you are new to Kubernetes it is strongly recommended to familiarize yourself with Kubernetes. [Kubernetes Concepts](https://kubernetes.io/docs/concepts/overview/) is a good place to start and will provide an overview. + +The following are Kubernetes concepts used within the project. An understanding of these concepts is imperative before attempting the deployment; + +- Deployment +- Pod +- ReplicaSets +- Service +- Ingress +- StatefulSet +- DaemonSet +- Ingress Controller +- ConfigMap +- Secret + +Insure **kubectl** is installed. A complete set of installation instruction are available [here](https://kubernetes.io/docs/tasks/tools/install-kubectl/). + +#### 3.1. Kubernetes Ingress Controller + +Install your preferred Ingress Controller for load-balancing and external access. + +Refer to the following documentation to install the Nginx-Ingress Controller used for this guide: . It is recommended that you install **v0.47.0** of the Nginx-Ingress Controller due to recent changes being made to support Kubernetes v1.22. + +If you are using helm, this can be done as follows: + +```bash +helm install ingress-nginx ingress-nginx --version="3.33.0" --repo https://kubernetes.github.io/ingress-nginx +``` + +> **NOTE: If you are installing Mojaloop v12.x with an Nginx-Ingress controller version newer than v0.22.0, ensure you create a custom [Mojaloop values config](https://github.com/mojaloop/helm/blob/v12.0.0/mojaloop/values.yaml) with the following changes prior to install:** +> +> ```YAML +> ## **LOOK FOR THIS LINE IN mojaloop/values.yaml CONFIG FILE** +> mojaloop-simulator: +> ingress: +> ## nginx ingress controller >= v0.22.0 <-- **COMMENT THE FOLLOWING THREE LINES BELOW:** +> # annotations: <-- COMMENTED +> # nginx.ingress.kubernetes.io/rewrite-target: '/$2' <-- COMMENTED +> # ingressPathRewriteRegex: (/|$)(.*) <-- COMMENTED +> +> ## nginx ingress controller < v0.22.0 <-- **UNCOMMENT THE FOLLOWING THREE LINES BELOW:** +> annotations: +> nginx.ingress.kubernetes.io/rewrite-target: '/' +> ingressPathRewriteRegex: "/" +> ``` +> +> **This is NOT necessary if you are installing Mojaloop v13.x or newer.** + +List of alternative Ingress Controllers: . + +#### 3.2. Kubernetes Admin Interfaces + +1. Kubernetes Dashboards + + The official Kubernetes Web UI Admin interface. + + Visit the following link for installation instructions (not needed if **MicroK8s** is installed): [Web UI (Dashboard) Installation Instructions](https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/). + + **IMPORTANT:** Ensure (not needed if **MicroK8s** is installed) you configure RBAC roles and create an associated service account, refer to the following example on how to create a sample user for testing purposes only: [Creating sample user](https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md). + + If you have installed MicroK8s, **enable the MicroK8s** dashboard: + + ```bash + microk8s.enable dashboard + ``` + + Refer to the following link for more information: [Add-on: dashboard](https://microk8s.io/docs/addon-dashboard). + + **Remember** to prefix all **kubectl** commands with **microk8s** if you opted not to create an alias. + +2. k8sLens + + A local desktop GUI based kubectl alternative which is easy to install and setup. + + Visit the following link for more information: . + +### 4. Helm + +Please review [Mojaloop Helm Chart](../repositories/helm.md) to understand the relationships between the deployed Mojaloop helm charts. + +Refer to the official documentation on how to install the latest version of Helm: . + +Refer to the following document if are using Helm v2: [Deployment with (Deprecated) Helm v2](./helm-legacy-deployment.md). + +Refer to the [Helm v2 to v3 Migration Guide](./helm-legacy-migration.md) if you wish to migrate an existing Helm v2 deployment to v3. + +#### 4.1. Helm configuration + +1. Add mojaloop repo to your Helm config: + + ```bash + helm repo add mojaloop https://mojaloop.io/helm/repo/ + ``` + + If the repo already exists, substitute 'add' with 'apply' in the above command. + +2. Update helm repositories: + + ```bash + helm repo update + ``` + +### 5. Mojaloop + +#### 5.1. Mojaloop Helm Deployment + +1. Install Mojaloop: + + 1.1. Installing latest version: + + ```bash + helm --namespace demo install moja mojaloop/mojaloop --create-namespace + ``` + + Or if you require a customized configuration: + + ```bash + helm --namespace demo install moja mojaloop/mojaloop --create-namespace -f {custom-values.yaml} + ``` + + _Note: Download and customize the [values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml). Also ensure that you are using the value.yaml from the correct version which can be found via [Helm Releases](https://github.com/mojaloop/helm/releases). You can confirm the installed version by using the following command: `helm --namespace demo list`. Under the **CHART** column, you should see something similar to 'mojaloop-**{version}**' with **{version}** being the deployed version._ + + ```bash + $ helm -n demo list + NAME NAMESPACE REVISION UPDATED STATUS CHART + moja demo 1 2021-06-11 15:06:04.533094 +0200 SAST deployed mojaloop-{version} + ``` + + _Note: The `--create-namespace` flag is only necessary if the `demo` namespace does not exist. You can alternatively create it using the following command: `kubectl create namespace demo`._ + + 1.2. Version specific installation: + + ```bash + helm --namespace demo install moja mojaloop/mojaloop --create-namespace --version {version} + ``` + + 1.3. List of Mojaloop releases: + + ```bash + $ helm search repo mojaloop/mojaloop -l + NAME CHART VERSION APP VERSION DESCRIPTION + mojaloop/mojaloop {version} {list of app-versions} Mojaloop Helm chart for Kubernetes + ... ... ... ... + ``` + +#### 5.2. Verifying Ingress Rules + +1. Update your /etc/hosts for local deployment: + + _Note: This is only applicable for local deployments, and is not needed if custom DNS or ingress rules are configured in a customized [values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml)_. + + ```bash + vi /etc/hosts + ``` + + _Windows the file can be updated in notepad - need to open with Administrative privileges. File location `C:\Windows\System32\drivers\etc\hosts`_. + + Include the following lines (_or alternatively combine them_) to the host config. + + The below required config is applicable to Helm release >= versions 6.2.2 for Mojaloop API Services; + + ``` + # Mojaloop Demo + 127.0.0.1 ml-api-adapter.local central-ledger.local account-lookup-service.local account-lookup-service-admin.local quoting-service.local central-settlement-service.local transaction-request-service.local central-settlement.local bulk-api-adapter.local moja-simulator.local sim-payerfsp.local sim-payeefsp.local sim-testfsp1.local sim-testfsp2.local sim-testfsp3.local sim-testfsp4.local mojaloop-simulators.local finance-portal.local operator-settlement.local settlement-management.local testing-toolkit.local testing-toolkit-specapi.local + ``` + +2. Test system health in your browser after installation. This will only work if you have an active helm chart deployment running. + + _Note: The examples below are only applicable to a local deployment. The entries should match the DNS values or ingress rules as configured in the [values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml) or otherwise matching any custom ingress rules configured_. + + **ml-api-adapter** health test: + + **central-ledger** health test: + +#### 5.3. Testing Mojaloop + +The [Mojaloop Testing Toolkit](../../documentation/mojaloop-technical-overview/ml-testing-toolkit/README.md) (**TTK**) is used for testing deployments, and has been integrated into Helm utilizing its CLI to easily test any Mojaloop deployment. + +1. Validating Mojaloop using Helm + + ```bash + helm -n demo test moja + ``` + + Or with logs printed to console + + ```bash + helm -n demo test moja --logs + ``` + + This will automatically execute the following [test cases](https://github.com/mojaloop/testing-toolkit-test-cases) using the [Mojaloop Testing Toolkit](../../documentation/mojaloop-technical-overview/ml-testing-toolkit/README.md) (**TTK**) CLI: + + - [TTK Hub setup and Simulator Provisioning Collection](https://github.com/mojaloop/testing-toolkit-test-cases/tree/master/collections/hub/provisioning). + + Use the following command to view the provisioning Collection logs: + + ```bash + kubectl -n demo logs pod/moja-ml-ttk-test-setup + ``` + + - [TTK Golden Path Test Collection](https://github.com/mojaloop/testing-toolkit-test-cases/tree/master/collections/hub/golden_path). + + Use the following command to view the Golden Path Collection logs: + + ```bash + kubectl -n demo logs pod/moja-ml-ttk-test-validation + ``` + + Example of the finally summary being displayed from the Golden Path test collection log output: + + ``` + Test Suite:GP Tests + Environment:Development + ┌───────────────────────────────────────────────────┐ + │ SUMMARY │ + ├───────────────────┬───────────────────────────────┤ + │ Total assertions │ 1557 │ + ├───────────────────┼───────────────────────────────┤ + │ Passed assertions │ 1557 │ + ├───────────────────┼───────────────────────────────┤ + │ Failed assertions │ 0 │ + ├───────────────────┼───────────────────────────────┤ + │ Total requests │ 297 │ + ├───────────────────┼───────────────────────────────┤ + │ Total test cases │ 61 │ + ├───────────────────┼───────────────────────────────┤ + │ Passed percentage │ 100.00% │ + ├───────────────────┼───────────────────────────────┤ + │ Started time │ Fri, 11 Jun 2021 15:45:53 GMT │ + ├───────────────────┼───────────────────────────────┤ + │ Completed time │ Fri, 11 Jun 2021 15:47:25 GMT │ + ├───────────────────┼───────────────────────────────┤ + │ Runtime duration │ 91934 ms │ + └───────────────────┴───────────────────────────────┘ + TTK-Assertion-Report-multi-2021-06-11T15:47:25.656Z.html was generated + ``` + +2. Accessing the Mojaloop Testing Toolkit UI + + Open the following link in a browser: . + + One is able to manually load and execute the Testing Toolkit Collections using the UI which allows one to visually inspect the requests, responses and assertions in more detail. This is a great way to learn more about Mojaloop. + + Refer to the [Mojaloop Testing Toolkit Documentation](../../documentation/mojaloop-technical-overview/ml-testing-toolkit/README.md) for more information and guides. + +#### 5.4. Testing Mojaloop with Postman + +[Postman](https://www.postman.com/downloads) can be used as an alternative to the [Mojaloop Testing Toolkit](../../documentation/mojaloop-technical-overview/ml-testing-toolkit/README.md). Refer to the [Automated Testing Guide](../contributors-guide/tools-and-technologies/automated-testing.md) for more information. + +The available [Mojaloop Postman Collections](https://github.com/mojaloop/postman) are similar to the [Mojaloop Testing Toolkit's Test Cases](https://github.com/mojaloop/testing-toolkit-test-cases)'s as follows: + +| Postman Collection | Mojaloop Testing Toolkit | Description | +|---------|----------|---------| +| [MojaloopHub_Setup Postman Collection](https://github.com/mojaloop/postman/blob/master/MojaloopHub_Setup.postman_collection.json) and [MojaloopSims_Onboarding](https://github.com/mojaloop/postman/blob/master/MojaloopSims_Onboarding.postman_collection.json) | [TTK Hub setup and Simulator Provisioning Collection](https://github.com/mojaloop/testing-toolkit-test-cases/tree/master/collections/hub/provisioning) | Hub Setup and Simulator Provisioning | +| [Golden_Path_Mojaloop](https://github.com/mojaloop/postman/blob/master/Golden_Path_Mojaloop.postman_collection.json) | [TTK Golden Path Test Collection](https://github.com/mojaloop/testing-toolkit-test-cases/tree/master/collections/hub/golden_path) | Golden Path Tests | + +Pre-requisites: + +- The following postman environment file should be imported or customized as required when running the above listed Postman collections: [Mojaloop-Local-MojaSims.postman_environment.json](https://github.com/mojaloop/postman/blob/master/environments/Mojaloop-Local-MojaSims.postman_environment.json). +- Ensure you download the **latest patch release version** from the [Mojaloop Postman Git Repository Releases](https://github.com/mojaloop/postman/releases). For example if you install Mojaloop v12.0.**X**, ensure that you have the latest Postman collection patch version v12.0.**Y**. + + +### 6. Overlay Services/3PPI + +As of [R.C. v13.1.0](https://github.com/mojaloop/helm/tree/release/v13.1.0) of Mojaloop, Third Party API is supported and will be published with the official release of Mojaloop v13.1.0. +which allows Third Party Payment Initiators (3PPIs) the ability to request an account link from a DFSP and initiate +payments on behalf of users. + +> Learn more about 3PPI: +> - Mojaloop's [Third Party API](https://github.com/mojaloop/mojaloop-specification/tree/master/thirdparty-api) +> - 3rd Party Use Cases: +> - [3rd Party Account Linking](https://sandbox.mojaloop.io/usecases/3ppi-account-linking.html) +> - [3rd Party Initiated Payments](https://sandbox.mojaloop.io/usecases/3ppi-transfer.html) + + +#### 6.1 Configuring a deployment for Third Party API support + +Third Party API support is **off** by default on the Mojaloop deployment. You can enable it by editing your `values.yaml` +file with the following settings: + +```yaml +... +account-lookup-service: + account-lookup-service: + config: + featureEnableExtendedPartyIdType: true # allows the ALS to support newer THIRD_PARTY_LINK PartyIdType + + account-lookup-service-admin: + config: + featureEnableExtendedPartyIdType: true # allows the ALS to support newer THIRD_PARTY_LINK PartyIdType + +... + +thirdparty: + enabled: true +... +``` + +In addition, the Third Party API has a number of dependencies that must be deployed manually for the thirdparty services +to run. [mojaloop/helm/thirdparty](https://github.com/mojaloop/helm/tree/master/thirdparty) contains details of these +dependencies, and also provides example k8s config files that install these dependencies for you. + + + + +```bash +# install redis and mysql for the auth-service +kubectl apply --namespace demo -f https://raw.githubusercontent.com/mojaloop/helm/master/thirdparty/chart-auth-svc/example_dependencies.yaml +# install mysql for the consent oracle +kubectl apply --namespace demo -f https://raw.githubusercontent.com/mojaloop/helm/master/thirdparty/chart-consent-oracle/example_dependencies.yaml + +# apply the above changes to your values.yaml file, and update your mojaloop installation to deploy thirdparty services: +helm upgrade --install --namespace demo moja mojaloop/mojaloop -f values.yaml +``` + +Once the helm upgrade has completed, you can verify that the third party services are up and running: + + +```bash +kubectl get po | grep tp-api +# tp-api-svc-b9bf78564-4g59d 1/1 Running 0 7m17s + +kubectl get po | grep auth-svc +# auth-svc-b75c954d4-9vq7w 1/1 Running 0 8m5s + +kubectl get po | grep consent-oracle +# consent-oracle-849cb69769-vq4rk 1/1 Running 0 8m31s + + +# and also make sure the ingress is exposed correctly +curl -H "Host: tp-api-svc.local" /health +# {"status":"OK","uptime":3545.77290063,"startTime":"2021-11-04T05:41:32.861Z","versionNumber":"11.21.0","services":[]} + +curl -H "Host: auth-service.local" /health + +# {"status":"OK","uptime":3682.48869561,"startTime":"2021-11-04T05:43:19.056Z","versionNumber":"11.10.1","services":[]} + +curl -H "Host: consent-oracle.local" /health +# {"status":"OK","uptime":3721.520096665,"startTime":"2021-11-04T05:43:48.382Z","versionNumber":"0.0.8","services":[]} +``` + +> You can also add the following entries to your `/etc/hosts` file to make it easy to talk to the thirdparty services +> ``` +> tp-api-svc.local auth-service.local consent-oracle.local +> ``` + +#### 6.2 Validating and Testing the Third Party API + +Once you have deployed the Third Party services, you need to deploy some simulators that are capable of simulating +the Third Party scenarios. + + +##### 6.2.1 Deploying the Simulators + +Once again, you can do this by modifying your `values.yaml` file, this time under the `mojaloop-simulator` entry: + +```yaml +... + +mojaloop-simulator: + simulators: + ... + pisp: + config: + thirdpartysdk: + enabled: true + dfspa: + config: + thirdpartysdk: + enabled: true + dfspb: {} +... +``` + +The above entry will create 3 new sets of mojaloop simulators: + +1. `pisp` - a PISP +2. `dfspa` - a DFSP that supports the Third Party API +3. `dfspb` - a normal DFSP simulator that doesn't support the Third Party API, but can receive payments + + +##### 6.2.2 Provisioning the Environment + +Once the above simulators have been deployed and are up and running, it's time to configure the Mojaloop Hub +and simulators so we can test the Third Party API. + +Use the [Third Party Provisioning Collection](https://github.com/mojaloop/testing-toolkit-test-cases#third-party-provisioning-collection) +from the mojaloop/testing-toolkit-test cases to provision the Third Party environment and the simulators +you set up in the last step. + +##### 6.2.3 Run the Third Party API Test Collection + +Once the provisioning steps are completed, you can run the [Third Party Test Collection](https://github.com/mojaloop/testing-toolkit-test-cases#third-party-test-collection) +to test that the Third Party services are deployed and configured correctly. diff --git a/deployment-guide/assets/diagrams/deployment/DockerAdvanceSettings.png b/legacy/deployment-guide/assets/diagrams/deployment/DockerAdvanceSettings.png similarity index 100% rename from deployment-guide/assets/diagrams/deployment/DockerAdvanceSettings.png rename to legacy/deployment-guide/assets/diagrams/deployment/DockerAdvanceSettings.png diff --git a/deployment-guide/assets/diagrams/deployment/DockerForDesktop.png b/legacy/deployment-guide/assets/diagrams/deployment/DockerForDesktop.png similarity index 100% rename from deployment-guide/assets/diagrams/deployment/DockerForDesktop.png rename to legacy/deployment-guide/assets/diagrams/deployment/DockerForDesktop.png diff --git a/deployment-guide/assets/diagrams/deployment/DockerIsRunning.png b/legacy/deployment-guide/assets/diagrams/deployment/DockerIsRunning.png similarity index 100% rename from deployment-guide/assets/diagrams/deployment/DockerIsRunning.png rename to legacy/deployment-guide/assets/diagrams/deployment/DockerIsRunning.png diff --git a/deployment-guide/assets/diagrams/deployment/EnableKubernetes.png b/legacy/deployment-guide/assets/diagrams/deployment/EnableKubernetes.png similarity index 100% rename from deployment-guide/assets/diagrams/deployment/EnableKubernetes.png rename to legacy/deployment-guide/assets/diagrams/deployment/EnableKubernetes.png diff --git a/legacy/deployment-guide/assets/diagrams/deployment/KubeInfrastructureArch.svg b/legacy/deployment-guide/assets/diagrams/deployment/KubeInfrastructureArch.svg new file mode 100644 index 000000000..26b8dcd92 --- /dev/null +++ b/legacy/deployment-guide/assets/diagrams/deployment/KubeInfrastructureArch.svg @@ -0,0 +1,2 @@ + + diff --git a/deployment-guide/assets/diagrams/deployment/KubernetesInstallWithDocker-1.png b/legacy/deployment-guide/assets/diagrams/deployment/KubernetesInstallWithDocker-1.png similarity index 100% rename from deployment-guide/assets/diagrams/deployment/KubernetesInstallWithDocker-1.png rename to legacy/deployment-guide/assets/diagrams/deployment/KubernetesInstallWithDocker-1.png diff --git a/deployment-guide/assets/diagrams/deployment/KubernetesInstallWithDocker-2.png b/legacy/deployment-guide/assets/diagrams/deployment/KubernetesInstallWithDocker-2.png similarity index 100% rename from deployment-guide/assets/diagrams/deployment/KubernetesInstallWithDocker-2.png rename to legacy/deployment-guide/assets/diagrams/deployment/KubernetesInstallWithDocker-2.png diff --git a/deployment-guide/assets/diagrams/deployment/kubernetesDashboard.png b/legacy/deployment-guide/assets/diagrams/deployment/kubernetesDashboard.png similarity index 100% rename from deployment-guide/assets/diagrams/deployment/kubernetesDashboard.png rename to legacy/deployment-guide/assets/diagrams/deployment/kubernetesDashboard.png diff --git a/legacy/deployment-guide/assets/diagrams/upgradeStrategies/helm-blue-green-upgrade-strategy.svg b/legacy/deployment-guide/assets/diagrams/upgradeStrategies/helm-blue-green-upgrade-strategy.svg new file mode 100644 index 000000000..a5e597d9c --- /dev/null +++ b/legacy/deployment-guide/assets/diagrams/upgradeStrategies/helm-blue-green-upgrade-strategy.svg @@ -0,0 +1,3 @@ + + +
    Target Data-layer Runtime Environment
    Kubernetes Cluster(s)
    Target Data-layer Runtime Environment...
    Mojaloop Runtime Environment
    Kubernetes Cluster(s)
    Mojaloop Runtime Environment...
    Mojaloop Target
    Deployment

    (New Release)
    Mojaloop Target...
    Mojaloop DMZ
    Mojaloop DMZ
    API
    Gateway
    API...
    DFSP(s)
    DFSP(...
    Sync & Data Migration

    (Transform data to new Schema)
    Sync & Data M...
    Backend Dependencies

    (MySQL, Kafka, etc)
    Backend Dependencies...
    Mojaloop Current
    Deployment
    +
    Backed Dependencies
    (MySQL, Kafka, etc)

    (Old Release)
    Mojaloop Current...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/legacy/deployment-guide/assets/diagrams/upgradeStrategies/helm-canary-upgrade-strategy.svg b/legacy/deployment-guide/assets/diagrams/upgradeStrategies/helm-canary-upgrade-strategy.svg new file mode 100644 index 000000000..894431623 --- /dev/null +++ b/legacy/deployment-guide/assets/diagrams/upgradeStrategies/helm-canary-upgrade-strategy.svg @@ -0,0 +1,3 @@ + + +
    Shared Data-layer Runtime Environment
    Kubernetes Cluster(s)
    Shared Data-layer Runtime Environment...
    Mojaloop Runtime Environment
    Kubernetes Cluster(s)
    Mojaloop Runtime Environment...
    Backend Dependencies

    (MySQL, Kafka, etc)
    Backend Dependencies...
    Mojaloop Current
    Deployment

    (Old Release)
    Mojaloop Current...
    Mojaloop Target
    Deployment

    (New Release)
    Mojaloop Target...
    Mojaloop DMZ
    Mojaloop DMZ
    API
    Gateway
    API...
    DFSP(s)
    DFSP(...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/legacy/deployment-guide/deployment-troubleshooting.md b/legacy/deployment-guide/deployment-troubleshooting.md new file mode 100644 index 000000000..cc26c8f3d --- /dev/null +++ b/legacy/deployment-guide/deployment-troubleshooting.md @@ -0,0 +1,126 @@ +# Deployment Troubleshooting + +## 1. Known issues + +### 1.1. Mojaloop Helm release v10.x or less does not support Kubernetes v1.16 or greater + +#### Description + +_Note: This is only applicable to Mojaloop Helm v10.x or less release._ + +When installing mojaloop helm charts, the following error occurs: + +```log +Error: validation failed: [unable to recognize "": no matches for kind "Deployment" in version "apps/v1beta2", unable to recognize "": no matches for kind "Deployment" in version "extensions/v1beta1", unable to recognize "": no matches for kind "StatefulSet" in version "apps/v1beta2", unable to recognize "": no matches for kind "StatefulSet" in version "apps/v1beta1"] +``` + +#### Reason + +In version 1.16 of Kubernetes breaking change has been introduced (more about it [in "Deprecations and Removals" of Kubernetes release notes](https://kubernetes.io/docs/setup/release/notes/#deprecations-and-removals). The Kubernetes API versions `apps/v1beta1` and `apps/v1beta2`are no longer supported and and have been replaced by `apps/v1`. + +Mojaloop helm charts v10 or less refer to deprecated ids, therefore it's not possible to install v10- on Kubernetes version above 1.15 without manually modification. + +Refer to the following issue for more info: [mojaloop/helm#219](https://github.com/mojaloop/helm/issues/219) + +#### Fixes + +Ensure that you are deploying Mojaloop Helm charts v10.x or less on v1.15 of Kubernetes. + +#### Additional details for `microk8s` fix + +Refer to the following section for more information on how to install the desired Kubernetes version: [Mojaloop Setup for Linux (Ubuntu) - 2.1. MicroK8S](./local-setup-linux.md#21-microk8s). + +## 2. Deployment issues + +### 2.1. `ERR_NAME_NOT_RESOLVED` Error + +#### Description + +The following error is displayed when attempting to access an end-point (e.g. central-ledger.local) via the Kubernetes Service directly in a browser: `ERR_NAME_NOT_RESOLVED` + +#### Fixes + +1. Verify that that Mojaloop was deployed by checking that the helm chart(s) was installed by executing: + + ```bash + helm list + ``` + + If the helm charts are not listed, see the [Deployment Guide - 5.1. Mojaloop Helm Deployment](./README.md#51-mojaloop-helm-deployment) section to install a chart. + +2. Ensure that all the Mojaloop Pods/Containers have started up correctly and are available through the Kubernetes dashboard. + +3. Note that the Mojaloop deployment via Helm can take a few minutes to initially startup depending on the system's available resources and specification. It is recommended that you wait at least 10m for all Pods/Containers to self heal before troubleshooting. + +### 2.3. MicroK8s - Connectivity Issues + +#### Description + +My pods can’t reach the internet or each other (but my MicroK8s host machine can). + +An example of this is that the Central-Ledger logs indicate that there is an error with the Broker transport as per the following example: + +```log +2019-11-05T12:28:10.470Z - info: Server running at: +2019-11-05T12:28:10.474Z - info: Handler Setup - Registering {"type":"prepare","enabled":true}! +2019-11-05T12:28:10.476Z - info: CreateHandler::connect - creating Consumer for topics: [topic-transfer-prepare] +2019-11-05T12:28:10.515Z - info: CreateHandler::connect - successfully connected to topics: [topic-transfer-prepare] +2019-11-05T12:30:20.960Z - error: Consumer::onError()[topics='topic-transfer-prepare'] - Error: Local: Broker transport failure) +``` + +#### Fixes + +Make sure packets to/from the pod network interface can be forwarded to/from the default interface on the host via the iptables tool. Such changes can be made persistent by installing the iptables-persistent package: + +```bash +sudo iptables -P FORWARD ACCEPT +sudo apt-get install iptables-persistent +``` + +or, if using ufw: + +```bash +sudo ufw default allow routed +``` + +The MicroK8s inspect command can be used to check the firewall configuration: + +```bash +microk8s.inspect +``` + +## 3. Ingress issues + +### 3.1. Ingress rules are not resolving for Nginx Ingress v0.22 or later when installing Mojaloop Helm v12.x or less + +#### Description + +_Note: This is only applicable to Mojaloop Helm v12.x or less release._ + +Ingress rules are unable to resolve to the correct path based on the annotations specified in the [values.yaml](https://github.com/mojaloop/helm/blob/v12.0.0/mojaloop/values.yaml) configuration files when using Nginx Ingress controllers v0.22 or later. + +This is due to the changes introduced in Nginx Ingress controllers that are v0.22 or later as per the following link: https://kubernetes.github.io/ingress-nginx/examples/rewrite/#rewrite-target. + +#### Fixes + +Make the following change to Ingress annotations (from --> to) in the values.yaml files: + +```yaml +nginx.ingress.kubernetes.io/rewrite-target: '/'` --> `nginx.ingress.kubernetes.io/rewrite-target: '/$1' +``` + +### 3.2. Ingress rules are not resolving for Nginx Ingress earlier than v0.22 + +#### Description + +Ingress rules are unable to resolve to the correct path based on the annotations specified in the [values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml) configuration files when using Nginx Ingress controllers that are older than v0.22. + +This is due to the changes introduced in Nginx Ingress controllers that are v0.22 or later as per the following link: https://kubernetes.github.io/ingress-nginx/examples/rewrite/#rewrite-target. + +#### Fixes + +Make the following change to all Ingress annotations (from --> to) in each of the values.yaml files: + +```yaml +nginx.ingress.kubernetes.io/rewrite-target: '/$1'` --> `nginx.ingress.kubernetes.io/rewrite-target: '/' +``` diff --git a/legacy/deployment-guide/helm-legacy-deployment.md b/legacy/deployment-guide/helm-legacy-deployment.md new file mode 100644 index 000000000..c3978fb9a --- /dev/null +++ b/legacy/deployment-guide/helm-legacy-deployment.md @@ -0,0 +1,65 @@ +# Mojaloop Deployment with (Deprecated) Helm v2 + +_Note: It is recommended that you upgrate from Helm v2 to v3 as v2 is at end-of-life. Refer to legacy instruction for [Helm v2](./helm-legacy-deployment.md). Please refer to the [Helm v2 to v3 Migration Guide](./helm-legacy-migration.md)._ + +This document exists for legacy purposes and describes how to install Mojaloop using Helm v2. Refer to the [Design Authority issue #52](https://github.com/mojaloop/design-authority/issues/52) for more information. + +## Deployment and Setup + +#### 4.1. Helm v2 configuration + +1. Config Helm CLI and install Helm Tiller on K8s cluster: + ```bash + helm init + ``` + _Note: if `helm init` fails with `connection refused error`, refer to [troubleshooting](./deployment-troubleshooting.md#helm_init_connection_refused)_ + +2. Validate Helm Tiller is up and running. _Windows replace `grep` with `findstr`_: + ```bash + kubectl -n kube-system get po | grep tiller + ``` + +3. Add mojaloop repo to your Helm config (optional): + ```bash + helm repo add mojaloop http://mojaloop.io/helm/repo/ + ``` + If the repo already exists, substitute 'add' with 'apply' in the above command. + +4. Add the additional dependency Helm repositories. This is needed to resolve Helm Chart dependencies required by Mojaloop charts. Linux use with sudo; + ```bash + helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator + helm repo add kiwigrid https://kiwigrid.github.io + helm repo add elastic https://helm.elastic.co + ``` + +5. Update helm repositories: + ```bash + helm repo update + ``` + +### 5. Mojaloop + +#### 5.1. Mojaloop Helm v2 Deployment + +1. Install Mojaloop: + + Default installation: + ```bash + helm --namespace demo --name moja install mojaloop/mojaloop + ``` + + Version specific installation: + ```bash + helm --namespace demo --name moja install mojaloop/mojaloop --version {version} + ``` + + List of available versions: + ```bash + helm search -l mojaloop/mojaloop + ``` + + Custom configured installation: + ```bash + helm --namespace demo --name moja install mojaloop/mojaloop -f {custom-values.yaml} + ``` + _Note: Download and customize the [values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml). Also ensure that you are using the value.yaml from the correct version which can be found via [Helm Releases](https://github.com/mojaloop/helm/releases)._ diff --git a/legacy/deployment-guide/helm-legacy-migration.md b/legacy/deployment-guide/helm-legacy-migration.md new file mode 100644 index 000000000..586b26539 --- /dev/null +++ b/legacy/deployment-guide/helm-legacy-migration.md @@ -0,0 +1,147 @@ +# Migration from Helm v2 to v3 + +_Note: It is recommended that you upgrate from Helm v2 to v3 as v2 is at end-of-life. Refer to [Deployment with (Deprecated) Helm v2](./helm-legacy-deployment.md) if you still require information on using Helm v2._ + +This document provides instructions on how to migrate existing Mojaloop installations from Helm v2 to v3, and is based of the official Helm ([Migrating Helm v2 to v3](https://helm.sh/docs/topics/v2_v3_migration/)) document. + +## Deployment and Setup + +#### 1. Helm configuration + +1. Install Helm v3 + + Follow the [Installation Helm](https://helm.sh/docs/intro/install/) documentation to download and install Helm v3, but ensure to rename to binary as `helm3` before storing it in your path (i.e. on linux moving it to the `usr/local/bin` folder). This will ensure that the existing Helm v2 binary is still accessible. + +2. Validate that Helm3 has been installed correctly + Run the following command to ensure that it is functioning: + ```bash + $ helm3 repo list + Error: no repositories to show + ``` + You should receive the following response `Error: no repositories to show` which is expected, and indicates that the Helm3 binary is working. + +3. Install the `helm-2to3` plugin + ```bash + helm3 plugin install https://github.com/helm/helm-2to3 + ``` + + Run the following command to confirm the plugin installation: + ```bash + $ helm3 plugin list + NAME VERSION DESCRIPTION + 2to3 0.2.0 migrate and cleanup Helm v2 configuration and releases in-place to Helm v3 + ``` + +4. Backup your exisitng Helm v2 data + + Make a copy of your existing `~/.helm` directory as the next (`move`) command will cause your Helm v2 configuration to be no longer available. + +5. Run the following commands to migrate your existing local configuration + + Try run a `dry-run` to ensure that everything looks fine: + ```bash + helm3 2to3 move config --dry-run + ``` + + Assuming that there are no errors, you can proceed with the following command: + ```bash + helm3 2to3 move config + ``` + + Run the following to ensure that the configuration was properly migrated, and your prviously Helm v2 configured repo config is shown: + ```bash + $ helm3 repo list + NAME URL + stable https://kubernetes-charts.storage.googleapis.com + local http://127.0.0.1:8879/charts + incubator http://storage.googleapis.com/kubernetes-charts-incubator + kiwigrid https://kiwigrid.github.io + elastic https://helm.elastic.co + kiwigrid https://kiwigrid.github.io + bitnami https://charts.bitnami.com/bitnami + mojaloop http://mojaloop.io/helm/repo/ + ``` + +#### 2. Migrating Helm Installations + + + ```bash + $ helm list + + NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE + moja 1 Thu Nov 14 15:01:00 2019 DEPLOYED mojaloop-10.4.0 v10.4.0 demo + ``` + + Dry-run the migration command to validate that everything looks fine: + ```bash + $ helm3 2to3 convert --dry-run moja + 2019/11/14 15:03:17 NOTE: This is in dry-run mode, the following actions will not be executed. + 2019/11/14 15:03:17 Run without --dry-run to take the actions described below: + 2019/11/14 15:03:17 + 2019/11/14 15:03:17 Release "moja" will be converted from Helm v2 to Helm v3. + 2019/11/14 15:03:17 [Helm 3] Release "moja" will be created. + 2019/11/14 15:03:17 [Helm 3] ReleaseVersion "moja.v1" will be created. + ``` + + Run the migration command: + ```bash + $ helm3 2to3 convert moja + 2019/11/14 15:03:57 Release "moja" will be converted from Helm v2 to Helm v3. + 2019/11/14 15:03:57 [Helm 3] Release "moja" will be created. + 2019/11/14 15:03:57 [Helm 3] ReleaseVersion "moja.v1" will be created. + 2019/11/14 15:03:57 [Helm 3] ReleaseVersion "moja.v1" created. + 2019/11/14 15:03:57 [Helm 3] Release "moja" created. + 2019/11/14 15:03:57 Release "moja" was converted successfully from Helm v2 to Helm v3. + 2019/11/14 15:03:57 Note: The v2 release information still remains and should be removed to avoid conflicts with the migrated v3 release. + 2019/11/14 15:03:57 v2 release information should only be removed using `helm 2to3` cleanup and when all releases have been migrated over. + ``` + + Optionaly add `--delete-v2-releases` to the above command if you do not wish to retain the release information for the existing Helm v2 installation. This can be cleaned up later using the `helm3 2to3 cleanup`. + + Validate that the migration was successful: + ```bash + $ helm list + NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE + moja 1 Thu Nov 14 15:01:00 2019 DEPLOYED mojaloop-10.4.0 v10.4.0 demo + + $ helm3 list -n demo + NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION + moja demo 1 2019-11-14 13:01:00.188487 +0000 UTC deployed mojaloop-10.4.0 10.4.0 + ``` + +#### 3. Cleanup + + This section will show you how to remove Tiller and any existing configuration or metadata from existing Helm v2 deployments. + + _NOTE: This may impact any Helm v2 deployments that have not been migrated. It is recommended that you only run these commands if you have migrated all existing Helm v2 to v3 deployments!_ + + ```bash + $ helm3 2to3 cleanup --dry-run + 2019/11/14 15:06:59 NOTE: This is in dry-run mode, the following actions will not be executed. + 2019/11/14 15:06:59 Run without --dry-run to take the actions described below: + 2019/11/14 15:06:59 + WARNING: "Helm v2 Configuration" "Release Data" "Release Data" will be removed. + This will clean up all releases managed by Helm v2. It will not be possible to restore them if you haven't made a backup of the releases. + Helm v2 may not be usable afterwards. + + [Cleanup/confirm] Are you sure you want to cleanup Helm v2 data? [y/N]: y + 2019/11/14 15:07:01 + Helm v2 data will be cleaned up. + 2019/11/14 15:07:01 [Helm 2] Releases will be deleted. + 2019/11/14 15:07:01 [Helm 2] ReleaseVersion "moja.v1" will be deleted. + 2019/11/14 15:07:01 [Helm 2] Home folder "/Users/user/.helm" will be deleted. + ``` + + This will show a list of all what will be removed & deleted during the cleanup process: + - Tiller service to be removed from kube-system namespace + - Remote Helm v2 deployments + - Local Helm v2 home configuration folder will be deleted + + If you are happy to proceed run the following command: + ```bash + helm3 2to3 cleanup + ``` + + If you no longer require Helm v2: + - Uninstall Helm v2 from your local system + - Rename the `helm3` binary to `helm` diff --git a/legacy/deployment-guide/local-setup-linux.md b/legacy/deployment-guide/local-setup-linux.md new file mode 100644 index 000000000..92bc0ef67 --- /dev/null +++ b/legacy/deployment-guide/local-setup-linux.md @@ -0,0 +1,143 @@ +# Mojaloop Setup for Linux (Ubuntu) + +Local setup on a Laptop or Desktop to run the Mojaloop project. + +## Setup Introduction + +This document will provide guidelines to a technical capable resources to setup, deploy and configure the Mojaloop applications on a local environment, utilizing Docker, Kubernetes and HELM charts. + +At this point the reader/implementer should be familiar with [Mojaloop's deployment guide](./README.md). Imported information is contained in that document and as such a prerequisite to this document. + +- [Mojaloop Setup for Linux (Ubuntu)](#mojaloop-setup-for-linux-ubuntu) + - [Setup Introduction](#setup-introduction) + - [1. Environment recommendations](#1-environment-recommendations) + - [2. Kubernetes](#2-kubernetes) + - [2.1. MicroK8S](#21-microk8s) + - [2.2. Docker](#22-docker) + - [3. Continue with Deployment](#3-continue-with-deployment) + +## 1. Environment recommendations + +This environment setup was validated on: + +- 64-bit version of Ubuntu Bionic 18.04(LTS). +- This guide is based on Ubuntu 18.04.2 (bionic) on a x86_64 desktop with 8 CPU's and 16GB RAM. + +## 2. Kubernetes + +Kubernetes installation for a local environment. + +### 2.1. MicroK8S + +We recommend install directly from the snap store, refer to [microk8s.io/docs](https://microk8s.io/docs) for more information. + +Don't have the snap command? [Installing snapd](https://snapcraft.io/docs/installing-snapd). + +1. Installing MicroK8s from snap. + + ```bash + sudo snap install microk8s --classic --channel=1.20/stable + ``` + + _Note: Please check the [release notes of your target Mojaloop Helm deployment](https://github.com/mojaloop/helm/releases) to see if there are any recommended Kubernetes version prior to installing MicroK8s. The channel parameter specifies the version of Kubernetes to be installed. More information can be found at [microk8s.io/docs/setting-snap-channel](https://microk8s.io/docs/setting-snap-channel)._ + +2. Configure user permission + + ```bash + sudo usermod -a -G microk8s $USER + sudo chown -f -R $USER ~/.kube + ``` + + You will also need to re-enter the session for the group update to take place: + + ```bash + su - $USER + ``` + +3. Verify MicroK8s is installed and available. + + ```bash + microk8s.status + ``` + +4. During installation you can use the --wait-ready flag to wait for the kubernetes services to initialize. + + ```bash + microk8s.status --wait -ready + ``` + +5. To avoid colliding with a **kubectl** already installed and to avoid overwriting any existing Kubernetes configuration file, MicroK8s adds a **microk8s.kubectl** command, configured to exclusively access the new **MicroK8s** install. + + ```bash + microk8s.kubectl get services + ``` + +6. This step is only necessary if you require **microk8s.kubectl** to function as a standard **kubectl** command. This **DOES NOT** mean that you can then use **kubectl** to access **OTHER** k8s clusters. + + An example of why you would use this: You have a bash script or 3rd party tool that expects **kubectl** to be available. E.g. If you want to use Helm, it will not work against **microk8s.kubectl**, thus one **MUST** setup the alias for Helm to function correctly. + + ```bash + snap alias microk8s.kubectl kubectl + ``` + + Reverting it at any time; + + ```bash + snap unalias kubectl + ``` + + We will stick with the standard command of prefixing with **microk8s.** for this guide. + +7. If you already have **kubectl** installed and would like to use it to access the **MicroK8s** deployment. + + ```bash + microk8s.kubectl config view --raw > $HOME/.kube/config + ``` + +8. View the current context. + + ```bash + microk8s.kubectl config get-contexts + ``` + +9. Make sure the current context is **microk8s**. If not, set it as the current context. + + ```bash + microk8s.kubectl config use-context microk8s + ``` + +10. Install an Ingress Controller + + Install an Nginx Ingress Controller for MicroK8s by running the command: + + ```bash + microk8s enable ingress + ``` + + Alternatively refer to [Deployment Guide - 3.2. Kubernetes Ingress Controller](./README.md#32-kubernetes-ingress-controller) for manual installation. + +### 2.2. Docker + +Docker is deployed as part of the MicroK8s installation. The docker daemon used by MicroK8s is listening on unix:///var/snap/microk8s/current/docker.sock. You can access it with the **microk8s.docker** command. + +1. If you require **microk8s.docker** to function as a standard **docker** command, you set an alias + + ```bash + sudo snap alias microk8s.docker docker + ``` + + Undo the alias: + + ```bash + sudo snap unalias docker + ``` + +2. Otherwise you can apply the native microK8s commands by prefixing the docker command with `microk8s.` + + ```bash + microk8s.docker ps + ``` + +## 3. Continue with Deployment + +1. Continue setup and configuration from the [Mojaloop's deployment guide - 3.2. Kubernetes Admin Interfaces](./README.md#32-kubernetes-admin-interfaces) document. diff --git a/legacy/deployment-guide/local-setup-mac.md b/legacy/deployment-guide/local-setup-mac.md new file mode 100644 index 000000000..718f69e2c --- /dev/null +++ b/legacy/deployment-guide/local-setup-mac.md @@ -0,0 +1,84 @@ +# Mojaloop local environment setup for Mac + +Local setup on a Laptop or Desktop to run the Mojaloop project. + +## Setup Introduction + +This document will provide guidelines to a technical capable resources to setup, deploy and configure the Mojaloop applications on a local environment, utilizing Docker, Kubernetes and HELM charts. + +At this point the reader/implementer should be familiar with [Mojaloop's deployment guide](./README.md). Imported information is contained in that document and as such a prerequisite to this document. + +- [Mojaloop local environment setup for Mac](#mojaloop-local-environment-setup-for-mac) + - [Setup Introduction](#setup-introduction) + - [1. Kubernetes](#1-kubernetes) + - [1.1. Kubernetes Installation with Docker](#11-kubernetes-installation-with-docker) + - [2. Continue with Deployment](#2-continue-with-deployment) + +## 1. Kubernetes + +This section will guide the reader through the deployment process to setup Kubernetes within Docker. + +> RECOMMENDATIONS - Aug 2022 +> +> We recommend installing Kubernetes using either [minikube](https://minikube.sigs.k8s.io/docs/start) or [microk8s](https://microk8s.io/docs/install-alternatives) instead, as this will allow you to easily specify your desired Kubernetes version (i.e. either v1.20 or v1.21). +> +> Alternatively, a specific version of Docker-desktop that includes a supported target Kubernetes version as specified in the [Deployment Guide (1. Pre-requisites)](README.md#1-pre-requisites) can be installed. See [Installing Docker for Windows](#11-kubernetes-installation-with-docker) section for more information. +> + +### 1.1. Kubernetes Installation with Docker + +1. Kubectl + + Complete set of **kubectl** installation instruction are available [here](https://kubernetes.io/docs/tasks/tools/install-kubectl/). + + ```bash + brew install kubernetes-cli + ``` + + To verify if the installation was successful, check the version; + + ```bash + kubectl version + ``` + +2. To install Kubernetes with Docker, follow the steps below; + + > RECOMMENDATIONS - Aug 2022 + > + > For Windows/MacOS, version [Docker Desktop v4.2.0](https://docs.docker.com/desktop/release-notes/#docker-desktop-420) comes packaged with Kubernetes v1.21.5 which meets the current requirements. + > + + * Click on the Docker icon on the status barr + * Select **Preferences** + * Go to **Advanced** + * Increase the CPU allocation to at least 4 + * Increase the Memory allocation to at least 8.0 GiB + + ![Kubernetes Install with Docker 1](./assets/diagrams/deployment/KubernetesInstallWithDocker-1.png) + + * Go to **Kubernetes** + * Select **Enable Kubernetes** tick box + * Make sure **Kubernetes** is selected + * Click **Apply** + * Click **Install** on the confirmation tab. + * The option is available to wait for completion or run as a background task. + + ![Kubernetes Install with Docker 2](./assets/diagrams/deployment/KubernetesInstallWithDocker-2.png) + +### 1.2. Kubernetes environment setup + +1. List the current Kubernetes context; + + ```bash + kubectl config get-contexts + ``` + +2. Change your Contexts; + + ```bash + kubectl config use-context docker-desktop + ``` + +## 2. Continue with Deployment + +1. Continue setup and configuration from the [Mojaloop's deployment guide - 3.1. Kubernetes Ingress Controller](./README.md#31-kubernetes-ingress-controller) document. diff --git a/legacy/deployment-guide/local-setup-windows.md b/legacy/deployment-guide/local-setup-windows.md new file mode 100644 index 000000000..94698b26b --- /dev/null +++ b/legacy/deployment-guide/local-setup-windows.md @@ -0,0 +1,129 @@ +# Mojaloop local environment setup for Windows + +Local setup on a Laptop or Desktop to run the Mojaloop project. + +## Setup Introduction + +This document will provide guidelines to a technical capable resources to setup, deploy and configure the Mojaloop applications on a local environment, utilizing Docker, Kubernetes and HELM charts. + +At this point the reader/implementer should be familiar with [Mojaloop's deployment guide](./README.md). Imported information is contained in that document and as such a prerequisite to this document. + +- [Mojaloop local environment setup for Windows](#mojaloop-local-environment-setup-for-windows) + - [Setup Introduction](#setup-introduction) + - [1. Kubernetes](#1-kubernetes) + - [1.1 Kubernetes Installation with Docker](#11-kubernetes-installation-with-docker) + - [1.2 Kubernetes environment setup](#12-kubernetes-environment-setup) + - [2. Continue with Deployment](#2-continue-with-deployment) + +## 1. Kubernetes + +This section will guide the reader through the deployment process to setup Kubernetes within Docker. + +> +> RECOMMENDATIONS - Aug 2022 +> +> We recommend installing Kubernetes using either [minikube](https://minikube.sigs.k8s.io/docs/start) or [microk8s](https://microk8s.io/docs/install-alternatives) instead, as this will allow you to easily specify your desired Kubernetes version (i.e. either v1.20 or v1.21). +> +> Alternatively, a specific version of Docker-desktop that includes a supported target Kubernetes version as specified in the [Deployment Guide (1. Pre-requisites)](README.md#1-pre-requisites) can be installed. See [Installing Docker for Windows](#11-kubernetes-installation-with-docker) section for more information. +> + +### 1.1 Kubernetes Installation with Docker + +- **kubectl** is part of the installation package when installing Docker Desktop for Windows. + + Please note the minimum system and operation requirements; + - Docker Desktop for Windows require Microsoft Hyper-V to run. Hyper-V will be enable as part of the installation process, + - Windows 10 64bit: Pro, Enterprise, Education (1607 Anniversary Update, Build 14393 or later), + - CPU SLAT-capable feature, + - At least 4GB of RAM. (At least 16GB will be required to run the Mojaloop project). + +1. Installing Docker for Windows: + + > + > RECOMMENDATIONS - Aug 2022 + > + > For Windows/MacOS, version [Docker Desktop v4.2.0](https://docs.docker.com/desktop/release-notes/#docker-desktop-420) comes packaged with Kubernetes v1.21.5 which meets the current requirements. + > + + You will require Docker Desktop for Windows 18.02 Edge (win50) and higher, or 18.06 Stable (win 70) and higher. Kubernetes on Docker Desktop for Windows is available on these versions and higher. They are downloadable from: + + ```url + https://docs.docker.com/docker-for-windows/install/ + ``` + + Once download is completed, the downloaded file can normally be found in your Download folder. Installation is as per normal installations for windows. A restart will be required after this step. + +2. Enable visualization: + + Docker Desktop for Windows requires Microsoft Hyper-V to run. The Docker Desktop installer enables Hyper-V for you. + + If Hyper-V is not enabled, A pop-up messages will request if you would like to turn this on. Read the messages and select 'Ok' if appropriate. + + You need to insure that **VT-X/AMD-v** is enabled from `cmd.exe`: + + ```bash + systeminfo + ``` + + If not, from `cmd.exe` run as Administrator and execute: + + ```bash + bcdedit /set hypervisorlaunchtype auto + ``` + + A reboot would be required again for the updates to take effect. + +3. Start Docker Desktop for Windows: + + Docker does not start automatically after installation. To start it, select **Docker Desktop** and click on it (or hit Enter). + + When the _whale_ in the status bar stays steady, **Docker Desktop** is up-and-running, and accessible from any terminal window. Note - if the _whale_ is not on the status bar, it will be in the **hidden icon** notifications area, click the up arrow on the taskbar to show it. + + ![Docker is Running](./assets/diagrams/deployment/DockerIsRunning.png) + +### 1.2 Kubernetes environment setup + +1. Setting up the Kubernetes runtime environment within Docker Desktop: + + - Open the Docker Desktop for Windows menu by right-clicking the Docker icon. + - Select **Settings** to open the settings dialog. + - Under the **General** tab you can configure when to start and update Docker. + + - Go to **Advanced** tab + - Increase the CPU allocation to at least 4 + - Increase the Memory allocation to at least 8.0 GiB + + (If your system resource allow, more can be allocated as indicated below.) + + ![Docker Advance Settings](./assets/diagrams/deployment/DockerAdvanceSettings.png) + + Kubernetes on Docker Desktop for Windows is available in 18.02 Edge (win50) and higher, and in 18.06 Stable (win 70) and higher. + + - go to **Kubernetes** tab + - Select **Enable Kubernetes** + - Select **Show system container (advanced)** + + ![Enable Kubernetes](./assets/diagrams/deployment/EnableKubernetes.png) + +2. Set the context to be used. + + As mentioned, the Kubernetes client command, `kubectl` is included and configured to connect to the local Kubernetes server. If you have `kubectl` already installed, be sure to change context to point to **docker-for-desktop**; + + Through `cmd.exe`: + + ```bash + kubectl config get-contexts + kubectl config use-context docker-for-desktop + ``` + + Or through the Docker Desktop for Windows menu: + + - right-clicking the Docker icon + - Select **Kubernetes** + - Select **docker-for-desktop** + + ![Docker For Desktop](./assets/diagrams/deployment/DockerForDesktop.png) + +## 2. Continue with Deployment + +1. Continue setup and configuration from the [Mojaloop's deployment guide - 3.1. Kubernetes Ingress Controller](./README.md#31-kubernetes-ingress-controller) document. diff --git a/legacy/deployment-guide/releases.md b/legacy/deployment-guide/releases.md new file mode 100644 index 000000000..d47f799bf --- /dev/null +++ b/legacy/deployment-guide/releases.md @@ -0,0 +1,41 @@ +# Mojaloop Releases + +Below you will find more information on the current and historical releases for Mojaloop. + +Refer to [Versioning Documentation](../contributors-guide/standards/versioning.md) for more information on the release strategy and standards. + +## Current Releases +* Helm: [![Git Releases](https://img.shields.io/github/release/mojaloop/helm.svg?style=flat)](https://github.com/mojaloop/helm/releases) +* Central-Ledger: [![Git Releases](https://img.shields.io/github/release/mojaloop/central-ledger.svg?style=flat)](https://github.com/mojaloop/central-ledger/releases) +* Ml-API-Adapter: [![Git Releases](https://img.shields.io/github/release/mojaloop/ml-api-adapter.svg?style=flat)](https://github.com/mojaloop/ml-api-adapter/releases) +* Central-Settlement: [![Git Releases](https://img.shields.io/github/release/mojaloop/central-settlement.svg?style=flat)](https://github.com/mojaloop/central-settlement/releases) +* Central-Event-Processor: [![Git Releases](https://img.shields.io/github/release/mojaloop/central-event-processor.svg?style=flat)](https://github.com/mojaloop/central-event-processor/releases) +* Email-Notifier: [![Git Releases](https://img.shields.io/github/release/mojaloop/email-notifier.svg?style=flat)](https://github.com/mojaloop/email-notifier/releases) +* Account-Lookup-Service: [![Git Releases](https://img.shields.io/github/release/mojaloop/account-lookup-service.svg?style=flat)](https://github.com/mojaloop/account-lookup-service/releases) +* Quoting-Service: [![Git Releases](https://img.shields.io/github/release/mojaloop/quoting-service.svg?style=flat)](https://github.com/mojaloop/quoting-service/releases) + + +## Helm Charts Packaged Releases + +Refer to [Mojaloop Helm Repository](../repositories/helm.md) documentation to find out more information about Helm. Below are some of the Helm releases made and timelines. Please note that this is not an exhaustive list. For an exhaustive list, please visit the [Helm releases page](https://github.com/mojaloop/helm/releases). + +| Version | Release Date | Tested | Notes | +| --- | :---: | :---: | --- | +| [9.2.0](https://github.com/mojaloop/helm/releases/tag/v9.2.0) | 2019/03/04 | ✓ | Sprint release | +| [8.8.0](https://github.com/mojaloop/helm/releases/tag/v8.8.0) | 2020/02/12 | ✓ | Sprint release | +| [8.7.0](https://github.com/mojaloop/helm/releases/tag/v8.7.0) | 2019/12/12 | ✓ | Sprint release | +| [8.4.0](https://github.com/mojaloop/helm/releases/tag/v8.4.0) | 2019/11/12 | ✓ | Sprint release | +| [8.1.0](https://github.com/mojaloop/helm/releases/tag/v8.1.0) | 2019/10/08 | ✓ | Sprint release | +| [7.4.3](https://github.com/mojaloop/helm/releases/tag/v7.4.3) | 2019/08/30 | ✓ | Sprint release | +| [7.4.1](https://github.com/mojaloop/helm/releases/tag/v7.4.1) | 2019/08/23 | ✓ | Sprint release | +| [6.3.1](https://github.com/mojaloop/helm/releases/tag/v6.3.1) | 2019/05/31 | ✓ | Sprint release | +| [5.5.0](https://github.com/mojaloop/helm/releases/tag/v5.5.0) | 2019/04/02 | - | Sprint release | +| [5.4.2](https://github.com/mojaloop/helm/releases/tag/v5.4.2) | 2019/03/29 | ✓ | Sprint release | +| [5.4.1](https://github.com/mojaloop/helm/releases/tag/v5.4.1) | 2019/03/21 | ✓ | Sprint release | +| [5.4.0](https://github.com/mojaloop/helm/releases/tag/v5.4.0) | 2019/03/19 | ✓ | Sprint release | +| [5.2.0](https://github.com/mojaloop/helm/releases/tag/v5.2.0) | 2019/02/20 | ✓ | Sprint release | +| [5.1.3](https://github.com/mojaloop/helm/releases/tag/v5.1.3) | 2019/02/14 | ✓ | Sprint release | +| [5.1.2](https://github.com/mojaloop/helm/releases/tag/v5.1.2) | 2019/02/11 | ✓ | Sprint release | +| [5.1.1](https://github.com/mojaloop/helm/releases/tag/v5.1.1) | 2019/02/08 | ✓ | Sprint release | +| [5.1.0](https://github.com/mojaloop/helm/releases/tag/v5.1.0) | 2019/02/06 | ✓ | Sprint release | +| [4.4.1](https://github.com/mojaloop/helm/releases/tag/v4.4.1) | 2019/01/31 | ✓ | Released at PI4 Convening in Jan 2019 | diff --git a/legacy/deployment-guide/upgrade-strategy-guide.md b/legacy/deployment-guide/upgrade-strategy-guide.md new file mode 100644 index 000000000..ef2e2b09e --- /dev/null +++ b/legacy/deployment-guide/upgrade-strategy-guide.md @@ -0,0 +1,115 @@ +# Upgrade Strategy Guide + +This document provides instructions on how to upgrade existing Mojaloop installations. It assumes that Mojaloop is currently installed using Helm, but these strategies can be applied in general. + +## Table of Contents + +- [Upgrade Strategy Guide](#upgrade-strategy-guide) + - [Table of Contents](#table-of-contents) + - [Helm Upgrades](#helm-upgrades) + - [Non-breaking Releases](#non-breaking-releases) + - [Breaking Releases](#breaking-releases) + - [Mojaloop installed without backend dependencies](#mojaloop-installed-without-backend-dependencies) + - [1. Target version has no datastore breaking changes](#1-target-version-has-no-datastore-breaking-changes) + - [Example Canary style deployment](#example-canary-style-deployment) + - [2. Target version has datastore breaking changes](#2-target-version-has-datastore-breaking-changes) + - [Mojaloop installed with backend dependencies](#mojaloop-installed-with-backend-dependencies) + - [Example Blue-green style deployment](#example-blue-green-style-deployment) + +## Helm Upgrades + +This section discusses the strategies of how upgrades could be applied to an existing Mojaloop Helm deployment that uses the [Mojaloop Helm Charts](https://github.com/mojaloop/helm). + +The scope of the breaking changes described below are applicable to the Switch Operator's Helm deployment with no direct impact (i.e. no functional changes such as a new Mojaloop API Specification version) to Participants (e.g. Financial Services Providers). Such functional changes may be part of a Helm release, but are out of scope for this section. + +Recommendations: + +1. all upgrades should be tested and verified in a pre-production environment +2. always consult the release notes as there may be some known issues, or useful notes that are applicable when upgrading +3. the [migrate:list command](https://knexjs.org/#Migrations) can be used to list pending datastore changes in the following repositories: + - + - + +### Non-breaking Releases + +Non-breaking changes will require no additional or special actions (unless otherwise stated in the release notes) to be taken other than running a standard [Helm upgrade](https://helm.sh/docs/helm/helm_upgrade) command. + +Be aware of the following optional parameter flag(s) that will be useful when upgrading: + +``` + -i, --install if a release by this name doesn't already exist, run an install + --reuse-values when upgrading, reuse the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' is specified, this is ignored + --version string specify a version constraint for the chart version to use. This constraint can be a specific tag (e.g. 1.1.1) or it may reference a valid range (e.g. ^2.0.0). If this is not specified, the latest version is used +``` + +See the following example of how these parameters can be applied: + +```bash +helm --namespace ${NAMESPACE} ${RELEASE_NAME} upgrade --install mojaloop/mojaloop --reuse-values --version ${RELEASE_VERSION} +``` + +It is possible to rollback using the [Helm rollback](https://helm.sh/docs/helm/helm_rollback/) command if desired. + +### Breaking Releases + +There are several strategies that can be employed when upgrading between breaking releases depending on the following deployment topologies: + +1. Mojaloop installed without backend dependencies (e.g. Kafka, MySQL, MongoDB, etc), with backend dependencies managed separately. This is preferred and will provide the most flexibility in upgrading, especially when there are breaking changes + +2. Mojaloop installed with backend dependencies, with backend dependencies tightly coupled to the Helm installation + +#### Mojaloop installed without backend dependencies + +This is the preferred deployment topology as it will provide the most flexibility when upgrading. By separating out the backend dependencies, it will enable one to deploy the target version of Mojaloop as a new deployment. + +This new deployment can either point to the existing backend dependencies or will require new backend dependencies depending on the following: + +##### 1. Target version has no datastore breaking changes + +In this scenario, we can utilise a Canary style deployment strategy by configuring the new deployment to the existing backend dependencies. The new deployment will by default upgrade the datastore schemas as required by running the `migration` (see [Central-ledger](https://github.com/mojaloop/central-ledger/tree/master/migrations), [Account-lookup-service](https://github.com/mojaloop/account-lookup-service/tree/master/migrations)) scripts. Alternatively, the migration scripts can be disabled (e.g. [central-ledger](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml#L147), with Account-lookup-service similarly being configured) if required, and a manual upgrade SQL script can be prepared (see [migrate:list command](https://knexjs.org/#Migrations) to list pending changes) if preferred. + +There should be no disruption to the current Mojaloop deployment. + +As the backend dependencies are shared between the current and target deployments, it will also be possible to move a sub-set of users to the target Mojaloop deployment allowing for one to validate the new deployment with minimal impact, and also provide the ability for users to easily switch back to the current deployment. + +###### Example Canary style deployment + +![Helm Canary Upgrade Strategy](./assets/diagrams/upgradeStrategies/helm-canary-upgrade-strategy.svg) + +1. Customize the [Mojaloop Chart values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml) for the desired target Mojaloop release: + 1. Ensure backend-end configurations are set to the existing (shared) deployed Backend dependencies + 2. If applicable, ensure ingress-rules do not overwrite the current deployment configuration +2. Deploy the target Mojaloop release (Blue) + 1. Monitor the migration script logs for any upgrade errors via the `run-migration` containers: + - `kubectl -n ${NAMESPACE} logs -l app.kubernetes.io/name=centralledger-service -c run-migration` + - `kubectl -n ${NAMESPACE} logs -l app.kubernetes.io/name=account-lookup-service-admin -c run-migration` +3. Execute sanity tests on the Current Green deployment environment (verify impact of datastore changes, and allow for rollback, or partial switch-over for DFSPs, etc) +4. Execute sanity tests on the Target Blue deployment environment +5. Cut-over API Gateway (or upgrade target Ingress rules) to from Current Green to Target Blue deployment environment + +##### 2. Target version has datastore breaking changes + +See [Mojaloop installed with backend dependencies](#mojaloop-installed-with-backend-dependencies). + +#### Mojaloop installed with backend dependencies + +In this scenario, we can utilise a Blue-green style deployment strategy by deploying new backend dependencies, and deploying the target Mojaloop release separately (with the additional benefit of aligning your deployment to the recommending deployment topology). + +Manual data migrating from the existing datastores to the new target backend dependencies will be required. It will also be necessary to keep the current and new datastores in sync as long as live transactions are being processed through the existing Mojaloop deployment. A maintenance window need to be scheduled to stop "live" transaction on the current deployment to ensure data consistency, and allow for the switch-over to occur safely. This will cause a disruption, but can be somewhat mitigated by ensuring that the maintenance window is scheduled during the least busiest time. + +##### Example Blue-green style deployment + +![Helm Blue-green Upgrade Strategy](./assets/diagrams/upgradeStrategies/helm-blue-green-upgrade-strategy.svg) + +1. Customize the [Mojaloop Chart values.yaml](https://github.com/mojaloop/helm/blob/master/mojaloop/values.yaml) for the desired target Mojaloop release: + 1. Ensure backend-end configurations are set to the target deployed Backend dependencies + 2. If applicable, ensure ingress-rules do not overwrite the current deployment configuration +2. Deploy the target Mojaloop release (Blue) +3. Create Migration process to sync and transform data into target deployed Backend datastore dependencies from Green to Blue +4. Schedule cut-over window +5. Execute cut-over during window + 1. Set current Green Backend datastore dependencies to read-only (where possible) + 2. Drain any remaining connections from Green + 3. Ensure Migration process is fully in-sync from Green to Blue + 4. Execute sanity tests on the Blue Target deployment environment + 5. Cut-over API Gateway (or upgrade target Ingress rules) to from Green Current to Blue Target deployment environment diff --git a/legacy/discussions/ISO_Integration.md b/legacy/discussions/ISO_Integration.md new file mode 100644 index 000000000..333ed8729 --- /dev/null +++ b/legacy/discussions/ISO_Integration.md @@ -0,0 +1,61 @@ +Mojaloop ISO Integration discussions + +# Mojaloop-ISO integration + +The proposed solution would be able to handle ISO to Open API translation and vice versa, by making use of an ISO-OPEN API converter/connecter plug-in or interface, similar to the Scheme Adapter in the Mojaloop system. As the Scheme adapter performs Mojaloop API to FSP API conversion, the custom plug-in/interface would function as a protocol and message translator between the ISO interface and the ML API or the Scheme Adapter. + +## Scope + +Define message flows in both and ISO and Open API networks and mappings between messages. + - Document failure scenarios and message flows for these. + - Define a mechanism for routing that is MSISDN-based . + - Mojaloop Transactions could be sent through existing payment rails conforming to their standards(such as ISO) + - Develop a scheme adapter/plug-ins that could perform ISO-Open API and vice versa. + - To be able to send Mojaloop transactions originating from ATM and POS over ISO networks, across Mojaloop systems + + ## ISO 8583 - Mojaloop - An Inter-network case study + +Africa is a great continent with a multitude of Financial Service providers who focuses on region based financial inclusion and services provision. The continent boasts of a vast network of Payment service providers and financial institutions. Some of the most prominent networks are listed below: + +- InterSwitch ( Nigeria) +- eProcess ( Ghana) +- Umoja Switch ( Tanzania) +- KenSwitch ( Kenya) +- ZimSwitch ( ZImbabwe) +- RSwitch ( Rwanda) + +Almost all of these networks make use of an ISO 8583 based Payments processing platform ( Postilion Switch) to drive ATM’s, POS & Mobile channels, process card based and non card based transactions for both acquiring and issuing verticals. + +As such, the proposition is to create a solution, where by the existing Payment networks could integrate with a Mojaloop based system like Mowali, without having to make any development or design changes to their existing infrastructure. + +In this case study, we are considering the case of Umoja Switch in Tanzania and provide them with a solution whereby, Umoja could provide Mojaloop transactions through their existing ATM deployments. + +### Umoja Switch + +UmojaSwitch was established in the year 2006 by six banks in Tanzania with the main purpose being able to establish a joint shared infrastructure for financial services and enjoying the economies of scale. + +The aim of establishment was to create a shared platform where financial institutions can integrate and interpolate through a shared switch. + +Eventually, the number of members joining the UmojaSwitch network continued to increase and as of now there are around 27 banks who has joined the Umoja Switch consortium. + +## ISO Networks to Open API + +The goal of the PoC would be to showcase how a Mojaloop transaction would be sent over a standard ISO switch/Network through to a Mojaloop system such as Mowali. + +As a part of this an ISO-Open API Adapter would be implemented which would process ISO messages originating from an ISO network like InterSwitch and send it through to an Open API network like Mowali. + +## Proposed Solution + +The proposed solution will consist of an interface or adapter/plugin that could process transactions between ISO networks and Mojaloop systems. + +The ISO payments platform makes use of an ISO interface which uses standard TCP/IP connection to send and respond to ISO messages to and from the various channels. In order to accept and process connections from the interface, our solution would have a TCP/IP listener, which would receive and process transactions from ISO network and then map it to Open API , after which the transactions will be sent over to a Mojaloop system like Mowali on a URL. + +In this case the payment networks are largely dependent on their respective (i.e. Visa/ MasterCard/Verve/etc) card or account number, which is used to define the BIN look up table for routing purposes . One of the options would be to predefine a Bin range (eg: 757575) that would identify a Mojaloop transaction and then let the payment network implement a routing logic that would send all Moja transactions through to the Open API network. + +The ISO-Open API adapter would process the ISO message received from the ISO switch and send it through to the Mojaloop system in Open API format. + +However, such changes would imply configurational changes to download applications on ATM and other terminal devices, but this could be handled as a standard operational change similar to the existing configurational changes performed as per the business requirements. + + + + diff --git a/legacy/discussions/Mojaloop Performance 2020.pdf b/legacy/discussions/Mojaloop Performance 2020.pdf new file mode 100644 index 000000000..719dec47e Binary files /dev/null and b/legacy/discussions/Mojaloop Performance 2020.pdf differ diff --git a/legacy/discussions/aws_tagging.md b/legacy/discussions/aws_tagging.md new file mode 100644 index 000000000..a50c7b2ef --- /dev/null +++ b/legacy/discussions/aws_tagging.md @@ -0,0 +1,127 @@ +# AWS Tagging Guidelines + Policies + +> **Note:** These guidelines are specific to the Mojaloop Community's AWS Environment for testing and validating Mojaloop installations, and are primarily for internal purposes. They may, however, be a useful reference to others wishing to implement similar tagging strategies in their own organizations. + +To better manage and understand our AWS usage and spending, we are implementing the following tagging guidelines. + +## Contents +- [Proposed tags and their meanings](#proposed-tags-and-their-meanings) + - [mojaloop/cost_center](#mojaloopcost_center) + - [mojaloop/owner](#mojaloopowner) +- [Manual Tagging](#manual-tagging) +- [Automated Tagging](#automated-tagging) +- [AWS Tagging Policies](#aws-tagging-policies) + - [Viewing Tag Reports + Compliance](#viewing-tag-reports--compliance) + - [Editing Tag Policies](#editing-tag-policies) + - [Attaching/Detaching Tag Policies](#attachingdetaching-tag-policies) + +## Proposed tags and their meanings + +We propose the following 2 tag _keys_: + +- `mojaloop/cost_center` +- `mojaloop/owner` + +### `mojaloop/cost_center` + +`mojaloop/cost_center` is a breakdown of different resources in AWS by the workstream or project that is incurring the associated costs. + +It loosely follows the format of `-[-subpurpose]`, where account is something like `oss`, `tips`, or `woccu`. +> Note: It's likely that most of the resources will be under the `oss` "account", but I managed to find some older resources that fall under the `tips` and `woccu` categories. We also want to plan for future types of resources that might be launched in the future. + +Some potential values for `mojaloop/cost_center` are: + +- `oss-qa`: Open source QA work, such as the existing dev1 and dev2 environments +- `oss-perf`: Open source performance work, such as the ongoing performance workstream +- `oss-perf-poc`: Performance/Architecture POC + +We also reserve some special values: +- `unknown`: This resource was evaluated (perhaps manually, or perhaps by an automated tool), and no appropriate `cost_center` could be determined. + - This will allow us to easily filter for the `mojaloop/cost_center:unknown` tags and produce a report +- `n/a`: This resource incurrs no cost, so we're not really worried about assigning a `cost_center` to it + - This can be useful for mass tagging resources that are hard to figure out where the belong, such as EC2 Security Groups + +### `mojaloop/owner` + +`mojaloop/owner` is a person who is responsible for the managing and shutdown of a given resource. + +The goal of this tag is to prevent long running resources that everybody else thinks _someone else_ knows about, but we no longer need. By applying this tag, we will be able to have a list of _who to go to_ in order to ask questions about the resource. + +The value can simply be a person's name, all lowercase: +- `lewis` +- `miguel` +- etc. + +Once again, we will reserve the following values: +- `unknown`: This resource was evaluated (perhaps manually, or perhaps by an automated tool), and no appropriate `cost_center` could be determined. + - This will allow us to easily filter for the `mojaloop/owner:unknown` tags and see what resources are 'orphaned' + + +## Manual Tagging + +We can use the "Tag Editor" in the AWS console to search for untagged resources. + +1. Log into the AWS Console +2. Under Resource Groups, select "Tag Editor" +![](./images/tagging_01.png) +3. From the tag editor, select a Region (I typically use "All regions"), and Resource Type (I also typically use "All resource types") +4. Now select "Search Resources", and wait for the resources to appear + +You can also search by tags, or the absense of tags to see what resources have not been tagged yet. +![](./images/tagging_02.png) + +5. Once you have a list of the resources, you can select and edit tags for many resources at once! +6. You can also export a `.csv` file of resources found in your search + + +## Automated Tagging + +We currently automate tagging on the following + +As we have a firmer grasp of our tagging guidelines, we need to introduce them into our tooling so that all of the grunt work of manual tagging. + +At the moment, this will look like introducing tags into: +1. Rancher - which currently manages our Kubernetes clusters for both QA and Performance purposes +2. IAC - The upcoming IAC code that will eventually be running our dev environments + + +## AWS Tagging Policies + +As of August 3, 2020, we have started introducing [AWS Tagging Policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_tag-policies.html) to better enforce tags and monitor our resources (especially with respect to costs). + + +### Viewing Tag Reports + Compliance + +1. Log in to the AWS Console +2. "Resource Groups" > "Tag Editor" +3. On the left sidebar, select "Tag Policies" + +From here you can see the tag policies "compliance report" + +![](./images/tagging_03.png) + + +### Editing Tag Policies + +> Note: This may require special admin priviledges to access these pages + +1. Log in to the AWS Console +2. Select "username@mojaloop" in the top right > "My Organization" +3. Select "Policies" > "Tag Policies" + +![](./images/tagging_04.png) + +4. From here, you can view the current tag policies + +![](./images/tagging_05.png) + +5. In the sidebar, you can click "View details" > "Edit policy" to edit the policy + + +### Attaching/Detaching Tag Policies + +1. Go to the "My Organization" page +2. Select the relevant account > "Tag policies" in the sidebar +3. From here you can Attach + Detach tag policies + +![](./images/tagging_06.png) diff --git a/legacy/discussions/code_improvement.md b/legacy/discussions/code_improvement.md new file mode 100644 index 000000000..284f97299 --- /dev/null +++ b/legacy/discussions/code_improvement.md @@ -0,0 +1,26 @@ +# Code_Improvement Project + +## Overview +Purpose to improve code quality and security for the Mojaloop project. Includes analysis and introduction of new open sources tools, process improvments, gates checks (w/in pull requests and builds) along with documentation. + +Scope: project is focused on quality and security but can lead to other areas such as test automation and DevOps automation and tools. + +## OutPut (phase one by end of January): +- Implementation and analysis of new OSS tools +- Update Release Scripts: Security aspects need to be embedded in release/devops (CI/CD) +- Update rules for Pull Requests: Security aspects embedded in pull requests (before check-ins) +- Update documentations: Standards and contribution guides +  +Slack Channel:#code_security + + ## Discussions: + ### Implement changes at the Dockerfile and CI/CD build process to help bolster our container security + - Create a non-root user within the Dockerfile + - Enable docker-content-trust on the docker host (this will be inside CircleCI) + - Run builds with --no-cache during CircleCI step to ensure that we are pulling in any new security patches each time (I don’t think this is a major issue since we don’t have CircleCI docker image caching on anyway + + ### Move from Javascript to Typescript + - Transition to typescript (mix and match js and ts) for more security/quality + - Typescript is preferred but not required: https://github.com/mojaloop/template-typescript-public + + diff --git a/legacy/discussions/cross_border_day_1.md b/legacy/discussions/cross_border_day_1.md new file mode 100644 index 000000000..5c5d51d79 --- /dev/null +++ b/legacy/discussions/cross_border_day_1.md @@ -0,0 +1,270 @@ +# Cross Border Discussion Day 1 + +>**Links** +>- [Day 2 Notes](./cross_border_day_2.md) +>- [Relevant Issue on DA Board](https://github.com/mojaloop/design-authority/issues/32) +>- [Mojaloop Spec Pull Request](https://github.com/mojaloop/mojaloop-specification/pull/22) + +## Attendees: + +In person +- Lewis, Crosslake +- Adrian, Coil +- Nico, MB +- Sam, MB +- Miguel, MB +- Carol Benson, Glenbrook +- Michael Richards, MB +- Henrik Karlsson, Ericsson +- Rob Reeve, MB +- Vanburn, Terra Pay +- Razin, Terra Pay +- Ram, Terra Pay +- JJ, Google +- Matt Bohan, Gates Foundation +- David Power, EY +- James Bush, MB +- Warren, MB +- Judit, MB +- Bart-Jan and Bruno from GSMA - Day #2 + +Phone +- Kim Walters, Crosslake +- Istvan Molnar, DPC +- Innocent Ephraim, MB + +## Session 1 + +**Goal: Update the API definitions** + +- Privacy: + - Can I send USD? _yes/no_ + - What can I send? _list of currencies_ + +Business agreements: there are a few ways this can happen +- Global scheme, made up of scheme to scheme agreements +- bilateral scheme agreements +- scheme to scheme +- region + + +Definitions: +- Gateway FSP: An FSP that 'bridges' across 2 networks +e.g. Mowali + - 2 logical networks (USD,XOF?) + - a single mojaloop network + +- Cross Network Provider (CNP) + - FXP, same thing? + +Michael: +- there is a reason for that assumption +- other legal implications here... + +- single entity, legally in 2 different jurisdictions + - a close analogy of a scheme without jurisdiction + +- participant: + - has a tx account that can be debited or credited + - bank, fxp etc. + +>Q: Can we have a participant that doesn't settle? Or would this be covered by CNP that is a party +>e.g. Visa, doesn't always settle in a given market, but holds an account + +- Resident vs. Non-resident + - reporting requirements are different + +- what are the technical requirements for reporters? + +- settlement + - not too worried about it at this stage (our focus is on the API changes) + - we assume that settlement is possible, but need to narrow scope witht the api first + +- Not only mojaloop + - need to allow for non-mojaloop -> mojaloop transfers and vice versa (both inbound and outbound) + - must still be interoperable + + +- who provides routing? + - switch? + - ALS? + - CNP? + + +>*Follow Up:* Need a formal definition of FXP and CNP roles, along with requirements and responsibilities + + +At a scheme level + - should the sceheme maintain a list of other schemes it allows its FSPs to connect with? + - or should the CNP take care of this? + +- not scheme -> scheme, but part of the onboarding CNP process +- but the scheme can/should still maintain rules + +- how will quoting work? Should an FSP send multiple quotes, one addressed to each CNP? Or should the switch have some rules engine that helps it determine who to send quotes to? + +James: We want to be flexible. Can see instances where we would want both to happen, so we shouldn't assume too much at this stage. + +Simplest option: The switch talks to the ALS, determines a transfer is not in our network, and then finds a list of CNPs + +CNP + FXP -> essentially the same thing +- they are *Roles*, and a DFSP can assume more than 1 role +- fxps can also exist in more than 1 zone (e.g. Mowali case) + - single network fxp is just an fxp, + - multi-network fxp is likely also a CNP + + +## Session 2 + +- debate about single or multiple lookups + - we should never return "empty result" + +- are wallets addressable by MSISDN? + - only 1 account at the moment + - but this is internal to the switch + - the oracle's job is to convert MSIDN -> Mojaloop Address + +- in the future: MSISDN + accounts will be less related + - this topic is adjacently related to addressing + +- 'going outisde' mojaloop with addressing will be a little tricky +- Standardize addressing? + - not something we want to do + +Ram: There are existing tools (no need to reinvent the wheel), outside the mojaloop scheme + +- sending to unknown currency + - currently: 1 routing table answer + - future: multiple answers + +- privacy: + - no real need for hard rules at the moment (at least not at the API level, rules come along with schemes) + - we do need a method for mediating information that one switch requires from another (and rejecting quotes should these prerequesites not be met) + +--- +- Domestic vs. Cross border: USer has/needs different information + - e.g. do we only want to support discovery in domestic case? +--- + +Adrian: A lot of this stuff is business rule and scheme specific +- maintains competitive space +- How much information is in the: + - lookup? + - Quote? + +--- +- Proposal: Address lookup -> Returns multiple responses? +- MSISDN -> ID, not an address. Someone, not an account + +- there should be only 1 response from the ALS +- Michael disagrees + +- need to separate out *addressing* from *routing* + +- we need to think about the downstream affects this will have on testing + - need to find a clear way to test these lookups + + +For example, airtel UPI issue (where existing MSIDSNs were replaced when they grandfathered in their mobile customers to become mobile money customers) + - we need to avoid a situation like that + +--- + +Bring it back to first (L1P) principles +- transfers should clear immediately +- no such thing as a future + +- For domestic: we can guarantee delivery, but cross-border is much harder +- need to maintain transparency requirement on CNPs + - this comes down to business rules + +- Reversible tx's or rules abour downstream issues + - ILP takes care of *most* of this for us + +- in TIPS case: 1 ID maps to 1 account +- as always, there needs to be a compromise between privacy and features (and that's ok!) + +--- + +At the end of a quote: +- ValueDate +- how much will be received +- what are the fees? (broken down, by step and currency) + +--- + +How do we support protocols that don't support quotes (this is a question for moja to non-moja systems) + +Risk: CNP: they hold the risk in this type of transaction + +CNP as a participant? + - holds an account with a participant + - direct vs indirect approach + - this doesn't affect the technical requirements (so out of scope for this discussion) + + +--- + +- fixed send and receive: + - What direction does data need to be appended to the quote? It depends on if it is fixed receive vs fixed send + +- Either: `A send 20 USD to B` OR `B receives 1000 PHP` + +- translating fees back for user: FXP __must__ apply the same rate for fees as the principal transfer + +- From L1P Perspective: __the goal is transparency__ + +- how about quotes outside of Mojaloop? + - CNP should take care of this - it is the last bastion of Mojaloopyness + +--- + +- Participant Object + - Attached to the Quotes, one entry per hop? + - So multi-hop quotes hold _n_ participant objects, where _n_ = number of hops + 1 + +As part of this we need: +- interoperable bits of data (common defs) +- scheme for encryption +- a place to put the data (in the quotes object) + +Should we worry about encryption for now? +- perhaps not, but still should allow for it in the API + +Encryption adds extra integration challenge +- what is the need to get data in the clear? + - from a techincal perspective: just use a blank encryption key + +Do we need to encrypt to ensure the switch(es) can't see the data? + - perhaps not at this stage + + +>### Decision: +>- No encryption for now +>- in outbound quote request: have a list of data requirements +>- for inbound quote request: participants fill out those requirements +>- if requirements are not met: abort the quote +>- Don't hardcode the data requirements, we should use existing standards + + +- we need to specify whether or not fields _have_ been verified + - ties in with tiered KYC processes + +- need a common dictionary of data that can/should be requested + + +## Boards: + +_board 1: Fixed send flows_ +![board_1](./images/cb_board_1.jpg) + +_board 2: Fixed receive flows_ +![board_2](./images/cb_board_2.jpg) + + + + + + + + diff --git a/legacy/discussions/cross_border_day_2.md b/legacy/discussions/cross_border_day_2.md new file mode 100644 index 000000000..fbbbfd799 --- /dev/null +++ b/legacy/discussions/cross_border_day_2.md @@ -0,0 +1,124 @@ +# Cross Border Discussion Day 2 + +>**Links** +>- [Day 1 Notes](./cross_border_day_1.md) +>- [Relevant Issue on DA Board](https://github.com/mojaloop/design-authority/issues/32) +>- [Mojaloop Spec Pull Request](https://github.com/mojaloop/mojaloop-specification/pull/22) + +## Next Steps: + +- Updated the proposal APIs +- Present the consolidated change to the CCB in writing +- Couple of weeks to put together the changes (Michael/Adrian to split up the work) +- Mid-November CCB call + + +## Session 1 + +Unanswered Questions: +- addressing + - break it down? + - cross-mojaloop + - what does a PayerFSP do with an address? + +- ALS + routing + - what optimizations does the API need to do/allow? + +- local vs. remote DFSP ids + +- Downstream failures + - When paymnet does clear, does the payer receive a notification (esp. with 'delayed' payments that may interface with non-mojaloop systems) + - Can a CNP send a `PATCH` of the tx to update the Payee somehow? + +--- + +- multiple quotes and route responses: + - how do display to the user? + - We need to establish rules for filtering routes + - hard to do: e.g. blacklisting a switch? or express a preference for certain routes + +- how will Sender DFSP discover the scheme rules for a receiver? +- does the Sender DFSP need to 'know' the final switch? Or can it just 'know' the next one? + +--- + +Running up against ML + non-ML assumptions +- does this mean CNP needs to do more work when connecting to non-ML? + - e.g. knowing the resulting scheme/switch? + - why? Failure handling + - based on yesterday's decision: Should the CNP do the work here? + +- Take a lesson from SWIFT: + - bank doesn't know where the money is going + - can we avoid this in ML? + +--- + +CNP: Goal is to 'act like' a normal member of the network + - This minimizes the responsibilities that the scheme assumes + +When is the TX considered completed? + - There might be cases where the scheme considers it done, but it is not techincally finished end to end + +How do we deal with service deteroriation? + - Scheme rules + +--- + +Back to quotes: + +- how to express quote information? + - are quotes and routes separate? Presumably, yes + +- The quote is the most expensive step + - Can we provide QOS information here as part of the lookup? + +Addressing: +- Need for a globally unique address + - Allow an address space for DFSPs and unique persons/accounts +- sheme says "this isn't in my space" +- CNP figures out the routes to get to that space + +--- + +### Michael's Tangent: + +- did we make the wrong assumptions about the CNP? + +**switch:** Knows CNPs + FXPs +**CNPs:** holds routing table and lookup + +- if the sender or receiver is an FXP, the the tx is *not* a cross-currency tx + +--- + +## Session 2 + +*Decision:* +- header value is CNP id +- partId object is the final FSP + +valueDate +- implied that funds are expected to clear before the valueDate +- can still have short expiry times on tx + +- CNP: + - returns an obfuscated set of fees + - fits into our current model + + +- condition: + - existing object cryptographically tied to the tx object + - but for multi-hop, we don't only know this + - fixed receive makes this tricker (which is what echo data hopes to solve) + + - We want **only 1 condition for all hops** + - the idea of a multi-condition is a "perversion" (according to some) + + +## Boards: + +_board 3: Cross Network lookup and quotes flow, fixed receive of 1000 PHP from USD_ +![board_3](./images/cb_board_3.jpg) + + diff --git a/legacy/discussions/crossborder.md b/legacy/discussions/crossborder.md new file mode 100644 index 000000000..4deec6f8d --- /dev/null +++ b/legacy/discussions/crossborder.md @@ -0,0 +1,396 @@ +**Cross-border Workstream Meeting** + +March 10th & 11th (London/remote) + +**Next Steps for PI:** + +• Proposal for how the CNP query and host oracle services and global goals - Adrian, Michael + +• Compound identifiers, ways in which this is captured in the system or expressed in apis - open + +• What information is captured in the data model or the extension list - Michael + +• Follow-up w/ SWIFT to discuss requirements - Matt + +**Open Items:** + +• Finalize CNP Requirements + +• Has to aggregate information and put them together into a single request & they will need to sign separately + +• Finalize FXP has to manage FX rates, the settlements and what expires when + +• CNPs can extend this and determine additional scheme rules + +• FXP handles rounding errors + +• FXP Guarantee a given rate + +• How do you get non-Mojaloop folks in the schema? + +• How do we integrate Mojaloop and some Mojaloop scheme to provide a full PVT payments - working group with Michael, Adrian, Sybrin, others as needed + +• How do we manage requests for regulatory reasons + +• Investigate identifier mappings (Map pathfinder accounts/mobile accounts to DFSP unique IDs) + +• Investigate Certification (Hash and PKKI) + + +Detailed Meeting Notes: +Day #1: + - Quote response + + ○ How do we code the SLA into the response + + ○ Ask a 2nd CNP to route + + ○ In the API - need to package up how to get it there + + ○ As a CMP in Mowali if I return a quote response the scheme has implications + + ○ Follow the whole route from payer to payee + + ○ Limiting the participation of CNP - they need to be the last hop + + § How to define the requirements of a CNP? + + - Message format + + ○ Http syntax + + ○ Started from the mojaloop scheme + + § Move towards the CNP should manage the conversion + + ○ SWIFT version + + ○ Security - TLS + + ○ Header/content encrypted in JWS + + - Retail system + + ○ Off network - remit to someone hub + + - Data Model + + ○ Structure: Ways in which we added new information, different routes, etc. + + ○ Privacy: Visibility and Security - only accessible to the people that can see it + + ○ Content of the data model + + - Transfer is done through the switch (movement of money) + + ○ In mowali - the amounts are expressed but the rate is important because it impacts settlements + + § Data flow - we add the rate when we send the quote back + + § Added in the extension list - should it be part of the standard? + + § Send and receive amount (differ currency) + + - Data element + + ○ Fee for each participant + + ○ Payer DFSP adds it up + + ○ Fee element for the transaction + + - Proposal + + ○ Account lookup service + + § List of local FSP + + ○ Switch - need to maintain state and lookup requests + + § Should look like a domestic transfer to the sender + + § Collect the information and send it back - + + ○ CNP - making assumptions to meet requirements + + § Do you need to see the route + + § Collecting different information downstream + + § Sending FSPs needs to know who is the receiver + + ○ CNP has to aggregate information and put them together into a single request & they will need to sign separately + + § Condition and fulfillment is part of a PKI structure + + § If there is more than one CNP - there needs to ensure the DFSP payee has to be certain the DFSP payer - connections + + § CNP needs to know everything, regulatory reporting - + + ○ Do we need to duplicate the structure in a Cross-network transfer? + + § Trying to prevent a rouge partner from joining + + § Trust the CNP to meet their SLAs + + ○ Mojaloop to another scheme - we don’t have control + + § Require they confirm receipt + + § How can I tell + + § How can I tell the person at the end got the money + + ○ External signing authority to confirm the money was received + + § If your scheme wants to participate in x-border then all the participants need to get signed + + § Public key - need to join a mojaloop network have to issue public keys + + § Central certificate issuing authority + + § Need a PKI structure in place + + ○ How do you get non-Mojaloop folks in the schema? + + § How do we integrate Mojaloop and some Mojaloop scheme to provide a full PVT payments - working group with Michael, Adrian, Sybrin, others as needed + + § Identify the participants - FSP, DFSP - all have signed + + § Parties - end users (Bob/Alice) + + § Single transaction (with multiple transfers) + + § No one commits their funds to everyone is satisfied + + § How to extend mojaloop and non-mojaloop scheme + + ○ Certification + + § Hash and PKKI + + § Gold and silver network + + § New partner - live on the network + + § Scheme decides requirement on the network + + § Self-signing cert + + ○ Liquidity + + § FXP does position mgmt + + § What requirements do we put on a FXP + + § Mobile money has less flexibility + + § Rules that happened across schemes + + ○ FXP has to manage the settlements, what expires when, etc.. + + § FXP has to manage the shortage of quote validity + + § Allow FXP to reject the requests + + ○ How do we manage requests for regulatory reasons + + § There is a dictionary + + □ Is the a requirement to share KYC? + + □ You can ask for many things - up to the participant + + □ Need to agree on the baseline scheme + +**Day #2:** + + - Switch data + + ○ Account numbers + + ○ Blacklist, white list (oversight and blocking) + + ○ Keeping it simple + + ○ Hub + + ○ Side service for folks that can do this + + § Mobile data capture + + § Side car + + § Digital process + + § Value added services for the hub (managed service) + + - Switch - need to maintain state and lookup requests + + - CNP can be an ordinary DFSP + + ○ All DFSP supports all the use cases + + ○ Full participants (might just provide a CNP or FXP service) + + - FXP definition and requirements + + ○ FXP - require rates/fees as part of the Quoting service - need standard industry rate + + § CNPs can extend this and determine additional scheme rules + + ○ FXP handles rounding errors + + ○ Guarantee a given rate + + ○ Manage settlement across schemas + + ○ FX rates + + ○ Should allow people that just do FX + + ○ Edge cases for failure + + § Details in the error messages to find the errors + + ○ FXP needs to point back the right information + + § How messages passed work + + § Edge cases - share what is done too date + + § Jo owns got a working API - identified + + § Changed the quote (intercepted the quote) -- + + § KYC extension list - extended the quote for this + + § Rates are in the extended list (are the list) + + § Where the FXP is applied ? + + § What do we do with fees downstream + + □ (payee DFSP takes place of the aggregation) + + - How to manage identifier resolution + + ○ 2 types of Identifiers + + § Global ones (pass to CNP) - to get a response + + § Local ones - expect the user to provide + + ○ Mojaloop we use identifiers as proxy + + ○ Merchant numbers might be specific to a scheme + + ○ Multiple identifiers for a single account + + ○ How do we uniquely identify the account? + + ○ Rely on CNP (restrict each identifiers in this scheme) + + ○ What sort of structures in place + + ○ Passport identification - place holders + + ○ Map pathfinder accounts/mobile accounts to DFSP unique IDs + + § Service - primary account is X + + § Each country has a service they provide + + § Each CNP understands the address scheme + + § Global one - need to know which ways to use + + ○ Sends a get parties to the switch + + § ALS never heard of them + + § 2 ways + + □ Global way (path finder and conversion to BIC) + - CNP + + ○ Not hosting anything + + ○ Route through the CNP - ask others + + ○ Constructing the alternative routes + + - Global registry does not exist + + ○ Ultimate beneficiary + + ○ Established communication + + ○ Challenge will we able to have 2 DFSPs share direct communication and will be a stretch? + + - Switch has schemes + + ○ A Hub operator following Scheme Rules may allow names of FSPs as decided by those Rules + + ○ The technology or the Admin API itself doesn’t restrict the names (apart from restrictions on length, type or characters, etc) + + ○ BGP: Border Gateway Protocol  + + - Query each CNP and then come up with optimizations, matrix that provides global route - goal would be not to query the CNP directly + +• How to connect with Mojaloop? + + - Any financial service can connect to Mowali + + - Scheme rules, technical + + - Regulatory + + - How do I assign stuff? - no one knows the steps + + - Mojaloop API - understand this. + + - 2 instances Mojaloop instances - TIPs and Mowali + + ○ WOCCU, Asia, US - applied for instance + + ○ Still pushing the boundries + + - What dos an integration look like + + ○ Need sandbox, simulators + + ○ Standard approach + +• Instance payment service + + - Get the flows flowing in a timely manner + + - Need real-time ledgers; what happens if they are offline? + + - Exception for off network (banks take advantage of float) + +• Discovery process (sending FSP) + + - Switch determines if they need to contact a FXP + + - What currency the receiving account can receive in + + - Multiple lookups + + - Data model - set of accounts, w/ one currency at a DFSP + + +Attendees: + + - Mike, Patricia - Thume + + - Michael R, Rob R, Sam - Modusbox + + - Kim, Lewis - Crosslake + + - Rolland, Greg, Phillip - Sybrin + + - Vanburn -- Terrapay + + - Megan, Simeon - Virtual diff --git a/discussions/decimal.md b/legacy/discussions/decimal.md similarity index 98% rename from discussions/decimal.md rename to legacy/discussions/decimal.md index be968f724..119e51501 100644 --- a/discussions/decimal.md +++ b/legacy/discussions/decimal.md @@ -1,4 +1,4 @@ -# Moajoop Decimal Type; Based on XML Schema Decimal Type +# Mojaloop Decimal Type; Based on XML Schema Decimal Type ## Decimal value type diff --git a/legacy/discussions/dicussion-docs.md b/legacy/discussions/dicussion-docs.md new file mode 100644 index 000000000..7b8efb24b --- /dev/null +++ b/legacy/discussions/dicussion-docs.md @@ -0,0 +1,30 @@ +# Discussion Documents + +## PI 10 +- [Performance Project](./Mojaloop%20Performance%202020.pdf) +- [Code Improvement Project](./code_improvement.md) +- [Cross Border Project](./crossborder.md) +- [PSIP Project](./pisp.md) + +## PI 9 + +- [Versioning Draft Proposal](./versioning_draft_proposal.md) +- [Code Improvement Project](./code_improvement.md) +- [Performance Project](./performance.md) +- [Cross Border Project](./crossborder.md) +- [PSIP Project](./pisp.md) + +## PI 8 + +- [Cross Border Meeting Notes Day 1](./cross_border_day_1.md) + +- [Cross Border Meeting Notes Day 2](./cross_border_day_2.md) + +- [ISO integration Overivew](./ISO_Integration.md) + +- [Mojaoop Decimal Type; Based on XML Schema Decimal Type](./decimal.md) + +## PI 7 + +- [Workbench Workstream](./workbench.md) + diff --git a/legacy/discussions/images/cb_board_1.jpg b/legacy/discussions/images/cb_board_1.jpg new file mode 100644 index 000000000..e53cad0b9 Binary files /dev/null and b/legacy/discussions/images/cb_board_1.jpg differ diff --git a/legacy/discussions/images/cb_board_2.jpg b/legacy/discussions/images/cb_board_2.jpg new file mode 100644 index 000000000..8afa47d94 Binary files /dev/null and b/legacy/discussions/images/cb_board_2.jpg differ diff --git a/legacy/discussions/images/cb_board_3.jpg b/legacy/discussions/images/cb_board_3.jpg new file mode 100644 index 000000000..7cce85870 Binary files /dev/null and b/legacy/discussions/images/cb_board_3.jpg differ diff --git a/legacy/discussions/images/mojaloop_spokes.png b/legacy/discussions/images/mojaloop_spokes.png new file mode 100644 index 000000000..b0c67eb08 Binary files /dev/null and b/legacy/discussions/images/mojaloop_spokes.png differ diff --git a/legacy/discussions/images/tagging_01.png b/legacy/discussions/images/tagging_01.png new file mode 100644 index 000000000..4379443ce Binary files /dev/null and b/legacy/discussions/images/tagging_01.png differ diff --git a/legacy/discussions/images/tagging_02.png b/legacy/discussions/images/tagging_02.png new file mode 100644 index 000000000..b86ac0a91 Binary files /dev/null and b/legacy/discussions/images/tagging_02.png differ diff --git a/legacy/discussions/images/tagging_03.png b/legacy/discussions/images/tagging_03.png new file mode 100644 index 000000000..d8ab17646 Binary files /dev/null and b/legacy/discussions/images/tagging_03.png differ diff --git a/legacy/discussions/images/tagging_04.png b/legacy/discussions/images/tagging_04.png new file mode 100644 index 000000000..a2913b226 Binary files /dev/null and b/legacy/discussions/images/tagging_04.png differ diff --git a/legacy/discussions/images/tagging_05.png b/legacy/discussions/images/tagging_05.png new file mode 100644 index 000000000..ba54dbf64 Binary files /dev/null and b/legacy/discussions/images/tagging_05.png differ diff --git a/legacy/discussions/images/tagging_06.png b/legacy/discussions/images/tagging_06.png new file mode 100644 index 000000000..8c4eb717f Binary files /dev/null and b/legacy/discussions/images/tagging_06.png differ diff --git a/legacy/discussions/performance.md b/legacy/discussions/performance.md new file mode 100644 index 000000000..a554f6610 --- /dev/null +++ b/legacy/discussions/performance.md @@ -0,0 +1,175 @@ +# Performance Workstream + +Wednesday, March 11, 2020 + +## Performance Goals: + +- Current HW system achieving stable 1k TPS, peak 5k and proven horizontal scalability + 1. More instances = more performance in almost linear fashion. + 1. Validate the minimum infrastructure to do 1K TPS (fin TPS) + 1. Determine the entry level configuration and cost (AWS and on-premise) + +## POCs: + +Test the impact or a direct replace of the mysql DB with an shared memory network service like redis (using redlock alg if locks are required) + +Test a different method of sharing state, using a light version of event-drive with some CQRS + +## Resources: + +- Slack Channel: `#perf-engineering` +- [Mid-PI performance presentation](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/March2020-PI9-MidPI-Review) +- [Setting up the monitoring components](https://github.com/mojaloop/helm/tree/master/monitoring) + +## Action/Follow-up Items: + +- What Kafka metrics (client & server side) should we be reviewing? - Confluent to assist +- Explore Locking and position settlement - Sybrin to assist + 1. Review RedLock - pessimistic locking vs automatic locking + 2. Remove the shared DB in the middle (automatic locking on Reddis) + +- Combine prepare/position handler w/ distributed DB +- Review node.js client and how it impact kafka, configuration of Node and ultimate Kafka client - Nakul +- Turn back on tracing to see how latency and applications are behaving +- Ensure the call counts have been rationalized (at a deeper level) +- Validate the processing times on the handlers and we are hitting the cache +- Async patterns in Node + 1. Missing someone who is excellent on mysql and percona + 2. Are we leveraging this correctly + +- What cache layer are we using (in memory) +- Review the event modeling implementation - identify the domain events +- Node.js/kubernetes - +- Focus on application issues not as much as arch issues +- How we are doing async technology - review this (Node.JS - larger issue) threaded models need to be optimize - Nakul + +## Meeting Notes/Details + +### History + +1. Technology has been put in place, hoped the design solves an enterprise problem + +2. Community effort did not prioritize on making the slices of the system enterprise grade or cheap to run + +3. OSS technology choices + +### Goals + +1. Optimize current system +2. Make it cheaper to run +3. Make it scalable to 5K TPS +4. Ensure value added services can effectively and securely access transaction data + +### Testing Constraints + +1. Only done the golden transfer - transfer leg +2. Flow of transfer +3. Simulators (legacy and advance) - using the legacy one for continuity +4. Disabled the timeout handler +5. 8 DFSP (participant organizations) w/ more DFSPs we would be able to scale + +### Process + +1. Jmeter initiates payer request +2. Legacy simulator Receives fulfill notify callback +3. Legacy simulator Handles Payee processing, initiatives Fulfillment Callback +4. Record in the positions table for each DFSP + - a. Partial algorithm where the locking is done to reserve the funds, do calculations and do the final commits + - b. Position handler is Processing one record at a time + +5. Future algorithm would do a bulk + +- One transfer is handler by one position handler + - Transfers are all pre-funded + +1. Reduced settlement costs +2. Can control how fast DFSPs respond to the fulfill request (complete the transfers committed first before handling new requests) +- System need to timeout transfers that go longer then 30 seconds + - Any redesign of the DBs + - Test Cases + +- Financial transaction + - End-to-end + - Prepare-only + - Fulfil only + +- Individual Mojaloop Characterization + - Services & Handlers + - Streaming Arch & Libraries + - Database + - What changed: 150 to 300 TPS? + +- How we process the messages +- Position handler (run in mixed mode, random + - Latency Measurement + +1. 5 sec for DB to process, X sec for Kafka to process +2. How to measure this? + +### Targets + +1. High enough the system has to function well +2. Crank the system up to add scale (x DFSPs addition) +3. Suspicious cases for investigations +4. Observing contentions around the DB +5. Shared DB, 600MS w/ out any errors + - Contention is fully on the DB + - Bottleneck is the DB (distribute systems so they run independently + + + +- 16 databases run end to end +- GSMA - 500 TPS +- What is the optimal design? + +### Contentions + +1. System handler contention + - Where the system can be scaled +1. If there are arch changes that we need to make we can explore this + - Consistency for each DFSP + - Threading of info flows - open question + +1. Sku'ed results of single DB for all DFSPs +1. Challenge is where get to with additional HW + - What are the limits of the application design +1. Financial transfers (in and out of the system) + - Audit systems + - Settlement activity + - Grouped into DB solves some issues + - Confluent feedback + +1. Shared DB issues, multiple DBs + +1. Application design level issues + +1. Seen situations where we ran a bunch of simulators/sandboxes + - Need to rely on tracers and scans once this gets in productions + - Miguel states we disable tracing for now + +### Known Issues + +1. Load CPU resources on boxes (node waiting around) - reoptimize code +2. Processing times increase over time + +## Optimization + 1. Distributed monolithic - PRISM - getting rid of redundant reads + 2. Combine the handlers - Prepare+Position & Fulfil+Position + +### What are we trying to fix? + 1. Can we scale the system? + 2. What does this cost to do this? (scale unit cost) + 3. Need to understand - how to do this from a small and large scale + 3. Optimized the resources + 4. 2.5 sprints + 5. Need to scale horizontal + 6. Add audit and repeatability - + +### Attendees: + +- Don, Joran (newly hired perf expert) - Coil +- Sam, Miguel, Roman, Valentine, Warren, Bryan, Rajiv - ModusBox +- Pedro - Crosslake +- Rhys, Nakul Mishra - Confluent +- Miller - Gates Foundation +- In-person: Lewis (CL), Rob (MB), Roland (Sybrin), Greg (Sybrin), Megan (V), Simeon (V), Kim (CL) diff --git a/legacy/discussions/pisp.md b/legacy/discussions/pisp.md new file mode 100644 index 000000000..d517d6f10 --- /dev/null +++ b/legacy/discussions/pisp.md @@ -0,0 +1,21 @@ +# PISP (3rd party payment initiation) + +## Goal: + +Updated Mojaloop specification documents, and POC implementation of a PISP + + +## Action Items: + +- Revisit /authorizaitons resource: [Michael] and raise with CCB +- Identity provider research and follow-up: [Matt de Haast] +- Share all sequence diagrams: [JJ] +- Outline proposal at high level including new API calls - Unassigned +- Mapping account information (info about accounts for PISP) - [Lewis] + +## Links: + +- [London Meeting Notes](./pisp_meeting_march_2020.md) +- [WIP Separate Docs Repo with sequence diagrams](https://github.com/jgeewax/mojaloop-pisp) +- [End to End Sequence Diagram](https://plantuml-server.kkeisuke.app/svg/xLhhRnkv4V--VmKX571iI8eaEx4Z875aoyu9Tt44hz8WWFg1sgMaFQz87ScreXRvtpl3nxuaEx7H5bVW0kJXvN1cE9pvpODvhpILEbkbWKvqoiXu58w9bfIhEPDa9MAMJlcBJ2LyGJuo6Iqfr-IM_P4nfOaMP4otv2DI7GOqqaAImPQf9ILKaSj1i0RUIPIiSLF3i1wirmrSXB_th8PCtZC90eVNuVZG40wxLRfma-XeQPR2wihWjz2o9ZNET0j7GOwECHaurhrTGbOXl724n-vmZOiblOVpmVh5-r2is6R99BD4bnS15veH0IS0rIRBH96r56kXQ4fYmHI1PIB1T8ba10svW6zWmi5uH82tCWTh1oXOaSrIa5mvu9fmefUCg6Z9LeniaZGbdB4Ozw_e7IDw8ppFVj0z9AEveSzl4fH9UA8Ju1MJsPPGSzDD4edrrb3-aQ7oagcru8eXN_oAH47l6UnoohqSVnEB9C8lCqOoPOz1LSIafd1GC2fGIZGAcko7WiV04RwhfTXmD5IQSDOEHXg9gLBP2WKigUu7hNU4WkMYJ6cuF4be1imv69dgH72aZwYK2T2BJ1DXRUwf3nI9sNqICMHZt2FETC9G8JXbQbbWI9H323I0suxP77IAQxSeinHsKmxIrap2VeYnHPP0C06n2XWie4S5Rz-IOQ8YTAmjUVisk1oqta7yz4Ta8x8qXlFUMVCwcLF-jswdWrzAJeeUdDoZAs7emU_Mks6txwBrMNmWCeVTbbNb0znJejj1p2fYO1sbV07Zet6jDB3ZseJa7TkUJ_b8muV1-wjKEG6uAOGzIRIqPePhhL30fXT7Hn-k9kIb2H6cZeuE2xr24eGj8xVNwVN9w01kVC4qcT7e3W-p5LbPJpX628TuL639U2GOj50_exP5aygfaHc8jYj4hHczKsIEm5WwueuDGz2rGpxzsYGBOyaoIpXF0IomOUAYY2Y3bWPR-87EyU2EYqrWvE1F2jq8dGvilW9VxyCFS1M880547q16dC8-gWpS454BzBaKgy0TqpiaUU2AIbxob2jwzWsLvJrwGnUxDtJS7nevzeRC1Urd1zW_F7Otz6DLGoH6xhTC0uxS5-W1iGz2LXObZ3YRIio6iFyBI0LrtKSC4S0EmI5rbFRj6l3u4Ry1pH_onT9HftooB6kPw_149pK-WL0GRfLcAq34jP1QJNdEcbF0l7tySq2w7FGd01M57Pf49ekbFaV8izo_CjK4qS0dnx3BakvBkZO92F16BS6WKux-Zy3gqe_X1yf1MaqW6kg0LGcqK82xRyZ8H1IP2RqqB6131lVY_BhleWEbkp1prOPTk2WlsEeYk35SVRnALqqvFdb6BsAsI0KsyCOfev1HgRehRQgXDWQkByOGmUj6_t48abeCLgiRvWeMj2LBxZ6HaHLJYYwOjNyg17YRpIb0BJY3R9-A3MRc0wI6ofF7LCPGF_vEWNhjzmVZJo40XpaGAY2uApWL-MKo6R_ijhi177lqQTmAHIOZrhTLXVis1Cg4cu3fU_i4_me8_6hiyXp5ZJvfdCN79_CttRWLTqxFMYUTqzFMMU_rSQiNTKvEpqvVpwFvwqRJyZ0N2PiiI_T9wkqe7a6eLXRAYvFj6dT1cJeQX8vNdGPhaNd29DALOhJH95NokLfRlQsBDVBLx-PVtqkQofgc3bRsgng9rJfbtsuWKdSMhU14AksM6zQxQaSnP2ajg2RqBg6D2ittGj_cVzU8fQHRfwxQSF2G3UbAP5nxkRTNbrUZlryrAejL2-VV6X269Q6DA9EIyMYBIv_3OQCYfkIOJbQ99LJ6dCf467FU3cx2wwlRCcTN4GjpvF7WwmEh_X2Ndsx2pn-1gA81XdTng-G-iJMzFohxjawa2Iea0ipej3gzLlVLfDVhTq_xlRFscxDNhKwt3uSsE_uHV2zL327YLWXAC5j_ED0p6Qht7m4qwEQ6lQSawfuHlKSdgBS72yaOGYyPBr4pgBgHFeTUQEpkeL0dfXU3l41D_rGaTyFF7w04kXPpUpzNzlGga3jOG6_Kj9oniI4sM3LBjmMK-YxE7kG6Vp1WZ1cJHsaMCrNKTpKSj1OsM0rPCi7QmpEgeQsh1n_4smiFjqOT6sMdKU-OdNMYdq7OadOEdb_DmIwzUUlupQpNEddJdRNEkgUiTK8xnxtESNmoxvxisVn_1V5_8VnV2FyaX2TFXlWdONWDlQ7LSDXdCSOCH_8H5rQoEsZtpDPf3Aq3bIoVIjdMfsYJV45Th3srBIh3AjRY6rOTfb4tIiCFIrY7W_85zCn2tc57q0w-i5BrZdsEW-LIYrSQTpK39N8OZYZl1_IGVEOn12hYjgtqfO2KerIz0GzcX-JMYd3ZACtaQeUCl63jHPlC6LE7NhHll8hkmIRRkWsBgT_-PFf8osTJw4ZPurFRuxIA0PrXZxE0fCtQTWXQICK43dlsuVNvOK1JJMw4w_NuWVR2XjYKcGi960G-AHh2jYUvJfnHpLJEkwOLaQUqikxbvimEwB1LfSenCHjSKtTk5DiZT9BdvReH_1srfxok_Cu1m_wra1lCv3-OoUuhAIeNjJEBnWdfbclS6D4KYePiaMwRq9D5D0FcPXQon3aWpfAmQmueEJeQVvuS7H7sBM9hRGUTXJBKswPDBZ8DKOGH3a4Yjm6TuG3Lze6WfMotsrKtxFg9Ht5Er00gGB0OHD6JHsH-r3YvFlV__hHi0dqRMcq8EZYIguMA2ieVPihDQKepQtSiWrdOo99iNHzhEpUoedmLwSzYYiAz6wezTQMenFAt7BXeutkQ9Z7LhC9iojri3UVNKApzqq2EUhalb8wEdbz-selwNsbNlkYVIXVMz1-0PbMsFIX4TulmoetX9Cd0eCyp5bHn4uYHvP7_Rbhpuwh7vvT-eFMOc18oU2CN3n8c8AHYwTmy4KI2Gscs0bT57uQb0ydyk4jW-eWW8ULF0owuLbio1x1XSYqJRlnvjRjdPuu67Gy18cXnM5oetIwc_Gy7eX_wXrLkJddFBdSKyp3WqWBSbPyVcOZ3oH6aZh4KCpe3kFezKte7dFqECm_Vm4S0BjsSSYY2uPpADsSp1ZU07dl7J6PsdgaOub8zFBgF5GzTbqH_udZFpAO5bDHTb_1iDSDNA-m4bKPNg7HoVdsHt3FktvfCJBHnokkc_kxDRPwb-D36gvAWFO3BC7wCRV34Vy-xuDA0jES7fFcppepoEpCiLVa8jcgV8F-yeLoRrq_VnLRrADSwWPZ39_lSLyp7CHct2SuXZLH4-0LSx99HI5mGBzvcPRRcKR1mDsSXZZKR68D2DiITK0skayY27LmoP3C0VsFpmc0gYo9mFJHYyLZkVD5C4inCD0v0vThZIQcE6LLAeF95KwL4PAg7ANUfn4EPlUhpwaLyOOW6xZnVyGR5joPHK5qmsIHmFUsg_6gPyVXRxGyhZOT75iRdj11_vje3Id2TxTRJVxvYPCftgf5AhL5r438QJhbnPpHmOlwlnjpNnG_cn3pU3PJcFhx_gUOhfh1vncF05Kno1JrSi1SXRPVauhPTFEHCbXYsQ6RphBtAyFy-r3995NZHBV3tU_WZMwN_1W00.svg) +- [Initial PISP Design Doc, v5](https://github.com/mojaloop/documentation-artifacts/blob/master/presentations/January%202020%20OSS%20Community%20Session/%5BEXTERNAL%5D%20Mojaloop_%20PISP%20Credit%20Transactions(3).pdf) diff --git a/legacy/discussions/versioning_draft_proposal.md b/legacy/discussions/versioning_draft_proposal.md new file mode 100644 index 000000000..790dd4452 --- /dev/null +++ b/legacy/discussions/versioning_draft_proposal.md @@ -0,0 +1,281 @@ +--- +Authors: Lewis Daly, Matthew De Haast, Samuel Kummary +Proposal Name: Mojaloop Versioning Proposal +Solution Proposal Status: Draft +Created: 26-Feb-2020 +Last Updated: 17-Mar-2020 +Approved/Rejected Date: N/A +--- + +# Mojaloop Versioning, A Proposal + +_Note: This document is a living draft of a proposal for versioning within Mojaloop. Once the proposal is ready, it will be submitted to the CCB for approval._ + +## Overview + +The aim is to produce a proposal that keeps the versioning Scheme simple to use and clear regarding compatibility issues. However, it needs to include all the details needed for a Mojaloop ecosystem as well. + +Goal: +Propose a standard for a new 'Mojaloop Version', which embodies: +1. Helm: Individual Service Versions, Monitoring Component Versions +2. API Versions: FSPIOP API, Hub Operations / Admin API, Settlement API +3. Internal Schema Versions: Database Schema and Internal Messaging Versions + +## Versioning Strategies/Background (Literature Review) + +How do current systems handle versioning? Give a brief overview of the current space. +* Most best practices follow semantic versioning for APIs, this will be covered more in [#1198](https://github.com/mojaloop/project/issues/1198) + +### Demonstrates zero-downtime deployment approaches with Kubernetes [5] + +Key observations: +* in order to support rollbacks, the services must be both forward and backwards compatible. +consecutive app versions must be schema compatible +* 'Never deploy any breaking schema changes', separate into multiple deployments instead + +For example, start with a PERSON table: +``` +PK ID + NAME + ADDRESS_LINE_1 + ADDRESS_LINE_2 + ZIPCODE + COUNTRY +``` + +And we want to break this down (normalize) into 2 tables, PERSON and ADDRESS: + +``` +#person +PK ID + NAME + +#address +PK ID +FK PERSON_ID + ADDRESS_LINE_1 + ADDRESS_LINE_2 + ZIPCODE + COUNTRY +``` + +If this change were made in one migration, 2 different versions of our application won't be compatible. Instead, the schema changes must be broken down: +1. Create ADDRESS table + * App use the PERSON table data as previously + * Trigger a copy of data to the ADDRESS table +2. The ADDRESS now becomes the 'source of truth' + * App now uses the ADDRESS table data + * Trigger a copy of new added to address to the PERSON table +3. Stop copying data +4. Remove extra columns from PERSON table + +This means for any one change of the database schema, multiple application versions will need to be created, and multiple deployments must be made in succession for this change to be made. +* [5] also notes how simple Kubernetes makes deploying such a change + * rolling upgrade deployments + * Tip: make sure your health endpoint waits for the migrations to finish! +* Q: so how do we make big changes that touch both the database schema and the API? + * this seems really hard, and would need a lot of coordination + * If we don't design it correctly, it could mean that a single schema change could require all DFSPs to be on board + * This is why I think the API version and Service version should be unrelated. We should be able to + deploy a new version of a service (which runs a migration), and supports an old API version + + +### Using a schema registry for Kafka Messages [6] + +* [6] suggests some approaches, such as using a schema registry for kafka messages, such as [Apache Arvo](https://docs.confluent.io/current/schema-registry/index.html) +* This adds a certain level of 'strictness' to the messages we produce, and will help enforce versioning +* Adds a separate 'schema registry' component, which ensures messages conform to a given schema. This doesn't really + help enforce versioning, and leaves the work up to us still, but does give more guarantees about the message formats. + +### Backwards and Forwards Compatibility [3], [4] + +* "The Robustness principle states that you should be “liberal in what you accept and conservative in what you send +”. In terms of APIs this implies a certain tolerance in consuming services." [3] +* Backwards Compatibility vs Backwards Incompatibility [4]: + * Generally, additions are considered backwards compatible + * Removing or changing names is backwards incompatible + * It's more something to assess on a case-by-case basis, but [Google's API Design Doc](https://cloud.google.com/apis/design/compatibility) helps lay out the cases. + +## Mojaloop Ecosystem +When discussing versioning we need to be clear that we are versioning interfaces for various parties. + +# Proposal +The following section will outline the versioning proposal. + +## A “Mojaloop Version” +A Mojaloop Version **x.y**.z can be defined that can encompass the versions of all the three APIs included (detailed below). +In the version **x.y**.z, ‘x’ indicates the Major version and ‘y’ a minor version, similar to the Mojaloop FSPIOP API versioning standards; ‘z’ represents the ‘hotfix’ version or a version released with the same major, minor version x.y but to keep things simple, there is a need to bundle all the components included in the Mojaloop ecosystem indicating what all items are included there. + +In effect we may say Mojaloop version **x.y** includes +1. Mojaloop FSPIOP API + * Maintained by the CCB (Change Control Board) + * Uses x.y format + * Currently version v1.0, v1.1 and v2.0 are in the pipeline +2. Settlement API + * Maintained by the CCB + * To use x.y format + * Currently version v1.1 and v2.0 is in the pipeline +3. Admin / Operations API + * Maintained by the CCB + * To use x.y format + * Can use version v1.0 +4. Helm + * Maintained by the Design Authority + * Uses x.y.z format + * PI (Program Increment) + Sprint based versioning. + > *Note:* _PI + Sprint based versioning_ make sense in the context of the current Mojaloop Program Increments, but will need to be revised at a later date. + * Bundles compatible versions of individual services together +5. Internal Schemas + * Maintained by the Design Authority + * DB Schema x.y + * Internal messaging Schema (Kafka) x.y + +| **Mojaloop** | x.y | | | +|---|---|---|--- +| | Owner/Maintainer | Format | Meaning | +| **APIs** | | | | +| - FSPIOP API | CCB | *x.y* | Major.Minor | +| - Settlement API | CCB | *x.y* | Major.Minor | +| - Admin/Operations API | CCB | *x.y* | Major.Minor | +| Helm | Design Authority | *x.y.z* | PI.Sprint.Increment | +| **Internal Schemas** | | | | +| - DB Schema | Design Authority | *x.y* | Major.Minor | +| - Internal Messaging | Design Authority | *x.y* | Major.Minor | + + + +For example: Mojaloop 1.0 includes +1. APIs + * FSPIOP API v1.0 + * Settlements API v1.1 + * Admin API v1.0 +2. Helm v9.1.0 + * Individual services' versions + * Monitoring components versions +3. Internal Schemas + * DB Schema v1.0 + * Internal messaging version v1.0 + +| **Mojaloop** | v1.0 | | | +|---|---|---|--- +| | Owner/Maintainer | Version | +| **APIs** | | | | +| - FSPIOP API | CCB | *1.0* | +| - Settlement API | CCB | *1.1* | +| - Admin/Operations API | CCB | *1.0* | +| Helm | Design Authority | *9.1.0* | +| **Internal Schemas** | | | | +| - DB Schema | Design Authority | *1.0* | +| - Internal Messaging | Design Authority | *1.0* | + +### Advantages + +1. The advantage of this strategy is primarily simplicity. A given version say - Mojaloop v1.0 can just be used in + discussions which then refers to specific versions of the three APIs - FSPIOP, Settlements, Admin APIs, along with the Helm version that is a bundle of the individual services which are compatible with each other and can be deployed together. +Along with these, the Schema versions for the DB and Internal messaging to communicate whether any changes have been made to these or not since the previously released version. +2. The other advantage, obviously, is that it caters for everyone who may be interested in differing levels of details +, whether high level or detailed. Because of the nature of the major and minor versions, it should be easy for Users and adopters to understand compatibility issues as well. + +### Compatibility +As described in [section 3.3 of the API Definition v1.0](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#33-api-versioning), whether or not a version is backwards compatible is + indicated by the **Major** version. All versions with the same major version must be compatible while those having different major versions, will most likely not be compatible. + +_Important Note: Hub operators will likely need to support multiple versions of the FSPIOP API at the same time, in order to cater for different participants as they can't all be expected to upgrade at the same time._ + +## Breaking down the “Mojaloop Version” +This section aims to break down the above proposed mojaloop version into its constituent parts, and provide support for the above proposed versioning strategy + +### APIs + +The [Mojaloop Spec](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#33-api-versioning) already outlines many of the decisions made around versioning APIs. + +In terms of common best practices, there are many approaches for requesting different versions, including adding in a + version in the url, but let's not worry about this because the spec already lays this out for us, using the HTML vendor extension: [3.3.4.1 Http Accept Header](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#3341-http-accept-header) + +As for version negotiation, the spec also states that in the event of an unsupported version being requested by a + client, a HTTP status 406 can be returned, along with an error message which describes the supported versions. [3.3.4.3 Non-Acceptable Version Requested by Client](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#3343-non-acceptable-version-requested-by-client) + +Another best practice around versioning is specifying to what level clients may request specific apis. +* In a development environment, many APIs will allow specificy up to the BUGFIX version, i.e. vX.X.X +* In production however, this is limited to Major versions only, e.g. v1, v2 +* e.g. The Google API Platform supports only major versions, not minor and patch versions +* Given the new features that may become available with v1.1 of the Mojaloop API, we might want to allow participants + to specify MAJOR and MINOR versions, i.e. vX.X. This practice should be avoided however, since minor versions should be backwards compatible + +Participants using the same MAJOR version of the API should be able to interact. Participants on different MAJOR +versions are not able to interact. For example, a participant on API v1.1 can send transfers to another participant on v1.0, but not to a different participant on v2.0. + +### Helm +This section deals with how Mojaloop services interact within a given deployment. Here, we attempt to propose questions such as "should an instance of central-ledger:v10.0.1 be able to talk to ml-api-adapter:v10.1.0? How about ml-api-adapter:v11.0.0?"? or "how do we make sure both central-ledger:v10.0.1 and central-ledger:v10.1.0 talk to the database at the same time?" + +There are two places where this happens: +1. Where services interact with saved state - MySQL Percona Databases +2. Where services interact with each other - Apache Kakfa and (some) internal APIs + +This implies we need to version: +* the database schema +* messages within Apache kafka + * need to make sure the right services can appropriately read the right messages. E.g. Can mojaloop/ml-api-adapter:v10 +.1.0 publish messages to kafka that mojaloop/central-ledger:v10.0.1 can understand? + * Q: If we decide to make breaking changes to the message format, how can we ensure that messages in the kafka streams + don't get picked up by the wong services? + +### Internal Schemas + +#### Database + +todo: anything to be said here? + +#### Kafka/Messaging +Currently, we use the lime protocol for our kafka message formats: https://limeprotocol.org/ + +Also refer to the mojaloop/central-services-stream readme for more information about the message format. + +The lime protocol provides for a type, field, which supports MIME type declarations. So we could potentially handle messages in a manner similar to the API above (e.g. application/vnd.specific+json). Versioning messages in this manner means that consumers reading these messages would need to be backwards and fowards compatible (consecutive message versions must be schema compatible). +* Q. does it make sense to put the version in the Kafka topic? + * One example, ml-api-adapter publishes messages to the prepare topic + * If we add versioning to this, ml-api-adapter:v10.0.0 publishes messages to a prepare_v10.0 topic, and a new instance + of the ml-api-adapter:v10.1.0 will publish to the prepare_v10.1 topic. + * subscribers can subscribe to whichever prepare topic they want, or both, depending on their own tolerance to such + messages + * This may have some serious performance side effects +* Another potential option would be to allow for a message 'adapter' in the deployment. Say the ml-api-adapter:v10.1.0 is producing messages to a prepare_v10.1 topic, and there is no corresponding central-ledger in the deployment to read such messages, we could have an adapter, which subscribes to prepare_v10.1, reformats them to be backwards compatible, and publishes them to prepare_v10.0 in the old format. + +Such an approach would allow for incremental schema changes to the messaging format as services are gradually upgraded. + +All in all, I didn't see too much about this subject, so we'll likely need to return later down the line. + +## Version Negotiation +todo: @sam Discuss how to deal with version negotiation strategy + +## Long Term Support +todo: Discuss how long term support fits into the versioning proposal. I don’t think we want to get into too much detail, but more outline what it might look like + +Mention current (lack of) lts support, current PI cadence + +## Appendix A: Definitions + +* **service**: Mojaloop follows a microservices oriented approach, where a large application is broken down into smaller + micro services. In this instance, Service refers to a containerized application running as part of a Mojaloop deployment. At the moment, this takes the form of a Docker container running inside of a Kubernetes cluster. e.g. mojaloop/central-ledger is the central-ledger service +* **service version**: The version of the given service. This currently doesn't follow semantic versioning, but may in the + future e.g. mojaloop/central-ledger:v10.0.1. The current approach is described in more detail in the [standards + /Versioning doc](https://github.com/mojaloop/documentation/blob/master/contributors-guide/standards/versioning.md). +* **helm**: Helm is an application package manager that runs on top of Kubernetes. It may also be referred to as the + "deployment". A single helm deployment runs many different services, and MAY run multiple versions of the same service simultaneously. We also refer to the deployment as it's repo, mojaloop/helm interchangeably. +* **helm version**: A helm version is the version of the packaged helm charts, e.g.mojaloop/helm:v1.1.0 +* **interface**: An interface is the protocol by which a Mojaloop switch interacts with the outside world. This includes + interactions with Participants (DFSPs) who transfer funds through the switch, hub operators running a Mojaloop switch, and admins performing administrative functions. +* **api**: Application Programming Interface - in most cases referring to the FSPIOP-API a.k.a. Open API for FSP + Interoperability defined [here](https://github.com/mojaloop/mojaloop-specification). +* **api version**: The Version of the FSPIOP-API, e.g. FSPIOP-API v1. For the purposes of this document, it refers to the + contract between a Mojaloop Switch and Participants (DFSPs) who implement the FSPIOP-API + +## References + +[1] LTS versioning within nodejs. This is a great example of an LTS strategy, and how to clearly communicate such a strategy. +[2] Semantic Versioning Reference +[3] https://www.ben-morris.com/rest-apis-dont-need-a-versioning-strategy-they-need-a-change-strategy/ +[4] https://cloud.google.com/apis/design/compatibility +[5] Nicolas Frankel - Zero-downtime deployment with Kubernetes, Spring Boot and Flyway +[6] Stackoverflow - Kafka Topic Message Versioning + diff --git a/legacy/discussions/workbench.md b/legacy/discussions/workbench.md new file mode 100644 index 000000000..34b7f49ee --- /dev/null +++ b/legacy/discussions/workbench.md @@ -0,0 +1,246 @@ +# Mojaloop Lab/Workbench Discussion + +___Goal:__ This discussion document aims to lay out the case and align the community around the development of an educational Mojaloop Lab environment._ + + +## 1. Goals for the PI8 Convening: + +1. Define terms and outline assumptions +2. Outline existing efforts and how the OSS Community aligns with them (GSMA, MIFOS, ModusBox) +3. Define users and usecases, and exclude the users we won't worry about +4. Recommendations for a few different solutions to the "Lab Problem" + - Documentation around business cases and personas Dan developed + - Basic implementation of Lab Configurer, help people build labs with different features + - Simple Mojaloop-over-spreadsheets demo, to get people using mojaloop without Postman +5. Basic implementation and demo +6. Pose important questions and discuss next steps + +## 2. Nomenclature + +**1. Tools:** +- 1.1 A device used to carry out a function +- 1.2 Different tools for different functions: You wouldn't use a screwdriver to drive a nail. +- 1.3 In a Mojaloop context, one example of a tool is the Bank Oracle + - The Bank Oracle is a tool that plugs into the Account Lookup Service, can be used to allow Mojaloop to connect to existing bank accounts with an IBAN + +**2. Workbench:** +- 2.1 Combines different tools together in one place +- 2.2 For example, a hand plane, table saw and chisel can make up a woodworking workbench, while a hacksaw, file and angle grinder can make up a metalworking workbench +- 2.3 In the mojaloop parlance, tools to test my DFSP's JWS keys are in a different workbench than tools that demonstrate to a fintech how wholesale api's can work on top of Mojaloop + +**3. Lab:** +- 3.1 A lab is a place you go to run experiments +- 3.2 We run experiments in order to learn, and test our assumptions + - For example, a DFSP can set up and run an _experiment_ where they send and receive Quotes using an in-development API +- 3.3 A single lab combines multiple workbenches together in one place + +**4. Simulator:** +- 4.1 A tool that simplifies or abstracts away some function so you can test one thing at a time +- 4.2 Pilots train with simulators _before_ flying a real life, dangerous and expensive plane. +- 4.3 Within Mojaloop: a simulator can simulate interacting with some component of the system + - Replace an entire switch to test a DFSP implementation + - Simulate 2 DFSPs to test a switch deployment + - A simulator also reduces the need for someone to be with the person testing. So a DFSP can send and receive via the switch, without interaction with the Hub Operator. + + +## 3. Assumptions + +>_Some of these may go without saying, but it's noting them here anyway._ + +- 1\. The Gates Foundation wants to encourage adoption for Mojaloop at all levels (not just switches) +- 2\. We don't need a lab environment to serve the needs of a Switch deployment or implementing DFSP - these needs will be met elsewhere +- 3\. The Mojaloop OSS Community wants to make itself attractive + - This doesn't mean removing all barriers to entry; but assessing which barriers we should be removing + + +## 4. Users + +We divide users in 2 camps: Primary users and Secondary users. + +### 4.1 Primary Users +1. DFSPs needing to integrate with Mojaloop: (shorthand: Implementing DFSP) +2. Organisations/Individuals wishing to learn about Mojaloop and wanting to build and test functionality or use cases as a DFSP (shorthand: Evaluating DFSP) +3. Organisations/Individuals wishing to learn about Mojaloop and wanting to build and test functionality or use cases as a Hub Operator (shorthand: Evaluating Hub Operators) +4. Regulators, Organisations or Individuals wishing to understand and evaluate Mojaloop and how it might impact their existing service (shorthand: General Evaluators) + +### 4.2 Secondary Users +5. Systems Integrators wishing to offer Mojaloop as a Service or pieces of Mojaloop integration as a Service (Systems integrator) +6. Individual Contributors (including bug bounty hunters?) (Individual Contributor) +7. Fintechs operating on top of or who will operate on top of a mojaloop-enabled switch (Mojaloop-powered fintech) +8. 3rd Party App Provider interacting with wholesale mobile money APIs, selling integrations to fintechs and the like (3rd party app provider) +9. Financial Advocates, who are interested in promoting Mojaloop and other technologies that help drive financial inclusion (Financial Inclusion Advocates) + +In addition to thinking of each of the above users, it's important to understand at what level these users exist at in relationship to a mojaloop deployment. For that we will borrow from Dan Kleinbaum's [_Fintech primer on Mojaloop_](https://medium.com/dfs-lab/what-the-fintech-a-primer-on-mojaloop-50ae1c0ccafb) + +![the 3 levels of mojaloopyness](./images/mojaloop_spokes.png) +>_The 3 levels of Mojaloopyness, https://medium.com/dfs-lab/what-the-fintech-a-primer-on-mojaloop-50ae1c0ccafb by Dan Kleinbaum_ + +**Level 1:** Running a Mojaloop switch (e.g. Hub Operators) +**Level 2:** Interacting with a Mojaloop Switch directly (e.g. DFSPs, Systems Integrators) +**Level 3:** Interacting with a DFSP over a Mojaloop Switch (e.g. Fintechs) + + +## 5. Use Cases + +__a.__ Test a Mojaloop compatible DFSP implementation +__b.__ Validate assumptions about Mojaloop +__c.__ View and use a reference implementation +__d.__ Learn about Mojaloop internals +__e.__ Learn about Mojaloop-enabled switches and associated use cases (technology) +__f.__ Assess how Mojaloop will change fintech business landscape +__g.__ Be able to demonstrate a value proposition for DFSPs/Fintechs/etc. to use mojaloop (instead of technology _x_) + + +## 6. User/Use Case Matrix: + +We can plot the users and use cases in a matrix: + + +| __Usecase:__ | a. Test DFSP Impl | b. Validate Assumptions | c. Reference Impl | d. Learn Internals | e. Learn about Tech | f. Evaluate Business Cases | g. Demonstrate ML Value | +| :----------------------------------- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| __User:__ | | | | | | | | +| __1. Implementing DFSP__ | X | | X | | | | | +| __2. Evalutating DFSP__ | | X | X | | X | X | | +| __3. Evaluating Hub Operator__ | | | X | | X | X | | +| __4. General Evaluator__ | | | | | X | X | | +| __5. Systems Integrator__ | X | X | X | X | | | X | +| __6. Individual Contributor__ | | X | X | X | | | | +| __7. Mojaloop-powered fintech__ | | X | | | X | X | X | +| __8. 3rd Party App Provider__ | | | | X | | | X | +| __9. Financial Inclusion Advocates__ | | X | | | | X | X | + + +## 7. Usecase Inputs and outputs: + +>_Pick 2 or 3 different users/usecases and drill down into the inputs and outputs for what meeting their needs may look like_ +>>_Note: As with anything of this nature, a lot of the users/usecases and associated conclusions are somewhat squishy, and can likely be put into different or altogether new boxes. Nonetheless, we will try to define these as well as possible._ + +### 7.1 Evaluating Hub Operator + Implementing DFSP +As stated in our above assumptions, we aren't going to worry about Hub operators and Implementing DFSPs here. + +### 7.2 Evaluating DFSP + +>_We think of an evaluating DFSP as one who is not necessarily part of a current switch implementation, but a party who is mojaloop-curious, and a potential candidate to evangelize mojaloop to - without the tangible goal of a switch implementation in sight._ + +**7.2.1 Use cases:** +- 1\. Validate assumptions about Mojaloop (how it works, what it does, what it _doesn't_ do) +- 2\. View and play with a reference implementation +- 3\. Learn about mojaloop-enabled hubs and associated use cases (technology perspective) +- 4\. Assess how Mojaloop will affect their business in the future + +**7.2.2 Examples from our user personas:** +- 1\. Carbon - Enable cash-outs and OTC remittances over their agent network +- 2\. Ssnapp - Enable multi payer/payee payments and rewards points over mojaloop +- 3\. Oneload - Simplify onboarding for other DFSPs to utilize OneLoad's agent network +- 4\. Juvo - Plug in to a Mojaloop switch for a credit scoring and lending marketplace + +**7.2.3 Outputs: (How can the Mojaloop OSS Community better serve these players?)** +- 1\. help to onboard to the mojaloop ecosystem +- 2\. help to understand the technology, where it works well, and the potential pitfalls/drawbacks +- 3\. minimize investment in getting things working so they can focus on building out use case prototypes +- 4\. take them from little to no understanding of Mojaloop -> demonstrating real prototypes + +**7.2.4 Inputs: (what are the things that we need to do to meet these goals)** +- 1\. Improved mojaloop documentation specific for this role. + - 1.1 Think about and design the documentation and onboarding flow specifically for *Evaluating DFSPs* + - 1.2 Documentation should be approachable by product manager etc. with little technical knowledge +- 2\. Technical deep dive on the technology behind mojaloop, why, how it works (perhaps we can repurpose the js demonstrator in an interactive walkthrough an end to end transaction) +- 3\. Improved guides for up and running on 2-3 major kubernetes providers, self service and install scripts +- 4\. Helm charts for 1-2 simulators/labs that can be spun up alongside a switch, with opinionated pre-configured settings + + +### 7.3 Mojaloop Powered Fintech + +>_A Mojaloop Powered fintech is a fintech operating or wishing to operate on top of a mojaloop switch. There will definitely be crossover between Fintechs and DFSPs in this classification, but we will focus here on fintechs who are at the third level on the above "Mojaloop Spokes"_ + +**7.3.1 Use cases:** +- 1\. Validate assumptions about Mojaloop (how it works, what it does, what it _doesn't_ do) +- 2\. Learn how mojaloop is aligned with wholesale APIs, and what it would take to get a DFSP using these APIs over a Mojaloop switch +- 3\. Learn about mojaloop-enabled hubs and associated use cases (technology perspective) +- 4\. Assess how Mojaloop will affect their business in the future + +**7.3.2 Examples from our user personas:** +- 1\. EastPay - compare and shop around for banks/payment providers based on Mojaloop's open fee structure +- 2\. Jumo - Open up transparent and fairer lending markets on top of a Mojaloop enabled switch? + +**7.3.3 Outputs: (How can the Mojaloop OSS Community better serve these players?)** +- 1\. Understand how Mojaloop and Wholesale APIs fit together (or don't) +- 2\. Enable fintechs to interact with Mojaloop over 1 or 2 wholesale banking APIs (e.g. GSMA MM api) +- 3\. take them from little to no understanding of Mojaloop -> demonstrating real prototypes + +**7.3.4 Inputs: (what are the things that we need to do to meet these goals)** +- 1\. Improved mojaloop documentation specific for this role. +- 2\. Documentation or working document on how Mojaloop will work with wholesale apis +- 3\. Self-deployed lab environment with DFSP that expose some wholesale apis with basic functionality for fintechs to test against + + +## 8. OSS Lab/Workbench efforts alongside others + +There are others in the community working on some of these needs we outlined above. How can we align ourselves together to: (1) Not duplicate efforts (nor step on each other's toes) and (2) Provide the most impact for end users and the Mojaloop community as a whole + +In general, we reached a consensus around the following: +- any OSS Lab effort should be focused with a specific end user in mind +- Our focus should be further out on the mojaloop spokes (DFSPs, Fintechs, 3rd Party app providers) + + +### 8.1 MIFOS +- 1\. Already extensive work done here with Fineract system, which provides out-of-the-box solution for Mojaloop enabled DFSPs +- 2\. working on open api implementations +- 3\. Working on lowering the barriers to entry for DFSPs and Fintechs +- 4\. Mifos Innovation Lab: "The Locomotion on top of Mojaloop's Rails" + - 4.1 Demonstrate end to end Mojaloop systems with DFSP integration + - 4.2 Build and contribute OS tools +- 5\. Working on real world deployments already +- 6\. See a need for a "Single Point of Entry to the Mojaloop Ecosystem" +- 7\. Have an existing Lab deployment with Mojaloop that is currently being upgraded to work with the latest Helm chart deployments + + +### 8.2 GSMA +- 1\. Have mobile money api, would like to see end to end solution with fintechs/DFSPs talking over a mojaloop switch +- 2\. The GSMA Lab has a very wide scope, Mojaloop is just one piece of this +- 3\. One main goal is the mobile money API- pushing for default standard for 3rd party integration into mobile money +- 4\. where does Mojaloop sit? + - 4.1 Is one of the branches that the GSMA Lab will be working on + - 4.2 Where can GSMA add the most value to Mojaloop? + - 4.2.1 Serve a need from the market to get the most impact + - 4.2.2 See a end-to-end prototype of the MM API talking over a Mojaloop switch + + +### 8.3 ModusBox +- 1\. More on the systems integrator perspective. Building a bunch of tools already to ease the development and onboarding process for switches and DFSPs +- 2\. Have open sourced the Mojaloop JS SDK +- 3\. Interested in showing 'how the engine works' to build confidence in business parters/customers +- 4\. Also interested (especially in WOCCU case) as a Mojaloop lab as a place for Fintechs to learn and test concepts on top of Mojaloop Switches + - 4.1 Once this is connected, the interesting use cases will start to develop beyond tranfers from A to B + - 4.2 MFIs (especially small-medium) don't have much capacity for experimentation or developing new business cases, but these cases can be driven from fintechs first +- 5\. How can we assist orgs. who have little-to-no technical capability to become confident with Mojaloop? + - 5.1 A technical lab environment won't do much in this case + - 5.2 Can we demonstrate Mojaloop over a spreadsheet? Everyone can understand spreadsheets. + +## 9. Questions + +- 1\. So much of this comes back to The Gates Foundation's proposed sales cycle for growing mojaloop adoption + - 1.1 Looking at the technical briefs from the hackathon alone, there are some __big__ players (Famoco, Ethiopay, GrameenPhone) that could really take mojaloop and run with it + - 1.2 How can the initial hurdle be overcome to drive adoption and help these orgs adopt mojaloop and contribute back to the ecosystem? + - 1.3 What does the entrypoint to the industry look like for Hub operators? + +- 2\. For evaluating DFSPs, what is their resource/risk allocation like? + - 2.1 If they think Mojaloop is a viable option for a future product, what type of time and resource investment will they put into it? + - 2.2 What are their alternatives? (This will be a case-by-case thing) + +- 3\. Is a certain amount of technical gatekeeping a good or bad thing? (This is a more philisophical question) + - 3.1 If we don't make it too easy to get up and running, we make sure that only interested and determined parties are using mojaloop, which self-selects for a better community (kinda) + - 3.2 But this locks out a lot of people who aren't up to scratch with kubernetes, docker etc. but may still have a good deal of experience with financial services etc. + +- 4\. Chicken and egg problem(?) between DFSPs and Hub operators. Does it go DFSPs -> Hub Operators or the other way around? + + +## 10. Recommendations + +- 1\. Find a target user that we can build a lab for/with + - 1.1 perhaps one of the more serious hackathon teams? +- 2\. Address and improve documentation gaps: driving from a role-specific (i.e. DFSP, fintech, hub operator) perspective +- 3\. Mojaloop over Spreadsheet demo +- 4\. Build a self-service lab prototype + - 4.1 Opinionated set of helm charts that can be deployed alongside general switch + - 4.2 Gather feedback from the community, and see where and how people are using it \ No newline at end of file diff --git a/gitbook.Dockerfile b/legacy/gitbook.Dockerfile similarity index 100% rename from gitbook.Dockerfile rename to legacy/gitbook.Dockerfile diff --git a/legacy/glossary.md b/legacy/glossary.md new file mode 100644 index 000000000..f2063b83a --- /dev/null +++ b/legacy/glossary.md @@ -0,0 +1,12 @@ +# Glossary of Terms + +| Term | Definition | Notes | +| --- | --- | --- | +| DFSP | Digital Financial Service Provider | | +| FSP | Financial Service Provider | | +| K8s | Short name for [Kubernetes](https://kubernetes.io/) | Read more here [https://kubernetes.io](https://kubernetes.io) | +| ALS | [Account-Lookup Service](mojaloop-technical-overview/account-lookup-service/README.md) | Refer to [Documentation](mojaloop-technical-overview/account-lookup-service/README.md) | +| CS | Central Services | | +| ALS | Account Lookup Services | | +| QS | Quoting Service | | +| SIM | Simulator | | diff --git a/legacy/hackathon-materials/README.md b/legacy/hackathon-materials/README.md new file mode 100644 index 000000000..99e95c391 --- /dev/null +++ b/legacy/hackathon-materials/README.md @@ -0,0 +1,7 @@ +# Hackathon Materials + +A set of documentation from past hackathons. In the future, we may spin this folder off into it's own fully fledged "Mojaloop Hackathon Guide". For now, it's a place to put reference material. + +Most of this initial material comes from The Include Everyone Mojaloop Hackathon in Kampala, Uganda late 2019. + +If you have additional material you want to add, or changes you want to make, please go ahead and raise a pull request. \ No newline at end of file diff --git a/legacy/hackathon-materials/images/lab_onboarding_01.png b/legacy/hackathon-materials/images/lab_onboarding_01.png new file mode 100644 index 000000000..3ff3c9558 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_01.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_02.png b/legacy/hackathon-materials/images/lab_onboarding_02.png new file mode 100644 index 000000000..9f587dd0b Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_02.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_04.png b/legacy/hackathon-materials/images/lab_onboarding_04.png new file mode 100644 index 000000000..3a048003f Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_04.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_05.png b/legacy/hackathon-materials/images/lab_onboarding_05.png new file mode 100644 index 000000000..7d2b805ff Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_05.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_06.png b/legacy/hackathon-materials/images/lab_onboarding_06.png new file mode 100644 index 000000000..d690a7f36 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_06.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_07.png b/legacy/hackathon-materials/images/lab_onboarding_07.png new file mode 100644 index 000000000..4446f55f1 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_07.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_08.png b/legacy/hackathon-materials/images/lab_onboarding_08.png new file mode 100644 index 000000000..a15a27f21 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_08.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_09.png b/legacy/hackathon-materials/images/lab_onboarding_09.png new file mode 100644 index 000000000..6a8e3e877 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_09.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_10.png b/legacy/hackathon-materials/images/lab_onboarding_10.png new file mode 100644 index 000000000..b699f92fc Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_10.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_11.png b/legacy/hackathon-materials/images/lab_onboarding_11.png new file mode 100644 index 000000000..40af4b86d Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_11.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_12.png b/legacy/hackathon-materials/images/lab_onboarding_12.png new file mode 100644 index 000000000..71fb2e738 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_12.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_13.png b/legacy/hackathon-materials/images/lab_onboarding_13.png new file mode 100644 index 000000000..3acbbd1f9 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_13.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_14.png b/legacy/hackathon-materials/images/lab_onboarding_14.png new file mode 100644 index 000000000..e132b02f6 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_14.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_15.png b/legacy/hackathon-materials/images/lab_onboarding_15.png new file mode 100644 index 000000000..d10967224 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_15.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_16.png b/legacy/hackathon-materials/images/lab_onboarding_16.png new file mode 100644 index 000000000..0b2341a04 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_16.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_17.png b/legacy/hackathon-materials/images/lab_onboarding_17.png new file mode 100644 index 000000000..3cbe498fe Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_17.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_18.png b/legacy/hackathon-materials/images/lab_onboarding_18.png new file mode 100644 index 000000000..9f7f274f3 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_18.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_19.png b/legacy/hackathon-materials/images/lab_onboarding_19.png new file mode 100644 index 000000000..eeaa8b422 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_19.png differ diff --git a/legacy/hackathon-materials/images/lab_onboarding_20.png b/legacy/hackathon-materials/images/lab_onboarding_20.png new file mode 100644 index 000000000..4848b3af4 Binary files /dev/null and b/legacy/hackathon-materials/images/lab_onboarding_20.png differ diff --git a/legacy/hackathon-materials/images/postman_01.png b/legacy/hackathon-materials/images/postman_01.png new file mode 100644 index 000000000..6164d22f3 Binary files /dev/null and b/legacy/hackathon-materials/images/postman_01.png differ diff --git a/legacy/hackathon-materials/images/postman_02.png b/legacy/hackathon-materials/images/postman_02.png new file mode 100644 index 000000000..ffcfa218f Binary files /dev/null and b/legacy/hackathon-materials/images/postman_02.png differ diff --git a/legacy/hackathon-materials/lab_onboarding.md b/legacy/hackathon-materials/lab_onboarding.md new file mode 100644 index 000000000..dd108d77c --- /dev/null +++ b/legacy/hackathon-materials/lab_onboarding.md @@ -0,0 +1,91 @@ +# ModusBox Mojaloop Lab +## Getting started with the Lab + +>***Note:** This document is specific to the ModusBox lab provided for the Include Everyone hackathon, but may generalize well in the future* + + +## 1.0 Obtaining an Access Token + +- 1.1 Go to the public gateway (the link has been removed as this environment is not public). + +- 1.2 Click “Sign Up”, and go through the steps to create a new account + + + + +- 1.3 Click “Sign Up” > follow the dialog box to the sign in page > Enter your details and “Sign In” + +
    + + + +- 1.4 In the top left, select “Applications” + + + + +- 1.5 Select “Default Application” from the list + + + +- 1.6 Navigate to “Production Keys” > set the validity of the key to “-1” > “Generate Keys” + +
    + + +- 1.7 Your access key along with a token will be created. Click “Show keys” + + + +- 1.8 Observe that your access token has been created. You can copy this for later reference + + + +- 1.9 Navigate to APIs in the top left menu + + + +- 1.10 From the list of APIs, select “CentralLedgerApi…” + + + + +- 1.11 You now need to subscribe the DefaultApplication to this api. You can do this in the top right > “Subscribe” + +
    + + + +- 1.12 Navigate to “Api Console”. Your access token should already be pre-filled for you. + + + +- 1.13 Now we can test out the `/health` endpoint of the central-ledger service. Browse down the list of endpoints > “Try it out” > “Execute” + +
    +
    +
    + + + +1.14 You should see a response similar to the following: + + +```json +{ + "status": "OK", + "uptime": 535767.333, + "startTime": "2019-09-17T15:11:37.794Z", + "versionNumber": "7.3.1", + "services": [ + { + "name": "datastore", + "status": "OK" + }, + { + "name": "broker", + "status": "OK" + } + ] +} +``` \ No newline at end of file diff --git a/legacy/hackathon-materials/preread.md b/legacy/hackathon-materials/preread.md new file mode 100644 index 000000000..97bf3d959 --- /dev/null +++ b/legacy/hackathon-materials/preread.md @@ -0,0 +1,67 @@ +# Hackathon Pre-Read: +> Goal: A simple reading and todo list for hackathon participants + +## Compulsory Reading +>Time to complete: 15-30 minutes + +- [Mojaloop Project Website](https://mojaloop.io/ ) + - Basic into the project + - Intro video +- [Mojaloop Documentation](https://mojaloop.io/documentation/) + - Overview + - Onboarding doc [todo: this needs work] + - Repo Details (get a lay of the land from the services) +- [Onboarding to the ModusBox Lab Environment](./lab_onboarding.md) + - Logging in and using the environment + - getting an access token and talking to the Lab from postman/curl + + +## Hackathon Onboarding Checklist +>Time to complete: 15-30 minutes + +### Slack: +> The Mojaloop OSS Community uses Slack for all of its communications and announcements. + + +1. Go to [mojaloop-slack.herokuapp.com](mojaloop-slack.herokuapp.com) > Enter your Email address and press "Join" +2. Follow the steps in the email to set up your Slack account +3. Go [here](https://slack.com/intl/en-gm/downloads/) to download slack for your computer +_Optional: You can also go to the Play Store or App Store and install Slack on your phone as well_ +4. Once Slack is installed, select "Channels" in the left bar and search for the `#this-hackathon-name` channel +_[todo: update this doc and replace `#this-hackathon-name` with a channel name specific for the hackathon]_ + + +### Postman +>Postman is a REST API testing and automation tool which we use to interact with the Lab environment and Mojaloop itself + +1. Go to [Postman Downloads](https://www.getpostman.com/downloads/) to download Postman for your machine +2. Clone or Download the [mojaloop/postman](https://github.com/mojaloop/postman) repository. This contains a number of postman 'Collections' which will help you to interact with Mojaloop and the Lab environment +3. Open Postman, and select "Import" from the top left and navigate to where you cloned the Postman repo + +![postman_01.png](./images/postman_01.png) + +4. Drag and drop all of the `collection.json` files into the dialog, and they will be imported into your environment +![postman_02.png](./images/postman_02.png) + +5. Do the same as above with the files in `./environment`. These files specify the environment variables for the collections +6. Now that the collections and environment are set up, we will use the Collection Runner to run one of the test collections. The Collection Runner will run through a list of HTTP requests inside of a collection, which we use to automate or test different processes. +7. Select "Runner" from the top left (next to import), and select the +_[todo: fill this section in after getting the Lab environment test runner]_ + + +## Extended Reading + +- Mojaloop API Specification + Use Cases. For a better understanding of the API and how the API can be used to implement various interoperable payment use cases + - [Mojaloop API Spec v1.0](https://github.com/mojaloop/mojaloop-specification/blob/master/API%20Definition%20v1.0.pdf) + - [Mojaloop Use Cases](https://github.com/mojaloop/mojaloop-specification/blob/master/Use%20Cases.pdf) + +- Getting a local Mojaloop Environment up and Running On Kubernetes. For running Mojaloop yourself, either on a local machine, or cloud server + - [Mojaloop Deployment Guide](https://mojaloop.io/documentation/deployment-guide/) + +- Getting started with contributing to Mojaloop: + - [Mojaloop Contributor's Guide](https://mojaloop.io/documentation/contributors-guide/) + - _[todo: Github + Zenhub setup]_ + +- Digging into the code: + - [central-ledger service](https://github.com/mojaloop/central-ledger) + - [ml-api-adpater service](https://github.com/mojaloop/ml-api-adapter) \ No newline at end of file diff --git a/legacy/index.js b/legacy/index.js new file mode 100644 index 000000000..90159aa25 --- /dev/null +++ b/legacy/index.js @@ -0,0 +1,32 @@ +/***** + License + -------------- + Copyright © 2020-2025 Mojaloop Foundation + The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Mojaloop Foundation for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + + * Mojaloop Foundation + - Name Surname + + * Miguel de Barros +*****/ + +const express = require('express') +const app = express() +app.use(express.static(__dirname + '/_book')) + +app.listen(process.env.PORT || 8989) diff --git a/legacy/meeting-notes/ccb-notes.md b/legacy/meeting-notes/ccb-notes.md new file mode 100644 index 000000000..b8c49a9df --- /dev/null +++ b/legacy/meeting-notes/ccb-notes.md @@ -0,0 +1,6 @@ +## CCB meetings: Overview +The Change Control Board meets every two weeks. + +The meetings are open for the public to participate, though discussions are usually limited to the Board members. However, attendees will be promoted to panelists in meetings if they have Change Requests or Solution Proposals to discuss. + +More details can be found here: https://github.com/mojaloop/mojaloop-specification/tree/master/ccb-meetings . \ No newline at end of file diff --git a/legacy/meeting-notes/da-notes.md b/legacy/meeting-notes/da-notes.md new file mode 100644 index 000000000..2e04a1be9 --- /dev/null +++ b/legacy/meeting-notes/da-notes.md @@ -0,0 +1,125 @@ +## DA meetings: Overview +The Design Authority meets every week for a weekly update and has ad-hoc or detailed sessions for Specific topics + +The meetings are open for the public to participate, though discussions are usually limited to the Board members. However, attendees will be promoted to panelists in meetings if they have designs to be reviewed or proposals for changes. + +More details can be found [here](https://github.com/mojaloop/design-authority/issues/42#workspaces/da-issue-log-5cdd507422733779191866e9/board?notFullScreen=false&repos=186592307) + +# DA Meeting - 30 September 2020 +Discussion around the topics mentioned started - the newly implemented "patch" in version 1.1 of the API spec was discussed and the majority of the meeting was spent on how to promote wider adoption of this new pattern. + +Concerns about the implementation and use of the "patch" command was raised, stating that further discussion is required to determine if we are not trying to patch a design flaw with another potential implementation flaw. + +See: https://github.com/mojaloop/design-authority/issues/68 + + +# DA Meeting - 2 September 2020 +First we discussed the topic about the "models" folder from being excluded from the unit test coverage checks. The decision taken was that if the folder contains business logic (which generally should not be the case), it must be refactored and moved out. Once at that "business logic isolated" state, coverage testing for that folder can be ignored. See: https://github.com/mojaloop/design-authority/issues/64 + +We concluded discussions on the separate scheme-adapter for a PISP - see issue on board: https://github.com/mojaloop/design-authority/issues/51 +Please have a look at the draft document at this location: https://github.com/mojaloop/pisp/blob/scratch/api-collision/docs/api-collision.md +The above link has a detailed discussion regarding the latest thinking and some examples of mitigations. +The decision has been taken to block this topic until further development on the PoC has been done, in order for the DA to assess if the designs are still aligned with the recommended approach. + +# DA Meeting - 26 August 2020 +We discussed https://github.com/mojaloop/design-authority/issues/51 further on our DA Meeting on 26/08/2020. + +Some of the key points were noted: + +In order to take advantage of Typescript, and to help speed up development, the PISP workstream has gone ahead and separated out the thirdparty-scheme-adapter already. + +One of the challenges identified with the "multi-scheme-adapter" approach was for cases where there are shared resources between the APIs, such as GET /parties/{type}/{id}. + +Our decision to break the Thirdparty API into it's own API (and not extend the FSPIOP-API) was predicated on the idea that "not all participants will want thirdparty functions", and therefore shouldn't have to worry about them. As a part of the decision to keep a separate Thirdparty API, we decided that some resources would be duplicated between the two. + +This could lead to problems down the line, where callbacks to some resources might not be able to reach their desired destination: for example if a DFSP needs to listen for PUT /parties/{type}/{id} callbacks for both the FSPIOP API and the Thirdparty API, it may not be possible for DFSPs to route such callbacks to the right place. + +Lewis Daly will spend more time working on some diagrams and design documents, and come back to the DA shortly + +# DA Meeting (Ad-Hoc) - 24 August 2020 +The topic for discussion was: https://github.com/mojaloop/design-authority/issues/65 +The Ad-Hoc meeting was conducted with a wider issue being addressed relating to recommendations required to be taken to the CCB for consideration to change/enhance the API spec. + +Many valid points were raised and discussed and Michael and Adrian suggested some collaboration on this platform to consolidate the ideas put forward in order to formulate a recommendation to the CCB. + +# DA Meeting - 19 August 2020 +The topic for discussion was: https://github.com/mojaloop/design-authority/issues/61 +The group agreed that there needs to be a balance between the need to eliminate reconciliation and liquidity management of (Payer) FSPs by not holding/reserving funds for longer than necessary. In addition, It was proposed to use 'grace time period' before timing out transfers to compensate for differences in clocks. It was also suggested that for risky transactions, the final notification in the form of a PATCH call that was introduced with FSPIOP API v1.1 can be used to mitigate risk to the Payee FSPs. + +One point made was that after the timeout period (plus the grace period to account for clock difference), a transfer status cannot be changed - it is either finalized or it isn't, but it cannot be changed. For example, if a timeout period (expressed as a time in future and not duration) is 10 seconds, then a Payer FSP (or Switch), may add a grace period of 1second and after waiting for 11seconds can query the downstream entity to find the transfer's status; At this point, if a transfer is finalized (Committed or Aborted), then the Payer FSP can take action accordingly; however if it is in an intermediate state, then the transfer has to be timed-out since the time-out period is done. + +The group agreed on the need to revisit the topic of implementing 'telescopic timeouts', which is not currently supported in favor of end-to-end encryption of (most) messages. + +# DA Meeting - 12 August 2020 +The topic for discussion was: https://github.com/mojaloop/design-authority/issues/63 +The DA discussed the topic of where and how to create and work on issue tickets. With over 50 repositories, it makes sense to create a ticket in the repo where it originated and keep working on it there until it is resolved. The Product Owner and Scrum Master would have context and should replicate a ticket in the Design Autority Repo with a link to the originating ticket. Please have a look at the DA Board for the decisions made here: https://github.com/mojaloop/design-authority#workspaces/da-issue-log-5cdd507422733779191866e9/board?repos=186592307 + +# DA Meeting - 5 August 2020 +The topic for discussion was: https://github.com/mojaloop/project/issues/852 +The "HSM Integration Approach" was touched on a few times, and the workgroup taking care of the design and implementation, tabled this for discussion at this week's DA meeting to answer a few questions arising from the last PI-Planning session where progress on this was again presented. + +As we have not completed the discussion, an ad-hoc DA meeting has been arranged for this Friday with a sub-section of the DA Members. The reason for that was because there were a few specific questions we did not have time to go into detail for, which will be clarified with the individuals who raised those questions. Please drop me a note if you would like to participate in that meeting. + +# DA Meeting - 29 July 2020 +Issue discussed: https://github.com/mojaloop/design-authority/issues/60 +Claudio noted three observations regarding usage of best practices in the Mojaloop Core codebase. One of the issues has an active issue and will be used for tracking it; the other two will be followed up as separate stories/bugs as well (standards). Claudio will provide examples and in some cases sample snippets that can be used. + +Istvan and Michael discussed the usage of a unique ID for lookup requests and proposed to have a follow-up meeting the upcoming week for those interested. The current trace headers (optional) usage for traceability (APM) was brought up as a solution, which after the DA review can be proposed to the CCB (if accepted by the DA). + +# DA Meeting - 22 July 2020 +Canceled as a result of the PI-11 Mojaloop Convening taking place + +# DA Meeting - 15 July 2020 +Sam walked through some of the high-level changes being introduced with Helm v10.4.0 release and various sections from the release notes: https://github.com/mojaloop/helm/releases/tag/v10.4.0 +Please have a look on the DA Topic board: https://github.com/mojaloop/design-authority/issues/56 + +Neal and Michael discussed the issue of shared DB, code between central-settlement and central-ledger; they’re going to continue with the current work on Continuous Gross Settlement but after the convening will get the inputs from the Perf/Arch PoC (Event sourcing / CQRS) and then align. https://github.com/mojaloop/design-authority/issues/58 + +# DA Meeting - 8 July 2020 +The TIPS team did a presentation of the design and implementation of a **Rules Engine** satisfying their requirements of interpretation in the **Settlements Portion**, to extend fees levied as part of a transfer. The implementation allows for rules to be interpreted at any stage during a transaction. A formal presentation will be made at the convening during the week of the 20th July 2020 after which more informed decisions as to the adaption of this implementation into the Core OSS codebase can be considered as a generic approach to implementation of a rules engine. +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/53 for a detailed problem statement, progression on meetings in the notes and remarks and also, if completed, the subsequent decision. + +# DA Meeting - 1 July 2020 +As part of the "Versioning" workstream, a "zero down-time deployment proposal" PoC is being conducted and feedback from that project has been presented in the form of a problem statement, solution and a demo. The team currently working on that is Lewis Daly, Mat de Haast and Sam Kummary. The feedback was well received and as this work is ongoing, the DA will follow up with any action items to come out of the upcoming presentation for this workstream at the PI 11 Meeting. +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/54 for a detailed problem statement, progression on meetings in the notes and remarks and also, if completed, the subsequent decision. + +# DA Meeting (Ad-Hoc) - 29 June 2020 +KNEX Discussion - continued. The KNEX discussion extended into talking about the possible use of third-party tools to assist in the generation of queries to help migration efforts. This has no direct bearing on the use of KNEX itself and after exploring a bit deeper, it was decided that there was no compelling reason to continue further investigation into the use of KNEX itself, but to keep an open mind and look out for alternative solutions out there as and when they are introduced. Those libraries will be measured against the current implementation to ensure we deploy the right tools for the right purpose. This issue is now closed. +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/27 for a detailed problem statement, progression on meetings in the notes and remarks and also, if completed, the subsequent decision. + +# DA Meeting (Ad-Hoc) - 25 June 2020 +KNEX Discussion - initiated +Conversations have been started, highlighting the problem statement of difficulty in generating or creating migration scripts when database changes occur, as well as the scenario of having to perform these upgrades on a database which is online at the time. +With this context in place, continued design sessions have been scheduled to determine if KNEX would be capable of handling the above scenario and if there are alternate libraries or tools out there to replace or supplement the current implementation, which may help alleviate this difficult task. +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/27 for a detailed problem statement, progression on meetings in the notes and remarks and also, if completed, the subsequent decision. + + +# DA Meeting - 24 June 2020 +Discussion today started with: Deprecation of Helm2 support - Issue #52, where it was agreed that migration to Helm3 should continue. Documentation to assist in the use of tools available to help in the migration should be provided. Find the link to this document at https://github.com/mojaloop/design-authority/issues/52 + +The topic of having a design approach of implementing a generic rules-based system was discussed with some specific reference first, to a requirement of having the capability to interrogate completed or in-flight transactions (either in the transfer stage or even as early in the quoting stage) in order to apply "interchange fees" for that transaction, depending on the transaction type, as interpreted by certain rules. +Various design decisions are going to be discussed around this topic as the requirement is the facility to attach rules at various points of the transaction path. +The current implementation of a Rules Engine in the TIPS project was discussed and a request to demonstrate the capabilities of that solution in order for the DA to see if it was generic anough to incorporate into the core Switch will be made in a follow-up discussion. +Please track the progression of the design decisions surrounding this issue on the board at https://github.com/mojaloop/design-authority/issues/53 + + +# DA Meeting - 17 June 2020 +Topic under discussion was: Understand and Define Mojaloop Roles for PISP, x-network, etc. use cases +The DA is happy for workstreams to go ahead and split out new APIs and Role definitions (e.g. Thirdparty API, CNP API etc.) +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/44 for a detailed problem statement and subsequent decision. + +# DA Meeting - 10 June 2020 +This week, the DA discussed: Discuss the PISP Simulator: https://github.com/mojaloop/design-authority/issues/46 +The decision was made that for the time being, the PISP workstream will work on it's own branch in the sdk-scheme-adapter, and such a division/abstraction of the sdk-scheme-adapter will be revisited at a later date (see #51) + +# DA Meeting - 3 June 2020 +We continued the discussion started last week regarding the separate API for PISP and decided to go with option 4: maximum API Separation, with common swagger/open api files for definition and data model reuse: +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/47 for a detailed problem statement and subsequent decision. + +# DA Meeting - 27 May 2020 +Consensus relating to the issue raised and discussed some time ago, as queried by Adrian, was reached amongst the attendees. The outcome is that the Switch development will not be restrictive and prescriptive but as far as recommendation for new contributions and modules are concerned, it will be preferred if those could be done in TypeScript. + +A new discussion topic was tabled: https://github.com/mojaloop/design-authority/issues/47 seeking to answer the question of whether to have a separate API for PISP, or simply extend the existing Open API. A position statement was prepared and added as a comment. All attendees were brought up to speed with the decision to be made and Issue-#47 will be the topic for the next DA meeting. + +Another, PISP related topic was tabled and will be scheduled for another DA meeting: https://github.com/mojaloop/design-authority/issues/48 - Answer the question of how to manage notifications so that a PISP can be registered as an interested party for notification of the success of a transfer + diff --git a/legacy/meeting-notes/readme.md b/legacy/meeting-notes/readme.md new file mode 100644 index 000000000..3051b0cf9 --- /dev/null +++ b/legacy/meeting-notes/readme.md @@ -0,0 +1,5 @@ +# Mojaloop OSS meeting Groups + +- Change Control Board +- Design Authority +- Scrum-of-scrum calls diff --git a/legacy/meeting-notes/scrum-of-scrum-notes.md b/legacy/meeting-notes/scrum-of-scrum-notes.md new file mode 100644 index 000000000..648d833d3 --- /dev/null +++ b/legacy/meeting-notes/scrum-of-scrum-notes.md @@ -0,0 +1,154 @@ +# Meeting Notes from Weekly Scrum-of-scrum meetings + +## OSS Scrum or scrum calls Thu **May 7th** 2020 + +1. Coil - Don: + a Performance: 'Big Gap' problem; changes to cs-stream; changed results; putting together a doc with changes for review; Joran's work on concurrent message processing on Kafka topics -> try to test it; seeing 40-50% throughput; + b LPS adapter: Working with Renjith (Applied Payments); putting together a lab / envt for partner teams to use it; Exploring collaboration with GSMA lab +2. Crosslake - Lewis: + a. Performance: Had report out with Confluent with Nakul, engagement wrapping up; Disseminating docs Nakul produced + b. PISP: Design discussions going on along with Implementation + c. Versioning: Figuring scope for ZDD deployments + d. Official launch related issues: DNS issues - worked on and were resolved +3. ModusBox - Sam: + a. Performance: Moving / standardizing Perf changes from PI-9 into master (not all PoCs); Working on goals, strategy for PI10 + b. Core-team: Bulk transfers - getting started by providing support in sdk-scheme-adapter + c. Maintenance (Bug Fixes): + i) Accents in names - Ongoing + ii) Mojaloop simulator on AWS deployments - almost done, working on QA scripts (on 'dev2' - second environment) + d. Testing toolkit: Currently available for testing - all resources in ML FSPIOP API Supported. Reports can be generated. Working on providing Command line options and more portability + e. CCB: Publishing v1.1 Spec this week - API Definition and corresponding Swagger (Open API) +4. Virtual / Mojaloop Foundation - Megan: + a. Launch of Mojaloop Foundation + b. Paula H - Executive Director of the Mojaloop Foundation. +5. Mojaloop Foundation - Simeon: + a. Provide feedback on the Community Survey + b. Hackathon possible in early June time-frame in collaboration with Google + c. Mojaloop Newsletter with interesting items such as ML FSPIOP v1.1 Spec, Helm v10.1.0 release, etc. to be launched next week. + +## OSS Scrum or scrum calls Thu **April 16th** 2020 + +1. Coil: + a. Don C: Perf - preliminary results - got some numbers - got individual handler numbers, to compare with individual handlers - focusing on DB - a thrid of time for one leg spent on perf + b. Don C: HSM: Renjit's team demo'ed the demo for next week - event prep +2. Crosslake: + a. Lewis D: PISP - Sprint planning - iterating designs + b. Lewis D: Hackathons - Discussed a few concepts with Innocent K (HiPiPo) + c. Lewis D: Has access to GSMA lab - will play around + d. Lewis D: Versioning: working on deck for PI10 + e. Kim W: Performance stream overall update - workshop with Confluent + f. Kim W: Performance stream update - Pedro putting together a proposal, presentation +3. Mifos: + a. Ed C: Demo Prep for PI10 meetings +4. Virtual: + a. Megan : Getting ready for the PI10 event and Logistics +5. DA: + a. Nico: Discussing PISP issue which Michael will be the owner of +6. Core team: + a. Sam K: Performance: Preparing Metrics; Doing performance runs to baseline master branches after moving some enhancements to master + b. Sam K: Accents in names issue - implementation ongoing + f. Sam K: Settlements V2 implementation being done by OSS-TIPS team ongoing - QA done for current iteration + g. Sam K: Testing toolkit: Improving unit test coverage. Assertions added for various endpoints + i. Sam K: CCB: V1.1 of the ML FSPIOP API Definition - First draft done, Reviews in progress +7. Mojaloop Community: + a. Community update by Simeon + +## OSS Scrum or scrum calls Thu **April 9th** 2020 + +1. Coil: + a. Don C: perf testing - Under utilization of resources - more tweaking to be done + b. Don C: HSM integration - demo prep + c. Don C: Legacy adapter - docs update - looking for feedback +2. Crosslake: + a. Kim W: FRMS meeting earlier today - proposals made + b. Kim W: PI10 meetings update, registrations - questions + c. Lewis D: PISP: more planning - working on stories, items, but discussing designs on Oauth, Fido + d. Lewis D: Performance: discussion with Pedro about PoC for arch changes, for Event Sourcing, CQRS, etc + e. Lewis D: Code standards - updated + f. Lewis D: Code quality & Security stream: HSM usage, demo, Security in the OSS community + g. Lewis D: Container scans working - will work with Victor, early benchmarks + h. Lewis D: Finally - versioning update +3. Mifos: + a. Ed C: Work on Payment Hub, integrating with Kafka, ML transactions going through, usiing Elastic Search, for backoffice ops moniring + b. Ed C: Demo Prep for PI10 meetings +4. Core team: + a. Sam K: Performance: Drafting reports, Moving metrics, other enhancements to master branches + b. Sam K: Performance: Wrapping-up final set of tests; Phase4 roadmap and kickoff planning + c. Sam K: Community Support: Fixing bugs (few major discussion items fixed), providing clarifications regarding implementation decisions, etc. + d. Sam K: Merchant Payment Support - Provide tests and validate Merchant "Request to Pay" use case, standardization on-going + e. Sam K: Accents in names issue - implementation ongoing + f. Sam K: Settlements V2 implementation being done by OSS-TIPS team ongoing + g. Sam K: Testing toolkit: Assertions being added for API resources, JWS done, mTLS being added + h. Sam K: Testing toolkit: Usage guide in progress along with adding Golden path related tests + i. Sam K: CCB: V1.1 of the ML FSPIOP API Definition - First draft done, waiting for review + +## OSS Scrum or scrum calls Thu **April 2nd** 2020 + +1. Mifos: + a. Ed C: Team continuing work on Payment Hub EE, Focus on Operational UI , capabilities for DFSP backends, Error event handling framework +2. Coil: + a. Don C: Performance - setup done and got started - on GCP - getting high latency times - need to troubleshoot and will probably get support from other contributors + b. Don C: ATM - OTP - Encryption +3. Crosslake: + a. Kim W: Agenda for PI10 drafted - email should good out soon + b. Kim W: Schedule for PI10: Tue - Fri; 11am - 4pm GMT - Remote / Virtual event + c. Lewis D: Perf meeting later today - architecture deep dive + d. Lewis D: Versioning - In progress + e. Lewis D: Code quality & Security - Overall Security architecture, HSM covered by Coil + f. Lewis D: Mojaloop in a Vagrant box - in progress +4. Core team: + a. Miguel dB: Performance: Wrapping up Perf work - nearing 900 TPS end-to-end; Currently attempting to identify / understand a single unit that needs this perf + b. Sam K: Performance: Wrapping-up final set of tests; Phase4 roadmap and kickoff planning + c. Sam K: Community Support: Fixing bugs (few major discussion items fixed), providing clarifications regarding implementation decisions, etc. + d. Sam K: Merchant Payment Support - Standardization on-going - Fixing issues in /authorizations + e. Sam K: Accents in names issue - implementation ongoing + f. Sam K: Settlements V2 implementation being done by OSS-TIPS team ongoing + g. Sam K: Testing toolkit: Assertions being added for API resources, JWS in progress + h. Sam K: CCB: V1.1 of the ML FSPIOP API Definition - drafting in progress + +## OSS Scrum of scrum call Thu **March 26th** 2020 + +1. DA: Nico - Versioning topic discussed by Lewis, Matt, Sam +2. Crosslake: + a. Kim W: Finalizing Agenda - Monday to Friday + b. Kim W: Reach out if you want to present / speak + c. Kim W: Preparing pre-reads + d. Kim W: Fraud & AML workshop: Justus to post summary and notes to GitHub after the workshops + e. Lewis D: Performance workshop / deep-dive possibly Monday + f. Lewis D: PISP Design discussions ongoing + g: Lewis D: Code quality and security stream: i. Docker container security recommendations. ii. GDPR Scope for Mojaloop +3. Mifos: + a. Ed C / Istvan M: Continue creating Lab + b. Ed C / Istvan M: Fineract , new instance of Payment Hub - good progress + c. Ed C / Istvan M: Working on operational monitoring of backend part (back-office debugging, monitoring, etc) +4. Simeon O - Community Manager in attendance +5. Core team: + a. Sam K: Performance: Finalized phase-3 work. Get to immediate goals for logical conclusion - still ongoing - Phase4 roadmap and kickoff + b. Sam K: Community Support: Fixing bugs, providing clarifications regarding implementation decisions, etc. + d. Sam K: Merchant Payment Support - Standardization on-going - Metrics being added, event framework added + e. Sam K: Accents in names issue - Discussing issue, designing solution + f. Sam K: Settlements V2 implementation being done by OSS-TIPS team ongoing + g. Sam K: Testing toolkit: Assertions being added for API resources, JWS in progress. Usage guide in progress + h. Sam K: CCB: V1.1 of the ML FSPIOP API Definition - drafting in progress + +## OSS Scrum or scrum call Thu **March 19th** 2020 + +1. Coil: + a. Don C: Looking at performance, network hops (avoid dup checks etc) + b. Adrian hB: Renjith & Matt working on translation ISO20022, (to JWEs, etc) - demo by the time we meet on how to use HSM +2. Crosslake: + a. Kim W: Finishing action items from the Mid-PI Workshop, follow-up items + b. Kim W: April Community event is happening but will be a Virtual event. Kim has a planning event and will confirm details: Suggestions welcome + c. Lewis D: Performance - to include Don in other discussions + d. Lewis D: Code quality - GDPR requirements proposal + e: Lewis D: Versioning - iinitial draft made as PR - will be presented to DA next week +3. Mifos: + a. Ed C, Istvan M: Payment Hub, envt in Azure, + b. Ed C, Istvan M: Transactions now going through + c. Ed C, Istvan M: Next phase: to implement back office screens to see screens for business users + d. Ed C, Istvan M: Workshop with Google on PISP +4. Core team: + a. Sam K: Perf - Combining prepare+position handler and fulfil+position handlers, characterization work ongoing + b. Sam K: Perf - Working on gaining an understanding of how 1 unit of Infrastructure looks like for a Mojaloop deployment + c. Sam K: Transaction requests service standardization: Added event framework, Adding metrics now + d. Sam K: Community Support: Fixing issues, upgrade issues, issue for allowing accents in names, etc,. diff --git a/mojaloop-background.md b/legacy/mojaloop-background.md similarity index 100% rename from mojaloop-background.md rename to legacy/mojaloop-background.md diff --git a/mojaloop-background/README.md b/legacy/mojaloop-background/README.md similarity index 100% rename from mojaloop-background/README.md rename to legacy/mojaloop-background/README.md diff --git a/mojaloop-background/core-scenarios.md b/legacy/mojaloop-background/core-scenarios.md similarity index 99% rename from mojaloop-background/core-scenarios.md rename to legacy/mojaloop-background/core-scenarios.md index 856716930..47fddaa2b 100644 --- a/mojaloop-background/core-scenarios.md +++ b/legacy/mojaloop-background/core-scenarios.md @@ -18,7 +18,7 @@ Mojaloop addresses a number of scenarios in which this software might help the p Hamim is working on his farm in Northern Uganda when he receives an urgent phone call from his brother, Kani. Kani is low on money and will not get paid until next week. Kani has no money to pay for food for his family and asks Hamim to help him out. Hamim and Kani have no means of transportation and it would take several days for Hamim to get to his Kani's home in Southern Uganda. While they both have mobile flip phones, they use different financial service providers. Kani tells Hamim that he needs 5,000 shillings to buy food until he gets paid next week for his job working in a local field. Hamin agrees to send Kani the money. -```text +``` *** Mojaloop technology does its job *** ``` @@ -28,7 +28,7 @@ Because Hamim has sent money to Kani before he has his information on his phone. Venya is waiting in line to buy plantains at her local market. She is corralling her elder child with one hand and has her baby in a sling. She often comes to this seller and she knows he has a good price. She also knows that even though she carries no money and he is not on her financial network, she can buy from him. As she approaches the head of the line she juggles the children and pulls out a simple flip phone. She tells him 1.5 kilograms and he tells her the price, which she agrees to. -```text +``` *** Mojaloop technology does its job *** ``` @@ -38,7 +38,7 @@ Because she's been here before the merchant already has her information on his p Nikisha is the accountant for one of the largest manufacturing companies in Johannesburg and employs over 250 workers. Their company uses a time and attendance system to track the number of hours that each employee works along with their hourly rate and employee ID. On a weekly basis Nikisha gets an update on her bulk payment system that shows all the employees, their user ID along and amount to be paid. Since the companies employees all have different financial service providers this system makes it really easy for Nikisha to confirm and distribute their pay with a couple of clicks. The company has a high turnover rate so new employees who get their first paycheck are automatically prompted to open an account as long as they provided a valid mobile number when they started. As Nikisha gets ready to send out this week's payments she opens up a bulk payment report. -```text +``` *** Mojaloop technology does its job *** ``` @@ -48,7 +48,7 @@ The bulk report for payments comes up by date range and, since Nikisha does this Salem works as an auditor for a large bank in Kampala, Uganda. His job is to monitor, manage and reduce risk for the company. order to do so each new user ID in the system is assigned a default tier level which means they can only transfer a small number and amount of funds in and out of the system over specific periods of time. As users acquire greater balances in their accounts and hold their accounts for longer periods of time their tier levels improve. Tier levels are handled automatically by the system so Salem does not need to worry about assigning or changing these levels under normal circumstances. Part of Salem's job as an auditor is to review the daily reports to ensure that everyone's funds are safe and secure and he kicks off his daily report to review the accounts. -```text +``` *** Mojaloop technology does its job *** ``` @@ -58,7 +58,7 @@ This morning when Salem reviews these reports he notices that one specific user Salem works as an auditor for a large bank in Kampala, Uganda. His job is to monitor and stop any fraudulent activity for the company. While the company has a set of rules that might flag individuals for Salem to investigate, he also has the authority to screen any user ID for fraudulent activities at any time. Each time Salem performs a fraud check on a user ID, the system records the date of the last check along with any comments that Salem might have made. This makes it very easy for Salem to search for IDs that might have never been checked for fraud or have not been checked in a very long time. Salem has been monitoring one particular ID that seems to have had an increased amount of incoming funds deposited into their account on a daily basis. Today he does a search of the user ID to investigate further. -```text +``` *** Mojaloop technology does its job *** ``` @@ -68,7 +68,7 @@ When the user ID is retrieved Salem is able to see the customer's name, birthdat Tadeo just bought his first mobile flip phone for him and his family to share. He is happy that he finally has a phone that he can use in emergencies, but he can also finally keep his money secure by opening up a bank account. Tadeo has never had a bank account since he lives in a very remote part of Africa with no personal means of transportation. Tadeo and his family have to rely on bartering or cash to buy any goods they need at the market. Although Tadeo is not proficient in reading, he is able to easily use his phone to setup and account for him and his family by following a couple of easy to read menu steps. -```text +``` *** Mojaloop technology does its job *** ``` @@ -78,13 +78,13 @@ Tadeo was able to use his phone to create an mWallet account using his National Jahari has a flip phone that all the family uses and he has setup different user numbers for each family member. Jahari is at the local market and needs to buy some meat for his family. Before he does, he wants to make sure he has enough funds in his account to purchase the goods and still have enough left over to set aside for future medical expenses and education. Jahari is happy that his money is secure and he is able to check his account balance anytime he needs to by simply entering his secure pin on his phone. Once he confirms his balance he will buy some goat and cow meat at the market. -```text +``` *** Mojaloop technology does its job *** ``` After Jahari has entered his pin on his phone he is able to see his account balance. He is also able to see any of his recent transactions as well as any fees that were associated with these transactions. After confirming his available funds he picks out his meat and brings it up to the merchant for payment. The merchant does a lot of business in this market and has a point of sales device. This is very helpful for Jahari and his family since they only have one phone and many times his wife or his children go to the market and do not have the phone with them. Jahari can generate a one time pin for family to use in these cases. The merchant is able to enter the purchase amount on the POS device and Jahari or any of his family members securely enters their user number and reviews the transaction. He confirms that the amount on the POS machine matches what the merchant verbally told him and he enters his one-time pin to approve the transaction. -```text +``` *** Mojaloop technology does its job *** ``` diff --git a/mojaloop-background/level-one-principles.md b/legacy/mojaloop-background/level-one-principles.md similarity index 100% rename from mojaloop-background/level-one-principles.md rename to legacy/mojaloop-background/level-one-principles.md diff --git a/legacy/mojaloop-publications.md b/legacy/mojaloop-publications.md new file mode 100644 index 000000000..f1dbb7fb1 --- /dev/null +++ b/legacy/mojaloop-publications.md @@ -0,0 +1,18 @@ +# Publications + +Publications are stored in the [Documentation Artifacts Github repository](https://github.com/mojaloop/documentation-artifacts). + +See below listing of current published publications. + +## OSS Community Convenings Sessions (Presentations and Notes) + +- [January 2020 (Phase 4 Kickoff) OSS Community Session](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/January%202020%20OSS%20Community%20Session) +- [September 2019 PI-8 (Phase 3 Wrap-up) OSS Community Session](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/September%202019%20PI-8_OSS_community%20session) +- [June 2019 PI-7 OSS Community Session](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/June%202019%20PI-7_OSS_community%20session) +- [April 2019 PI-6_OSS Community Session](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/April%202019%20PI-6_OSS_community%20session) +- [January 2010 PI-5 OSS Community Session](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/January%202019) + +## Mojaloop Standard Publications + +- [Moajoop Decimal Type; Based on XML Schema Decimal Type](./discussions/decimal.md) +- [Mojaloop API Specification](https://github.com/mojaloop/mojaloop-specification/blob/master/API%20Definition%20v1.0.pdf) diff --git a/legacy/mojaloop-roadmap.md b/legacy/mojaloop-roadmap.md new file mode 100644 index 000000000..3ab842449 --- /dev/null +++ b/legacy/mojaloop-roadmap.md @@ -0,0 +1,75 @@ +# Mojaloop Roadmap + +The roadmap is built around the concept of three pillars, which are: + +1. Make it easier to deploy Mojaloop +2. Make sure deployments have every opportunity to make themselves profitable +3. Connect to other payments services in the ecosystem + +These three pillars are underpinned by a fourth workstream, that of continuous development of a quality +product. +* Make Adoption Easier +* Achieve Scale +* Connect to Other Systems +* Quality Product + +## Make Adoption Easier +(Promote a better understanding of Mojaloop) +* Develop “Mojaloop Journey” – a manual to take adopters from concept to live service +* Better portals for both Hub and Payment Manager + * Develop Configuration support + * Showcase extensions using Biz Ops Framework + * Bootcamp +* Easier Deployment + * Make IaC more accessible + * Pre-configs for different deployment types + * On-Prem + * Azure +* Better Showcase +* Capitalise on MiniLoop + * Demos etc as part of deployment + * Testing support (Quality Product) +* Fintech sandbox +* Integration with FRMS, demonstrate with a live deployment (PoC) + +## Achieve Scale +Drive scale through: +* Merchant Payments + * QR-based Push + * Merchant acquiring + * Mobile wallets, MFIs +* PISP + * MRTP + * Bill Payments + * Aggregators + * Salaries etc + * Support for bulk through PISP interface +* Bulk + * Partially complete – needs completing for older CBS + +## Connect to Other Systems +* Cross-Border + * Next Generation Settlement (part of TigerBeetle, vNext, “Quality Product”) + * Integrated Forex services & API + * Payments addressing solutions for international transactions +* Integrations into emerging DPG ecosystem + * Payments addressing using MOSIP national ID + * Integration with MOSIP, Mifos, OpenG2P + * Oracle/ALS development + * Opportunity for thought leadership on the integration of DPGs +* Working within international ecosystems +* Wholesale CBDC +* Compatibility with Interledger developments +* Development of an Interledger Cross Network Provider (CNP) + +## Maintain and Develop the Ecosystem +Continuous: +* Ongoing maintenance +* Adopt MiniLoop for testing etc + +In order to support the scale we want to achieve under Pillar 2: +* Continue the development of vNext, work towards a migration +* Adoption of TigerBeetle for vNext + +In order to support the interconnections we want to achieve under Pillar 3: +* Accelerate TigerBeetle, vNext for agile deployment of next gen settlement engine diff --git a/legacy/mojaloop-technical-overview/README.md b/legacy/mojaloop-technical-overview/README.md new file mode 100644 index 000000000..8aadf39ae --- /dev/null +++ b/legacy/mojaloop-technical-overview/README.md @@ -0,0 +1,16 @@ +# Mojaloop Technical Overview + +## Mojaloop Services + +The basic idea behind Mojaloop is that we need to connect multiple Digital Financial Services Providers (DFSPs) together into a competitive and interoperable network in order to maximize opportunities for poor people to get access to financial services with low or no fees. We don't want a single monopoly power in control of all payments in a country, or a system that shuts out new players. It also doesn't help if there are too many isolated subnetworks. The following diagrams shows the Mojaloop interconnects between DFSPs and the Mojaloop Hub (schema implementation example) for a Peer-to-Peer (P2P) Transfer: + +Mojaloop addresses these issues in several key ways: +* A set of central services provides a hub through which money can flow from one DFSP to another. This is similar to how money moves through a central bank or clearing house in developed countries. Besides a central ledger, central services can provide identity lookup, fraud management, and enforce scheme rules. +* A standard set of interfaces a DFSP can implement to connect to the system, and example code that shows how to use the system. A DFSP that wants to connect up can adapt our example code or implement the standard interfaces into their own software. The goal is for it to be as straightforward as possible for a DFSP to connect to the interoperable network. +* Complete working open-source implementations of both sides of the interfaces - an example DFSP that can send and receive payments and the client that an existing DFSP could host to connect to the network. + +![Mojaloop End-to-end Architecture Flow PI5](./assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg) + +The Mojaloop Hub is the primary container and reference we use to describe the Mojaloop ecosystem which is split in to the following domains: +* Mojaloop Open Source Services - Core Mojaloop Open Source Software (OSS) that has been supported by the Bill & Melinda Gates Foundation in partnership with the Open Source Community. +* Mojaloop Hub - Overall Mojaloop reference (and customizable) implementation for Hub Operators is based on the above OSS solution. diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/README.md b/legacy/mojaloop-technical-overview/account-lookup-service/README.md new file mode 100644 index 000000000..f0ff84f03 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/README.md @@ -0,0 +1,123 @@ +# Account Lookup Service + +The **Account Lookup Service** (**ALS**) _(refer to section `6.2.1.2`)_ as per the [Mojaloop {{ book.importedVars.mojaloop.spec.version }} Specification]({{ book.importedVars.mojaloop.spec.uri.doc }}) implements the following use-cases: + +* Participant Look-up +* Party Look-up +* Manage Participants Registry information + * Adding Participant Registry information + * Deleting Participant Registry information + +Use-cases that have been implemented over and above for Hub Operational use: +* Admin Operations + * Manage Oracle End-point Routing information + * Manage Switch End-point Routing information + +## 1. Design Considerations + +### 1.1. Account Lookup Service (ALS) +The ALS design provides a generic Central-Service component as part of the core Mojaloop. The purpose of this component is to provide routing and alignment to the Mojaloop API Specification. This component will support multiple Look-up registries (Oracles). This ALS will provide an Admin API to configure routing/config for each of the Oracles similiar to the Central-Service API for the End-point configuration for DFSP routing by the Notification-Handler (ML-API-Adapter Component). The ALS will in all intense purpose be a switch with a persistence store for the storage/management of the routing rules/config. + +#### 1.1.1. Assumptions + +* The ALS design will only cater for a single switch for the time being. +* Support for multiple switches will utilise the same DNS resolution mechanism that is being developed for the Cross Border/Network design. + +#### 1.1.2. Routing + +The routing configuration will be based on the following: +* PartyIdType - See section `7.5.6` of the Mojaloop Specification +* Currency - See section `7.5.5` of the Mojaloop Specification. Currency code defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic string. This will be optional, however `isDefault` indicator must be set to `true` if the `Currency` is not provided. +* isDefault - Indicator that a specific Oracle is the default provider for a specific PartyIdType. Note that there can be many default Oracles, but there can only be a single Oracle default for a specific PartyIdType. The default Oracle for a specific PartyIdType will only be selected if the originating request does not include a Currency filter. + + +### 1.2. ALS Oracle +The ALS Oracle be implemented as either a **Service** or **Adapter** (semantic dependant on use - Mediation = Adapter, Service = Implementation) will provide a look-up registry component with similar functionality of the `/participants` Mojaloop API resources. It has however loosely based on the ML API specification as it's interface implements a sync pattern which reduces the correlation/persistence requirements of the Async Callback pattern implemented directly by the ML API Spec. This will provide all ALS Oracle Services/Adapters with a standard interface which will be mediated by the ALS based on its routing configuration. +This component (or back-end systems) will also be responsible for the persistence & defaulting of the Participant details. + +## 2. Participant Lookup Design + +### 2.1. Architecture overview +![Architecture Flow Account-Lookup for Participants](./assets/diagrams/architecture/arch-flow-account-lookup-participants.svg) + +_Note: The Participant Lookup use-case similarly applies to for a Payee Initiated use-case such as transactionRequests. The difference being that the Payee is the initiation in the above diagram._ + +### 2.2. Sequence diagrams + +#### 2.2.1. GET Participants + +- [Sequence Diagram for GET Participants](als-get-participants.md) + +#### 2.2.2. POST Participants + +- [Sequence Diagram for POST Participants](als-post-participants.md) + +#### 2.2.3. POST Participants (Batch) + +- [Sequence Diagram for POST Participants (Batch)](als-post-participants-batch.md) + +#### 2.2.4. DEL Participants + +- [Sequence Diagram for DEL Participants](als-del-participants.md) + +## 3. Party Lookup Design + +### 3.1. Architecture overview +![Architecture Flow Account-Lookup for Parties](./assets/diagrams/architecture/arch-flow-account-lookup-parties.svg) + +### 3.2. Sequence diagram + +#### 3.2.1. GET Parties + +- [Sequence Diagram for GET Parties](als-get-parties.md) + +## 4. ALS Admin Design + +### 4.1. Architecture overview +![Architecture Flow Account-Lookup for Admin Get Oracles](./assets/diagrams/architecture/arch-flow-account-lookup-admin.svg) + +### 4.2. Sequence diagram + +#### 4.2.1 GET Oracles + +- [Sequence Diagram for GET Oracles](als-admin-get-oracles.md) + +#### 4.2.2 POST Oracle + +- [Sequence Diagram for POST Oracle](als-admin-post-oracles.md) + +#### 4.2.3 PUT Oracle + +- [Sequence Diagram for PUT Oracle](als-admin-put-oracles.md) + +#### 4.2.4 DELETE Oracle + +- [Sequence Diagram for DELETE Oracle](als-admin-del-oracles.md) + +#### 4.2.5 DELETE Endpoint Cache + +- [Sequence Diagram for DELETE Endpoint Cache](als-del-endpoint.md) + +## 5. Database Design + +### 5.1. ALS Database Schema + +#### Notes +- `partyIdType` - Values are currently seeded as per section _`7.5.6`_ [Mojaloop {{ book.importedVars.mojaloop.spec.version }} Specification]({{ book.importedVars.mojaloop.spec.uri.doc }}). +- `currency` - See section `7.5.5` of the Mojaloop Specification. Currency code defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic string. This will be optional, and must provide a "default" config if no Currency is either provided or provide a default if the Currency is provided, but only the "default" End-point config exists. +- `endPointType` - Type identifier for the end-point (e.g. `URL`) which provides flexibility for future transport support. +- `migration*` - Meta-data tables used by Knex Framework engine. +- A `centralSwitchEndpoint` must be associated to the `OracleEndpoint` by the Admin API upon insertion of a new `OracleEndpoint` record. If the `centralSwitchEndpoint` is not provided as part of the API Request, then it must be defaulted. + +![Acount Lookup Service ERD](./assets/entities/AccountLookupService-schema.png) + +* [Acount Lookup Service DBeaver ERD](./assets/entities/AccountLookupDB-schema-DBeaver.erd) +* [Acount Lookup Service MySQL Workbench Export](./assets/entities/AccountLookup-ddl-MySQLWorkbench.sql) + +## 6. ALS Oracle Design + +Detail design for the Oracle is out of scope for this document. The Oracle design and implementation is specific to each Oracle's requirements. + +### 6.1. API Specification + +Refer to **ALS Oracle API** in the [API Specifications](../../api/README.md#als-oracle-api) section. diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/als-admin-del-oracles.md b/legacy/mojaloop-technical-overview/account-lookup-service/als-admin-del-oracles.md new file mode 100644 index 000000000..b02a6c44d --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/als-admin-del-oracles.md @@ -0,0 +1,7 @@ +# DELETE Oracles + +Design for the Deletion of an Oracle Endpoint by a Hub Operator. + +## Sequence Diagram + +![seq-acct-lookup-admin-del-oracle-7.3.4.svg](./assets/diagrams/sequence/seq-acct-lookup-admin-del-oracle-7.3.4.svg) diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/als-admin-get-oracles.md b/legacy/mojaloop-technical-overview/account-lookup-service/als-admin-get-oracles.md new file mode 100644 index 000000000..63ff4cefe --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/als-admin-get-oracles.md @@ -0,0 +1,7 @@ +# GET Oracles + +Design for getting a list of all Oracle Endpoints by the Hub Operator with the option of querying but currency and/or type. + +## Sequence Diagram + +![seq-acct-lookup-admin-get-oracle-7.3.1](./assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1) diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/als-admin-post-oracles.md b/legacy/mojaloop-technical-overview/account-lookup-service/als-admin-post-oracles.md new file mode 100644 index 000000000..9f2b210e0 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/als-admin-post-oracles.md @@ -0,0 +1,7 @@ +# POST Oracles + +Design for the creation of an Oracle Endpoint by a Hub Operator. + +## Sequence Diagram + +![seq-acct-lookup-admin-post-oracle-7.3.2.svg](./assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.svg) diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/als-admin-put-oracles.md b/legacy/mojaloop-technical-overview/account-lookup-service/als-admin-put-oracles.md new file mode 100644 index 000000000..46446c731 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/als-admin-put-oracles.md @@ -0,0 +1,7 @@ +# PUT Oracles + +Design for the Update of an Oracle Endpoint by a Hub Operator. + +## Sequence Diagram + +![seq-acct-lookup-admin-put-oracle-7.3.3.svg](./assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.svg) diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/als-del-endpoint.md b/legacy/mojaloop-technical-overview/account-lookup-service/als-del-endpoint.md new file mode 100644 index 000000000..5f8ed7d52 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/als-del-endpoint.md @@ -0,0 +1,7 @@ +# DELETE Endpoint Cache + +Design for the disabling of an Oracle by the Hub Operator. + +## Sequence Diagram + +![seq-acct-lookup-del-endpoint-cache-7.3.0](./assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0) diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/als-del-participants.md b/legacy/mojaloop-technical-overview/account-lookup-service/als-del-participants.md new file mode 100644 index 000000000..7e2621e74 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/als-del-participants.md @@ -0,0 +1,11 @@ +# DEL Participants + +Design for the deletion of a Participant by a DFSP. + +## Notes + +- Reference section 6.2.2.4 - Note: The ALS should verify that it is the Party’s current FSP that is deleting the FSP information. ~ This has been addressed in the design by insuring that the Party currently belongs to the FSPs requesting the deletion of the record. Any other validations are out of scope for the Switch and should be addressed at the schema level. + +## Sequence Diagram + +![seq-acct-lookup-del-participants-7.1.2.svg](./assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.svg) diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/als-get-participants.md b/legacy/mojaloop-technical-overview/account-lookup-service/als-get-participants.md new file mode 100644 index 000000000..8844c37c2 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/als-get-participants.md @@ -0,0 +1,7 @@ +# GET Participants + +Design for the retrieval of a Participant by a DFSP. + +## Sequence Diagram + +![seq-acct-lookup-get-participants-7.1.0.svg](./assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.svg) diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/als-get-parties.md b/legacy/mojaloop-technical-overview/account-lookup-service/als-get-parties.md new file mode 100644 index 000000000..4d1b87249 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/als-get-parties.md @@ -0,0 +1,7 @@ +# GET Parties + +Design for the retrieval of a Party by a DFSP. + +## Sequence Diagram + +![seq-acct-lookup-get-parties-7.2.0.svg](./assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.svg) diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/als-post-participants-batch.md b/legacy/mojaloop-technical-overview/account-lookup-service/als-post-participants-batch.md new file mode 100644 index 000000000..0bad74bc8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/als-post-participants-batch.md @@ -0,0 +1,14 @@ +# Sequence Diagram for POST Participants (Batch) + +Design for the creation of a Participant by a DFSP via a batch request. + +## Notes + +- Operation only supports requests which contain: + - All Participant's FSPs match the FSPIOP-Source + - All Participant's will be of the same Currency as per the [Mojaloop {{ book.importedVars.mojaloop.spec.version }} Specification]({{ book.importedVars.mojaloop.spec.uri.doc }}) +- Duplicate POST Requests with matching TYPE and optional CURRENCY will be considered an __update__ operation. The existing record must be completely __replaced__ in its entirety. + +## Sequence Diagram + +![seq-acct-lookup-post-participants-batch-7.1.1.svg](./assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.svg) diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/als-post-participants.md b/legacy/mojaloop-technical-overview/account-lookup-service/als-post-participants.md new file mode 100644 index 000000000..088171ce8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/als-post-participants.md @@ -0,0 +1,7 @@ +# POST Participant + +Design for the creation of a Participant by a DFSP via a request. + +## Sequence Diagram + +![seq-acct-lookup-post-participants-7.1.3.svg](./assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.svg) diff --git a/mojaloop-technical-overview/central-settlements/.gitkeep b/legacy/mojaloop-technical-overview/account-lookup-service/assets/.gitkeep similarity index 100% rename from mojaloop-technical-overview/central-settlements/.gitkeep rename to legacy/mojaloop-technical-overview/account-lookup-service/assets/.gitkeep diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-admin.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-admin.svg new file mode 100644 index 000000000..d46ffa284 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-admin.svg @@ -0,0 +1,3 @@ + + +
    Account Lookup Service Admin
    (ALS)
    Account Lookup Service Adm...
    HUB
    Backend



    HUB...
    Account Lookup Admin
    Account Lookup Admin
    HUB Operator
    HUB Operator
    A1. Request Oracle Endpoints 
    GET /oracles
    A1. Requ...
    A1.3. Return List of Oracles
    A1.3. Re...
    ALS
    DB
    ALS...
    Key
    Key
    A1.2. Lookup All Oracle Registry Service End-points 
    API
    Internal Use-Only
    API...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-participants.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-participants.svg new file mode 100644 index 000000000..2bb5d7029 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-participants.svg @@ -0,0 +1,3 @@ + + +
    Account Lookup Service
    (ALS)

    [Not supported by viewer]
    FSP
    Backend

    (Does not natively speak Mojaloop API)



    [Not supported by viewer]
    Scheme-Adapter

    (Converts from Mojaloop API to backend FSP API)

    [Not supported by viewer]
    FSP
    Backend
      

    (Natively speaks Mojaloop API)



    [Not supported by viewer]
    Participants Account Lookup
    [Not supported by viewer]
    Payer FSP
    [Not supported by viewer]
    Payee FSP
    [Not supported by viewer]
    Party Store
    [Not supported by viewer]
    Party
    Store
    [Not supported by viewer]
    Persistance store
    [Not supported by viewer]
    Central Ledger
    Service
    [Not supported by viewer]
    A5. Retrieve Participant End-points GET /participants/<participantId>/endpoints
    A1. Request Participant Lookup
    GET /participants/<idType>/<id>
    [Not supported by viewer]
    A3. Request Participant Lookup via Oracle
    GET /participants/<idType>/<id>
    [Not supported by viewer]
    Oracle Merchant
    Registry Service
    <idType = 'BUSINESS'>
    [Not supported by viewer]
    A4. Alt
    A4. Alt

    <font color="#000000"><br></font>
    Persistance store
    [Not supported by viewer]
    Oracle Bank Account
    Registry Service
    <idType = 'ACCOUNT_ID'>
    [Not supported by viewer]
    A4. Alt
    A4. Alt

    <font color="#000000"><br></font>
    Oracle Pathfinder
    Registry Service
    Adapter
    <idType = 'MSISDN'>
    [Not supported by viewer]
    A4. Retrieve Participant Data
    [Not supported by viewer]

    <font color="#000000"><br></font>
    A3. Alt
    A3. Alt

    <font color="#000000"><br></font>
    A3. Alt
    A3. Alt

    <font color="#000000"><br></font>
    Mojaloop Central Services
    [Not supported by viewer]
    A7. User Lookup
    PUT /participants/<idType>/<id>
    A7. User Lookup <br>PUT /participants/<idType>/<id>
    Central Ledger DB
    Central Ledger DB
    A6. Retrieve Participant End-point Data
    A6. Retrieve Participant End-point Data

    <font color="#000000"><br></font>
    ALS
    DB
    [Not supported by viewer]
    A2. Lookup Oracle Adapter/Service End-points based on <idType>
    Hub Operator Schema Hosted
    [Not supported by viewer]
    Externally Hosted
    [Not supported by viewer]
    PathFinder GSMA
    [Not supported by viewer]
    API
    Internal Use-Only
    API <br>Internal Use-Only
    Mojaloop API
    Specification v1.0
    Mojaloop API<br>Specification v1.0<br>
    Key
    [Not supported by viewer]
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-parties.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-parties.svg new file mode 100644 index 000000000..0dd8b76e6 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-parties.svg @@ -0,0 +1,3 @@ + + +
    Account Lookup Service
    (ALS)

    [Not supported by viewer]
    FSP
    Backend

    (Does not natively speak Mojaloop API)



    [Not supported by viewer]
    Scheme-Adapter

    (Converts from Mojaloop API to backend FSP API)

    [Not supported by viewer]
    FSP
    Backend
      

    (Natively speaks Mojaloop API)



    [Not supported by viewer]
    Parties Account Lookup
    [Not supported by viewer]
    Payer FSP
    [Not supported by viewer]
    Payee FSP
    [Not supported by viewer]
    Party Store
    [Not supported by viewer]
    Party
    Store
    [Not supported by viewer]
    A10. Get 
    receiver 
    details
    [Not supported by viewer]
    Persistance store
    [Not supported by viewer]
    Central Ledger
    Service
    [Not supported by viewer]
    A7. Retrieve PayeeFSP Participant End-pointsGET /participants/<participantId>/endpoints
    A1. Request Party Lookup
    GET /parties/<idType>/<id>
    [Not supported by viewer]
    A4. Request Participant Lookup via Oracle
    GET /participants/<idType>/<id>
    [Not supported by viewer]
    A9. User Lookup
    GET /parties/<idType>/<id>
    A9. User Lookup <br>GET /parties/<idType>/<id>
    Oracle Merchant
    Registry Service
    <idType = 'BUSINESS'>
    [Not supported by viewer]
    A5. Alt
    [Not supported by viewer]

    <font color="#000000"><br></font>
    Persistance store
    [Not supported by viewer]
    Oracle Bank Account
    Registry Service
    <idType = 'ACCOUNT_ID'>
    [Not supported by viewer]
    A5. Alt
    A5. Alt

    <font color="#000000"><br></font>
    Oracle Pathfinder
    Registry Service
    Adapter
    <idType = 'MSISDN'>
    [Not supported by viewer]
    A5. Retrieve Participant Data
    [Not supported by viewer]

    <font color="#000000"><br></font>
    A4. Alt
    A4. Alt

    <font color="#000000"><br></font>
    A4. Alt
    A4. Alt

    <font color="#000000"><br></font>
    Mojaloop Central Services
    [Not supported by viewer]
    A11. User Lookup
    PUT /parties/<idType>/<id>
    A11. User Lookup <br>PUT /parties/<idType>/<id>
    A14. User Lookup
    PUT /parties/<idType>/<id>
    A14. User Lookup <br>PUT /parties/<idType>/<id>
    Central Ledger DB
    Central Ledger DB
    A8. Retrieve Participant End-point Data
    A8. Retrieve Participant End-point Data

    <font color="#000000"><br></font>
    ALS
    DB
    [Not supported by viewer]
    Hub Operator Schema Hosted
    [Not supported by viewer]
    Externally Hosted
    [Not supported by viewer]
    PathFinder GSMA
    [Not supported by viewer]
    API
    Internal Use-Only
    API <br>Internal Use-Only
    Mojaloop API
    Specification v1.0
    Mojaloop API<br>Specification v1.0<br>
    Key
    [Not supported by viewer]
    A3. Lookup Oracle Registry ServiceEnd-points based on <idType>A12. Retrieve PayerFSP Participant End-pointsGET /participants/<participantId>/endpointsA6. Retrieve PayeeFSP Data for ValidationGET /participants/<participantId>(retrieve FSP Data)
    A13. Retrieve Participant End-point Data
    <font style="font-size: 13px">A13. Retrieve Participant End-point Data</font>
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.puml b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.puml new file mode 100644 index 000000000..3a6a6eecb --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.puml @@ -0,0 +1,92 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.4 Delete Oracle Endpoint + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS Admin Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service Admin API" as ALSADM +control "DELETE Oracle Handler" as ORC_HANDLER +database "ALS Store" as DB + +box "Account Lookup Service" #LightYellow +participant ALSADM +participant ORC_HANDLER +participant DB +end box + +' start flow + +activate OPERATOR +group Get Oracle Endpoint + OPERATOR -> ALSADM: Request to Delete Oracle Endpoint -\nDELETE /oracles/{ID} + activate ALSADM + + ALSADM -> ORC_HANDLER: Delete Oracle Endpoint + + activate ORC_HANDLER + ORC_HANDLER -> DB: Update existing Oracle Endpoint By ID + hnote over DB #lightyellow + Update isActive = false + end note + alt Delete existing Oracle Endpoint (success) + activate DB + DB -> ORC_HANDLER: Return Success + deactivate DB + + ORC_HANDLER -> ALSADM: Return success response + deactivate ORC_HANDLER + ALSADM --> OPERATOR: Return HTTP Status: 204 + + deactivate ALSADM + deactivate OPERATOR + end + alt Delete existing Oracle Endpoint (failure) + DB -> ORC_HANDLER: Throws Error (Not Found) + ORC_HANDLER -> ALSADM: Throw Error + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + ALSADM --> OPERATOR: Return HTTP Status: 502 + end +end + +@enduml diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.svg new file mode 100644 index 000000000..6cbc84f40 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.svg @@ -0,0 +1,197 @@ + + + + + + + + + + + 7.3.4 Delete Oracle Endpoint + + + + Account Lookup Service + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Account Lookup Service Admin API + + + + + Account Lookup Service Admin API + + + + + DELETE Oracle Handler + + + + + DELETE Oracle Handler + + + + + ALS Store + + + + + ALS Store + + + + + + + + Get Oracle Endpoint + + + + + 1 + + + Request to Delete Oracle Endpoint - + + + DELETE /oracles/{ID} + + + + + 2 + + + Delete Oracle Endpoint + + + + + 3 + + + Update existing Oracle Endpoint By ID + + + + Update isActive = false + + + + + alt + + + [Delete existing Oracle Endpoint (success)] + + + + + 4 + + + Return Success + + + + + 5 + + + Return success response + + + + + 6 + + + Return + + + HTTP Status: + + + 204 + + + + + alt + + + [Delete existing Oracle Endpoint (failure)] + + + + + 7 + + + Throws Error (Not Found) + + + + + 8 + + + Throw Error + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 9 + + + Return + + + HTTP Status: + + + 502 + + diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.puml b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.puml new file mode 100644 index 000000000..b800d83f9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.puml @@ -0,0 +1,116 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.1 Get All Oracle Endpoints + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS Admin Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service Admin API" as ALSADM +control "Get Oracles Handler" as ORC_HANDLER +database "ALS Store" as DB + +box "Account Lookup Service" #LightYellow +participant ALSADM +participant ORC_HANDLER +participant DB +end box + +' start flow + +activate OPERATOR +group Get Oracle Endpoints + OPERATOR -> ALSADM: Request to GET all Oracle Endpoints -\nGET /oracles?currency=USD&type=MSISDN + activate ALSADM + + ALSADM -> ORC_HANDLER: Get Oracle Endpoints + activate ORC_HANDLER + ORC_HANDLER -> DB: Get oracle endpoints + activate DB + + alt Get Oracle Endpoints (success) + DB --> ORC_HANDLER: Return Oracle Endpoints + deactivate DB + + deactivate DB + ORC_HANDLER -> ALSADM: Return Oracle Endpoints + deactivate ORC_HANDLER + note left of ALSADM #yellow + Message: + { + [ + { + "oracleId": , + "oracleIdType": , + "endpoint": { + "value": , + "endpointType": + }, + "currency": , + "isDefault": + } + ] + } + end note + ALSADM --> OPERATOR: Return HTTP Status: 200 + + deactivate ALSADM + deactivate OPERATOR + end + + alt Get Oracle Endpoints (failure) + DB --> ORC_HANDLER: Throw Error + deactivate DB + ORC_HANDLER -> ALSADM: Throw Error + deactivate ORC_HANDLER + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + + ALSADM --> OPERATOR: Return HTTP Status: 502 + + deactivate ALSADM + deactivate OPERATOR + + + end +end + +@enduml diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.svg new file mode 100644 index 000000000..7447557a3 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + 7.3.1 Get All Oracle Endpoints + + + + Account Lookup Service + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Account Lookup Service Admin API + + + + + Account Lookup Service Admin API + + + + + Get Oracles Handler + + + + + Get Oracles Handler + + + + + ALS Store + + + + + ALS Store + + + + + + + + Get Oracle Endpoints + + + + + 1 + + + Request to GET all Oracle Endpoints - + + + GET /oracles?currency=USD&type=MSISDN + + + + + 2 + + + Get Oracle Endpoints + + + + + 3 + + + Get oracle endpoints + + + + + alt + + + [Get Oracle Endpoints (success)] + + + + + 4 + + + Return Oracle Endpoints + + + + + 5 + + + Return Oracle Endpoints + + + + + Message: + + + { + + + [ + + + { + + + "oracleId": <string>, + + + "oracleIdType": <PartyIdType>, + + + "endpoint": { + + + "value": <string>, + + + "endpointType": <EndpointType> + + + }, + + + "currency": <Currency>, + + + "isDefault": <boolean> + + + } + + + ] + + + } + + + + + 6 + + + Return + + + HTTP Status: + + + 200 + + + + + alt + + + [Get Oracle Endpoints (failure)] + + + + + 7 + + + Throw Error + + + + + 8 + + + Throw Error + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 9 + + + Return + + + HTTP Status: + + + 502 + + diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.puml b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.puml new file mode 100644 index 000000000..083b0fac2 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.puml @@ -0,0 +1,112 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.2 Create Oracle Endpoints + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS Admin Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service Admin API" as ALSADM +control "POST Oracle Handler" as ORC_HANDLER +database "ALS Store" as DB + +box "Account Lookup Service" #LightYellow +participant ALSADM +participant ORC_HANDLER +participant DB +end box + +' start flow + +activate OPERATOR +group Get Oracle Endpoint + OPERATOR -> ALSADM: Request to Create Oracle Endpoint -\nPOST /oracles + note left of ALSADM #yellow + Message: + { + "oracleIdType": , + "endpoint": { + "value": , + "endpointType": + }, + "currency": , + "isDefault": + } + end note + activate ALSADM + + ALSADM -> ORC_HANDLER: Create Oracle Endpoint + + activate ORC_HANDLER + ORC_HANDLER -> ORC_HANDLER: Build Oracle Endpoint Data Object + ORC_HANDLER -> DB: Insert Oracle Endpoint Data Object + activate DB + + alt Create Oracle Entry (success) + DB --> ORC_HANDLER: Return success response + deactivate DB + + ORC_HANDLER -> ALSADM: Return success response + deactivate ORC_HANDLER + ALSADM --> OPERATOR: Return HTTP Status: 201 + + deactivate ALSADM + deactivate OPERATOR + end + + alt Create Oracle Entry (failure) + DB --> ORC_HANDLER: Throw Error + deactivate DB + ORC_HANDLER -> ALSADM: Throw Error + deactivate ORC_HANDLER + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + + ALSADM --> OPERATOR: Return HTTP Status: 502 + + deactivate ALSADM + deactivate OPERATOR + + + end +end + +@enduml diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.svg new file mode 100644 index 000000000..0638bdb48 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.svg @@ -0,0 +1,233 @@ + + + + + + + + + + + 7.3.2 Create Oracle Endpoints + + + + Account Lookup Service + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Account Lookup Service Admin API + + + + + Account Lookup Service Admin API + + + + + POST Oracle Handler + + + + + POST Oracle Handler + + + + + ALS Store + + + + + ALS Store + + + + + + + + Get Oracle Endpoint + + + + + 1 + + + Request to Create Oracle Endpoint - + + + POST /oracles + + + + + Message: + + + { + + + "oracleIdType": <PartyIdType>, + + + "endpoint": { + + + "value": <string>, + + + "endpointType": <EndpointType> + + + }, + + + "currency": <Currency>, + + + "isDefault": <boolean> + + + } + + + + + 2 + + + Create Oracle Endpoint + + + + + 3 + + + Build Oracle Endpoint Data Object + + + + + 4 + + + Insert Oracle Endpoint Data Object + + + + + alt + + + [Create Oracle Entry (success)] + + + + + 5 + + + Return success response + + + + + 6 + + + Return success response + + + + + 7 + + + Return + + + HTTP Status: + + + 201 + + + + + alt + + + [Create Oracle Entry (failure)] + + + + + 8 + + + Throw Error + + + + + 9 + + + Throw Error + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 10 + + + Return + + + HTTP Status: + + + 502 + + diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.puml b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.puml new file mode 100644 index 000000000..142eae685 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.puml @@ -0,0 +1,131 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.3 Update Oracle Endpoint + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS Admin Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service Admin API" as ALSADM +control "PUT Oracle Handler" as ORC_HANDLER +database "ALS Store" as DB + +box "Account Lookup Service" #LightYellow +participant ALSADM +participant ORC_HANDLER +participant DB +end box + +' start flow + +activate OPERATOR +group Get Oracle Endpoint + OPERATOR -> ALSADM: Request to Update Oracle Endpoint -\nPUT /oracles/{ID} + note left of ALSADM #yellow + Message: + { + "oracleIdType": , + "endpoint": { + "value": , + "endpointType": + }, + "currency": , + "isDefault": + } + end note + activate ALSADM + + ALSADM -> ORC_HANDLER: Update Oracle Endpoint + + activate ORC_HANDLER + ORC_HANDLER -> DB: Find existing Oracle Endpoint + alt Find existing Oracle Endpoint (success) + activate DB + DB -> ORC_HANDLER: Return Oracle Endpoint Result + deactivate DB + ORC_HANDLER -> ORC_HANDLER: Update Returned Oracle Data Object + ORC_HANDLER -> DB: Update Oracle Data Object + activate DB + alt Update Oracle Entry (success) + DB --> ORC_HANDLER: Return success response + deactivate DB + + ORC_HANDLER -> ALSADM: Return success response + deactivate ORC_HANDLER + ALSADM --> OPERATOR: Return HTTP Status: 204 + + deactivate ALSADM + deactivate OPERATOR + end + + alt Update Oracle Entry (failure) + DB --> ORC_HANDLER: Throw Error + deactivate DB + ORC_HANDLER -> ALSADM: Throw Error + deactivate ORC_HANDLER + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + + ALSADM --> OPERATOR: Return HTTP Status: 502 + + deactivate ALSADM + deactivate OPERATOR + + + end + end + alt Find existing Oracle Endpoint (failure) + DB -> ORC_HANDLER: Returns Empty Object + ORC_HANDLER -> ALSADM: Throw Error + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + ALSADM --> OPERATOR: Return HTTP Status: 502 + end +end + +@enduml diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.svg new file mode 100644 index 000000000..98da55c5c --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.svg @@ -0,0 +1,319 @@ + + + + + + + + + + + 7.3.3 Update Oracle Endpoint + + + + Account Lookup Service + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Account Lookup Service Admin API + + + + + Account Lookup Service Admin API + + + + + PUT Oracle Handler + + + + + PUT Oracle Handler + + + + + ALS Store + + + + + ALS Store + + + + + + + + Get Oracle Endpoint + + + + + 1 + + + Request to Update Oracle Endpoint - + + + PUT /oracles/{ID} + + + + + Message: + + + { + + + "oracleIdType": <PartyIdType>, + + + "endpoint": { + + + "value": <string>, + + + "endpointType": <EndpointType> + + + }, + + + "currency": <Currency>, + + + "isDefault": <boolean> + + + } + + + + + 2 + + + Update Oracle Endpoint + + + + + 3 + + + Find existing Oracle Endpoint + + + + + alt + + + [Find existing Oracle Endpoint (success)] + + + + + 4 + + + Return Oracle Endpoint Result + + + + + 5 + + + Update Returned Oracle Data Object + + + + + 6 + + + Update Oracle Data Object + + + + + alt + + + [Update Oracle Entry (success)] + + + + + 7 + + + Return success response + + + + + 8 + + + Return success response + + + + + 9 + + + Return + + + HTTP Status: + + + 204 + + + + + alt + + + [Update Oracle Entry (failure)] + + + + + 10 + + + Throw Error + + + + + 11 + + + Throw Error + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 12 + + + Return + + + HTTP Status: + + + 502 + + + + + alt + + + [Find existing Oracle Endpoint (failure)] + + + + + 13 + + + Returns Empty Object + + + + + 14 + + + Throw Error + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 15 + + + Return + + + HTTP Status: + + + 502 + + diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.puml b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.puml new file mode 100644 index 000000000..3095e7bad --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.puml @@ -0,0 +1,104 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.0 Delete Endpoint Cache + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS API Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service API" as ALSAPI +control "Delete Endpoint Cache Handler" as DEL_HANDLER +database "Cache" as Cache + +box "Account Lookup Service" #LightYellow +participant ALSAPI +participant DEL_HANDLER +participant Cache +end box + +' start flow + +activate OPERATOR +group Delete Endpoint Cache + OPERATOR -> ALSAPI: Request to DELETE Endpoint Cache - DELETE /endpointcache + activate ALSAPI + activate ALSAPI + + ALSAPI -> DEL_HANDLER: Delete Cache + activate DEL_HANDLER + DEL_HANDLER -> Cache: Stop Cache + activate Cache + + + alt Stop Cache Status (success) + Cache --> DEL_HANDLER: Return status + deactivate Cache + + DEL_HANDLER -> Cache: Initialize Cache + activate Cache + Cache -> DEL_HANDLER: Return Status + deactivate Cache + DEL_HANDLER -> ALSAPI: Return Status + deactivate DEL_HANDLER + ALSAPI --> OPERATOR: Return HTTP Status: 202 + + deactivate ALSAPI + deactivate OPERATOR + end + + alt Validate Status (service failure) + Cache --> DEL_HANDLER: Throw Error + deactivate Cache + DEL_HANDLER -> ALSAPI: Throw Error + deactivate DEL_HANDLER + note left of ALSAPI #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + + ALSAPI --> OPERATOR: Return HTTP Status: 502 + + deactivate ALSAPI + deactivate OPERATOR + + + end +end + +@enduml diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.svg new file mode 100644 index 000000000..ab60d1d1b --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.svg @@ -0,0 +1,208 @@ + + + + + + + + + + + 7.3.0 Delete Endpoint Cache + + + + Account Lookup Service + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Account Lookup Service API + + + + + Account Lookup Service API + + + + + Delete Endpoint Cache Handler + + + + + Delete Endpoint Cache Handler + + + + + Cache + + + + + Cache + + + + + + + + + Delete Endpoint Cache + + + + + 1 + + + Request to DELETE Endpoint Cache - DELETE /endpointcache + + + + + 2 + + + Delete Cache + + + + + 3 + + + Stop Cache + + + + + alt + + + [Stop Cache Status (success)] + + + + + 4 + + + Return status + + + + + 5 + + + Initialize Cache + + + + + 6 + + + Return Status + + + + + 7 + + + Return Status + + + + + 8 + + + Return + + + HTTP Status: + + + 202 + + + + + alt + + + [Validate Status (service failure)] + + + + + 9 + + + Throw Error + + + + + 10 + + + Throw Error + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 11 + + + Return + + + HTTP Status: + + + 502 + + diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.plantuml b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.plantuml new file mode 100644 index 000000000..978a1e303 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.plantuml @@ -0,0 +1,213 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.1.2. Delete Participant Details + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +actor "Payer FSP" as PAYER_FSP +actor "Payee FSP" as PAYEE_FSP +boundary "Account Lookup\nService (ALS)" as ALS_API +control "ALS Participant\nHandler" as ALS_PARTICIPANT_HANDLER +entity "ALS CentralService\nEndpoint DAO" as ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +entity "ALS CentralService\nParticipant DAO" as ALS_CENTRALSERVICE_PARTICIPANT_DAO +'entity "ALS Participant Oracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +entity "ALS Parties\nFSP DAO" as ALS_PARTIES_FSP_DAO +entity "ALS Participant Endpoint\nOracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +database "ALS Database" as ALS_DB +boundary "Oracle Service API" as ORACLE_API +boundary "Central Service API" as CENTRALSERVICE_API + +box "Financial Service Provider" #LightGrey +participant PAYER_FSP +end box + +box "Account Lookup Service" #LightYellow +participant ALS_API +participant ALS_PARTICIPANT_HANDLER +participant ALS_PARTICIPANT_ORACLE_DAO +participant ALS_DB +participant ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +participant ALS_CENTRALSERVICE_PARTICIPANT_DAO +participant ALS_PARTIES_FSP_DAO +end box + +box "Central Services" #LightGreen +participant CENTRALSERVICE_API +end box + +box "ALS Oracle Service/Adapter" #LightBlue +participant ORACLE_API +end box + +box "Financial Service Provider" #LightGrey +participant PAYEE_FSP +end box + +' START OF FLOW + +group Get Party Details + PAYER_FSP ->> ALS_API: Request to delete Participant details\nDEL - /participants/{TYPE}/{ID}?currency={CURRENCY}\nResponse code: 202\nError code: 200x, 300x, 310x, 320x + activate ALS_API + note left ALS_API #lightgray + Validate request against + Mojaloop Interface Specification. + Error code: 300x, 310x + end note + + ALS_API -> ALS_PARTICIPANT_HANDLER: Request to delete Participant details + + alt oracleEndpoint match found & parties information retrieved + activate ALS_PARTICIPANT_HANDLER + '********************* Retrieve Oracle Routing Information - START ************************ + ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Oracle Routing Config\nError code: 200x, 310x, 320x + ref over ALS_PARTICIPANT_HANDLER, ALS_DB + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Oracle Routing Config Sequence]] + ||| + end ref + '********************* Retrieve Oracle Routing Information - END ************************ + ||| + '********************* Retrieve Switch Routing Information - START ************************ +' ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Switch Routing Config\nError code: 200x, 310x, 320x +' ref over ALS_PARTICIPANT_HANDLER, ALS_DB +' GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Switch Routing Config Sequence]] +' ||| +' end ref + '********************* Retrieve Switch Routing Information - END ************************ + + ||| + + '********************* Validate FSPIOP-Source Participant - START ************************ + group Validate FSPIOP-Source Participant + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Request FSPIOP-Source participant information\nError code: 200x + activate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_CENTRALSERVICE_PARTICIPANT_DAO -> CENTRALSERVICE_API: GET - /participants/{FSPIOP-Source}\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Return FSPIOP-Source participant information + deactivate CENTRALSERVICE_API + + ALS_CENTRALSERVICE_PARTICIPANT_DAO --> ALS_PARTICIPANT_HANDLER: Return FSPIOP-Source participant information + + deactivate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate FSPIOP-Source participant\nError code: 320x + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate that PARTICIPANT.fspId == FSPIOP-Source\nError code: 3100 + end group + '********************* Validate Participant - END ************************ + + ||| + + '********************* Request Oracle Participant Information - START ************************ + + ALS_PARTICIPANT_HANDLER <-> ORACLE_API: Get Participant Information for PayerFSP\nError code: 200x, 310x, 320x + ref over ALS_PARTICIPANT_HANDLER, ORACLE_API + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Request Participant Information from Oracle Sequence]] + ||| + end ref + + '********************* Request Oracle Participant Information - END ************************ + + ||| + + '********************* Validate Participant Ownership - START ************************ + ' Reference section 6.2.2.4 - Note: The ALS should verify that it is the Party’s current FSP that is deleting the FSP information. Is this adequate? + group Validate Participant Ownership + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate that PARTICIPANT.fspId matches Participant Information retrieved from Oracle.\nError code: 3100 + end group + '********************* Validate Participant - END ************************ + + ||| + + '********************* Delete Oracle Participant Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_ORACLE_DAO: Request to delete Participant's FSP details DEL - /participants/{TYPE}/{ID}?currency={CURRENCY}\nError code: 200x, 310x, 320x + activate ALS_PARTICIPANT_ORACLE_DAO + ALS_PARTICIPANT_ORACLE_DAO -> ORACLE_API: Request to delete Participant's FSP details DEL - /participants/{TYPE}/{ID}?currency={CURRENCY}\nResponse code: 200 \nError code: 200x, 310x, 320x + activate ORACLE_API + ORACLE_API --> ALS_PARTICIPANT_ORACLE_DAO: Return result + deactivate ORACLE_API + ALS_PARTICIPANT_ORACLE_DAO --> ALS_PARTICIPANT_HANDLER: Return result + deactivate ALS_PARTICIPANT_ORACLE_DAO + + '********************* Delete Oracle Participant Information - END ************************ + ||| + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP Participant Callback Endpoint\nError code: 200x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Return delete request result + ALS_API ->> PAYER_FSP: Callback indiciating success:\nPUT - /participants/{TYPE}/{ID}?currency={CURRENCY} + + else Validation failure or Oracle was unable process delete request + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{TYPE}/{ID}/error + + else Empty list of switchEndpoint results returned + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Handle error\nError code: 200x + hnote right ALS_PARTICIPANT_HANDLER #red + Error Handling Framework + end note + end alt + + deactivate ALS_PARTICIPANT_HANDLER +end +@enduml diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.svg new file mode 100644 index 000000000..4612fee5f --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.svg @@ -0,0 +1,632 @@ + + + + + + + + + + + 7.1.2. Delete Participant Details + + + + Financial Service Provider + + + + Account Lookup Service + + + + Central Services + + + + ALS Oracle Service/Adapter + + + + Financial Service Provider + + + + + + + + + Payer FSP + + + + + Payer FSP + + + + + Account Lookup + + + Service (ALS) + + + + + Account Lookup + + + Service (ALS) + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Handler + + + + + ALS Participant Endpoint + + + Oracle DAO + + + + + ALS Participant Endpoint + + + Oracle DAO + + + + + ALS Database + + + + + ALS Database + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Participant DAO + + + + + ALS CentralService + + + Participant DAO + + + + + ALS Parties + + + FSP DAO + + + + + ALS Parties + + + FSP DAO + + + + + Central Service API + + + + + Central Service API + + + + + Oracle Service API + + + + + Oracle Service API + + + + + Payee FSP + + + + + Payee FSP + + + + + + + + Get Party Details + + + + 1 + + + Request to delete Participant details + + + DEL - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + Response code: + + + 202 + + + Error code: + + + 200x, 300x, 310x, 320x + + + + + Validate request against + + + Mojaloop Interface Specification. + + + Error code: + + + 300x, 310x + + + + + 2 + + + Request to delete Participant details + + + + + alt + + + [oracleEndpoint match found & parties information retrieved] + + + + + 3 + + + Get Oracle Routing Config + + + Error code: + + + 200x, 310x, 320x + + + + + ref + + + GET Participants - + + + + Get Oracle Routing Config Sequence + + + + + + + Validate FSPIOP-Source Participant + + + + + 4 + + + Request FSPIOP-Source participant information + + + Error code: + + + 200x + + + + + 5 + + + GET - /participants/{FSPIOP-Source} + + + Error code: + + + 200x, 310x, 320x + + + + + 6 + + + Return FSPIOP-Source participant information + + + + + 7 + + + Return FSPIOP-Source participant information + + + + + 8 + + + Validate FSPIOP-Source participant + + + Error code: + + + 320x + + + + + 9 + + + Validate that PARTICIPANT.fspId == FSPIOP-Source + + + Error code: + + + 3100 + + + + + 10 + + + Get Participant Information for PayerFSP + + + Error code: + + + 200x, 310x, 320x + + + + + ref + + + GET Participants - + + + + Request Participant Information from Oracle Sequence + + + + + + + Validate Participant Ownership + + + + + 11 + + + Validate that PARTICIPANT.fspId matches Participant Information retrieved from Oracle. + + + Error code: + + + 3100 + + + + + 12 + + + Request to delete Participant's FSP details DEL - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + Error code: + + + 200x, 310x, 320x + + + + + 13 + + + Request to delete Participant's FSP details DEL - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 14 + + + Return result + + + + + 15 + + + Return result + + + + + 16 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + Error code: + + + 200x + + + + + 17 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Error code: + + + 200x, 310x, 320x + + + + + 18 + + + List of PayerFSP Participant Callback Endpoints + + + + + 19 + + + List of PayerFSP Participant Callback Endpoints + + + + + 20 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + + + + 21 + + + Return delete request result + + + + 22 + + + Callback indiciating success: + + + PUT - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + + [Validation failure or Oracle was unable process delete request] + + + + + 23 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 24 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 25 + + + List of PayerFSP Participant Callback Endpoints + + + + + 26 + + + List of PayerFSP Participant Callback Endpoints + + + + + 27 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + + + + 28 + + + Handle error + + + Error code: + + + 200x, 310x, 320x + + + + 29 + + + Callback: PUT - /participants/{TYPE}/{ID}/error + + + + [Empty list of switchEndpoint results returned] + + + + + 30 + + + Handle error + + + Error code: + + + 200x + + + + Error Handling Framework + + diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.plantuml b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.plantuml new file mode 100644 index 000000000..09be5f1df --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.plantuml @@ -0,0 +1,180 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.1.0. Get Participant Details + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +actor "Payer FSP" as PAYER_FSP +boundary "Account Lookup\nService (ALS)" as ALS_API +control "ALS Participant\nHandler" as ALS_PARTICIPANT_HANDLER +entity "ALS Endpoint Type\nConfig DAO" as ALS_TYPE_ENDPOINT_CONFIG_DAO +entity "ALS CentralService\nEndpoint DAO" as ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +entity "ALS Participant\nOracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +entity "ALS Participant Endpoint\nOracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +database "ALS Database" as ALS_DB +boundary "Oracle Service API" as ORACLE_API +boundary "Central Service API" as CENTRALSERVICE_API + +box "Financial Service Provider" #LightGrey +participant PAYER_FSP +end box + +box "Account Lookup Service" #LightYellow +participant ALS_API +participant ALS_PARTICIPANT_HANDLER +participant ALS_TYPE_ENDPOINT_CONFIG_DAO +participant ALS_PARTICIPANT_ORACLE_DAO +participant ALS_DB +participant ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +end box + +box "Central Services" #LightGreen +participant CENTRALSERVICE_API +end box + +box "ALS Oracle Service/Adapter" #LightBlue +participant ORACLE_API +end box + +' START OF FLOW + +group Get Participant's FSP Details + + + PAYER_FSP ->> ALS_API: Request to get participant's FSP details \nGET - /participants/{TYPE}/{ID}?currency={CURRENCY}\nResponse code: 202 \nError code: 200x, 300x, 310x, 320x + activate ALS_API + note left ALS_API #lightgray + Validate request against + Mojaloop Interface Specification. + Error code: 300x, 310x + end note + + ALS_API -> ALS_PARTICIPANT_HANDLER: Request to get participant's FSP details + + alt oracleEndpoint match found + group #lightskyblue IMPLEMENTATION: Get Oracle Routing Config Sequence [CACHED] + activate ALS_PARTICIPANT_HANDLER + ALS_PARTICIPANT_HANDLER -> ALS_TYPE_ENDPOINT_CONFIG_DAO: Fetch Oracle Routing information based on\n{TYPE} and {CURRENCY} if provided\nError code: 200x + activate ALS_TYPE_ENDPOINT_CONFIG_DAO + ALS_TYPE_ENDPOINT_CONFIG_DAO -> ALS_DB: Retrieve oracleEndpoint\nError code: 200x + activate ALS_DB + hnote over ALS_DB #lightyellow + oracleEndpoint + endpointType + partyIdType + currency (optional) + end note + ALS_DB --> ALS_TYPE_ENDPOINT_CONFIG_DAO: Return oracleEndpoint result set + deactivate ALS_DB + ALS_TYPE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of **oracleEndpoint** for the Participant + deactivate ALS_TYPE_ENDPOINT_CONFIG_DAO + opt #lightskyblue oracleEndpoint IS NULL + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Error code: 3200 + end + end group + + group #lightskyblue IMPLEMENTATION: Request Participant Information from Oracle Sequence + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_ORACLE_DAO: Request to get participant's FSP details \nGET - /participants/{TYPE}/{ID}?currency={CURRENCY}\nError code: 200x, 310x, 320x + activate ALS_PARTICIPANT_ORACLE_DAO + ALS_PARTICIPANT_ORACLE_DAO -> ORACLE_API: Request to get participant's FSP details \nGET - /participants/{TYPE}/{ID}?currency={CURRENCY}\nResponse code: 200 \nError code: 200x, 310x, 320x + activate ORACLE_API + ORACLE_API --> ALS_PARTICIPANT_ORACLE_DAO: Return list of Participant information + deactivate ORACLE_API + ALS_PARTICIPANT_ORACLE_DAO --> ALS_PARTICIPANT_HANDLER: Return list of Participant information + deactivate ALS_PARTICIPANT_ORACLE_DAO + end group + +' group #lightskyblue IMPLEMENTATION: Get Switch Routing Config Sequence [CACHED] +' note right of ALS_PARTICIPANT_HANDLER #lightgray +' **REFERENCE**: Get Oracle Routing Config Sequence: oracleEndpoint +' end note +' alt #lightskyblue oracleEndpoint IS NOT NULL +' ALS_PARTICIPANT_HANDLER -> ALS_TYPE_ENDPOINT_CONFIG_DAO: Fetch Switch Routing information\nError code: 200x +' ALS_TYPE_ENDPOINT_CONFIG_DAO -> ALS_DB: Retrieve switchEndpoint\nError code: 200x +' activate ALS_DB +' hnote over ALS_DB #lightyellow +' switchEndpoint +' endpointType +' end note +' ALS_DB -> ALS_TYPE_ENDPOINT_CONFIG_DAO: Return switchEndpoint result set +' deactivate ALS_DB +' ALS_TYPE_ENDPOINT_CONFIG_DAO -> ALS_PARTICIPANT_HANDLER: Return **switchEndpoint** +' else +' ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Error code: 2000 +' end alt +' end group + + '********************* Get PayerFSP Participant End-point Information - START ************************ + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Return list of Participant information + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{TYPE}/{ID}?currency={CURRENCY} + else oracleEndpoint IS NULL OR error occurred + + '********************* Get PayerFSP Participant End-point Information - START ************************ + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints. \nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{TYPE}/{ID}/error + else switchEndpoint IS NULL + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Handle error\nError code: 200x + hnote right ALS_PARTICIPANT_HANDLER #red + Error Handling Framework + end note + end alt + deactivate ALS_API + + deactivate ALS_PARTICIPANT_HANDLER + +end +@enduml diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.svg new file mode 100644 index 000000000..74687dae8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.svg @@ -0,0 +1,558 @@ + + + + + + + + + + + 7.1.0. Get Participant Details + + + + Financial Service Provider + + + + Account Lookup Service + + + + Central Services + + + + ALS Oracle Service/Adapter + + + + + + + + + + Payer FSP + + + + + Payer FSP + + + + + Account Lookup + + + Service (ALS) + + + + + Account Lookup + + + Service (ALS) + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Handler + + + + + ALS Endpoint Type + + + Config DAO + + + + + ALS Endpoint Type + + + Config DAO + + + + + ALS Participant + + + Oracle DAO + + + + + ALS Participant + + + Oracle DAO + + + + + ALS Database + + + + + ALS Database + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Endpoint DAO + + + + + Central Service API + + + + + Central Service API + + + + + Oracle Service API + + + + + Oracle Service API + + + + + + + + Get Participant's FSP Details + + + + 1 + + + Request to get participant's FSP details + + + GET - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + Response code: + + + 202 + + + Error code: + + + 200x, 300x, 310x, 320x + + + + + Validate request against + + + Mojaloop Interface Specification. + + + Error code: + + + 300x, 310x + + + + + 2 + + + Request to get participant's FSP details + + + + + alt + + + [oracleEndpoint match found] + + + + + IMPLEMENTATION: Get Oracle Routing Config Sequence + + + [CACHED] + + + + + 3 + + + Fetch Oracle Routing information based on + + + {TYPE} and {CURRENCY} if provided + + + Error code: + + + 200x + + + + + 4 + + + Retrieve oracleEndpoint + + + Error code: + + + 200x + + + + oracleEndpoint + + + endpointType + + + partyIdType + + + currency (optional) + + + + + 5 + + + Return oracleEndpoint result set + + + + + 6 + + + List of + + + oracleEndpoint + + + for the Participant + + + + + opt + + + [oracleEndpoint IS NULL] + + + + + 7 + + + Error code: + + + 3200 + + + + + IMPLEMENTATION: Request Participant Information from Oracle Sequence + + + + + 8 + + + Request to get participant's FSP details + + + GET - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + Error code: + + + 200x, 310x, 320x + + + + + 9 + + + Request to get participant's FSP details + + + GET - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 10 + + + Return list of Participant information + + + + + 11 + + + Return list of Participant information + + + + + 12 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 13 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 14 + + + List of PayerFSP Participant Callback Endpoints + + + + + 15 + + + List of PayerFSP Participant Callback Endpoints + + + + + 16 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + + + + 17 + + + Return list of Participant information + + + + 18 + + + Callback: PUT - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + + [oracleEndpoint IS NULL OR error occurred] + + + + + 19 + + + Retrieve the Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 20 + + + Retrieve the Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints. + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 21 + + + List of Participant Callback Endpoints + + + + + 22 + + + List of Participant Callback Endpoints + + + + + 23 + + + Match Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + + + + 24 + + + Handle error + + + Error code: + + + 200x, 310x, 320x + + + + 25 + + + Callback: PUT - /participants/{TYPE}/{ID}/error + + + + [switchEndpoint IS NULL] + + + + + 26 + + + Handle error + + + Error code: + + + 200x + + + + Error Handling Framework + + diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.plantuml b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.plantuml new file mode 100644 index 000000000..776445cc5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.plantuml @@ -0,0 +1,215 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.2.0. Get Party Details + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +actor "Payer FSP" as PAYER_FSP +actor "Payee FSP" as PAYEE_FSP +boundary "Account Lookup\nService (ALS)" as ALS_API +control "ALS Participant\nHandler" as ALS_PARTICIPANT_HANDLER +entity "ALS CentralService\nEndpoint DAO" as ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +entity "ALS CentralService\nParticipant DAO" as ALS_CENTRALSERVICE_PARTICIPANT_DAO +'entity "ALS Participant Oracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +entity "ALS Parties\nFSP DAO" as ALS_PARTIES_FSP_DAO +database "ALS Database" as ALS_DB +boundary "Oracle Service API" as ORACLE_API +boundary "Central Service API" as CENTRALSERVICE_API + +box "Financial Service Provider" #LightGrey +participant PAYER_FSP +end box + +box "Account Lookup Service" #LightYellow +participant ALS_API +participant ALS_PARTICIPANT_HANDLER +participant ALS_DB +participant ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +participant ALS_CENTRALSERVICE_PARTICIPANT_DAO +participant ALS_PARTIES_FSP_DAO +end box + +box "Central Services" #LightGreen +participant CENTRALSERVICE_API +end box + +box "ALS Oracle Service/Adapter" #LightBlue +participant ORACLE_API +end box + +box "Financial Service Provider" #LightGrey +participant PAYEE_FSP +end box + +' START OF FLOW + +group Get Party Details + PAYER_FSP ->> ALS_API: Request to get parties's FSP details\nGET - /parties/{TYPE}/{ID}?currency={CURRENCY}\nResponse code: 202\nError code: 200x, 300x, 310x, 320x + activate ALS_API + note left ALS_API #lightgray + Validate request against + Mojaloop Interface Specification. + Error code: 300x, 310x + end note + + ALS_API -> ALS_PARTICIPANT_HANDLER: Request to get parties's FSP details + + alt oracleEndpoint match found & parties information retrieved + activate ALS_PARTICIPANT_HANDLER + '********************* Retrieve Oracle Routing Information - START ************************ + ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Oracle Routing Config\nError code: 200x, 310x, 320x + ref over ALS_PARTICIPANT_HANDLER, ALS_DB + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Oracle Routing Config Sequence]] + ||| + end ref + '********************* Retrieve Oracle Routing Information - END ************************ + ||| + '********************* Retrieve Switch Routing Information - START ************************ +' ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Switch Routing Config\nError code: 200x, 310x, 320x +' ref over ALS_PARTICIPANT_HANDLER, ALS_DB +' GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Switch Routing Config Sequence]] +' ||| +' end ref + '********************* Retrieve Switch Routing Information - END ************************ + ||| + group Validate FSPIOP-Source Participant + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Request FSPIOP-Source participant information\nError code: 200x + activate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_CENTRALSERVICE_PARTICIPANT_DAO -> CENTRALSERVICE_API: GET - /participants/{FSPIOP-Source}\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Return FSPIOP-Source participant information + deactivate CENTRALSERVICE_API + + ALS_CENTRALSERVICE_PARTICIPANT_DAO --> ALS_PARTICIPANT_HANDLER: Return FSPIOP-Source participant information + + deactivate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate FSPIOP-Source participant\nError code: 320x + end group + ||| + + '********************* Request Oracle Participant Information - START ************************ + + ALS_PARTICIPANT_HANDLER <-> ORACLE_API: Get Participant Information for PayeeFSP\nError code: 200x, 310x, 320x + ref over ALS_PARTICIPANT_HANDLER, ORACLE_API + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Request Participant Information from Oracle Sequence]] + ||| + end ref + + '********************* Request Oracle Participant Information - END ************************ + ||| + '********************* Request Parties Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_PARTIES_FSP_DAO: Request Parties information from FSP.\nError code: 200x + + activate ALS_PARTIES_FSP_DAO + ALS_PARTIES_FSP_DAO ->> PAYEE_FSP: Parties Callback to Destination:\nGET - /parties/{TYPE}/{ID}?currency={CURRENCY}\nResponse code: 202\nError code: 200x, 310x, 320x + deactivate ALS_PARTIES_FSP_DAO + activate PAYEE_FSP + + PAYEE_FSP ->> ALS_API: Callback with Participant Information:\nPUT - /parties/{TYPE}/{ID}?currency={CURRENCY}\nError code: 200x, 300x, 310x, 320x + deactivate PAYEE_FSP + + ALS_API -> ALS_API: Validate request against\nMojaloop Interface Specification\nError code: 300x, 310x + ALS_API -> ALS_PARTICIPANT_HANDLER: Process Participant Callback Information for PUT + + '********************* Request Parties Information - END ************************ + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP Participant Callback Endpoint\nError code: 200x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTIES_PUT + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Return Participant Information to PayerFSP + ALS_API ->> PAYER_FSP: Callback with Parties Information:\nPUT - /parties/{TYPE}/{ID}?currency={CURRENCY} + + else Empty list of End-Points returned for either (PayeeFSP or Oracle) config information or Error occurred for PayerFSP + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{TYPE}/{ID}/error + else Empty list of End-Points returned for PayerFSP config information or Error occurred for PayeeFSP + + '********************* Get PayeeFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayeeFSP Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayeeFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayeeFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayeeFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayeeFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYEE_FSP: Callback: PUT - /participants/{TYPE}/{ID}/error + else Empty list of switchEndpoint results returned + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Handle error\nError code: 200x + hnote right ALS_PARTICIPANT_HANDLER #red + Error Handling Framework + end note + end alt + + deactivate ALS_PARTICIPANT_HANDLER +end +@enduml diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.svg new file mode 100644 index 000000000..7b3342d7b --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.svg @@ -0,0 +1,699 @@ + + + + + + + + + + + 7.2.0. Get Party Details + + + + Financial Service Provider + + + + Account Lookup Service + + + + Central Services + + + + ALS Oracle Service/Adapter + + + + Financial Service Provider + + + + + + + + + Payer FSP + + + + + Payer FSP + + + + + Account Lookup + + + Service (ALS) + + + + + Account Lookup + + + Service (ALS) + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Handler + + + + + ALS Database + + + + + ALS Database + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Participant DAO + + + + + ALS CentralService + + + Participant DAO + + + + + ALS Parties + + + FSP DAO + + + + + ALS Parties + + + FSP DAO + + + + + Central Service API + + + + + Central Service API + + + + + Oracle Service API + + + + + Oracle Service API + + + + + Payee FSP + + + + + Payee FSP + + + + + + + + Get Party Details + + + + 1 + + + Request to get parties's FSP details + + + GET - /parties/{TYPE}/{ID}?currency={CURRENCY} + + + Response code: + + + 202 + + + Error code: + + + 200x, 300x, 310x, 320x + + + + + Validate request against + + + Mojaloop Interface Specification. + + + Error code: + + + 300x, 310x + + + + + 2 + + + Request to get parties's FSP details + + + + + alt + + + [oracleEndpoint match found & parties information retrieved] + + + + + 3 + + + Get Oracle Routing Config + + + Error code: + + + 200x, 310x, 320x + + + + + ref + + + GET Participants - + + + + Get Oracle Routing Config Sequence + + + + + + + Validate FSPIOP-Source Participant + + + + + 4 + + + Request FSPIOP-Source participant information + + + Error code: + + + 200x + + + + + 5 + + + GET - /participants/{FSPIOP-Source} + + + Error code: + + + 200x, 310x, 320x + + + + + 6 + + + Return FSPIOP-Source participant information + + + + + 7 + + + Return FSPIOP-Source participant information + + + + + 8 + + + Validate FSPIOP-Source participant + + + Error code: + + + 320x + + + + + 9 + + + Get Participant Information for PayeeFSP + + + Error code: + + + 200x, 310x, 320x + + + + + ref + + + GET Participants - + + + + Request Participant Information from Oracle Sequence + + + + + + + 10 + + + Request Parties information from FSP. + + + Error code: + + + 200x + + + + 11 + + + Parties Callback to Destination: + + + GET - /parties/{TYPE}/{ID}?currency={CURRENCY} + + + Response code: + + + 202 + + + Error code: + + + 200x, 310x, 320x + + + + 12 + + + Callback with Participant Information: + + + PUT - /parties/{TYPE}/{ID}?currency={CURRENCY} + + + Error code: + + + 200x, 300x, 310x, 320x + + + + + 13 + + + Validate request against + + + Mojaloop Interface Specification + + + Error code: + + + 300x, 310x + + + + + 14 + + + Process Participant Callback Information for PUT + + + + + 15 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + Error code: + + + 200x + + + + + 16 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Error code: + + + 200x, 310x, 320x + + + + + 17 + + + List of PayerFSP Participant Callback Endpoints + + + + + 18 + + + List of PayerFSP Participant Callback Endpoints + + + + + 19 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTIES_PUT + + + + + 20 + + + Return Participant Information to PayerFSP + + + + 21 + + + Callback with Parties Information: + + + PUT - /parties/{TYPE}/{ID}?currency={CURRENCY} + + + + [Empty list of End-Points returned for either (PayeeFSP or Oracle) config information or Error occurred for PayerFSP] + + + + + 22 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 23 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 24 + + + List of PayerFSP Participant Callback Endpoints + + + + + 25 + + + List of PayerFSP Participant Callback Endpoints + + + + + 26 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR + + + + + 27 + + + Handle error + + + Error code: + + + 200x, 310x, 320x + + + + 28 + + + Callback: PUT - /participants/{TYPE}/{ID}/error + + + + [Empty list of End-Points returned for PayerFSP config information or Error occurred for PayeeFSP] + + + + + 29 + + + Retrieve the PayeeFSP Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 30 + + + Retrieve the PayeeFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 31 + + + List of PayeeFSP Participant Callback Endpoints + + + + + 32 + + + List of PayeeFSP Participant Callback Endpoints + + + + + 33 + + + Match PayeeFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR + + + + + 34 + + + Handle error + + + Error code: + + + 200x, 310x, 320x + + + + 35 + + + Callback: PUT - /participants/{TYPE}/{ID}/error + + + + [Empty list of switchEndpoint results returned] + + + + + 36 + + + Handle error + + + Error code: + + + 200x + + + + Error Handling Framework + + diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.plantuml b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.plantuml new file mode 100644 index 000000000..7769e3a8d --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.plantuml @@ -0,0 +1,213 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.1.3 Post Participant Details by Type and ID + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +actor "Payer FSP" as PAYER_FSP +boundary "Account Lookup\nService (ALS)" as ALS_API +control "ALS Participant\nHandler" as ALS_PARTICIPANT_HANDLER +entity "ALS CentralService\nEndpoint DAO" as ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +entity "ALS CentralService\nParticipant DAO" as ALS_CENTRALSERVICE_PARTICIPANT_DAO +entity "ALS Participant\nOracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +database "ALS Database" as ALS_DB +boundary "Oracle Service API" as ORACLE_API +boundary "Central Service API" as CENTRALSERVICE_API + +box "Financial Service Provider" #LightGrey +participant PAYER_FSP +end box + +box "Account Lookup Service" #LightYellow +participant ALS_API +participant ALS_PARTICIPANT_HANDLER +participant ALS_PARTICIPANT_ORACLE_DAO +participant ALS_DB +participant ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +participant ALS_CENTRALSERVICE_PARTICIPANT_DAO +end box + +box "Central Services" #LightGreen +participant CENTRALSERVICE_API +end box + +box "ALS Oracle Service/Adapter" #LightBlue +participant ORACLE_API +end box + +' START OF FLOW + +group Post Participant's FSP Details + note right of PAYER_FSP #yellow + Headers - postParticipantsByTypeIDHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - postParticipantsByTypeIDMessage: + { + "fspId": "string" + } + end note + PAYER_FSP ->> ALS_API: Request to add participant's FSP details\nPOST - /participants/{Type}/{ID}\nResponse code: 202 \nError code: 200x, 300x, 310x, 320x + + activate ALS_API + note left ALS_API #lightgray + Validate request against + Mojaloop Interface Specification. + Error code: 300x, 310x + end note + + ALS_API -> ALS_PARTICIPANT_HANDLER: Process create participant's FSP details + deactivate ALS_API + activate ALS_PARTICIPANT_HANDLER + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate that PARTICIPANT.fspId == FSPIOP-Source\nError code: 3100 + + '********************* Sort into Participant buckets based on {TYPE} - END ************************ + + alt Validation passed + + + '********************* Fetch Oracle Routing Information - START ************************ + + '********************* Retrieve Oracle Routing Information - START ************************ + + ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Oracle Routing Config based on Type (and optional Currency)\nError code: 300x, 310x + ref over ALS_PARTICIPANT_HANDLER, ALS_DB + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Oracle Routing Config Sequence]] + ||| + end ref + + '********************* Retrieve Oracle Routing Information - END ************************ + + ||| + +' '********************* Fetch Oracle Routing Information - END ************************ +' +' '********************* Retrieve Switch Routing Information - START ************************ +' +' ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Switch Routing Config\nError code: 300x, 310x +' ref over ALS_PARTICIPANT_HANDLER, ALS_DB +' ||| +' GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Switch Routing Config Sequence]] +' ||| +' end ref +' +' '********************* Retrieve Switch Routing Information - END ************************ +' ||| + + '********************* Validate Participant - START ************************ + group Validate Participant's FSP + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Request participant (PARTICIPANT.fspId) information for {Type}\nError code: 200x + activate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_CENTRALSERVICE_PARTICIPANT_DAO -> CENTRALSERVICE_API: GET - /participants/{PARTICIPANT.fspId}\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Return participant information + deactivate CENTRALSERVICE_API + + ALS_CENTRALSERVICE_PARTICIPANT_DAO --> ALS_PARTICIPANT_HANDLER: Return participant information + + deactivate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate participant\nError code: 320x + end group + '********************* Validate Participant - END ************************ + + '********************* Create Participant Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_ORACLE_DAO: Create participant's FSP details\nPOST - /participants\nError code: 200x, 310x, 320x + activate ALS_PARTICIPANT_ORACLE_DAO + ALS_PARTICIPANT_ORACLE_DAO -> ORACLE_API: Create participant's FSP details\nPOST - /participants\nResponse code: 204 \nError code: 200x, 310x, 320x + activate ORACLE_API + + ORACLE_API --> ALS_PARTICIPANT_ORACLE_DAO: Return result of Participant Create request + deactivate ORACLE_API + + ALS_PARTICIPANT_ORACLE_DAO --> ALS_PARTICIPANT_HANDLER: Return result of Participant Create request + deactivate ALS_PARTICIPANT_ORACLE_DAO + + '********************* Create Participant Information - END ************************ + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Return list of Participant information from ParticipantResult + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{Type}/{ID} + + else Validation failure + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{Type}/{ID}/error + end alt + + + deactivate ALS_PARTICIPANT_HANDLER +end +@enduml diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.svg new file mode 100644 index 000000000..07a5a256d --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.svg @@ -0,0 +1,598 @@ + + + + + + + + + + + 7.1.3 Post Participant Details by Type and ID + + + + Financial Service Provider + + + + Account Lookup Service + + + + Central Services + + + + ALS Oracle Service/Adapter + + + + + + + + + Payer FSP + + + + + Payer FSP + + + + + Account Lookup + + + Service (ALS) + + + + + Account Lookup + + + Service (ALS) + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Oracle DAO + + + + + ALS Participant + + + Oracle DAO + + + + + ALS Database + + + + + ALS Database + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Participant DAO + + + + + ALS CentralService + + + Participant DAO + + + + + Central Service API + + + + + Central Service API + + + + + Oracle Service API + + + + + Oracle Service API + + + + + + + + Post Participant's FSP Details + + + + + Headers - postParticipantsByTypeIDHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - postParticipantsByTypeIDMessage: + + + { + + + "fspId": "string" + + + } + + + + 1 + + + Request to add participant's FSP details + + + POST - /participants/{Type}/{ID} + + + Response code: + + + 202 + + + Error code: + + + 200x, 300x, 310x, 320x + + + + + Validate request against + + + Mojaloop Interface Specification. + + + Error code: + + + 300x, 310x + + + + + 2 + + + Process create participant's FSP details + + + + + 3 + + + Validate that PARTICIPANT.fspId == FSPIOP-Source + + + Error code: + + + 3100 + + + + + alt + + + [Validation passed] + + + + + 4 + + + Get Oracle Routing Config based on Type (and optional Currency) + + + Error code: + + + 300x, 310x + + + + + ref + + + GET Participants - + + + + Get Oracle Routing Config Sequence + + + + + + + Validate Participant's FSP + + + + + 5 + + + Request participant (PARTICIPANT.fspId) information for {Type} + + + Error code: + + + 200x + + + + + 6 + + + GET - /participants/{PARTICIPANT.fspId} + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 7 + + + Return participant information + + + + + 8 + + + Return participant information + + + + + 9 + + + Validate participant + + + Error code: + + + 320x + + + + + 10 + + + Create participant's FSP details + + + POST - /participants + + + Error code: + + + 200x, 310x, 320x + + + + + 11 + + + Create participant's FSP details + + + POST - /participants + + + Response code: + + + 204 + + + Error code: + + + 200x, 310x, 320x + + + + + 12 + + + Return result of Participant Create request + + + + + 13 + + + Return result of Participant Create request + + + + + 14 + + + Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 15 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 16 + + + List of PayerFSP Participant Callback Endpoints + + + + + 17 + + + List of PayerFSP Participant Callback Endpoints + + + + + 18 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + + + + 19 + + + Return list of Participant information from ParticipantResult + + + + 20 + + + Callback: PUT - /participants/{Type}/{ID} + + + + [Validation failure] + + + + + 21 + + + Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 22 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 23 + + + List of PayerFSP Participant Callback Endpoints + + + + + 24 + + + List of PayerFSP Participant Callback Endpoints + + + + + 25 + + + Match Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + + + + 26 + + + Handle error + + + Error code: + + + 200x, 310x, 320x + + + + 27 + + + Callback: PUT - /participants/{Type}/{ID}/error + + diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.plantuml b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.plantuml new file mode 100644 index 000000000..c92838dc9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.plantuml @@ -0,0 +1,238 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.1.1. Post Participant (Batch) Details + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +actor "Payer FSP" as PAYER_FSP +boundary "Account Lookup\nService (ALS)" as ALS_API +control "ALS Participant\nHandler" as ALS_PARTICIPANT_HANDLER +entity "ALS CentralService\nEndpoint DAO" as ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +entity "ALS CentralService\nParticipant DAO" as ALS_CENTRALSERVICE_PARTICIPANT_DAO +entity "ALS Participant\nOracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +database "ALS Database" as ALS_DB +boundary "Oracle Service API" as ORACLE_API +boundary "Central Service API" as CENTRALSERVICE_API + +box "Financial Service Provider" #LightGrey +participant PAYER_FSP +end box + +box "Account Lookup Service" #LightYellow +participant ALS_API +participant ALS_PARTICIPANT_HANDLER +participant ALS_PARTICIPANT_ORACLE_DAO +participant ALS_DB +participant ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +participant ALS_CENTRALSERVICE_PARTICIPANT_DAO +end box + +box "Central Services" #LightGreen +participant CENTRALSERVICE_API +end box + +box "ALS Oracle Service/Adapter" #LightBlue +participant ORACLE_API +end box + +' START OF FLOW + +group Post Participant's FSP Details + note right of PAYER_FSP #yellow + Headers - postParticipantsHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - postParticipantsMessage: + { + "requestId": "string", + "partyList": [ + { + "partyIdType": "string", + "partyIdentifier": "string", + "partySubIdOrType": "string", + "fspId": "string" + } + ], + "currency": "string" + } + end note + PAYER_FSP ->> ALS_API: Request to add participant's FSP details\nPOST - /participants\nResponse code: 202 \nError code: 200x, 300x, 310x, 320x + + activate ALS_API + note left ALS_API #lightgray + Validate request against + Mojaloop Interface Specification. + Error code: 300x, 310x + end note + + ALS_API -> ALS_PARTICIPANT_HANDLER: Process create participant's FSP details + deactivate ALS_API + activate ALS_PARTICIPANT_HANDLER + + '********************* Sort into Participant buckets based on {TYPE} - START ************************ + loop for Participant in ParticipantList + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate that PARTICIPANT.fspId == FSPIOP-Source\nError code: 3100 + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Group Participant lists into a Map (ParticipantMap) based on {TYPE} + + end loop + + '********************* Sort into Participant buckets based on {TYPE} - END ************************ + + alt Validation passed and the ParticipantMap was created successfully + + loop for keys in ParticipantMap -> TypeKey + + '********************* Fetch Oracle Routing Information - START ************************ + + '********************* Retrieve Oracle Routing Information - START ************************ + + ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Oracle Routing Config based on TypeKey (and optional Currency)\nError code: 300x, 310x + ref over ALS_PARTICIPANT_HANDLER, ALS_DB + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Oracle Routing Config Sequence]] + ||| + end ref + + '********************* Retrieve Oracle Routing Information - END ************************ + + ||| + +' '********************* Fetch Oracle Routing Information - END ************************ +' +' '********************* Retrieve Switch Routing Information - START ************************ +' +' ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Switch Routing Config\nError code: 300x, 310x +' ref over ALS_PARTICIPANT_HANDLER, ALS_DB +' ||| +' GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Switch Routing Config Sequence]] +' ||| +' end ref +' +' '********************* Retrieve Switch Routing Information - END ************************ +' ||| + + '********************* Validate Participant - START ************************ + group Validate Participant's FSP + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Request participant (PARTICIPANT.fspId) information for {TypeKey}\nError code: 200x + activate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_CENTRALSERVICE_PARTICIPANT_DAO -> CENTRALSERVICE_API: GET - /participants/{PARTICIPANT.fspId}\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Return participant information + deactivate CENTRALSERVICE_API + + ALS_CENTRALSERVICE_PARTICIPANT_DAO --> ALS_PARTICIPANT_HANDLER: Return participant information + + deactivate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate participant\nError code: 320x + end group + '********************* Validate Participant - END ************************ + + '********************* Create Participant Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_ORACLE_DAO: Create participant's FSP details\nPOST - /participants\nError code: 200x, 310x, 320x + activate ALS_PARTICIPANT_ORACLE_DAO + ALS_PARTICIPANT_ORACLE_DAO -> ORACLE_API: Create participant's FSP details\nPOST - /participants\nResponse code: 204 \nError code: 200x, 310x, 320x + activate ORACLE_API + + ORACLE_API --> ALS_PARTICIPANT_ORACLE_DAO: Return result of Participant Create request + deactivate ORACLE_API + + ALS_PARTICIPANT_ORACLE_DAO --> ALS_PARTICIPANT_HANDLER: Return result of Participant Create request + deactivate ALS_PARTICIPANT_ORACLE_DAO + + '********************* Create Participant Information - END ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Store results in ParticipantResultMap[TypeKey] + + end loop + + loop for keys in ParticipantResultMap -> TypeKey + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Combine ParticipantResultMap[TypeKey] results into ParticipantResult + end loop + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Return list of Participant information from ParticipantResult + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{requestId} + + else Validation failure and/or the ParticipantMap was not created successfully + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{requestId}/error + end alt + + + deactivate ALS_PARTICIPANT_HANDLER +end +@enduml diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.svg b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.svg new file mode 100644 index 000000000..e3883aba0 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.svg @@ -0,0 +1,674 @@ + + + + + + + + + + + 7.1.1. Post Participant (Batch) Details + + + + Financial Service Provider + + + + Account Lookup Service + + + + Central Services + + + + ALS Oracle Service/Adapter + + + + + + + + + + Payer FSP + + + + + Payer FSP + + + + + Account Lookup + + + Service (ALS) + + + + + Account Lookup + + + Service (ALS) + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Oracle DAO + + + + + ALS Participant + + + Oracle DAO + + + + + ALS Database + + + + + ALS Database + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Participant DAO + + + + + ALS CentralService + + + Participant DAO + + + + + Central Service API + + + + + Central Service API + + + + + Oracle Service API + + + + + Oracle Service API + + + + + + + + Post Participant's FSP Details + + + + + Headers - postParticipantsHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - postParticipantsMessage: + + + { + + + "requestId": "string", + + + "partyList": [ + + + { + + + "partyIdType": "string", + + + "partyIdentifier": "string", + + + "partySubIdOrType": "string", + + + "fspId": "string" + + + } + + + ], + + + "currency": "string" + + + } + + + + 1 + + + Request to add participant's FSP details + + + POST - /participants + + + Response code: + + + 202 + + + Error code: + + + 200x, 300x, 310x, 320x + + + + + Validate request against + + + Mojaloop Interface Specification. + + + Error code: + + + 300x, 310x + + + + + 2 + + + Process create participant's FSP details + + + + + loop + + + [for Participant in ParticipantList] + + + + + 3 + + + Validate that PARTICIPANT.fspId == FSPIOP-Source + + + Error code: + + + 3100 + + + + + 4 + + + Group Participant lists into a Map (ParticipantMap) based on {TYPE} + + + + + alt + + + [Validation passed and the ParticipantMap was created successfully] + + + + + loop + + + [for keys in ParticipantMap -> TypeKey] + + + + + 5 + + + Get Oracle Routing Config based on TypeKey (and optional Currency) + + + Error code: + + + 300x, 310x + + + + + ref + + + GET Participants - + + + + Get Oracle Routing Config Sequence + + + + + + + Validate Participant's FSP + + + + + 6 + + + Request participant (PARTICIPANT.fspId) information for {TypeKey} + + + Error code: + + + 200x + + + + + 7 + + + GET - /participants/{PARTICIPANT.fspId} + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 8 + + + Return participant information + + + + + 9 + + + Return participant information + + + + + 10 + + + Validate participant + + + Error code: + + + 320x + + + + + 11 + + + Create participant's FSP details + + + POST - /participants + + + Error code: + + + 200x, 310x, 320x + + + + + 12 + + + Create participant's FSP details + + + POST - /participants + + + Response code: + + + 204 + + + Error code: + + + 200x, 310x, 320x + + + + + 13 + + + Return result of Participant Create request + + + + + 14 + + + Return result of Participant Create request + + + + + 15 + + + Store results in ParticipantResultMap[TypeKey] + + + + + loop + + + [for keys in ParticipantResultMap -> TypeKey] + + + + + 16 + + + Combine ParticipantResultMap[TypeKey] results into ParticipantResult + + + + + 17 + + + Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 18 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 19 + + + List of PayerFSP Participant Callback Endpoints + + + + + 20 + + + List of PayerFSP Participant Callback Endpoints + + + + + 21 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT + + + + + 22 + + + Return list of Participant information from ParticipantResult + + + + 23 + + + Callback: PUT - /participants/{requestId} + + + + [Validation failure and/or the ParticipantMap was not created successfully] + + + + + 24 + + + Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 25 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 26 + + + List of PayerFSP Participant Callback Endpoints + + + + + 27 + + + List of PayerFSP Participant Callback Endpoints + + + + + 28 + + + Match Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR + + + + + 29 + + + Handle error + + + Error code: + + + 200x, 310x, 320x + + + + 30 + + + Callback: PUT - /participants/{requestId}/error + + diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookup-ddl-MySQLWorkbench.sql b/legacy/mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookup-ddl-MySQLWorkbench.sql new file mode 100644 index 000000000..e538b6351 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookup-ddl-MySQLWorkbench.sql @@ -0,0 +1,195 @@ +-- MySQL dump 10.13 Distrib 5.7.17, for macos10.12 (x86_64) +-- +-- Host: 127.0.0.1 Database: account_lookup +-- ------------------------------------------------------ +-- Server version 8.0.12 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `currency` +-- + +DROP TABLE IF EXISTS `currency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `currency` ( + `currencyId` varchar(3) NOT NULL, + `name` varchar(128) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`currencyId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `currency` +-- + +LOCK TABLES `currency` WRITE; +/*!40000 ALTER TABLE `currency` DISABLE KEYS */; +INSERT INTO `currency` VALUES ('AED','UAE dirham',1,'2019-03-28 09:07:47'),('AFA','Afghanistan afghani (obsolete)',1,'2019-03-28 09:07:47'),('AFN','Afghanistan afghani',1,'2019-03-28 09:07:47'),('ALL','Albanian lek',1,'2019-03-28 09:07:47'),('AMD','Armenian dram',1,'2019-03-28 09:07:47'),('ANG','Netherlands Antillian guilder',1,'2019-03-28 09:07:47'),('AOA','Angolan kwanza',1,'2019-03-28 09:07:47'),('AOR','Angolan kwanza reajustado',1,'2019-03-28 09:07:47'),('ARS','Argentine peso',1,'2019-03-28 09:07:47'),('AUD','Australian dollar',1,'2019-03-28 09:07:47'),('AWG','Aruban guilder',1,'2019-03-28 09:07:47'),('AZN','Azerbaijanian new manat',1,'2019-03-28 09:07:47'),('BAM','Bosnia-Herzegovina convertible mark',1,'2019-03-28 09:07:47'),('BBD','Barbados dollar',1,'2019-03-28 09:07:47'),('BDT','Bangladeshi taka',1,'2019-03-28 09:07:47'),('BGN','Bulgarian lev',1,'2019-03-28 09:07:47'),('BHD','Bahraini dinar',1,'2019-03-28 09:07:47'),('BIF','Burundi franc',1,'2019-03-28 09:07:47'),('BMD','Bermudian dollar',1,'2019-03-28 09:07:47'),('BND','Brunei dollar',1,'2019-03-28 09:07:47'),('BOB','Bolivian boliviano',1,'2019-03-28 09:07:47'),('BRL','Brazilian real',1,'2019-03-28 09:07:47'),('BSD','Bahamian dollar',1,'2019-03-28 09:07:47'),('BTN','Bhutan ngultrum',1,'2019-03-28 09:07:47'),('BWP','Botswana pula',1,'2019-03-28 09:07:47'),('BYN','Belarusian ruble',1,'2019-03-28 09:07:47'),('BZD','Belize dollar',1,'2019-03-28 09:07:47'),('CAD','Canadian dollar',1,'2019-03-28 09:07:47'),('CDF','Congolese franc',1,'2019-03-28 09:07:47'),('CHF','Swiss franc',1,'2019-03-28 09:07:47'),('CLP','Chilean peso',1,'2019-03-28 09:07:47'),('CNY','Chinese yuan renminbi',1,'2019-03-28 09:07:47'),('COP','Colombian peso',1,'2019-03-28 09:07:47'),('CRC','Costa Rican colon',1,'2019-03-28 09:07:47'),('CUC','Cuban convertible peso',1,'2019-03-28 09:07:47'),('CUP','Cuban peso',1,'2019-03-28 09:07:47'),('CVE','Cape Verde escudo',1,'2019-03-28 09:07:47'),('CZK','Czech koruna',1,'2019-03-28 09:07:47'),('DJF','Djibouti franc',1,'2019-03-28 09:07:47'),('DKK','Danish krone',1,'2019-03-28 09:07:47'),('DOP','Dominican peso',1,'2019-03-28 09:07:47'),('DZD','Algerian dinar',1,'2019-03-28 09:07:47'),('EEK','Estonian kroon',1,'2019-03-28 09:07:47'),('EGP','Egyptian pound',1,'2019-03-28 09:07:47'),('ERN','Eritrean nakfa',1,'2019-03-28 09:07:47'),('ETB','Ethiopian birr',1,'2019-03-28 09:07:47'),('EUR','EU euro',1,'2019-03-28 09:07:47'),('FJD','Fiji dollar',1,'2019-03-28 09:07:47'),('FKP','Falkland Islands pound',1,'2019-03-28 09:07:47'),('GBP','British pound',1,'2019-03-28 09:07:47'),('GEL','Georgian lari',1,'2019-03-28 09:07:47'),('GGP','Guernsey pound',1,'2019-03-28 09:07:47'),('GHS','Ghanaian new cedi',1,'2019-03-28 09:07:47'),('GIP','Gibraltar pound',1,'2019-03-28 09:07:47'),('GMD','Gambian dalasi',1,'2019-03-28 09:07:47'),('GNF','Guinean franc',1,'2019-03-28 09:07:47'),('GTQ','Guatemalan quetzal',1,'2019-03-28 09:07:47'),('GYD','Guyana dollar',1,'2019-03-28 09:07:47'),('HKD','Hong Kong SAR dollar',1,'2019-03-28 09:07:47'),('HNL','Honduran lempira',1,'2019-03-28 09:07:47'),('HRK','Croatian kuna',1,'2019-03-28 09:07:47'),('HTG','Haitian gourde',1,'2019-03-28 09:07:47'),('HUF','Hungarian forint',1,'2019-03-28 09:07:47'),('IDR','Indonesian rupiah',1,'2019-03-28 09:07:47'),('ILS','Israeli new shekel',1,'2019-03-28 09:07:47'),('IMP','Isle of Man pound',1,'2019-03-28 09:07:47'),('INR','Indian rupee',1,'2019-03-28 09:07:47'),('IQD','Iraqi dinar',1,'2019-03-28 09:07:47'),('IRR','Iranian rial',1,'2019-03-28 09:07:47'),('ISK','Icelandic krona',1,'2019-03-28 09:07:47'),('JEP','Jersey pound',1,'2019-03-28 09:07:47'),('JMD','Jamaican dollar',1,'2019-03-28 09:07:47'),('JOD','Jordanian dinar',1,'2019-03-28 09:07:47'),('JPY','Japanese yen',1,'2019-03-28 09:07:47'),('KES','Kenyan shilling',1,'2019-03-28 09:07:47'),('KGS','Kyrgyz som',1,'2019-03-28 09:07:47'),('KHR','Cambodian riel',1,'2019-03-28 09:07:47'),('KMF','Comoros franc',1,'2019-03-28 09:07:47'),('KPW','North Korean won',1,'2019-03-28 09:07:47'),('KRW','South Korean won',1,'2019-03-28 09:07:47'),('KWD','Kuwaiti dinar',1,'2019-03-28 09:07:47'),('KYD','Cayman Islands dollar',1,'2019-03-28 09:07:47'),('KZT','Kazakh tenge',1,'2019-03-28 09:07:47'),('LAK','Lao kip',1,'2019-03-28 09:07:47'),('LBP','Lebanese pound',1,'2019-03-28 09:07:47'),('LKR','Sri Lanka rupee',1,'2019-03-28 09:07:47'),('LRD','Liberian dollar',1,'2019-03-28 09:07:47'),('LSL','Lesotho loti',1,'2019-03-28 09:07:47'),('LTL','Lithuanian litas',1,'2019-03-28 09:07:47'),('LVL','Latvian lats',1,'2019-03-28 09:07:47'),('LYD','Libyan dinar',1,'2019-03-28 09:07:47'),('MAD','Moroccan dirham',1,'2019-03-28 09:07:47'),('MDL','Moldovan leu',1,'2019-03-28 09:07:47'),('MGA','Malagasy ariary',1,'2019-03-28 09:07:47'),('MKD','Macedonian denar',1,'2019-03-28 09:07:47'),('MMK','Myanmar kyat',1,'2019-03-28 09:07:47'),('MNT','Mongolian tugrik',1,'2019-03-28 09:07:47'),('MOP','Macao SAR pataca',1,'2019-03-28 09:07:47'),('MRO','Mauritanian ouguiya',1,'2019-03-28 09:07:47'),('MUR','Mauritius rupee',1,'2019-03-28 09:07:47'),('MVR','Maldivian rufiyaa',1,'2019-03-28 09:07:47'),('MWK','Malawi kwacha',1,'2019-03-28 09:07:47'),('MXN','Mexican peso',1,'2019-03-28 09:07:47'),('MYR','Malaysian ringgit',1,'2019-03-28 09:07:47'),('MZN','Mozambique new metical',1,'2019-03-28 09:07:47'),('NAD','Namibian dollar',1,'2019-03-28 09:07:47'),('NGN','Nigerian naira',1,'2019-03-28 09:07:47'),('NIO','Nicaraguan cordoba oro',1,'2019-03-28 09:07:47'),('NOK','Norwegian krone',1,'2019-03-28 09:07:47'),('NPR','Nepalese rupee',1,'2019-03-28 09:07:47'),('NZD','New Zealand dollar',1,'2019-03-28 09:07:47'),('OMR','Omani rial',1,'2019-03-28 09:07:47'),('PAB','Panamanian balboa',1,'2019-03-28 09:07:47'),('PEN','Peruvian nuevo sol',1,'2019-03-28 09:07:47'),('PGK','Papua New Guinea kina',1,'2019-03-28 09:07:47'),('PHP','Philippine peso',1,'2019-03-28 09:07:47'),('PKR','Pakistani rupee',1,'2019-03-28 09:07:47'),('PLN','Polish zloty',1,'2019-03-28 09:07:47'),('PYG','Paraguayan guarani',1,'2019-03-28 09:07:47'),('QAR','Qatari rial',1,'2019-03-28 09:07:47'),('RON','Romanian new leu',1,'2019-03-28 09:07:47'),('RSD','Serbian dinar',1,'2019-03-28 09:07:47'),('RUB','Russian ruble',1,'2019-03-28 09:07:47'),('RWF','Rwandan franc',1,'2019-03-28 09:07:47'),('SAR','Saudi riyal',1,'2019-03-28 09:07:47'),('SBD','Solomon Islands dollar',1,'2019-03-28 09:07:47'),('SCR','Seychelles rupee',1,'2019-03-28 09:07:47'),('SDG','Sudanese pound',1,'2019-03-28 09:07:47'),('SEK','Swedish krona',1,'2019-03-28 09:07:47'),('SGD','Singapore dollar',1,'2019-03-28 09:07:47'),('SHP','Saint Helena pound',1,'2019-03-28 09:07:47'),('SLL','Sierra Leone leone',1,'2019-03-28 09:07:47'),('SOS','Somali shilling',1,'2019-03-28 09:07:47'),('SPL','Seborgan luigino',1,'2019-03-28 09:07:47'),('SRD','Suriname dollar',1,'2019-03-28 09:07:47'),('STD','Sao Tome and Principe dobra',1,'2019-03-28 09:07:47'),('SVC','El Salvador colon',1,'2019-03-28 09:07:47'),('SYP','Syrian pound',1,'2019-03-28 09:07:47'),('SZL','Swaziland lilangeni',1,'2019-03-28 09:07:47'),('THB','Thai baht',1,'2019-03-28 09:07:47'),('TJS','Tajik somoni',1,'2019-03-28 09:07:47'),('TMT','Turkmen new manat',1,'2019-03-28 09:07:47'),('TND','Tunisian dinar',1,'2019-03-28 09:07:47'),('TOP','Tongan pa\'anga',1,'2019-03-28 09:07:47'),('TRY','Turkish lira',1,'2019-03-28 09:07:47'),('TTD','Trinidad and Tobago dollar',1,'2019-03-28 09:07:47'),('TVD','Tuvaluan dollar',1,'2019-03-28 09:07:47'),('TWD','Taiwan New dollar',1,'2019-03-28 09:07:47'),('TZS','Tanzanian shilling',1,'2019-03-28 09:07:47'),('UAH','Ukrainian hryvnia',1,'2019-03-28 09:07:47'),('UGX','Uganda new shilling',1,'2019-03-28 09:07:47'),('USD','US dollar',1,'2019-03-28 09:07:47'),('UYU','Uruguayan peso uruguayo',1,'2019-03-28 09:07:47'),('UZS','Uzbekistani sum',1,'2019-03-28 09:07:47'),('VEF','Venezuelan bolivar fuerte',1,'2019-03-28 09:07:47'),('VND','Vietnamese dong',1,'2019-03-28 09:07:47'),('VUV','Vanuatu vatu',1,'2019-03-28 09:07:47'),('WST','Samoan tala',1,'2019-03-28 09:07:47'),('XAF','CFA franc BEAC',1,'2019-03-28 09:07:47'),('XAG','Silver (ounce)',1,'2019-03-28 09:07:47'),('XAU','Gold (ounce)',1,'2019-03-28 09:07:47'),('XCD','East Caribbean dollar',1,'2019-03-28 09:07:47'),('XDR','IMF special drawing right',1,'2019-03-28 09:07:47'),('XFO','Gold franc',1,'2019-03-28 09:07:47'),('XFU','UIC franc',1,'2019-03-28 09:07:47'),('XOF','CFA franc BCEAO',1,'2019-03-28 09:07:47'),('XPD','Palladium (ounce)',1,'2019-03-28 09:07:47'),('XPF','CFP franc',1,'2019-03-28 09:07:47'),('XPT','Platinum (ounce)',1,'2019-03-28 09:07:47'),('YER','Yemeni rial',1,'2019-03-28 09:07:47'),('ZAR','South African rand',1,'2019-03-28 09:07:47'),('ZMK','Zambian kwacha (obsolete)',1,'2019-03-28 09:07:47'),('ZMW','Zambian kwacha',1,'2019-03-28 09:07:47'),('ZWD','Zimbabwe dollar (initial)',1,'2019-03-28 09:07:47'),('ZWL','Zimbabwe dollar (3rd denomination)',1,'2019-03-28 09:07:47'),('ZWN','Zimbabwe dollar (1st denomination)',1,'2019-03-28 09:07:47'),('ZWR','Zimbabwe dollar (2nd denomination)',1,'2019-03-28 09:07:47'); +/*!40000 ALTER TABLE `currency` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `endpointType` +-- + +DROP TABLE IF EXISTS `endpointType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `endpointType` ( + `endpointTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `type` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`endpointTypeId`), + UNIQUE KEY `endpointtype_type_unique` (`type`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `endpointType` +-- + +LOCK TABLES `endpointType` WRITE; +/*!40000 ALTER TABLE `endpointType` DISABLE KEYS */; +INSERT INTO `endpointType` VALUES (1,'URL','REST URLs',1,'2019-03-28 09:07:47'); +/*!40000 ALTER TABLE `endpointType` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `migration` +-- + +DROP TABLE IF EXISTS `migration`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `migration` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `batch` int(11) DEFAULT NULL, + `migration_time` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `migration` +-- + +LOCK TABLES `migration` WRITE; +/*!40000 ALTER TABLE `migration` DISABLE KEYS */; +INSERT INTO `migration` VALUES (1,'01_currency.js',1,'2019-03-28 11:07:46'),(2,'02_endpointType.js',1,'2019-03-28 11:07:46'),(3,'03_endpointType-indexes.js',1,'2019-03-28 11:07:46'),(4,'04_partyIdType.js',1,'2019-03-28 11:07:46'),(5,'05_partyIdType-indexes.js',1,'2019-03-28 11:07:46'),(6,'08_oracleEndpoint.js',1,'2019-03-28 11:07:47'),(7,'09_oracleEndpoint-indexes.js',1,'2019-03-28 11:07:47'); +/*!40000 ALTER TABLE `migration` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `migration_lock` +-- + +DROP TABLE IF EXISTS `migration_lock`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `migration_lock` ( + `index` int(10) unsigned NOT NULL AUTO_INCREMENT, + `is_locked` int(11) DEFAULT NULL, + PRIMARY KEY (`index`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `migration_lock` +-- + +LOCK TABLES `migration_lock` WRITE; +/*!40000 ALTER TABLE `migration_lock` DISABLE KEYS */; +INSERT INTO `migration_lock` VALUES (1,0); +/*!40000 ALTER TABLE `migration_lock` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `oracleEndpoint` +-- + +DROP TABLE IF EXISTS `oracleEndpoint`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `oracleEndpoint` ( + `oracleEndpointId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `partyIdTypeId` int(10) unsigned NOT NULL, + `endpointTypeId` int(10) unsigned NOT NULL, + `currencyId` varchar(255) DEFAULT NULL, + `value` varchar(512) NOT NULL, + `isDefault` tinyint(1) NOT NULL DEFAULT '0', + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`oracleEndpointId`), + KEY `oracleendpoint_currencyid_foreign` (`currencyId`), + KEY `oracleendpoint_partyidtypeid_index` (`partyIdTypeId`), + KEY `oracleendpoint_endpointtypeid_index` (`endpointTypeId`), + CONSTRAINT `oracleendpoint_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `oracleendpoint_endpointtypeid_foreign` FOREIGN KEY (`endpointTypeId`) REFERENCES `endpointType` (`endpointtypeid`), + CONSTRAINT `oracleendpoint_partyidtypeid_foreign` FOREIGN KEY (`partyIdTypeId`) REFERENCES `partyIdType` (`partyidtypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `oracleEndpoint` +-- + +LOCK TABLES `oracleEndpoint` WRITE; +/*!40000 ALTER TABLE `oracleEndpoint` DISABLE KEYS */; +/*!40000 ALTER TABLE `oracleEndpoint` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `partyIdType` +-- + +DROP TABLE IF EXISTS `partyIdType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `partyIdType` ( + `partyIdTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL, + `description` varchar(512) NOT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`partyIdTypeId`), + UNIQUE KEY `partyidtype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `partyIdType` +-- + +LOCK TABLES `partyIdType` WRITE; +/*!40000 ALTER TABLE `partyIdType` DISABLE KEYS */; +INSERT INTO `partyIdType` VALUES (1,'MSISDN','A MSISDN (Mobile Station International Subscriber Directory Number, that is, the phone number) is used as reference to a participant. The MSISDN identifier should be in international format according to the ITU-T E.164 standard. Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix.',1,'2019-03-28 09:07:47'),(2,'EMAIL','An email is used as reference to a participant. The format of the email should be according to the informational RFC 3696.',1,'2019-03-28 09:07:47'),(3,'PERSONAL_ID','A personal identifier is used as reference to a participant. Examples of personal identification are passport number, birth certificate number, and national registration number. The identifier number is added in the PartyIdentifier element. The personal identifier type is added in the PartySubIdOrType element.',1,'2019-03-28 09:07:47'),(4,'BUSINESS','A specific Business (for example, an organization or a company) is used as reference to a participant. The BUSINESS identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the PartySubIdOrType element should be used.',1,'2019-03-28 09:07:47'),(5,'DEVICE','A specific device (for example, a POS or ATM) ID connected to a specific business or organization is used as reference to a Party. For referencing a specific device under a specific business or organization, use the PartySubIdOrType element.',1,'2019-03-28 09:07:47'),(6,'ACCOUNT_ID','A bank account number or FSP account ID should be used as reference to a participant. The ACCOUNT_ID identifier can be in any format, as formats can greatly differ depending on country and FSP.',1,'2019-03-28 09:07:47'),(7,'IBAN','A bank account number or FSP account ID is used as reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without whitespace.',1,'2019-03-28 09:07:47'),(8,'ALIAS','An alias is used as reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias is a username in the FSP system. The ALIAS identifier can be in any format. It is also possible to use the PartySubIdOrType element for identifying an account under an Alias defined by the PartyIdentifier.',1,'2019-03-28 09:07:47'); +/*!40000 ALTER TABLE `partyIdType` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2019-03-28 11:09:54 diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookupDB-schema-DBeaver.erd b/legacy/mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookupDB-schema-DBeaver.erd new file mode 100644 index 000000000..ea177ae89 --- /dev/null +++ b/legacy/mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookupDB-schema-DBeaver.erd @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/legacy/mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookupService-schema.png b/legacy/mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookupService-schema.png new file mode 100644 index 000000000..bdca208cd Binary files /dev/null and b/legacy/mojaloop-technical-overview/account-lookup-service/assets/entities/AccountLookupService-schema.png differ diff --git a/legacy/mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI5.svg b/legacy/mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI5.svg new file mode 100644 index 000000000..d87484a3c --- /dev/null +++ b/legacy/mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI5.svg @@ -0,0 +1,3 @@ + + +
    Mojaloop Adapter
    Mojaloop Adapter
    Central-Ledger
    Central-Ledger
    Mojaloop
    Adapter
    [Not supported by viewer]
    C 1. Transfer
    C 1. Transfer
    request_to_prepare
    request_to_prepare
    C 1.2
    [Not supported by viewer]
    C 1.3
    [Not supported by viewer]
    prepared.notification
    prepared.notification
    C 1.4
    C 1.4
    fulfiled.notification
    fulfiled.notification
    request_to_fulfil
    request_to_fulfil
    Fulfil Transfer
    Fulfil Transfer
    C 1.8
    C 1.8
    C 1.9
    [Not supported by viewer]
    C 1.10
    [Not supported by viewer]
    C 1.11
    C 1.11
    C 1.12 Fulfil Notify
    C 1.12 Fulfil Notify
    C 1.1
    C 1.1
    C 1.5
    C 1.5
    DB
    DB
    Mojaloop
    Open Source Services
    [Not supported by viewer]
    positions
    positions
    Account Lookup Service
    (Parties / Participant)
    [Not supported by viewer]
    FSP
    Backend

    (Does not natively speak Mojaloop API)



    [Not supported by viewer]
    Scheme-Adapter

    (Converts from Mojaloop API to backend FSP API)
    [Not supported by viewer]
    A 2. MSISDN
    based lookup
    A 2. MSISDN <br>based lookup
    DB
    DB
     Database
     Database
    FSP
    Backend
      

    (Natively speaks Mojaloop API)



    [Not supported by viewer]
    A
    A
    A 1. User Lookup
    A 1. User Lookup
    A 3. Receiver Details
    A 3. Receiver Details
    B
    B
    Merchant 
    Registry
    [Not supported by viewer]
    A 2. mID based
    lookup
    A 2. mID based <br>lookup
    B 1. Quote
    B 1. Quote
    Mojaloop Hub
    <font>Mojaloop Hub<br></font>
    Payer FSP
    [Not supported by viewer]
    Payee FSP
    [Not supported by viewer]
    Ledger
    Ledger<br>
    Ledger
    Ledger<br>
    C
    C
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    C 1.6
    Prepare
    Transfer
    [Not supported by viewer]
    C 1.7
    C 1.7
    C 1.11
    C 1.11
    C 1.12
    C 1.12
    Fulfil Notify
    Fulfil Notify
    C 1.13
    Fulfil Notify
    [Not supported by viewer]
    B 2. Fee /
    Commission
    [Not supported by viewer]
    A 4. Get 
    receiver 
    details
    [Not supported by viewer]
    B 1. Quote
    B 1. Quote
    D 6.
    D 6.
    Central-Settlement
    Central-Settlement
    D 5. Update Positions
    [Not supported by viewer]
    settlement.notifications
    settlement.notifications
    kafka
    kafka
    Scheme Settlement Processor
    <span>Scheme Settlement Processor</span><br>
    Hub Operator
    Hub Operator
    D 1. Create
    Settlement
    [Not supported by viewer]
    D
    D
    D 2. Query
    Settlement
    Report
    (Pull)
    [Not supported by viewer]
    D 4. Send
    Acks
    (Push)
    [Not supported by viewer]
    Settlement
    Bank
    Settlement<br>Bank<br>
    D 3. Process Settlements
    [Not supported by viewer]
    Bank
    [Not supported by viewer]
    D 7. Position Notifications Change result
    D 7. Position Notifications Change result
    D 7. Settlement Notification
    D 7. Settlement Notification
    kafka
    kafka
    GSMA
    [Not supported by viewer]
    (Schema customised by Hub Operator)
    [Not supported by viewer]
    Pathfinder
    [Not supported by viewer]
    ALS Oracle MSISDN Adapter
    [Not supported by viewer]
    ALS Oracle Merchant Service
    [Not supported by viewer]
    API
    Internal Use-Only
    API <br>Internal Use-Only
    Mojaloop API
    Specification v1.0
    Mojaloop API<br>Specification v1.0<br>
    Key
    [Not supported by viewer]
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg b/legacy/mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg new file mode 100644 index 000000000..f75130984 --- /dev/null +++ b/legacy/mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg @@ -0,0 +1,3 @@ + + +
    Mojaloop Adapter
    Mojaloop Adapter
    Central-Services
    (Ledger - API, Handlers)
    Central-Services<br>(Ledger - API, Handlers)<br>
    Mojaloop
    Adapter
    [Not supported by viewer]
    C 1. Transfer
    C 1. Transfer
    request_to_prepare
    request_to_prepare
    C 1.2
    [Not supported by viewer]
    C 1.3
    [Not supported by viewer]
    prepared.notification
    prepared.notification
    C 1.4
    C 1.4
    fulfiled.notification
    fulfiled.notification
    request_to_fulfil
    request_to_fulfil
    Fulfil Transfer
    Fulfil Transfer
    C 1.8
    C 1.8
    C 1.9
    [Not supported by viewer]
    C 1.10
    [Not supported by viewer]
    C 1.11
    C 1.11
    C 1.12 Fulfil Notify
    C 1.12 Fulfil Notify
    C 1.1
    C 1.1
    C 1.5
    C 1.5
    DB
    DB
    Mojaloop
    Open Source Services
    [Not supported by viewer]
    positions
    positions
    Account Lookup Service
    (Parties / Participant)
    [Not supported by viewer]
    FSP
    Backend

    (Does not natively speak Mojaloop API)



    [Not supported by viewer]
    Scheme-Adapter

    (Converts from Mojaloop API to backend FSP API)
    [Not supported by viewer]
    A 2. MSISDN
    based lookup
    A 2. MSISDN <br>based lookup
    DB
    DB
     Database
     Database
    FSP
    Backend
      

    (Natively speaks Mojaloop API)



    [Not supported by viewer]
    A
    A
    A 1. User Lookup
    A 1. User Lookup
    A 3. Receiver Details
    A 3. Receiver Details
    B
    B
    Merchant 
    Registry
    [Not supported by viewer]
    A 2. mID based
    lookup
    A 2. mID based <br>lookup
    B 1. Quote
    B 1. Quote
    Mojaloop Hub
    <font>Mojaloop Hub<br></font>
    Payer FSP
    [Not supported by viewer]
    Payee FSP
    [Not supported by viewer]
    Ledger
    Ledger<br>
    Ledger
    Ledger<br>
    C
    C
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    C 1.6
    Prepare
    Transfer
    [Not supported by viewer]
    C 1.7
    C 1.7
    C 1.11
    C 1.11
    C 1.12
    C 1.12
    Fulfil Notify
    Fulfil Notify
    C 1.13
    Fulfil Notify
    [Not supported by viewer]
    B 2. Fee /
    Commission
    [Not supported by viewer]
    A 4. Get 
    receiver 
    details
    [Not supported by viewer]
    B 1. Quote
    B 1. Quote
    D 6.
    D 6.
    Central-Settlement
    Central-Settlement
    D 5. Update Positions
    [Not supported by viewer]
    settlement.notifications
    settlement.notifications
    kafka
    kafka
    Scheme Settlement Processor
    <span>Scheme Settlement Processor</span><br>
    Hub Operator
    Hub Operator
    D 1. Create
    Settlement
    [Not supported by viewer]
    D
    D
    D 2. Query
    Settlement
    Report
    (Pull)
    [Not supported by viewer]
    D 4. Send
    Acks
    (Push)
    [Not supported by viewer]
    Settlement
    Bank
    Settlement<br>Bank<br>
    D 3. Process Settlements
    [Not supported by viewer]
    Bank
    [Not supported by viewer]
    D 7. Position Notifications Change result
    D 7. Position Notifications Change result
    D 7. Settlement Notification
    D 7. Settlement Notification
    kafka
    kafka
    GSMA
    [Not supported by viewer]
    (Schema customised by Hub Operator)
    [Not supported by viewer]
    Pathfinder
    [Not supported by viewer]
    ALS Oracle MSISDN Adapter
    [Not supported by viewer]
    ALS Oracle Merchant Service
    [Not supported by viewer]
    API
    Internal Use-Only
    API <br>Internal Use-Only
    Mojaloop API
    Specification v1.0
    Mojaloop API<br>Specification v1.0<br>
    Key
    [Not supported by viewer]
    Quoting-Service
    Quoting-Service
    ALS Oracle Simulator
    [Not supported by viewer]
    A 2. *ID based
    lookup
    A 2. *ID based <br>lookup
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-simple.svg b/legacy/mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-simple.svg new file mode 100644 index 000000000..a2fbbe512 --- /dev/null +++ b/legacy/mojaloop-technical-overview/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-simple.svg @@ -0,0 +1,3 @@ + + +
    C 4. Transfer
    Fulfil Notify
    [Not supported by viewer]
    Account Lookup Services
    [Not supported by viewer]
    Pathfinder
    Pathfinder
    FSP
    Backend


    (Does not natively speak Mojaloop API)








    [Not supported by viewer]
    S
    c
    h
    e
    m
    e

    A
    d
    a
    p
    t
    e
    r

    [Not supported by viewer]
    A 2. MSISDN based lookup
    A 2. MSISDN based lookup
    FSP
    Backend
      

    (Natively speaks Mojaloop API)









    [Not supported by viewer]
    A
    A
    A 1. User
    Lookup
    A 1. User <br>Lookup
    B
    B
    Merchant 
    Registry
    [Not supported by viewer]
    A 2. mID based lookup
    A 2. mID based lookup
    Mojaloop Hub
    [Not supported by viewer]
    Payer FSP
    [Not supported by viewer]
    Payee FSP
    [Not supported by viewer]
    Ledger
    Ledger<br>
    Ledger
    Ledger<br>
    C
    C
    C 1. Transfer
        Prepare
    [Not supported by viewer]
    A 3. Receiver
    Details
    A 3. Receiver<br>Details<br>
     Fee /
    Comm
    [Not supported by viewer]
    Get Receiver
    Details
    [Not supported by viewer]
     C 2. Transfer
    Prepare
    [Not supported by viewer]
    C 5. Transfer
    Fulfil Notify
    [Not supported by viewer]
    Transfer
    Prepare
    [Not supported by viewer]
    C 3. Transfer
    Fulfil
    C 3. Transfer<br>Fulfil<br>
    Transfer
    Fulfil
    [Not supported by viewer]
    B 1. Quote
    B 1. Quote
    Central Services
    [Not supported by viewer]
    B 1. Quote
    B 1. Quote<br>
    Settlement Provider
    Settlement Provider
    Hub Operator
    Hub Operator
    D 1. Create Settlement
    D 1. Create Settlement
    D
    D
    D 2. Query Settlement Report
    (Pull)
    D 2. Query Settlement Report<br>(Pull)<br>
    D 3. Send Acknowledgements
    (Push)
    D 3. Send Acknowledgements<br>(Push)<br>
    Quoting Service
    <font style="font-size: 18px">Quoting Service</font>
    Central Services
    • Transfers
    • Settlements
    • Auditing
    • Notifications
    [Not supported by viewer]
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/assets/diagrams/architecture/central_ledger_block_diagram.png b/legacy/mojaloop-technical-overview/assets/diagrams/architecture/central_ledger_block_diagram.png new file mode 100644 index 000000000..48199cf3e Binary files /dev/null and b/legacy/mojaloop-technical-overview/assets/diagrams/architecture/central_ledger_block_diagram.png differ diff --git a/mojaloop-technical-overview/central-bulk-transfers/README.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/README.md similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/README.md rename to legacy/mojaloop-technical-overview/central-bulk-transfers/README.md diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-ddl-MySQLWorkbench.sql b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-ddl-MySQLWorkbench.sql new file mode 100644 index 000000000..f6995bc85 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-ddl-MySQLWorkbench.sql @@ -0,0 +1,1600 @@ +-- MySQL dump 10.13 Distrib 8.0.16, for macos10.14 (x86_64) +-- +-- Host: 127.0.0.1 Database: central_ledger +-- ------------------------------------------------------ +-- Server version 8.0.13 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; + SET NAMES utf8 ; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `amountType` +-- + +DROP TABLE IF EXISTS `amountType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `amountType` ( + `amountTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`amountTypeId`), + UNIQUE KEY `amounttype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `balanceOfPayments` +-- + +DROP TABLE IF EXISTS `balanceOfPayments`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `balanceOfPayments` ( + `balanceOfPaymentsId` int(10) unsigned NOT NULL, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL COMMENT 'Possible values and meaning are defined in https://www.imf.org/external/np/sta/bopcode/', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`balanceOfPaymentsId`), + UNIQUE KEY `balanceofpayments_name_unique` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='See https://www.imf.org/external/np/sta/bopcode/guide.htm'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkProcessingState` +-- + +DROP TABLE IF EXISTS `bulkProcessingState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkProcessingState` ( + `bulkProcessingStateId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkProcessingStateId`), + UNIQUE KEY `bulkprocessingstate_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransfer` +-- + +DROP TABLE IF EXISTS `bulkTransfer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransfer` ( + `bulkTransferId` varchar(36) NOT NULL, + `bulkQuoteId` varchar(36) DEFAULT NULL, + `payerParticipantId` int(10) unsigned DEFAULT NULL, + `payeeParticipantId` int(10) unsigned DEFAULT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`), + KEY `bulktransfer_payerparticipantid_index` (`payerParticipantId`), + KEY `bulktransfer_payeeparticipantid_index` (`payeeParticipantId`), + CONSTRAINT `bulktransfer_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransferDuplicateCheck` (`bulktransferid`), + CONSTRAINT `bulktransfer_payeeparticipantid_foreign` FOREIGN KEY (`payeeParticipantId`) REFERENCES `participant` (`participantid`), + CONSTRAINT `bulktransfer_payerparticipantid_foreign` FOREIGN KEY (`payerParticipantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferAssociation` +-- + +DROP TABLE IF EXISTS `bulkTransferAssociation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferAssociation` ( + `bulkTransferAssociationId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `bulkTransferId` varchar(36) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `bulkProcessingStateId` int(10) unsigned NOT NULL, + `lastProcessedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `errorCode` int(10) unsigned DEFAULT NULL, + `errorDescription` varchar(128) DEFAULT NULL, + PRIMARY KEY (`bulkTransferAssociationId`), + UNIQUE KEY `bulktransferassociation_transferid_bulktransferid_unique` (`transferId`,`bulkTransferId`), + KEY `bulktransferassociation_bulktransferid_foreign` (`bulkTransferId`), + KEY `bulktransferassociation_bulkprocessingstateid_foreign` (`bulkProcessingStateId`), + CONSTRAINT `bulktransferassociation_bulkprocessingstateid_foreign` FOREIGN KEY (`bulkProcessingStateId`) REFERENCES `bulkProcessingState` (`bulkprocessingstateid`), + CONSTRAINT `bulktransferassociation_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferDuplicateCheck` +-- + +DROP TABLE IF EXISTS `bulkTransferDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferDuplicateCheck` ( + `bulkTransferId` varchar(36) NOT NULL, + `hash` varchar(256) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferError` +-- + +DROP TABLE IF EXISTS `bulkTransferError`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferError` ( + `bulkTransferErrorId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `bulkTransferStateChangeId` bigint(20) unsigned NOT NULL, + `errorCode` int(10) unsigned NOT NULL, + `errorDescription` varchar(128) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferErrorId`), + KEY `bulktransfererror_bulktransferstatechangeid_index` (`bulkTransferStateChangeId`), + CONSTRAINT `bulktransfererror_bulktransferstatechangeid_foreign` FOREIGN KEY (`bulkTransferStateChangeId`) REFERENCES `bulkTransferStateChange` (`bulktransferstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferExtension` +-- + +DROP TABLE IF EXISTS `bulkTransferExtension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferExtension` ( + `bulkTransferExtensionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `bulkTransferId` varchar(36) NOT NULL, + `isFulfilment` tinyint(1) NOT NULL DEFAULT '0', + `key` varchar(128) NOT NULL, + `value` text NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferExtensionId`), + KEY `bulktransferextension_bulktransferid_index` (`bulkTransferId`), + CONSTRAINT `bulktransferextension_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferFulfilment` +-- + +DROP TABLE IF EXISTS `bulkTransferFulfilment`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferFulfilment` ( + `bulkTransferId` varchar(36) NOT NULL, + `completedDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`), + CONSTRAINT `bulktransferfulfilment_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransferFulfilmentDuplicateCheck` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferFulfilmentDuplicateCheck` +-- + +DROP TABLE IF EXISTS `bulkTransferFulfilmentDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferFulfilmentDuplicateCheck` ( + `bulkTransferId` varchar(36) NOT NULL, + `hash` varchar(256) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`), + CONSTRAINT `bulktransferfulfilmentduplicatecheck_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferState` +-- + +DROP TABLE IF EXISTS `bulkTransferState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferState` ( + `bulkTransferStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL COMMENT 'bulkTransferState associated to the Mojaloop API', + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferStateChange` +-- + +DROP TABLE IF EXISTS `bulkTransferStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferStateChange` ( + `bulkTransferStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `bulkTransferId` varchar(36) NOT NULL, + `bulkTransferStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferStateChangeId`), + KEY `bulktransferstatechange_bulktransferid_index` (`bulkTransferId`), + KEY `bulktransferstatechange_bulktransferstateid_index` (`bulkTransferStateId`), + CONSTRAINT `bulktransferstatechange_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`), + CONSTRAINT `bulktransferstatechange_bulktransferstateid_foreign` FOREIGN KEY (`bulkTransferStateId`) REFERENCES `bulkTransferState` (`bulktransferstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `contactType` +-- + +DROP TABLE IF EXISTS `contactType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `contactType` ( + `contactTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`contactTypeId`), + UNIQUE KEY `contacttype_name_unique` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `currency` +-- + +DROP TABLE IF EXISTS `currency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `currency` ( + `currencyId` varchar(3) NOT NULL, + `name` varchar(128) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `scale` int(10) unsigned NOT NULL DEFAULT '4', + PRIMARY KEY (`currencyId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `endpointType` +-- + +DROP TABLE IF EXISTS `endpointType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `endpointType` ( + `endpointTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`endpointTypeId`), + UNIQUE KEY `endpointtype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `event` +-- + +DROP TABLE IF EXISTS `event`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `event` ( + `eventId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`eventId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `geoCode` +-- + +DROP TABLE IF EXISTS `geoCode`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `geoCode` ( + `geoCodeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `quotePartyId` bigint(20) unsigned NOT NULL COMMENT 'Optionally the GeoCode for the Payer/Payee may have been provided. If the Quote Response has the GeoCode for the Payee, an additional row is added', + `latitude` varchar(50) NOT NULL COMMENT 'Latitude of the initiating Party', + `longitude` varchar(50) NOT NULL COMMENT 'Longitude of the initiating Party', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`geoCodeId`), + KEY `geocode_quotepartyid_foreign` (`quotePartyId`), + CONSTRAINT `geocode_quotepartyid_foreign` FOREIGN KEY (`quotePartyId`) REFERENCES `quoteParty` (`quotepartyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ilpPacket` +-- + +DROP TABLE IF EXISTS `ilpPacket`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `ilpPacket` ( + `transferId` varchar(36) NOT NULL, + `value` text NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + CONSTRAINT `ilppacket_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ledgerAccountType` +-- + +DROP TABLE IF EXISTS `ledgerAccountType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `ledgerAccountType` ( + `ledgerAccountTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`ledgerAccountTypeId`), + UNIQUE KEY `ledgeraccounttype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ledgerEntryType` +-- + +DROP TABLE IF EXISTS `ledgerEntryType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `ledgerEntryType` ( + `ledgerEntryTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`ledgerEntryTypeId`), + UNIQUE KEY `ledgerentrytype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `migration` +-- + +DROP TABLE IF EXISTS `migration`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `migration` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `batch` int(11) DEFAULT NULL, + `migration_time` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=138 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `migration_lock` +-- + +DROP TABLE IF EXISTS `migration_lock`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `migration_lock` ( + `index` int(10) unsigned NOT NULL AUTO_INCREMENT, + `is_locked` int(11) DEFAULT NULL, + PRIMARY KEY (`index`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participant` +-- + +DROP TABLE IF EXISTS `participant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participant` ( + `participantId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantId`), + UNIQUE KEY `participant_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantContact` +-- + +DROP TABLE IF EXISTS `participantContact`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantContact` ( + `participantContactId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `contactTypeId` int(10) unsigned NOT NULL, + `value` varchar(256) NOT NULL, + `priorityPreference` int(11) NOT NULL DEFAULT '9', + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantContactId`), + KEY `participantcontact_participantid_index` (`participantId`), + KEY `participantcontact_contacttypeid_index` (`contactTypeId`), + CONSTRAINT `participantcontact_contacttypeid_foreign` FOREIGN KEY (`contactTypeId`) REFERENCES `contactType` (`contacttypeid`), + CONSTRAINT `participantcontact_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantCurrency` +-- + +DROP TABLE IF EXISTS `participantCurrency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantCurrency` ( + `participantCurrencyId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `currencyId` varchar(3) NOT NULL, + `ledgerAccountTypeId` int(10) unsigned NOT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantCurrencyId`), + UNIQUE KEY `participantcurrency_pcl_unique` (`participantId`,`currencyId`,`ledgerAccountTypeId`), + KEY `participantcurrency_ledgeraccounttypeid_foreign` (`ledgerAccountTypeId`), + KEY `participantcurrency_participantid_index` (`participantId`), + KEY `participantcurrency_currencyid_index` (`currencyId`), + CONSTRAINT `participantcurrency_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `participantcurrency_ledgeraccounttypeid_foreign` FOREIGN KEY (`ledgerAccountTypeId`) REFERENCES `ledgerAccountType` (`ledgeraccounttypeid`), + CONSTRAINT `participantcurrency_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantEndpoint` +-- + +DROP TABLE IF EXISTS `participantEndpoint`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantEndpoint` ( + `participantEndpointId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `endpointTypeId` int(10) unsigned NOT NULL, + `value` varchar(512) NOT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantEndpointId`), + KEY `participantendpoint_participantid_index` (`participantId`), + KEY `participantendpoint_endpointtypeid_index` (`endpointTypeId`), + CONSTRAINT `participantendpoint_endpointtypeid_foreign` FOREIGN KEY (`endpointTypeId`) REFERENCES `endpointType` (`endpointtypeid`), + CONSTRAINT `participantendpoint_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantLimit` +-- + +DROP TABLE IF EXISTS `participantLimit`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantLimit` ( + `participantLimitId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantCurrencyId` int(10) unsigned NOT NULL, + `participantLimitTypeId` int(10) unsigned NOT NULL, + `value` decimal(18,4) NOT NULL DEFAULT '0.0000', + `thresholdAlarmPercentage` decimal(5,2) NOT NULL DEFAULT '10.00', + `startAfterParticipantPositionChangeId` bigint(20) unsigned DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantLimitId`), + KEY `participantlimit_participantcurrencyid_index` (`participantCurrencyId`), + KEY `participantlimit_participantlimittypeid_index` (`participantLimitTypeId`), + KEY `participantlimit_startafterparticipantpositionchangeid_index` (`startAfterParticipantPositionChangeId`), + CONSTRAINT `participantlimit_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `participantlimit_participantlimittypeid_foreign` FOREIGN KEY (`participantLimitTypeId`) REFERENCES `participantLimitType` (`participantlimittypeid`), + CONSTRAINT `participantlimit_startafterparticipantpositionchangeid_foreign` FOREIGN KEY (`startAfterParticipantPositionChangeId`) REFERENCES `participantPositionChange` (`participantpositionchangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantLimitType` +-- + +DROP TABLE IF EXISTS `participantLimitType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantLimitType` ( + `participantLimitTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`participantLimitTypeId`), + UNIQUE KEY `participantlimittype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantParty` +-- + +DROP TABLE IF EXISTS `participantParty`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantParty` ( + `participantPartyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `partyId` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`participantPartyId`), + UNIQUE KEY `participantparty_participantid_partyid_unique` (`participantId`,`partyId`), + KEY `participantparty_participantid_index` (`participantId`), + CONSTRAINT `participantparty_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantPosition` +-- + +DROP TABLE IF EXISTS `participantPosition`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantPosition` ( + `participantPositionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `participantCurrencyId` int(10) unsigned NOT NULL, + `value` decimal(18,4) NOT NULL, + `reservedValue` decimal(18,4) NOT NULL, + `changedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`participantPositionId`), + KEY `participantposition_participantcurrencyid_index` (`participantCurrencyId`), + CONSTRAINT `participantposition_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantPositionChange` +-- + +DROP TABLE IF EXISTS `participantPositionChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantPositionChange` ( + `participantPositionChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `participantPositionId` bigint(20) unsigned NOT NULL, + `transferStateChangeId` bigint(20) unsigned NOT NULL, + `value` decimal(18,4) NOT NULL, + `reservedValue` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`participantPositionChangeId`), + KEY `participantpositionchange_participantpositionid_index` (`participantPositionId`), + KEY `participantpositionchange_transferstatechangeid_index` (`transferStateChangeId`), + CONSTRAINT `participantpositionchange_participantpositionid_foreign` FOREIGN KEY (`participantPositionId`) REFERENCES `participantPosition` (`participantpositionid`), + CONSTRAINT `participantpositionchange_transferstatechangeid_foreign` FOREIGN KEY (`transferStateChangeId`) REFERENCES `transferStateChange` (`transferstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `party` +-- + +DROP TABLE IF EXISTS `party`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `party` ( + `partyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quotePartyId` bigint(20) unsigned NOT NULL, + `firstName` varchar(128) DEFAULT NULL, + `middleName` varchar(128) DEFAULT NULL, + `lastName` varchar(128) DEFAULT NULL, + `dateOfBirth` datetime DEFAULT NULL, + PRIMARY KEY (`partyId`), + KEY `party_quotepartyid_foreign` (`quotePartyId`), + CONSTRAINT `party_quotepartyid_foreign` FOREIGN KEY (`quotePartyId`) REFERENCES `quoteParty` (`quotepartyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Optional pers. data provided during Quote Request & Response'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `partyIdentifierType` +-- + +DROP TABLE IF EXISTS `partyIdentifierType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `partyIdentifierType` ( + `partyIdentifierTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) NOT NULL, + PRIMARY KEY (`partyIdentifierTypeId`), + UNIQUE KEY `partyidentifiertype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `partyType` +-- + +DROP TABLE IF EXISTS `partyType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `partyType` ( + `partyTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL, + `description` varchar(256) NOT NULL, + PRIMARY KEY (`partyTypeId`), + UNIQUE KEY `partytype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quote` +-- + +DROP TABLE IF EXISTS `quote`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quote` ( + `quoteId` varchar(36) NOT NULL, + `transactionReferenceId` varchar(36) NOT NULL COMMENT 'Common ID (decided by the Payer FSP) between the FSPs for the future transaction object', + `transactionRequestId` varchar(36) DEFAULT NULL COMMENT 'Optional previously-sent transaction request', + `note` text COMMENT 'A memo that will be attached to the transaction', + `expirationDate` datetime DEFAULT NULL COMMENT 'Optional expiration for the requested transaction', + `transactionInitiatorId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction initiator', + `transactionInitiatorTypeId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction initiator type', + `transactionScenarioId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction scenario', + `balanceOfPaymentsId` int(10) unsigned DEFAULT NULL COMMENT 'This is part of the transaction type that contains the elements- balance of payment', + `transactionSubScenarioId` int(10) unsigned DEFAULT NULL COMMENT 'This is part of the transaction type sub scenario as defined by the local scheme', + `amountTypeId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction type that contains valid elements for - Amount Type', + `amount` decimal(18,4) NOT NULL DEFAULT '0.0000' COMMENT 'The amount that the quote is being requested for. Need to be interpert in accordance with the amount type', + `currencyId` varchar(255) DEFAULT NULL COMMENT 'Trading currency pertaining to the Amount', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteId`), + KEY `quote_transactionreferenceid_foreign` (`transactionReferenceId`), + KEY `quote_transactionrequestid_foreign` (`transactionRequestId`), + KEY `quote_transactioninitiatorid_foreign` (`transactionInitiatorId`), + KEY `quote_transactioninitiatortypeid_foreign` (`transactionInitiatorTypeId`), + KEY `quote_transactionscenarioid_foreign` (`transactionScenarioId`), + KEY `quote_balanceofpaymentsid_foreign` (`balanceOfPaymentsId`), + KEY `quote_transactionsubscenarioid_foreign` (`transactionSubScenarioId`), + KEY `quote_amounttypeid_foreign` (`amountTypeId`), + KEY `quote_currencyid_foreign` (`currencyId`), + CONSTRAINT `quote_amounttypeid_foreign` FOREIGN KEY (`amountTypeId`) REFERENCES `amountType` (`amounttypeid`), + CONSTRAINT `quote_balanceofpaymentsid_foreign` FOREIGN KEY (`balanceOfPaymentsId`) REFERENCES `balanceOfPayments` (`balanceofpaymentsid`), + CONSTRAINT `quote_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quote_transactioninitiatorid_foreign` FOREIGN KEY (`transactionInitiatorId`) REFERENCES `transactionInitiator` (`transactioninitiatorid`), + CONSTRAINT `quote_transactioninitiatortypeid_foreign` FOREIGN KEY (`transactionInitiatorTypeId`) REFERENCES `transactionInitiatorType` (`transactioninitiatortypeid`), + CONSTRAINT `quote_transactionreferenceid_foreign` FOREIGN KEY (`transactionReferenceId`) REFERENCES `transactionReference` (`transactionreferenceid`), + CONSTRAINT `quote_transactionrequestid_foreign` FOREIGN KEY (`transactionRequestId`) REFERENCES `transactionReference` (`transactionreferenceid`), + CONSTRAINT `quote_transactionscenarioid_foreign` FOREIGN KEY (`transactionScenarioId`) REFERENCES `transactionScenario` (`transactionscenarioid`), + CONSTRAINT `quote_transactionsubscenarioid_foreign` FOREIGN KEY (`transactionSubScenarioId`) REFERENCES `transactionSubScenario` (`transactionsubscenarioid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteDuplicateCheck` +-- + +DROP TABLE IF EXISTS `quoteDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteDuplicateCheck` ( + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `hash` varchar(1024) DEFAULT NULL COMMENT 'hash value received for the quote request', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteError` +-- + +DROP TABLE IF EXISTS `quoteError`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteError` ( + `quoteErrorId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `quoteResponseId` bigint(20) unsigned DEFAULT NULL COMMENT 'The response to the intial quote', + `errorCode` int(10) unsigned NOT NULL, + `errorDescription` varchar(128) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`quoteErrorId`), + KEY `quoteerror_quoteid_foreign` (`quoteId`), + KEY `quoteerror_quoteresponseid_foreign` (`quoteResponseId`), + CONSTRAINT `quoteerror_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteerror_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteExtension` +-- + +DROP TABLE IF EXISTS `quoteExtension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteExtension` ( + `quoteExtensionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `quoteResponseId` bigint(20) unsigned NOT NULL COMMENT 'The response to the intial quote', + `transactionId` varchar(36) NOT NULL COMMENT 'The transaction reference that is part of the initial quote', + `key` varchar(128) NOT NULL, + `value` text NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteExtensionId`), + KEY `quoteextension_quoteid_foreign` (`quoteId`), + KEY `quoteextension_quoteresponseid_foreign` (`quoteResponseId`), + KEY `quoteextension_transactionid_foreign` (`transactionId`), + CONSTRAINT `quoteextension_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteextension_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`), + CONSTRAINT `quoteextension_transactionid_foreign` FOREIGN KEY (`transactionId`) REFERENCES `transactionReference` (`transactionreferenceid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteParty` +-- + +DROP TABLE IF EXISTS `quoteParty`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteParty` ( + `quotePartyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `partyTypeId` int(10) unsigned NOT NULL COMMENT 'Specifies the type of party this row relates to; typically PAYER or PAYEE', + `partyIdentifierTypeId` int(10) unsigned NOT NULL COMMENT 'Specifies the type of identifier used to identify this party e.g. MSISDN, IBAN etc...', + `partyIdentifierValue` varchar(128) NOT NULL COMMENT 'The value of the identifier used to identify this party', + `partySubIdOrTypeId` int(10) unsigned DEFAULT NULL COMMENT 'A sub-identifier or sub-type for the Party', + `fspId` varchar(255) DEFAULT NULL COMMENT 'This is the FSP ID as provided in the quote. For the switch between multi-parties it is required', + `participantId` int(10) unsigned DEFAULT NULL COMMENT 'Reference to the resolved FSP ID (if supplied/known). If not an error will be reported', + `merchantClassificationCode` varchar(4) DEFAULT NULL COMMENT 'Used in the context of Payee Information, where the Payee happens to be a merchant accepting merchant payments', + `partyName` varchar(128) DEFAULT NULL COMMENT 'Display name of the Party, could be a real name or a nick name', + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL COMMENT 'The role this Party is playing in the transaction', + `ledgerEntryTypeId` int(10) unsigned NOT NULL COMMENT 'The type of financial entry this Party is presenting', + `amount` decimal(18,4) NOT NULL, + `currencyId` varchar(3) NOT NULL COMMENT 'Trading currency pertaining to the party amount', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quotePartyId`), + KEY `quoteparty_quoteid_foreign` (`quoteId`), + KEY `quoteparty_partytypeid_foreign` (`partyTypeId`), + KEY `quoteparty_partyidentifiertypeid_foreign` (`partyIdentifierTypeId`), + KEY `quoteparty_partysubidortypeid_foreign` (`partySubIdOrTypeId`), + KEY `quoteparty_participantid_foreign` (`participantId`), + KEY `quoteparty_transferparticipantroletypeid_foreign` (`transferParticipantRoleTypeId`), + KEY `quoteparty_ledgerentrytypeid_foreign` (`ledgerEntryTypeId`), + KEY `quoteparty_currencyid_foreign` (`currencyId`), + CONSTRAINT `quoteparty_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quoteparty_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `quoteparty_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`), + CONSTRAINT `quoteparty_partyidentifiertypeid_foreign` FOREIGN KEY (`partyIdentifierTypeId`) REFERENCES `partyIdentifierType` (`partyidentifiertypeid`), + CONSTRAINT `quoteparty_partysubidortypeid_foreign` FOREIGN KEY (`partySubIdOrTypeId`) REFERENCES `partyIdentifierType` (`partyidentifiertypeid`), + CONSTRAINT `quoteparty_partytypeid_foreign` FOREIGN KEY (`partyTypeId`) REFERENCES `partyType` (`partytypeid`), + CONSTRAINT `quoteparty_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteparty_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Temporary view structure for view `quotePartyView` +-- + +DROP TABLE IF EXISTS `quotePartyView`; +/*!50001 DROP VIEW IF EXISTS `quotePartyView`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8mb4; +/*!50001 CREATE VIEW `quotePartyView` AS SELECT + 1 AS `quoteId`, + 1 AS `quotePartyId`, + 1 AS `partyType`, + 1 AS `identifierType`, + 1 AS `partyIdentifierValue`, + 1 AS `partySubIdOrType`, + 1 AS `fspId`, + 1 AS `merchantClassificationCode`, + 1 AS `partyName`, + 1 AS `firstName`, + 1 AS `lastName`, + 1 AS `middleName`, + 1 AS `dateOfBirth`, + 1 AS `longitude`, + 1 AS `latitude`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `quoteResponse` +-- + +DROP TABLE IF EXISTS `quoteResponse`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteResponse` ( + `quoteResponseId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `transferAmountCurrencyId` varchar(3) NOT NULL COMMENT 'CurrencyId of the transfer amount', + `transferAmount` decimal(18,4) NOT NULL COMMENT 'The amount of money that the Payer FSP should transfer to the Payee FSP', + `payeeReceiveAmountCurrencyId` varchar(3) DEFAULT NULL COMMENT 'CurrencyId of the payee receive amount', + `payeeReceiveAmount` decimal(18,4) DEFAULT NULL COMMENT 'The amount of Money that the Payee should receive in the end-to-end transaction. Optional as the Payee FSP might not want to disclose any optional Payee fees', + `payeeFspFeeCurrencyId` varchar(3) DEFAULT NULL COMMENT 'CurrencyId of the payee fsp fee amount', + `payeeFspFeeAmount` decimal(18,4) DEFAULT NULL COMMENT 'Payee FSP’s part of the transaction fee', + `payeeFspCommissionCurrencyId` varchar(3) DEFAULT NULL COMMENT 'CurrencyId of the payee fsp commission amount', + `payeeFspCommissionAmount` decimal(18,4) DEFAULT NULL COMMENT 'Transaction commission from the Payee FSP', + `ilpCondition` varchar(256) NOT NULL, + `responseExpirationDate` datetime DEFAULT NULL COMMENT 'Optional expiration for the requested transaction', + `isValid` tinyint(1) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteResponseId`), + KEY `quoteresponse_quoteid_foreign` (`quoteId`), + KEY `quoteresponse_transferamountcurrencyid_foreign` (`transferAmountCurrencyId`), + KEY `quoteresponse_payeereceiveamountcurrencyid_foreign` (`payeeReceiveAmountCurrencyId`), + KEY `quoteresponse_payeefspcommissioncurrencyid_foreign` (`payeeFspCommissionCurrencyId`), + CONSTRAINT `quoteresponse_payeefspcommissioncurrencyid_foreign` FOREIGN KEY (`payeeFspCommissionCurrencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quoteresponse_payeereceiveamountcurrencyid_foreign` FOREIGN KEY (`payeeReceiveAmountCurrencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quoteresponse_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteresponse_transferamountcurrencyid_foreign` FOREIGN KEY (`transferAmountCurrencyId`) REFERENCES `currency` (`currencyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='This table is the primary store for quote responses'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteResponseDuplicateCheck` +-- + +DROP TABLE IF EXISTS `quoteResponseDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteResponseDuplicateCheck` ( + `quoteResponseId` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'The response to the intial quote', + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `hash` varchar(255) DEFAULT NULL COMMENT 'hash value received for the quote response', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteResponseId`), + KEY `quoteresponseduplicatecheck_quoteid_foreign` (`quoteId`), + CONSTRAINT `quoteresponseduplicatecheck_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteresponseduplicatecheck_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteResponseIlpPacket` +-- + +DROP TABLE IF EXISTS `quoteResponseIlpPacket`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteResponseIlpPacket` ( + `quoteResponseId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `value` text NOT NULL COMMENT 'ilpPacket returned from Payee in response to a quote request', + PRIMARY KEY (`quoteResponseId`), + CONSTRAINT `quoteresponseilppacket_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Temporary view structure for view `quoteResponseView` +-- + +DROP TABLE IF EXISTS `quoteResponseView`; +/*!50001 DROP VIEW IF EXISTS `quoteResponseView`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8mb4; +/*!50001 CREATE VIEW `quoteResponseView` AS SELECT + 1 AS `quoteResponseId`, + 1 AS `quoteId`, + 1 AS `transferAmountCurrencyId`, + 1 AS `transferAmount`, + 1 AS `payeeReceiveAmountCurrencyId`, + 1 AS `payeeReceiveAmount`, + 1 AS `payeeFspFeeCurrencyId`, + 1 AS `payeeFspFeeAmount`, + 1 AS `payeeFspCommissionCurrencyId`, + 1 AS `payeeFspCommissionAmount`, + 1 AS `ilpCondition`, + 1 AS `responseExpirationDate`, + 1 AS `isValid`, + 1 AS `createdDate`, + 1 AS `ilpPacket`, + 1 AS `longitude`, + 1 AS `latitude`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Temporary view structure for view `quoteView` +-- + +DROP TABLE IF EXISTS `quoteView`; +/*!50001 DROP VIEW IF EXISTS `quoteView`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8mb4; +/*!50001 CREATE VIEW `quoteView` AS SELECT + 1 AS `quoteId`, + 1 AS `transactionReferenceId`, + 1 AS `transactionRequestId`, + 1 AS `note`, + 1 AS `expirationDate`, + 1 AS `transactionInitiator`, + 1 AS `transactionInitiatorType`, + 1 AS `transactionScenario`, + 1 AS `balanceOfPaymentsId`, + 1 AS `transactionSubScenario`, + 1 AS `amountType`, + 1 AS `amount`, + 1 AS `currency`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `segment` +-- + +DROP TABLE IF EXISTS `segment`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `segment` ( + `segmentId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `segmentType` varchar(50) NOT NULL, + `enumeration` int(11) NOT NULL DEFAULT '0', + `tableName` varchar(50) NOT NULL, + `value` bigint(20) NOT NULL, + `changedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`segmentId`), + KEY `segment_keys_index` (`segmentType`,`enumeration`,`tableName`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlement` +-- + +DROP TABLE IF EXISTS `settlement`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlement` ( + `settlementId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`settlementId`), + KEY `settlement_currentstatechangeid_foreign` (`currentStateChangeId`), + CONSTRAINT `settlement_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementStateChange` (`settlementstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementParticipantCurrency` +-- + +DROP TABLE IF EXISTS `settlementParticipantCurrency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementParticipantCurrency` ( + `settlementParticipantCurrencyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `netAmount` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + `settlementTransferId` varchar(36) DEFAULT NULL, + PRIMARY KEY (`settlementParticipantCurrencyId`), + KEY `settlementparticipantcurrency_settlementid_index` (`settlementId`), + KEY `settlementparticipantcurrency_participantcurrencyid_index` (`participantCurrencyId`), + KEY `settlementparticipantcurrency_settlementtransferid_index` (`settlementTransferId`), + KEY `spc_currentstatechangeid_foreign` (`currentStateChangeId`), + CONSTRAINT `settlementparticipantcurrency_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `settlementparticipantcurrency_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `spc_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementParticipantCurrencyStateChange` (`settlementparticipantcurrencystatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementParticipantCurrencyStateChange` +-- + +DROP TABLE IF EXISTS `settlementParticipantCurrencyStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementParticipantCurrencyStateChange` ( + `settlementParticipantCurrencyStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementParticipantCurrencyId` bigint(20) unsigned NOT NULL, + `settlementStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `externalReference` varchar(50) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementParticipantCurrencyStateChangeId`), + KEY `spcsc_settlementparticipantcurrencyid_index` (`settlementParticipantCurrencyId`), + KEY `spcsc_settlementstateid_index` (`settlementStateId`), + CONSTRAINT `spcsc_settlementparticipantcurrencyid_foreign` FOREIGN KEY (`settlementParticipantCurrencyId`) REFERENCES `settlementParticipantCurrency` (`settlementparticipantcurrencyid`), + CONSTRAINT `spcsc_settlementstateid_foreign` FOREIGN KEY (`settlementStateId`) REFERENCES `settlementState` (`settlementstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementSettlementWindow` +-- + +DROP TABLE IF EXISTS `settlementSettlementWindow`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementSettlementWindow` ( + `settlementSettlementWindowId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementSettlementWindowId`), + UNIQUE KEY `settlementsettlementwindow_unique` (`settlementId`,`settlementWindowId`), + KEY `settlementsettlementwindow_settlementid_index` (`settlementId`), + KEY `settlementsettlementwindow_settlementwindowid_index` (`settlementWindowId`), + CONSTRAINT `settlementsettlementwindow_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementsettlementwindow_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementState` +-- + +DROP TABLE IF EXISTS `settlementState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementState` ( + `settlementStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementStateChange` +-- + +DROP TABLE IF EXISTS `settlementStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementStateChange` ( + `settlementStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `settlementStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementStateChangeId`), + KEY `settlementstatechange_settlementid_index` (`settlementId`), + KEY `settlementstatechange_settlementstateid_index` (`settlementStateId`), + CONSTRAINT `settlementstatechange_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementstatechange_settlementstateid_foreign` FOREIGN KEY (`settlementStateId`) REFERENCES `settlementState` (`settlementstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementTransferParticipant` +-- + +DROP TABLE IF EXISTS `settlementTransferParticipant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementTransferParticipant` ( + `settlementTransferParticipantId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL, + `ledgerEntryTypeId` int(10) unsigned NOT NULL, + `amount` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementTransferParticipantId`), + KEY `settlementtransferparticipant_settlementid_index` (`settlementId`), + KEY `settlementtransferparticipant_settlementwindowid_index` (`settlementWindowId`), + KEY `settlementtransferparticipant_participantcurrencyid_index` (`participantCurrencyId`), + KEY `stp_transferparticipantroletypeid_index` (`transferParticipantRoleTypeId`), + KEY `settlementtransferparticipant_ledgerentrytypeid_index` (`ledgerEntryTypeId`), + CONSTRAINT `settlementtransferparticipant_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `settlementtransferparticipant_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `settlementtransferparticipant_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementtransferparticipant_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`), + CONSTRAINT `stp_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindow` +-- + +DROP TABLE IF EXISTS `settlementWindow`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementWindow` ( + `settlementWindowId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`settlementWindowId`), + KEY `settlementwindow_currentstatechangeid_foreign` (`currentStateChangeId`), + CONSTRAINT `settlementwindow_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementWindowStateChange` (`settlementwindowstatechangeid`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindowState` +-- + +DROP TABLE IF EXISTS `settlementWindowState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementWindowState` ( + `settlementWindowStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementWindowStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindowStateChange` +-- + +DROP TABLE IF EXISTS `settlementWindowStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementWindowStateChange` ( + `settlementWindowStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `settlementWindowStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementWindowStateChangeId`), + KEY `settlementwindowstatechange_settlementwindowid_index` (`settlementWindowId`), + KEY `settlementwindowstatechange_settlementwindowstateid_index` (`settlementWindowStateId`), + CONSTRAINT `settlementwindowstatechange_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`), + CONSTRAINT `settlementwindowstatechange_settlementwindowstateid_foreign` FOREIGN KEY (`settlementWindowStateId`) REFERENCES `settlementWindowState` (`settlementwindowstateid`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `token` +-- + +DROP TABLE IF EXISTS `token`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `token` ( + `tokenId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `value` varchar(256) NOT NULL, + `expiration` bigint(20) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`tokenId`), + UNIQUE KEY `token_value_unique` (`value`), + KEY `token_participantid_index` (`participantId`), + CONSTRAINT `token_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionInitiator` +-- + +DROP TABLE IF EXISTS `transactionInitiator`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transactionInitiator` ( + `transactionInitiatorId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionInitiatorId`), + UNIQUE KEY `transactioninitiator_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionInitiatorType` +-- + +DROP TABLE IF EXISTS `transactionInitiatorType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transactionInitiatorType` ( + `transactionInitiatorTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionInitiatorTypeId`), + UNIQUE KEY `transactioninitiatortype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionReference` +-- + +DROP TABLE IF EXISTS `transactionReference`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transactionReference` ( + `transactionReferenceId` varchar(36) NOT NULL COMMENT 'Common ID (decided by the Payer FSP) between the FSPs for the future transaction object', + `quoteId` varchar(36) DEFAULT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System row creation timestamp', + PRIMARY KEY (`transactionReferenceId`), + KEY `transactionreference_quoteid_index` (`quoteId`), + CONSTRAINT `transactionreference_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quoteDuplicateCheck` (`quoteid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionScenario` +-- + +DROP TABLE IF EXISTS `transactionScenario`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transactionScenario` ( + `transactionScenarioId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionScenarioId`), + UNIQUE KEY `transactionscenario_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionSubScenario` +-- + +DROP TABLE IF EXISTS `transactionSubScenario`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transactionSubScenario` ( + `transactionSubScenarioId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL COMMENT 'Possible sub-scenario, defined locally within the scheme', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionSubScenarioId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transfer` +-- + +DROP TABLE IF EXISTS `transfer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transfer` ( + `transferId` varchar(36) NOT NULL, + `amount` decimal(18,4) NOT NULL, + `currencyId` varchar(3) NOT NULL, + `ilpCondition` varchar(256) NOT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + KEY `transfer_currencyid_index` (`currencyId`), + CONSTRAINT `transfer_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `transfer_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transferDuplicateCheck` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferDuplicateCheck` +-- + +DROP TABLE IF EXISTS `transferDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferDuplicateCheck` ( + `transferId` varchar(36) NOT NULL, + `hash` varchar(256) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferError` +-- + +DROP TABLE IF EXISTS `transferError`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferError` ( + `transferId` varchar(36) NOT NULL, + `transferStateChangeId` bigint(20) unsigned NOT NULL, + `errorCode` int(10) unsigned NOT NULL, + `errorDescription` varchar(128) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + KEY `transfererror_transferstatechangeid_foreign` (`transferStateChangeId`), + CONSTRAINT `transfererror_transferstatechangeid_foreign` FOREIGN KEY (`transferStateChangeId`) REFERENCES `transferStateChange` (`transferstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferErrorDuplicateCheck` +-- + +DROP TABLE IF EXISTS `transferErrorDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferErrorDuplicateCheck` ( + `transferId` varchar(36) NOT NULL, + `hash` varchar(256) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + CONSTRAINT `transfererrorduplicatecheck_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferExtension` +-- + +DROP TABLE IF EXISTS `transferExtension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferExtension` ( + `transferExtensionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `key` varchar(128) NOT NULL, + `value` text NOT NULL, + `isFulfilment` tinyint(1) NOT NULL DEFAULT '0', + `isError` tinyint(1) NOT NULL DEFAULT '0', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferExtensionId`), + KEY `transferextension_transferid_foreign` (`transferId`), + CONSTRAINT `transferextension_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferFulfilment` +-- + +DROP TABLE IF EXISTS `transferFulfilment`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferFulfilment` ( + `transferId` varchar(36) NOT NULL, + `ilpFulfilment` varchar(256) DEFAULT NULL, + `completedDate` datetime NOT NULL, + `isValid` tinyint(1) DEFAULT NULL, + `settlementWindowId` bigint(20) unsigned DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + KEY `transferfulfilment_settlementwindowid_foreign` (`settlementWindowId`), + CONSTRAINT `transferfulfilment_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`), + CONSTRAINT `transferfulfilment_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transferFulfilmentDuplicateCheck` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferFulfilmentDuplicateCheck` +-- + +DROP TABLE IF EXISTS `transferFulfilmentDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferFulfilmentDuplicateCheck` ( + `transferId` varchar(36) NOT NULL, + `hash` varchar(256) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + CONSTRAINT `transferfulfilmentduplicatecheck_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferParticipant` +-- + +DROP TABLE IF EXISTS `transferParticipant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferParticipant` ( + `transferParticipantId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL, + `ledgerEntryTypeId` int(10) unsigned NOT NULL, + `amount` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferParticipantId`), + KEY `transferparticipant_transferid_index` (`transferId`), + KEY `transferparticipant_participantcurrencyid_index` (`participantCurrencyId`), + KEY `transferparticipant_transferparticipantroletypeid_index` (`transferParticipantRoleTypeId`), + KEY `transferparticipant_ledgerentrytypeid_index` (`ledgerEntryTypeId`), + CONSTRAINT `transferparticipant_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `transferparticipant_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `transferparticipant_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`), + CONSTRAINT `transferparticipant_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferParticipantRoleType` +-- + +DROP TABLE IF EXISTS `transferParticipantRoleType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferParticipantRoleType` ( + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferParticipantRoleTypeId`), + UNIQUE KEY `transferparticipantroletype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferRules` +-- + +DROP TABLE IF EXISTS `transferRules`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferRules` ( + `transferRulesId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `rule` text NOT NULL, + `enabled` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferRulesId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferState` +-- + +DROP TABLE IF EXISTS `transferState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferState` ( + `transferStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL COMMENT 'transferState associated to the Mojaloop API', + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferStateChange` +-- + +DROP TABLE IF EXISTS `transferStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferStateChange` ( + `transferStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `transferStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferStateChangeId`), + KEY `transferstatechange_transferid_index` (`transferId`), + KEY `transferstatechange_transferstateid_index` (`transferStateId`), + CONSTRAINT `transferstatechange_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`), + CONSTRAINT `transferstatechange_transferstateid_foreign` FOREIGN KEY (`transferStateId`) REFERENCES `transferState` (`transferstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferTimeout` +-- + +DROP TABLE IF EXISTS `transferTimeout`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferTimeout` ( + `transferTimeoutId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferTimeoutId`), + UNIQUE KEY `transfertimeout_transferid_unique` (`transferId`), + CONSTRAINT `transfertimeout_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Final view structure for view `quotePartyView` +-- + +/*!50001 DROP VIEW IF EXISTS `quotePartyView`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`central_ledger`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `quotePartyView` AS select `qp`.`quoteId` AS `quoteId`,`qp`.`quotePartyId` AS `quotePartyId`,`pt`.`name` AS `partyType`,`pit`.`name` AS `identifierType`,`qp`.`partyIdentifierValue` AS `partyIdentifierValue`,`spit`.`name` AS `partySubIdOrType`,`qp`.`fspId` AS `fspId`,`qp`.`merchantClassificationCode` AS `merchantClassificationCode`,`qp`.`partyName` AS `partyName`,`p`.`firstName` AS `firstName`,`p`.`lastName` AS `lastName`,`p`.`middleName` AS `middleName`,`p`.`dateOfBirth` AS `dateOfBirth`,`gc`.`longitude` AS `longitude`,`gc`.`latitude` AS `latitude` from (((((`quoteParty` `qp` join `partyType` `pt` on((`pt`.`partyTypeId` = `qp`.`partyTypeId`))) join `partyIdentifierType` `pit` on((`pit`.`partyIdentifierTypeId` = `qp`.`partyIdentifierTypeId`))) left join `party` `p` on((`p`.`quotePartyId` = `qp`.`quotePartyId`))) left join `partyIdentifierType` `spit` on((`spit`.`partyIdentifierTypeId` = `qp`.`partySubIdOrTypeId`))) left join `geoCode` `gc` on((`gc`.`quotePartyId` = `qp`.`quotePartyId`))) */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; + +-- +-- Final view structure for view `quoteResponseView` +-- + +/*!50001 DROP VIEW IF EXISTS `quoteResponseView`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`central_ledger`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `quoteResponseView` AS select `qr`.`quoteResponseId` AS `quoteResponseId`,`qr`.`quoteId` AS `quoteId`,`qr`.`transferAmountCurrencyId` AS `transferAmountCurrencyId`,`qr`.`transferAmount` AS `transferAmount`,`qr`.`payeeReceiveAmountCurrencyId` AS `payeeReceiveAmountCurrencyId`,`qr`.`payeeReceiveAmount` AS `payeeReceiveAmount`,`qr`.`payeeFspFeeCurrencyId` AS `payeeFspFeeCurrencyId`,`qr`.`payeeFspFeeAmount` AS `payeeFspFeeAmount`,`qr`.`payeeFspCommissionCurrencyId` AS `payeeFspCommissionCurrencyId`,`qr`.`payeeFspCommissionAmount` AS `payeeFspCommissionAmount`,`qr`.`ilpCondition` AS `ilpCondition`,`qr`.`responseExpirationDate` AS `responseExpirationDate`,`qr`.`isValid` AS `isValid`,`qr`.`createdDate` AS `createdDate`,`qrilp`.`value` AS `ilpPacket`,`gc`.`longitude` AS `longitude`,`gc`.`latitude` AS `latitude` from ((((`quoteResponse` `qr` join `quoteResponseIlpPacket` `qrilp` on((`qrilp`.`quoteResponseId` = `qr`.`quoteResponseId`))) join `quoteParty` `qp` on((`qp`.`quoteId` = `qr`.`quoteId`))) join `partyType` `pt` on((`pt`.`partyTypeId` = `qp`.`partyTypeId`))) left join `geoCode` `gc` on((`gc`.`quotePartyId` = `qp`.`quotePartyId`))) where (`pt`.`name` = 'PAYEE') */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; + +-- +-- Final view structure for view `quoteView` +-- + +/*!50001 DROP VIEW IF EXISTS `quoteView`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`central_ledger`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `quoteView` AS select `q`.`quoteId` AS `quoteId`,`q`.`transactionReferenceId` AS `transactionReferenceId`,`q`.`transactionRequestId` AS `transactionRequestId`,`q`.`note` AS `note`,`q`.`expirationDate` AS `expirationDate`,`ti`.`name` AS `transactionInitiator`,`tit`.`name` AS `transactionInitiatorType`,`ts`.`name` AS `transactionScenario`,`q`.`balanceOfPaymentsId` AS `balanceOfPaymentsId`,`tss`.`name` AS `transactionSubScenario`,`amt`.`name` AS `amountType`,`q`.`amount` AS `amount`,`q`.`currencyId` AS `currency` from (((((`quote` `q` join `transactionInitiator` `ti` on((`ti`.`transactionInitiatorId` = `q`.`transactionInitiatorId`))) join `transactionInitiatorType` `tit` on((`tit`.`transactionInitiatorTypeId` = `q`.`transactionInitiatorTypeId`))) join `transactionScenario` `ts` on((`ts`.`transactionScenarioId` = `q`.`transactionScenarioId`))) join `amountType` `amt` on((`amt`.`amountTypeId` = `q`.`amountTypeId`))) left join `transactionSubScenario` `tss` on((`tss`.`transactionSubScenarioId` = `q`.`transactionSubScenarioId`))) */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2019-10-14 21:12:45 diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-schema-DBeaver.erd b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-schema-DBeaver.erd new file mode 100644 index 000000000..12059bab5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-schema-DBeaver.erd @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COLOR LEGEND: +Green - subject specific entity +Gray - transfer specific entity +Brown - bulk transfer entity +Red - settlement specific entity +Blue - lookup entity +Cyan - impl. specific +Yellow - tbd + + \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-schema.png b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-schema.png new file mode 100644 index 000000000..6afdaf2ea Binary files /dev/null and b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/database/central-ledger-schema.png differ diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/architecture/Figure60-Example-Bulk-Transfer-Process-Spec1.0.png b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/architecture/Figure60-Example-Bulk-Transfer-Process-Spec1.0.png new file mode 100644 index 000000000..aa361a64a Binary files /dev/null and b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/architecture/Figure60-Example-Bulk-Transfer-Process-Spec1.0.png differ diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/architecture/bulk-transfer-arch-flows.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/architecture/bulk-transfer-arch-flows.svg new file mode 100644 index 000000000..b22f23afe --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/architecture/bulk-transfer-arch-flows.svg @@ -0,0 +1,3 @@ + + +
    1.7 Increment Position (fsp1)
    [Not supported by viewer]
    1.6 Increment
    Position (fsp1)

    [Not supported by viewer]
    Fulfil
    Sucess
    [Not supported by viewer]
    2.6 Fulfil
    Success
    [Not supported by viewer]
    <alt> 2.6  Fulfil Reject
    [Not supported by viewer]
    Fulfil
    Reject
    [Not supported by viewer]
    <alt> 2.7 Decrement
    Position (fsp1)

    [Not supported by viewer]
    Central - Services
    <font style="font-size: 18px">Central - Services</font>
    3.0 Reject
    [Not supported by viewer]
    1.0 Bulk Transfer 
    Request

    [Not supported by viewer]
    3.1 Decrement
    Position (fsp1)

    [Not supported by viewer]
    ML-Adapter
    [Not supported by viewer]
    Bulk Transfer
    Bulk Transfer<br>
    Notification
    Event Handler
    [Not supported by viewer]
    notifications
    notifications
    FSP1
    (Payer)

    [Not supported by viewer]
    FSP2
    (Payee)
    [Not supported by viewer]
    1.1
    Prepare Request
    [Not supported by viewer]
    1.2 Accpeted
    (202)
    [Not supported by viewer]
    Bulk Transfer
    Bulk Transfer<br>
    2.0 Bulk Fulfil 
    Success / 
    Reject

    [Not supported by viewer]
    bulk fulfil
    bulk fulfil
    2.7 Decrement
    Position (fsp2)

    [Not supported by viewer]
    2.1 Bulk Fulfil 
    Success / Reject

    [Not supported by viewer]
    2.2 OK
    (202)
    [Not supported by viewer]
    OK (200)
    [Not supported by viewer]
    OK (200)
    [Not supported by viewer]
    Transfer Timeout
    Handler
    [Not supported by viewer]
    2.12 Bulk Fulfil Notify Callback /
    <alt> 2.12 Bulk Reject Response (Fulfil reject) /
    3.6 Bulk Reject Response (Timeout) /
    <alt> 1.8 Bulk Prepare Failure 
    [Not supported by viewer]
    1.12 Bulk Prepare Notify /
    2.13 Bulk Fulfil Notify /
    <alt> 2.13 Bulk Reject Response (Fulfil reject)
    3.7 Bulk Reject Response (Timeout)

    [Not supported by viewer]
    positions
    positions<br>
    bulk processing
    bulk processing
    BulkFulfil
    Handler
    [Not supported by viewer]
    1.3 Bulk Prepare Consume
    [Not supported by viewer]
    BulkPrepare
    Handler
    BulkPrepare<br>Handler
     prepare
     prepare
    fulfil
    fulfil
    BulkProcessing Handler
    BulkProcessing Handler<br>
    1.4 Individual Prepare
    [Not supported by viewer]
    1.5 Individual Prepare
    [Not supported by viewer]
    1.5
     / 1.9 / 2.9 / 3.3
     Individual Notify
    [Not supported by viewer]
    1.8 / 2.8 / 3.2 Individual
    Notify
    [Not supported by viewer]
    1.6 / 1.10 / 2.10 / 3.4 Bulk Notify
    [Not supported by viewer]
    1.7 / 1.11 / 2.11 / 3.5 Bulk Notify
    [Not supported by viewer]
    2.3 Bulk Fulfil Consume
    [Not supported by viewer]
    2.4 Individual
    Fulfil
    [Not supported by viewer]
    2.5 Individual
    Fulfil
    [Not supported by viewer]
    FulfilHandler
    FulfilHandler
    Success/
    Reject
    [Not supported by viewer]
    PositionHandler
    PositionHandler
    PrepareHandler
    PrepareHandler
    Object Store
    [Not supported by viewer]
    <alt> 1.4 Bulk Prepare Failure
    [Not supported by viewer]
    <alt> 1.6 Individual Prepare Failure
    [Not supported by viewer]
    <alt> 1.8 Individual
    Failure Notify

    [Not supported by viewer]
    <alt> 2.4 Bulk Fulfil Failure
    [Not supported by viewer]
    <alt> 2.6 Individual Fulfil Failure
    [Not supported by viewer]
    bulk prepare
    bulk prepare
    Object Store
    [Not supported by viewer]
    Object Store
    [Not supported by viewer]
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml new file mode 100644 index 000000000..5bdd8119f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml @@ -0,0 +1,217 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declare title +title 1.1.0. DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "Bulk API Adapter" as BULK_API +control "Bulk API Notification \nHandler" as NOTIFY_HANDLER +collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE +boundary "Central Service API" as CSAPI +collections "topic-\nbulk-prepare" as TOPIC_BULK_PREPARE +control "Bulk Prepare\nHandler" as BULK_PREP_HANDLER +collections "topic-\ntransfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Handler" as PREP_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +control "Bulk Processing\nHandler" as BULK_PROC_HANDLER +collections "topic-\nnotifications" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "Bulk API Adapter Service" #LightBlue + participant BULK_API + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant OBJECT_STORE + participant CSAPI + participant TOPIC_BULK_PREPARE + participant BULK_PREP_HANDLER + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_BULK_PROCESSING + participant BULK_PROC_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate BULK_PREP_HANDLER +activate PREP_HANDLER +activate POS_HANDLER +activate BULK_PROC_HANDLER +group DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + note right of DFSP1 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - bulkTransferMessage: + { + bulkTransferId: , + bulkQuoteId: , + payeeFsp: , + payerFsp: , + individualTransfers: [ + { + transferId: , + transferAmount: + { + currency: , + amount: + }, + ilpPacket: , + condition: , + extensionList: { extension: [ + { key: , value: } + ] } + } + ], + extensionList: { extension: [ + { key: , value: } + ] }, + expiration: + } + end note + DFSP1 ->> BULK_API: POST - /bulkTransfers + activate BULK_API + BULK_API -> BULK_API: Validate incoming message\nError codes: 3000-3002, 3100-3107 + loop + BULK_API -> OBJECT_STORE: Persist individual transfers in the bulk to\nobject store: **MLOS.individualTransfers** + activate OBJECT_STORE + OBJECT_STORE --> BULK_API: Return messageId reference to the stored object(s) + deactivate OBJECT_STORE + end + note right of BULK_API #yellow + Message: + { + id: + to: , + from: , + type: "application/json" + content: { + headers: , + payload: { + bulkTransferId: , + bulkQuoteId": , + payerFsp: , + payeeFsp: , + expiration: , + hash: + } + }, + metadata: { + event: { + id: , + type: "bulk-prepare", + action: "bulk-prepare", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + BULK_API -> TOPIC_BULK_PREPARE: Route & Publish Bulk Prepare event \nfor Payer\nError code: 2003 + activate TOPIC_BULK_PREPARE + TOPIC_BULK_PREPARE <-> TOPIC_BULK_PREPARE: Ensure event is replicated \nas configured (ACKS=all)\nError code: 2003 + TOPIC_BULK_PREPARE --> BULK_API: Respond replication acknowledgements \nhave been received + deactivate TOPIC_BULK_PREPARE + BULK_API -->> DFSP1: Respond HTTP - 202 (Accepted) + deactivate BULK_API + ||| + TOPIC_BULK_PREPARE <- BULK_PREP_HANDLER: Consume message + ref over TOPIC_BULK_PREPARE, BULK_PREP_HANDLER, TOPIC_TRANSFER_PREPARE: Bulk Prepare Handler Consume \n + alt Success + BULK_PREP_HANDLER -> TOPIC_TRANSFER_PREPARE: Produce (stream) single transfer message\nfor each individual transfer [loop] + else Failure + BULK_PREP_HANDLER --> TOPIC_NOTIFICATIONS: Produce single message for the entire bulk + end + ||| + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume message + ref over TOPIC_TRANSFER_PREPARE, PREP_HANDLER, TOPIC_TRANSFER_POSITION: Prepare Handler Consume\n + alt Success + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + else Failure + PREP_HANDLER --> TOPIC_BULK_PROCESSING: Produce message + end + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, POS_HANDLER, TOPIC_BULK_PROCESSING: Position Handler Consume\n + POS_HANDLER -> TOPIC_BULK_PROCESSING: Produce message + ||| + TOPIC_BULK_PROCESSING <- BULK_PROC_HANDLER: Consume message + ref over TOPIC_BULK_PROCESSING, BULK_PROC_HANDLER, TOPIC_NOTIFICATIONS: Bulk Processing Handler Consume\n + BULK_PROC_HANDLER -> OBJECT_STORE: Persist bulk message by destination to the\nobject store: **MLOS.bulkTransferResults** + activate OBJECT_STORE + OBJECT_STORE --> BULK_PROC_HANDLER: Return the reference to the stored \nnotification object(s): **messageId** + deactivate OBJECT_STORE + BULK_PROC_HANDLER -> TOPIC_NOTIFICATIONS: Send Bulk Prepare notification + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + NOTIFY_HANDLER -> OBJECT_STORE: Retrieve bulk notification(s) by reference & destination:\n**MLOS.bulkTransferResults.messageId + destination** + activate OBJECT_STORE + OBJECT_STORE --> NOTIFY_HANDLER: Return notification(s) payload + deactivate OBJECT_STORE + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send Bulk Prepare notification to Payee + ||| +end +deactivate POS_HANDLER +deactivate BULK_PREP_HANDLER +deactivate PREP_HANDLER +deactivate BULK_PROC_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.svg new file mode 100644 index 000000000..b24804c17 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.svg @@ -0,0 +1,788 @@ + + + + + + + + + + + 1.1.0. DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + + + + Financial Service Providers + + + + Bulk API Adapter Service + + + + Central Service + + + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + Bulk API Adapter + + + + + Bulk API Adapter + + + + + Bulk API Notification + + + Handler + + + + + Bulk API Notification + + + Handler + + + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + Central Service API + + + + + Central Service API + + + + + + + topic- + + + bulk-prepare + + + + + topic- + + + bulk-prepare + + + Bulk Prepare + + + Handler + + + + + Bulk Prepare + + + Handler + + + + + + + topic- + + + transfer-prepare + + + + + topic- + + + transfer-prepare + + + Prepare Handler + + + + + Prepare Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + Position Handler + + + + + Position Handler + + + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Bulk Processing + + + Handler + + + + + Bulk Processing + + + Handler + + + + + + + topic- + + + notifications + + + + + topic- + + + notifications + + + + + + DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + + + + + Headers - transferHeaders: { + + + Content-Length: <int>, + + + Content-Type: <string>, + + + Date: <date>, + + + FSPIOP-Source: <string>, + + + FSPIOP-Destination: <string>, + + + FSPIOP-Encryption: <string>, + + + FSPIOP-Signature: <string>, + + + FSPIOP-URI: <uri>, + + + FSPIOP-HTTP-Method: <string> + + + } + + + Payload - bulkTransferMessage: + + + { + + + bulkTransferId: <uuid>, + + + bulkQuoteId: <uuid>, + + + payeeFsp: <string>, + + + payerFsp: <string>, + + + individualTransfers: [ + + + { + + + transferId: <uuid>, + + + transferAmount: + + + { + + + currency: <string>, + + + amount: <string> + + + }, + + + ilpPacket: <string>, + + + condition: <string>, + + + extensionList: { extension: [ + + + { key: <string>, value: <string> } + + + ] } + + + } + + + ], + + + extensionList: { extension: [ + + + { key: <string>, value: <string> } + + + ] }, + + + expiration: <string> + + + } + + + + 1 + + + POST - /bulkTransfers + + + + + 2 + + + Validate incoming message + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + loop + + + + + 3 + + + Persist individual transfers in the bulk to + + + object store: + + + MLOS.individualTransfers + + + + + 4 + + + Return messageId reference to the stored object(s) + + + + + Message: + + + { + + + id: <messageId> + + + to: <payeeFspName>, + + + from: <payerFspName>, + + + type: "application/json" + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + bulkTransferId: <uuid>, + + + bulkQuoteId": <uuid>, + + + payerFsp: <string>, + + + payeeFsp: <string>, + + + expiration: <timestamp>, + + + hash: <string> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: "bulk-prepare", + + + action: "bulk-prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 5 + + + Route & Publish Bulk Prepare event + + + for Payer + + + Error code: + + + 2003 + + + + + 6 + + + Ensure event is replicated + + + as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 7 + + + Respond replication acknowledgements + + + have been received + + + + + 8 + + + Respond HTTP - 202 (Accepted) + + + + + 9 + + + Consume message + + + + + ref + + + Bulk Prepare Handler Consume + + + + + alt + + + [Success] + + + + + 10 + + + Produce (stream) single transfer message + + + for each individual transfer [loop] + + + + [Failure] + + + + + 11 + + + Produce single message for the entire bulk + + + + + 12 + + + Consume message + + + + + ref + + + Prepare Handler Consume + + + + + alt + + + [Success] + + + + + 13 + + + Produce message + + + + [Failure] + + + + + 14 + + + Produce message + + + + + 15 + + + Consume message + + + + + ref + + + Position Handler Consume + + + + + 16 + + + Produce message + + + + + 17 + + + Consume message + + + + + ref + + + Bulk Processing Handler Consume + + + + + 18 + + + Persist bulk message by destination to the + + + object store: + + + MLOS.bulkTransferResults + + + + + 19 + + + Return the reference to the stored + + + notification object(s): + + + messageId + + + + + 20 + + + Send Bulk Prepare notification + + + + + 21 + + + Consume message + + + + + 22 + + + Retrieve bulk notification(s) by reference & destination: + + + MLOS.bulkTransferResults.messageId + destination + + + + + 23 + + + Return notification(s) payload + + + + + ref + + + Send notification to Participant (Payee) + + + + + 24 + + + Send Bulk Prepare notification to Payee + + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml new file mode 100644 index 000000000..a9c53292f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml @@ -0,0 +1,320 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declare title +title 1.1.1. Bulk Prepare Handler Consume + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-\nbulk-prepare" as TOPIC_BULK_PREPARE +collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE +control "Bulk Prepare \nHandler" as BULK_PREP_HANDLER +collections "topic-\ntransfer-prepare" as TOPIC_TRANSFER_PREPARE +collections "topic-event" as TOPIC_EVENTS +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-bulk-\nprocessing" as TOPIC_BULK_PROCESSING +entity "Bulk DAO" as BULK_DAO +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant OBJECT_STORE + participant TOPIC_BULK_PREPARE + participant BULK_PREP_HANDLER + participant TOPIC_TRANSFER_PREPARE + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant TOPIC_BULK_PROCESSING + participant BULK_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate BULK_PREP_HANDLER +group Bulk Prepare Handler Consume + TOPIC_BULK_PREPARE <- BULK_PREP_HANDLER: Consume Bulk Prepare message + activate TOPIC_BULK_PREPARE + deactivate TOPIC_BULK_PREPARE + group Validate Bulk Prepare Transfer + group Duplicate Check + note right of BULK_PREP_HANDLER #cyan + The Specification doesn't touch on the duplicate handling + of bulk transfers, so the current design mostly follows the + strategy used for individual transfers, except in two places: + + 1. For duplicate requests where hash matches, the current design + includes only the status of the bulk & timestamp (if completed), + but not the individual transfers (for which a GET should be used). + + 2. For duplicate requests where hash matches, but are not in a + finalized state, only the state of the bulkTransfer is sent. + end note + ||| + BULK_PREP_HANDLER -> DB: Request Duplicate Check + ref over BULK_PREP_HANDLER, DB: Request Duplicate Check (using message.content.payload)\n + DB --> BULK_PREP_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break Return TRUE & Log ('Not implemented') + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of BULK_PREP_HANDLER #yellow + { + id: , + from: , + to: , + type: "application/json", + content: { + headers: , + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request", + extensionList: { + extension: [ + { + key: "_cause", + value: + } + ] + } + }, + uriParams: { + id: + } + } + }, + metadata: { + correlationId: , + event: { + id: , + type: "notification", + action: "bulk-prepare", + createdAt: , + state: { + status: "error", + code: "3106", + description: "Modified request" + }, + responseTo: + } + } + } + end note + BULK_PREP_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError codes: 3106 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else hasDuplicateId == FALSE + group Validate Bulk Transfer Prepare Request + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: FSPIOP Source matches Payer + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Check expiration + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Payer and Payee FSP's are different + group Validate Payer + BULK_PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payer Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> BULK_PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Validate Payer\nError codes: 3202 + end + group Validate Payee + BULK_PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payee Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> BULK_PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Validate Payee\nError codes: 3203 + end + end + ||| + alt Validate Bulk Transfer Prepare Request (success) + group Persist Bulk Transfer State (with bulkTransferState='RECEIVED') + BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Persist bulkTransfer + hnote over DB #lightyellow + bulkTransfer + bulkTransferExtension + bulkTransferStateChange + end note + activate DB + deactivate DB + BULK_DAO --> BULK_PREP_HANDLER: Return state + deactivate BULK_DAO + end + else Validate Bulk Transfer Prepare Request (failure) + group Persist Bulk Transfer State (with bulkTransferState='INVALID') (Introducing a new status INVALID to mark these entries) + BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer\n(when Payee/Payer/crypto-condition validation fails)\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Persist transfer + hnote over DB #lightyellow + bulkTransfer + bulkTransferExtension + bulkTransferStateChange + bulkTransferError + end note + activate DB + deactivate DB + BULK_DAO --> BULK_PREP_HANDLER: Return state + deactivate BULK_DAO + end + end + end + end + alt Validate Bulk Prepare Transfer (success) + loop for each individual transfer in the bulk + BULK_PREP_HANDLER -> OBJECT_STORE: Retrieve individual transfers from the bulk using\nreference: **MLOS.individualTransfers.messageId** + activate OBJECT_STORE + note right of OBJECT_STORE #lightgrey + Add elements such as Expiry time, Payer FSP, Payee FSP, etc. to each + transfer to make their format similar to a single transfer + end note + OBJECT_STORE --> BULK_PREP_HANDLER: Stream bulk's individual transfers + deactivate OBJECT_STORE + + group Insert Bulk Transfer Association (with bulkProcessingState='RECEIVED') + BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer association\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Insert bulkTransferAssociation + hnote over DB #lightyellow + bulkTransferAssociation + bulkTransferStateChange + end note + activate DB + deactivate DB + BULK_DAO --> BULK_PREP_HANDLER: Return state + deactivate BULK_DAO + end + + note right of BULK_PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "prepare", + action: "bulk-prepare", + createdAt: , + state: { + status: "success", + code: 0, + description:"action successful" + } + } + } + } + end note + BULK_PREP_HANDLER -> TOPIC_TRANSFER_PREPARE: Route & Publish Prepare event to the Payee for the Individual Transfer\nError codes: 2003 + activate TOPIC_TRANSFER_PREPARE + deactivate TOPIC_TRANSFER_PREPARE + end + else Validate Bulk Prepare Transfer (failure) + note right of BULK_PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json", + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": + "errorDescription": "", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "bulk-processing", + action: "bulk-abort", + createdAt: , + state: { + status: "error", + code: + description: + } + } + } + } + end note + BULK_PREP_HANDLER -> TOPIC_BULK_PROCESSING: Publish Processing (failure) event for Payer\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + group Insert Bulk Transfer Association (with bulkProcessingState='INVALID') + BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer association\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Insert bulkTransferAssociation + hnote over DB #lightyellow + bulkTransferAssociation + bulkTransferStateChange + end note + activate DB + deactivate DB + BULK_DAO --> BULK_PREP_HANDLER: Return state + deactivate BULK_DAO + end + + end +end +deactivate BULK_PREP_HANDLER +@enduml + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.svg new file mode 100644 index 000000000..eb4b20b44 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.svg @@ -0,0 +1,1009 @@ + + + + + + + + + + + 1.1.1. Bulk Prepare Handler Consume + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + + + topic- + + + bulk-prepare + + + + + topic- + + + bulk-prepare + + + Bulk Prepare + + + Handler + + + + + Bulk Prepare + + + Handler + + + + + + + topic- + + + transfer-prepare + + + + + topic- + + + transfer-prepare + + + + + topic-event + + + + + topic-event + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + topic-bulk- + + + processing + + + + + topic-bulk- + + + processing + + + Bulk DAO + + + + + Bulk DAO + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Bulk Prepare Handler Consume + + + + + 1 + + + Consume Bulk Prepare message + + + + + Validate Bulk Prepare Transfer + + + + + Duplicate Check + + + + + The Specification doesn't touch on the duplicate handling + + + of bulk transfers, so the current design mostly follows the + + + strategy used for individual transfers, except in two places: + + + 1. For duplicate requests where hash matches, the current design + + + includes only the status of the bulk & timestamp (if completed), + + + but not the individual transfers (for which a GET should be used). + + + 2. For duplicate requests where hash matches, but are not in a + + + finalized state, only the state of the bulkTransfer is sent. + + + + + 2 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check (using message.content.payload) + + + + + 3 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + break + + + [Return TRUE & Log ('Not implemented')] + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + { + + + id: <messageId>, + + + from: <ledgerName>, + + + to: <payerFspName>, + + + type: "application/json", + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + errorInformation: { + + + errorCode: "3106", + + + errorDescription: "Modified request", + + + extensionList: { + + + extension: [ + + + { + + + key: "_cause", + + + value: <FSPIOPError> + + + } + + + ] + + + } + + + }, + + + uriParams: { + + + id: <bulkTransferId> + + + } + + + } + + + }, + + + metadata: { + + + correlationId: <uuid>, + + + event: { + + + id: <uuid>, + + + type: "notification", + + + action: "bulk-prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: "3106", + + + description: "Modified request" + + + }, + + + responseTo: <uuid> + + + } + + + } + + + } + + + + + 4 + + + Publish Notification (failure) event for Payer + + + Error codes: + + + 3106 + + + + [hasDuplicateId == FALSE] + + + + + Validate Bulk Transfer Prepare Request + + + + + 5 + + + FSPIOP Source matches Payer + + + + + 6 + + + Check expiration + + + + + 7 + + + Payer and Payee FSP's are different + + + + + Validate Payer + + + + + 8 + + + Request to retrieve Payer Participant details (if it exists) + + + + + 9 + + + Request Participant details + + + + participant + + + participantCurrency + + + + + 10 + + + Return Participant details if it exists + + + + + 11 + + + Return Participant details if it exists + + + + + 12 + + + Validate Payer + + + Error codes: + + + 3202 + + + + + Validate Payee + + + + + 13 + + + Request to retrieve Payee Participant details (if it exists) + + + + + 14 + + + Request Participant details + + + + participant + + + participantCurrency + + + + + 15 + + + Return Participant details if it exists + + + + + 16 + + + Return Participant details if it exists + + + + + 17 + + + Validate Payee + + + Error codes: + + + 3203 + + + + + alt + + + [Validate Bulk Transfer Prepare Request (success)] + + + + + Persist Bulk Transfer State (with bulkTransferState='RECEIVED') + + + + + 18 + + + Request to persist bulk transfer + + + Error codes: + + + 2003 + + + + + 19 + + + Persist bulkTransfer + + + + bulkTransfer + + + bulkTransferExtension + + + bulkTransferStateChange + + + + + 20 + + + Return state + + + + [Validate Bulk Transfer Prepare Request (failure)] + + + + + Persist Bulk Transfer State (with bulkTransferState='INVALID') (Introducing a new status INVALID to mark these entries) + + + + + 21 + + + Request to persist bulk transfer + + + (when Payee/Payer/crypto-condition validation fails) + + + Error codes: + + + 2003 + + + + + 22 + + + Persist transfer + + + + bulkTransfer + + + bulkTransferExtension + + + bulkTransferStateChange + + + bulkTransferError + + + + + 23 + + + Return state + + + + + alt + + + [Validate Bulk Prepare Transfer (success)] + + + + + loop + + + [for each individual transfer in the bulk] + + + + + 24 + + + Retrieve individual transfers from the bulk using + + + reference: + + + MLOS.individualTransfers.messageId + + + + + Add elements such as Expiry time, Payer FSP, Payee FSP, etc. to each + + + transfer to make their format similar to a single transfer + + + + + 25 + + + Stream bulk's individual transfers + + + + + Insert Bulk Transfer Association (with bulkProcessingState='RECEIVED') + + + + + 26 + + + Request to persist bulk transfer association + + + Error codes: + + + 2003 + + + + + 27 + + + Insert bulkTransferAssociation + + + + bulkTransferAssociation + + + bulkTransferStateChange + + + + + 28 + + + Return state + + + + + Message: + + + { + + + id: <messageId> + + + from: <payerFspName>, + + + to: <payeeFspName>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "prepare", + + + action: "bulk-prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0, + + + description:"action successful" + + + } + + + } + + + } + + + } + + + + + 29 + + + Route & Publish Prepare event to the Payee for the Individual Transfer + + + Error codes: + + + 2003 + + + + [Validate Bulk Prepare Transfer (failure)] + + + + + Message: + + + { + + + id: <messageId> + + + from: <ledgerName>, + + + to: <bulkTransferMessage.payerFsp>, + + + type: "application/json", + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": <possible codes: [2003, 3100, 3105, 3106, 3202, 3203, 3300, 3301]> + + + "errorDescription": "<refer to section 7.6 for description>", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "bulk-processing", + + + action: "bulk-abort", + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 30 + + + Publish Processing (failure) event for Payer + + + Error codes: + + + 2003 + + + + + Insert Bulk Transfer Association (with bulkProcessingState='INVALID') + + + + + 31 + + + Request to persist bulk transfer association + + + Error codes: + + + 2003 + + + + + 32 + + + Insert bulkTransferAssociation + + + + bulkTransferAssociation + + + bulkTransferStateChange + + + + + 33 + + + Return state + + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.plantuml new file mode 100644 index 000000000..aee02560a --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.plantuml @@ -0,0 +1,324 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Rajiv Mothilal + * Samuel Kummary + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declate title +title 1.2.1. Prepare Handler Consume individual transfers from Bulk + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-\ntransfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Handler" as PREP_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +collections "topic-\nevent" as TOPIC_EVENTS +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +entity "Position DAO" as POS_DAO +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant TOPIC_BULK_PROCESSING + participant POS_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate PREP_HANDLER +group Prepare Handler Consume + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume Prepare event message + activate TOPIC_TRANSFER_PREPARE + deactivate TOPIC_TRANSFER_PREPARE + + break + group Validate Event + PREP_HANDLER <-> PREP_HANDLER: Validate event - Rule: type == 'prepare' && action == 'bulk-prepare'\nError codes: 2001 + end + end + + group Persist Event Information + ||| + PREP_HANDLER -> TOPIC_EVENTS: Publish event information + ref over PREP_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + + group Validate Prepare Transfer + PREP_HANDLER <-> PREP_HANDLER: Schema validation of the incoming message + PREP_HANDLER <-> PREP_HANDLER: Verify the message's signature (to be confirmed in future requirement) + + group Validate Duplicate Check + ||| + PREP_HANDLER -> DB: Request Duplicate Check + ref over PREP_HANDLER, DB: Request Duplicate Check\n + DB --> PREP_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + note right of PREP_HANDLER #lightgrey + In the context of a bulk (when compared to regular transfers), duplicate + individual transfers are now considered and reported with Modified Request, + because they could have already been handled for another bulk. + end note + break + note right of PREP_HANDLER #yellow + { + id: + from: , + to: , + type: "application/json", + content: { + headers: , + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request - Individual transfer prepare duplicate", + extensionList: { extension: [ { key: "_cause", value: } ] } + } + }, + uriParams: { id: } + }, + metadata: { + correlationId: , + event: { + type: "bulk-processing", + action: "prepare-duplicate", + createdAt: , + state: { + code: "3106", + status: "error", + description: "Modified request - Individual transfer prepare duplicate" + }, + id: , + responseTo: + } + } + end note + PREP_HANDLER -> TOPIC_BULK_PROCESSING: Publish Processing (failure) event for Payer\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + break + note right of PREP_HANDLER #yellow + { + id: + from: , + to: , + type: "application/json", + content: { + headers: , + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request", + extensionList: { extension: [ { key: "_cause", value: } ] } + } + }, + uriParams: { id: } + }, + metadata: { + correlationId: , + event: { + type: "bulk-processing", + action: "prepare-duplicate", + createdAt: , + state: { + code: "3106", + status: "error", + description: "Modified request" + }, + id: , + responseTo: + } + } + end note + PREP_HANDLER -> TOPIC_BULK_PROCESSING: Publish Processing (failure) event for Payer\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + else hasDuplicateId == FALSE + note right of PREP_HANDLER #lightgrey + The validation of Payer, Payee can be skipped for individual transfers in Bulk + as they should've/would've been validated already in the bulk prepare part. + However, leaving it here for now, as in the future, this can be leveraged + when bulk transfers to multiple Payees are supported by the Specification. + end note + group Validate Payer + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payer Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payer\nError codes: 3202 + end + group Validate Payee + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payee Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payee\nError codes: 3203 + end + + alt Validate Prepare Transfer (success) + group Persist Transfer State (with transferState='RECEIVED-PREPARE') + PREP_HANDLER -> POS_DAO: Request to persist transfer\nError codes: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer + hnote over DB #lightyellow + transfer + transferParticipant + transferStateChange + transferExtension + ilpPacket + end note + activate DB + deactivate DB + POS_DAO --> PREP_HANDLER: Return success + deactivate POS_DAO + end + else Validate Prepare Transfer (failure) + group Persist Transfer State (with transferState='INVALID') (Introducing a new status INVALID to mark these entries) + PREP_HANDLER -> POS_DAO: Request to persist transfer\n(when Payee/Payer/crypto-condition validation fails)\nError codes: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer + hnote over DB #lightyellow + transfer + transferParticipant + transferStateChange + transferExtension + transferError + ilpPacket + end note + activate DB + deactivate DB + POS_DAO --> PREP_HANDLER: Return success + deactivate POS_DAO + end + end + end + end + + alt Validate Prepare Transfer (success) + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json", + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "position", + action: "bulk-prepare", + createdAt: , + state: { + status: "success", + code: 0, + description:"action successful" + } + } + } + } + end note + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer\nError codes: 2003 + else Validate Prepare Transfer (failure) + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json" + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": + "errorDescription": "", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "bulk-processing", + action: "prepare", + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + PREP_HANDLER -> TOPIC_BULK_PROCESSING: Publish Prepare failure event to Bulk Processing Topic (for Payer) \nError codes: 2003 + end +end + +deactivate PREP_HANDLER +@enduml + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.svg new file mode 100644 index 000000000..af0e4479c --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.svg @@ -0,0 +1,975 @@ + + + + + + + + + + + 1.2.1. Prepare Handler Consume individual transfers from Bulk + + + + Central Service + + + + + + + + + + + + + + + + + + + + topic- + + + transfer-prepare + + + + + topic- + + + transfer-prepare + + + Prepare Handler + + + + + Prepare Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic- + + + event + + + + + topic- + + + event + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Position DAO + + + + + Position DAO + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Prepare Handler Consume + + + + + 1 + + + Consume Prepare event message + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'prepare' && action == 'bulk-prepare' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate Prepare Transfer + + + + + 4 + + + Schema validation of the incoming message + + + + + 5 + + + Verify the message's signature (to be confirmed in future requirement) + + + + + Validate Duplicate Check + + + + + 6 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check + + + + + 7 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + In the context of a bulk (when compared to regular transfers), duplicate + + + individual transfers are now considered and reported with Modified Request, + + + because they could have already been handled for another bulk. + + + + + break + + + + + { + + + id: <messageId> + + + from: <ledgerName>, + + + to: <payerFspName>, + + + type: "application/json", + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + errorInformation: { + + + errorCode: "3106", + + + errorDescription: "Modified request - Individual transfer prepare duplicate", + + + extensionList: { extension: [ { key: "_cause", value: <FSPIOPError> } ] } + + + } + + + }, + + + uriParams: { id: <transferId> } + + + }, + + + metadata: { + + + correlationId: <uuid>, + + + event: { + + + type: "bulk-processing", + + + action: "prepare-duplicate", + + + createdAt: <timestamp>, + + + state: { + + + code: "3106", + + + status: "error", + + + description: "Modified request - Individual transfer prepare duplicate" + + + }, + + + id: <uuid>, + + + responseTo: <uuid> + + + } + + + } + + + + + 8 + + + Publish Processing (failure) event for Payer + + + Error codes: + + + 2003 + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + break + + + + + { + + + id: <messageId> + + + from: <ledgerName>, + + + to: <payerFspName>, + + + type: "application/json", + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + errorInformation: { + + + errorCode: "3106", + + + errorDescription: "Modified request", + + + extensionList: { extension: [ { key: "_cause", value: <FSPIOPError> } ] } + + + } + + + }, + + + uriParams: { id: <transferId> } + + + }, + + + metadata: { + + + correlationId: <uuid>, + + + event: { + + + type: "bulk-processing", + + + action: "prepare-duplicate", + + + createdAt: <timestamp>, + + + state: { + + + code: "3106", + + + status: "error", + + + description: "Modified request" + + + }, + + + id: <uuid>, + + + responseTo: <uuid> + + + } + + + } + + + + + 9 + + + Publish Processing (failure) event for Payer + + + Error codes: + + + 2003 + + + + [hasDuplicateId == FALSE] + + + + + The validation of Payer, Payee can be skipped for individual transfers in Bulk + + + as they should've/would've been validated already in the bulk prepare part. + + + However, leaving it here for now, as in the future, this can be leveraged + + + when bulk transfers to multiple Payees are supported by the Specification. + + + + + Validate Payer + + + + + 10 + + + Request to retrieve Payer Participant details (if it exists) + + + + + 11 + + + Request Participant details + + + + participant + + + participantCurrency + + + + + 12 + + + Return Participant details if it exists + + + + + 13 + + + Return Participant details if it exists + + + + + 14 + + + Validate Payer + + + Error codes: + + + 3202 + + + + + Validate Payee + + + + + 15 + + + Request to retrieve Payee Participant details (if it exists) + + + + + 16 + + + Request Participant details + + + + participant + + + participantCurrency + + + + + 17 + + + Return Participant details if it exists + + + + + 18 + + + Return Participant details if it exists + + + + + 19 + + + Validate Payee + + + Error codes: + + + 3203 + + + + + alt + + + [Validate Prepare Transfer (success)] + + + + + Persist Transfer State (with transferState='RECEIVED-PREPARE') + + + + + 20 + + + Request to persist transfer + + + Error codes: + + + 2003 + + + + + 21 + + + Persist transfer + + + + transfer + + + transferParticipant + + + transferStateChange + + + transferExtension + + + ilpPacket + + + + + 22 + + + Return success + + + + [Validate Prepare Transfer (failure)] + + + + + Persist Transfer State (with transferState='INVALID') (Introducing a new status INVALID to mark these entries) + + + + + 23 + + + Request to persist transfer + + + (when Payee/Payer/crypto-condition validation fails) + + + Error codes: + + + 2003 + + + + + 24 + + + Persist transfer + + + + transfer + + + transferParticipant + + + transferStateChange + + + transferExtension + + + transferError + + + ilpPacket + + + + + 25 + + + Return success + + + + + alt + + + [Validate Prepare Transfer (success)] + + + + + Message: + + + { + + + id: <messageId> + + + from: <payerFspName>, + + + to: <payeeFspName>, + + + type: "application/json", + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "position", + + + action: "bulk-prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0, + + + description:"action successful" + + + } + + + } + + + } + + + } + + + + + 26 + + + Route & Publish Position event for Payer + + + Error codes: + + + 2003 + + + + [Validate Prepare Transfer (failure)] + + + + + Message: + + + { + + + id: <messageId> + + + from: <ledgerName>, + + + to: <payerFspName>, + + + type: "application/json" + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": <possible codes: [2003, 3100, 3105, 3106, 3202, 3203, 3300, 3301]> + + + "errorDescription": "<refer to section 35.1.3 for description>", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "bulk-processing", + + + action: "prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 27 + + + Publish Prepare failure event to Bulk Processing Topic (for Payer) + + + Error codes: + + + 2003 + + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.plantuml new file mode 100644 index 000000000..44d640284 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.plantuml @@ -0,0 +1,116 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Rajiv Mothilal + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declate title +title 1.3.0. Position Handler Consume individual transfers from Bulk + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + alt Consume Prepare message for Payer + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'bulk-prepare'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS: Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Prepare Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Fulfil message for Payee + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'bulk-commit'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Fulfil Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Abort message + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'timeout-reserved'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Abort Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + end + +end +deactivate POS_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.svg new file mode 100644 index 000000000..a6c1ce040 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.svg @@ -0,0 +1,298 @@ + + + + + + + + + + + 1.3.0. Position Handler Consume individual transfers from Bulk + + + + Central Service + + + + + + + + + + + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Handler + + + + + Position Handler + + + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + Position Handler Consume + + + + + alt + + + [Consume Prepare message for Payer] + + + + + 1 + + + Consume Position event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'position' && action == 'bulk-prepare' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Prepare Position Handler Consume + + + + + 4 + + + Produce message + + + + [Consume Fulfil message for Payee] + + + + + 5 + + + Consume Position event message for Payee + + + + + break + + + + + Validate Event + + + + + 6 + + + Validate event - Rule: type == 'position' && action == 'bulk-commit' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 7 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Fulfil Position Handler Consume + + + + + 8 + + + Produce message + + + + [Consume Abort message] + + + + + 9 + + + Consume Position event message + + + + + break + + + + + Validate Event + + + + + 10 + + + Validate event - Rule: type == 'position' && action == 'timeout-reserved' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 11 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Abort Position Handler Consume + + + + + 12 + + + Produce message + + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.plantuml new file mode 100644 index 000000000..370eaf388 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.plantuml @@ -0,0 +1,365 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Rajiv Mothilal + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declate title +title 1.3.1. Prepare Position Handler Consume (single message, includes individual transfers from Bulk) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER + +entity "Position\nManagement\nFacade" as POS_MGMT +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant TOPIC_BULK_PROCESSING + participant POS_MGMT + participant POS_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Prepare Position Handler Consume + POS_HANDLER -> POS_MGMT: Request transfers to be processed + activate POS_MGMT + POS_MGMT -> POS_MGMT: Check 1st transfer to select the Participant and Currency + group DB TRANSACTION + ' DB Trans: This is where 1st DB Transaction would start in 2 DB transacation future model for horizontal scaling + POS_MGMT -> POS_MGMT: Loop through batch and build list of transferIds and calculate sumTransfersInBatch,\nchecking all in Batch are for the correct Paricipant and Currency\nError code: 2001, 3100 + POS_MGMT -> DB: Retrieve current state of all transfers in array from DB with select whereIn\n(FYI: The two DB transaction model needs to add a mini-state step here (RECEIVED_PREPARE => RECEIVDED_PREPARE_PROCESSING) so that the transfers are left alone if processing has started) + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_MGMT: Return current state of all selected transfers from DB + deactivate DB + POS_MGMT <-> POS_MGMT: Validate current state (transferStateChange.transferStateId == 'RECEIVED_PREPARE')\nError code: 2001 against failing transfers\nBatch is not rejected as a whole. + + note right of POS_MGMT #lightgray + List of transfers used during processing + **reservedTransfers** is list of transfers to be processed in the batch + **abortedTransfers** is the list of transfers in the incorrect state going into the process. Currently the transferStateChange is set to ABORTED - this should only be done if not already in a final state (idempotency) + **processedTransfers** is the list of transfers that have gone through the position management algorithm. Both successful and failed trasnfers appear here as the order and "running position" against each is necessary for reconciliation + + Scalar intermidate values used in the algorithm + **transferAmount** = payload.amount.amount + **sumTransfersInBatch** = SUM amount against each Transfer in batch + **currentPosition** = participantPosition.value + **reservedPosition** = participantPosition.{original}reservedValue + **effectivePosition** = currentPosition + reservedPosition + **heldPosition** = effectivePosition + sumTransfersInBatch + **availablePosition** = participantLimit(NetDebitCap) - effectivePosition + **sumReserved** = SUM of transfers that have met rule criteria and processed + end note + note over POS_MGMT,DB + Going to reserve the sum of the valid transfers in the batch against the Participants Positon in the Currency of this batch + and calculate the available position for the Participant to use + end note + POS_MGMT -> DB: Select effectivePosition FOR UPDATE from DB for Payer + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_MGMT: Return effectivePosition (currentPosition and reservedPosition) from DB for Payer + deactivate DB + POS_MGMT -> POS_MGMT: Increment reservedValue to heldPosition\n(reservedValue = reservedPosition + sumTransfersInBatch) + POS_MGMT -> DB: Persist reservedValue + activate DB + hnote over DB #lightyellow + UPDATE **participantPosition** + SET reservedValue += sumTransfersInBatch + end note + deactivate DB + ' DB Trans: This is where 1st DB Transaction would end in 2 DB transacation future model for horizontal scaling + + + POS_MGMT -> DB: Request position limits for Payer Participant + activate DB + hnote over DB #lightyellow + FROM **participantLimit** + WHERE participantLimit.limitTypeId = 'NET-DEBIT-CAP' + AND participantLimit.participantId = payload.payerFsp + AND participantLimit.currencyId = payload.amount.currency + end note + DB --> POS_MGMT: Return position limits + deactivate DB + POS_MGMT <-> POS_MGMT: **availablePosition** = participantLimit(netDebitCap) - effectivePosition (same as = netDebitCap - currentPosition - reservedPosition) + note over POS_MGMT,DB + For each transfer in the batch, validate the availablility of position to meet the transfer amount + this will be as per the position algorithm documented below + end note + POS_MGMT <-> POS_MGMT: Validate availablePosition for each tranfser (see algorithm below)\nError code: 4001 + note right of POS_MGMT #lightgray + 01: sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED + 02: sumProcessed =0 // Record the sum of the transfers already processed in this batch + 03: processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position + 04: foreach transfer in reservedTransfers + 05: sumProcessed += transfer.amount // the total processed so far **(NEED TO UPDATE IN CODE)** + 06: if availablePosition >= transfer.amount + 07: transfer.state = "RESERVED" + 08: availablePosition -= preparedTransfer.amount + 09: sumRESERVED += preparedTransfer.amount + 10: else + 11: preparedTransfer.state = "ABORTED" + 12: preparedTransfer.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + 13: end if + 14: runningPosition = currentPosition + sumReserved // the initial value of the Participants position plus the total value that has been accepted in the batch so far + 15: runningReservedValue = sumTransfersInBatch - sumProcessed + reservedPosition **(NEED TO UPDATE IN CODE)** // the running down of the total reserved value at the begining of the batch. + 16: Add transfer to the processedTransfer list recording the transfer state and running position and reserved values { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue } + 16: end foreach + end note + note over POS_MGMT,DB + Once the outcome for all transfers is known,update the Participant's position and remove the reserved amount associated with the batch + (If there are any alarm limits, process those returning limits in which the threshold has been breached) + Do a bulk insert of the trasnferStateChanges associated with processing, using the result to complete the participantPositionChange and bulk insert of these to persist the running position + end note + POS_MGMT->POS_MGMT: Assess any limit thresholds on the final position\nadding to alarm list if triggered + + ' DB Trans: This is where 2nd DB Transaction would start in 2 DB transacation future model for horizontal scaling + POS_MGMT->DB: Persist latest position **value** and **reservedValue** to DB for Payer + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value += sumRESERVED, + reservedValue -= sumTransfersInBatch + end note + activate DB + deactivate DB + + POS_MGMT -> DB: Bulk persist transferStateChange for all processedTransfers + hnote over DB #lightyellow + batch INSERT **transferStateChange** + select for update from transfer table where transferId in ([transferBatch.transferId,...]) + build list of transferStateChanges from transferBatch + + end note + activate DB + deactivate DB + + POS_MGMT->POS_MGMT: Populate batchParticipantPositionChange from the resultant transferStateChange and the earlier processedTransfer list + + note right of POS_MGMT #lightgray + Effectively: + SET transferStateChangeId = processedTransfer.transferStateChangeId, + participantPositionId = preparedTransfer.participantPositionId, + value = preparedTransfer.positionValue, + reservedValue = preparedTransfer.positionReservedValue + end note + POS_MGMT -> DB: Bulk persist the participant position change for all processedTransfers + hnote over DB #lightyellow + batch INSERT **participantPositionChange** + end note + activate DB + deactivate DB + ' DB Trans: This is where 2nd DB Transaction would end in 2 DB transacation future model for horizontal scaling + end + POS_MGMT --> POS_HANDLER: Return a map of transferIds and their transferStateChanges + deactivate POS_MGMT + alt Calculate & Validate Latest Position Prepare (success) + POS_HANDLER -> POS_HANDLER: Notifications for Position Validation Success \nReference: Position Validation Success case (Prepare) + else Calculate & Validate Latest Position Prepare (failure) + note right of POS_HANDLER #red: Validation failure! + + group Persist Transfer State (with transferState='ABORTED' on position check fail) + POS_HANDLER -> POS_DAO: Request to persist transfer\nError code: 2003 + activate POS_DAO + note right of POS_HANDLER #lightgray + transferStateChange.state = "ABORTED", + transferStateChange.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + end note + POS_DAO -> DB: Persist transfer state + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + POS_HANDLER -> POS_HANDLER: Notifications for failures\nReference: Failure in Position Validation (Prepare) + end +end + + +group Reference: Failure in Position Validation (Prepare) + alt If action == 'bulk-prepare' + note right of POS_HANDLER #yellow + Message: + { + id: "" + from: , + to: , + type: "application/json" + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "bulk-processing", + action: "bulk-prepare", + createdAt: , + state: { + status: "error", + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_BULK_PROCESSING: Publish Position failure event (in Prepare) to Bulk Processing Topic (for Payer) \nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + else If action == 'prepare' + note right of POS_HANDLER #yellow + Message: + { + id: "" + from: , + to: , + type: "application/json" + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "notification", + action: "position", + createdAt: , + state: { + status: "error", + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + +end + +group Reference: Position Validation Success case (Prepare) + alt If action == 'bulk-prepare' + note right of POS_HANDLER #yellow + Message: + { + id: "" + from: , + to: , + type: "application/json" + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "bulk-processing", + action: "bulk-prepare", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_BULK_PROCESSING: Publish Position Success event (in Prepare) to Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + else If action == 'prepare' + note right of POS_HANDLER #yellow + Message: + { + id: "" + from: , + to: , + type: "application/json" + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "notification", + action: "abort", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end +end + +deactivate POS_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.svg new file mode 100644 index 000000000..1403dc6ab --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.svg @@ -0,0 +1,1092 @@ + + + + + + + + + + + 1.3.1. Prepare Position Handler Consume (single message, includes individual transfers from Bulk) + + + + Central Service + + + + + + + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Position + + + Management + + + Facade + + + + + Position + + + Management + + + Facade + + + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Prepare Position Handler Consume + + + + + 1 + + + Request transfers to be processed + + + + + 2 + + + Check 1st transfer to select the Participant and Currency + + + + + DB TRANSACTION + + + + + 3 + + + Loop through batch and build list of transferIds and calculate sumTransfersInBatch, + + + checking all in Batch are for the correct Paricipant and Currency + + + Error code: + + + 2001, 3100 + + + + + 4 + + + Retrieve current state of all transfers in array from DB with select whereIn + + + (FYI: The two DB transaction model needs to add a mini-state step here (RECEIVED_PREPARE => RECEIVDED_PREPARE_PROCESSING) so that the transfers are left alone if processing has started) + + + + transferStateChange + + + transferParticipant + + + + + 5 + + + Return current state of all selected transfers from DB + + + + + 6 + + + Validate current state (transferStateChange.transferStateId == 'RECEIVED_PREPARE') + + + Error code: + + + 2001 + + + against failing transfers + + + Batch is not rejected as a whole. + + + + + List of transfers used during processing + + + reservedTransfers + + + is list of transfers to be processed in the batch + + + abortedTransfers + + + is the list of transfers in the incorrect state going into the process. Currently the transferStateChange is set to ABORTED - this should only be done if not already in a final state (idempotency) + + + processedTransfers + + + is the list of transfers that have gone through the position management algorithm. Both successful and failed trasnfers appear here as the order and "running position" against each is necessary for reconciliation + + + Scalar intermidate values used in the algorithm + + + transferAmount + + + = payload.amount.amount + + + sumTransfersInBatch + + + = SUM amount against each Transfer in batch + + + currentPosition + + + = participantPosition.value + + + reservedPosition + + + = participantPosition.{original}reservedValue + + + effectivePosition + + + = currentPosition + reservedPosition + + + heldPosition + + + = effectivePosition + sumTransfersInBatch + + + availablePosition + + + = participantLimit(NetDebitCap) - effectivePosition + + + sumReserved + + + = SUM of transfers that have met rule criteria and processed + + + + + Going to reserve the sum of the valid transfers in the batch against the Participants Positon in the Currency of this batch + + + and calculate the available position for the Participant to use + + + + + 7 + + + Select effectivePosition FOR UPDATE from DB for Payer + + + + participantPosition + + + + + 8 + + + Return effectivePosition (currentPosition and reservedPosition) from DB for Payer + + + + + 9 + + + Increment reservedValue to heldPosition + + + (reservedValue = reservedPosition + sumTransfersInBatch) + + + + + 10 + + + Persist reservedValue + + + + UPDATE + + + participantPosition + + + SET reservedValue += sumTransfersInBatch + + + + + 11 + + + Request position limits for Payer Participant + + + + FROM + + + participantLimit + + + WHERE participantLimit.limitTypeId = 'NET-DEBIT-CAP' + + + AND participantLimit.participantId = payload.payerFsp + + + AND participantLimit.currencyId = payload.amount.currency + + + + + 12 + + + Return position limits + + + + + 13 + + + availablePosition + + + = participantLimit(netDebitCap) - effectivePosition (same as = netDebitCap - currentPosition - reservedPosition) + + + + + For each transfer in the batch, validate the availablility of position to meet the transfer amount + + + this will be as per the position algorithm documented below + + + + + 14 + + + Validate availablePosition for each tranfser (see algorithm below) + + + Error code: + + + 4001 + + + + + 01: sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED + + + 02: sumProcessed =0 // Record the sum of the transfers already processed in this batch + + + 03: processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position + + + 04: foreach transfer in reservedTransfers + + + 05: sumProcessed += transfer.amount // the total processed so far + + + (NEED TO UPDATE IN CODE) + + + 06: if availablePosition >= transfer.amount + + + 07: transfer.state = "RESERVED" + + + 08: availablePosition -= preparedTransfer.amount + + + 09: sumRESERVED += preparedTransfer.amount + + + 10: else + + + 11: preparedTransfer.state = "ABORTED" + + + 12: preparedTransfer.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + + + 13: end if + + + 14: runningPosition = currentPosition + sumReserved // the initial value of the Participants position plus the total value that has been accepted in the batch so far + + + 15: runningReservedValue = sumTransfersInBatch - sumProcessed + reservedPosition + + + (NEED TO UPDATE IN CODE) + + + // the running down of the total reserved value at the begining of the batch. + + + 16: Add transfer to the processedTransfer list recording the transfer state and running position and reserved values { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue } + + + 16: end foreach + + + + + Once the outcome for all transfers is known,update the Participant's position and remove the reserved amount associated with the batch + + + (If there are any alarm limits, process those returning limits in which the threshold has been breached) + + + Do a bulk insert of the trasnferStateChanges associated with processing, using the result to complete the participantPositionChange and bulk insert of these to persist the running position + + + + + 15 + + + Assess any limit thresholds on the final position + + + adding to alarm list if triggered + + + + + 16 + + + Persist latest position + + + value + + + and + + + reservedValue + + + to DB for Payer + + + + UPDATE + + + participantPosition + + + SET value += sumRESERVED, + + + reservedValue -= sumTransfersInBatch + + + + + 17 + + + Bulk persist transferStateChange for all processedTransfers + + + + batch INSERT + + + transferStateChange + + + select for update from transfer table where transferId in ([transferBatch.transferId,...]) + + + build list of transferStateChanges from transferBatch + + + + + 18 + + + Populate batchParticipantPositionChange from the resultant transferStateChange and the earlier processedTransfer list + + + + + Effectively: + + + SET transferStateChangeId = processedTransfer.transferStateChangeId, + + + participantPositionId = preparedTransfer.participantPositionId, + + + value = preparedTransfer.positionValue, + + + reservedValue = preparedTransfer.positionReservedValue + + + + + 19 + + + Bulk persist the participant position change for all processedTransfers + + + + batch INSERT + + + participantPositionChange + + + + + 20 + + + Return a map of transferIds and their transferStateChanges + + + + + alt + + + [Calculate & Validate Latest Position Prepare (success)] + + + + + 21 + + + Notifications for Position Validation Success + + + Reference: Position Validation Success case (Prepare) + + + + [Calculate & Validate Latest Position Prepare (failure)] + + + + + Validation failure! + + + + + Persist Transfer State (with transferState='ABORTED' on position check fail) + + + + + 22 + + + Request to persist transfer + + + Error code: + + + 2003 + + + + + transferStateChange.state = "ABORTED", + + + transferStateChange.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + + + + + 23 + + + Persist transfer state + + + + transferStateChange + + + + + 24 + + + Return success + + + + + 25 + + + Notifications for failures + + + Reference: Failure in Position Validation (Prepare) + + + + + Reference: Failure in Position Validation (Prepare) + + + + + alt + + + [If action == 'bulk-prepare'] + + + + + Message: + + + { + + + id: "<messageId>" + + + from: <ledgerName>, + + + to: <transferMessage.payerFsp>, + + + type: "application/json" + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 4001, + + + "errorDescription": "Payer FSP insufficient liquidity", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "bulk-processing", + + + action: "bulk-prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 26 + + + Publish Position failure event (in Prepare) to Bulk Processing Topic (for Payer) + + + Error codes: + + + 2003 + + + + [If action == 'prepare'] + + + + + Message: + + + { + + + id: "<messageId>" + + + from: <ledgerName>, + + + to: <transferMessage.payerFsp>, + + + type: "application/json" + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 4001, + + + "errorDescription": "Payer FSP insufficient liquidity", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "notification", + + + action: "position", + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 27 + + + Publish Notification (failure) event for Payer + + + Error code: + + + 2003 + + + + + Reference: Position Validation Success case (Prepare) + + + + + alt + + + [If action == 'bulk-prepare'] + + + + + Message: + + + { + + + id: "<messageId>" + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: "application/json" + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "bulk-processing", + + + action: "bulk-prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 28 + + + Publish Position Success event (in Prepare) to Bulk Processing Topic + + + Error codes: + + + 2003 + + + + [If action == 'prepare'] + + + + + Message: + + + { + + + id: "<messageId>" + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: "application/json" + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "notification", + + + action: "abort", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 29 + + + Publish Notification event + + + Error code: + + + 2003 + + diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.plantuml similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.plantuml rename to legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.plantuml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.svg new file mode 100644 index 000000000..fa4186d7d --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.svg @@ -0,0 +1,860 @@ + + + + + + + + + + + 1.4.0. Bulk Processing Handler Consume + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + topic-bulk- + + + processing + + + + + topic-bulk- + + + processing + + + Bulk Processing + + + Handler + + + + + Bulk Processing + + + Handler + + + + + + + topic-event + + + + + topic-event + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + + + topic-notification + + + + + topic-notification + + + Bulk DAO + + + + + Bulk DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Bulk Processing Handler Consume + + + + + 1 + + + Consume message + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: + + + type == 'bulk-processing' && action IN + + + ['prepare-duplicate', 'bulk-prepare', + + + 'bulk-timeout-received', 'fulfil-duplicate', + + + 'bulk-commit', 'bulk-timeout-reserved'] + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Process Message + + + + + 4 + + + Retrieve current state of Bulk Transfer + + + + + 5 + + + Retrieve current state of Bulk Transfer + + + + bulkTransfer + + + bulkTransferStateChange + + + + + 6 + + + Return + + + bulkTransferInfo + + + + + 7 + + + Return + + + bulkTransferInfo + + + + + Validate Bulk Transfer State + + + + + Initialize variables + + + : + + + let criteriaState + + + let incompleteBulkState + + + let completedBulkState + + + let bulkTransferState + + + let processingState + + + let errorCode, errorMessage + + + let produceNotification = false + + + + + alt + + + [bulkTransferInfo.bulkTransferState IN ['RECEIVED', 'PENDING_PREPARE']] + + + + + criteriaState = 'RECEIVED' + + + incompleteBulkState = 'PENDING_PREPARE' + + + completedBulkState = 'ACCEPTED' + + + + + alt + + + [action == 'prepare-duplicate' AND state.status == 'error'] + + + + + processingState = 'RECEIVED_DUPLICATE' + + + errorCode = payload.errorInformation.errorCode + + + errorDescription = payload.errorInformation.errorDescription + + + + [action == 'bulk-prepare' AND state.status == 'error'] + + + + + processingState = 'RECEIVED_INVALID' + + + errorCode = payload.errorInformation.errorCode + + + errorDescription = payload.errorInformation.errorDescription + + + + [action == 'bulk-prepare' AND state.status == 'success'] + + + + + processingState = 'ACCEPTED' + + + + [action IN ['bulk-timeout-received', 'bulk-timeout-reserved']] + + + + + incompleteBulkState = 'EXPIRING' + + + completedBulkState = 'COMPLETED' + + + processingState = 'EXPIRED' + + + errorCode = payload.errorInformation.errorCode + + + errorDescription = payload.errorInformation.errorDescription + + + + [all other actions] + + + + + throw + + + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + + + [bulkTransferInfo.bulkTransferState IN ['ACCEPTED']] + + + + + alt + + + [action == 'bulk-timeout-reserved'] + + + + + criteriaState = 'ACCEPTED' + + + incompleteBulkState = 'EXPIRING' + + + completedBulkState = 'COMPLETED' + + + processingState = 'EXPIRED' + + + + [all other actions] + + + + + throw + + + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + + + [bulkTransferInfo.bulkTransferState IN ['PROCESSING', 'PENDING_FULFIL', 'EXPIRING']] + + + + + criteriaState = 'PROCESSING' + + + incompleteBulkState = 'PENDING_FULFIL' + + + completedBulkState = 'COMPLETED' + + + + + alt + + + [action == 'fulfil-duplicate'] + + + + + processingState = 'FULFIL_DUPLICATE' + + + + [action == 'bulk-commit' AND state.status == 'success'] + + + + + processingState = 'COMPLETED' + + + + [action == 'reject' AND state.status == 'success'] + + + + + processingState = 'REJECTED' + + + + [action IN ['commit', 'abort'] AND state.status == 'error'] + + + + + processingState = 'FULFIL_INVALID' + + + + [action == 'bulk-timeout-reserved'] + + + + + incompleteBulkState = 'EXPIRING' + + + completedBulkState = 'COMPLETED' + + + processingState = 'EXPIRED' + + + errorCode = payload.errorInformation.errorCode + + + errorDescription = payload.errorInformation.errorDescription + + + + [all other actions] + + + + + throw + + + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + + + [all other ['PENDING_INVALID', 'COMPLETED', 'REJECTED', 'INVALID']] + + + + + throw + + + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + + + + 8 + + + Persist individual transfer processing state + + + + + 9 + + + Persist individual transfer processing state + + + -- store errorCode/errorMessage when + + + state.status == 'error' + + + + bulkTransferAssociation + + + + + 10 + + + Return success + + + + + 11 + + + Check previously defined completion criteria + + + + + 12 + + + Select EXISTS (LIMIT 1) in criteriaState + + + + bulkTransferAssociation + + + + + 13 + + + Return + + + existingIndividualTransfer + + + + + 14 + + + Return + + + existingIndividualTransfer + + + + + alt + + + [individual transfer exists] + + + + + bulkTransferState = incompleteBulkState + + + + [no transfer in criteriaState exists] + + + + + bulkTransferState = completedBulkState + + + produceNotification = true + + + + + 15 + + + Persist bulkTransferState from previous step + + + + + 16 + + + Persist bulkTransferState + + + + bulkTransferStateChange + + + + + 17 + + + Return success + + + + + alt + + + [produceNotification == true] + + + + + 18 + + + Request to retrieve all bulk transfer and individual transfer results + + + + + 19 + + + Get bulkTransferResult + + + + bulkTransfer + + + bulkTransferStateChange + + + bulkTransferAssociation + + + + + 20 + + + Return + + + bulkTransferResult + + + + + 21 + + + Return + + + bulkTransferResult + + + + + Send Bulk Notification(s) + + + + + Depending on the action decide where to + + + send notification: payer, payee OR both + + + + + 22 + + + Generate & Persist bulk message to object store: + + + MLOS.bulkTransferResults + + + by destination + + + + + 23 + + + Return reference to the stored object(s) + + + MLOS.bulkTransferResults.messageId + + + + + Message: + + + { + + + id: <messageId> + + + from: <source>, + + + to: <destination>, + + + type: "application/json" + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + bulkTransferId: <uuid>, + + + bulkTransferState: <string> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "notification", + + + action: "bulk-[prepare | commit | abort | processing]", + + + createdAt: <timestamp>, + + + state: { + + + status: state.status, + + + code: state.code + + + } + + + } + + + } + + + } + + + + + 24 + + + Publish Notification event for Payer/Payee + + + Error codes: + + + 2003 + + + + [produceNotification == false] + + + + + Do nothing (awaitAllTransfers) + + diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.plantuml similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.plantuml rename to legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.plantuml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.svg new file mode 100644 index 000000000..90d6889fc --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.svg @@ -0,0 +1,835 @@ + + + + + + + + + + + 2.1.0. DFSP2 sends a Bulk Fulfil Success Transfer request + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API + + + Notification Handler + + + + + ML API + + + Notification Handler + + + + + + + mongo- + + + object-store + + + + + mongo- + + + object-store + + + Central Service API + + + + + Central Service API + + + + + + + topic- + + + bulk-fulfil + + + + + topic- + + + bulk-fulfil + + + Bulk Fulfil + + + Handler + + + + + Bulk Fulfil + + + Handler + + + + + + + topic- + + + fulfil + + + + + topic- + + + fulfil + + + Fulfil + + + Handler + + + + + Fulfil + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + Position + + + Handler + + + + + Position + + + Handler + + + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Bulk Processing + + + Handler + + + + + Bulk Processing + + + Handler + + + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + + DFSP2 sends a Bulk Fulfil Success Transfer request to DFSP1 + + + + + Headers - transferHeaders: { + + + Content-Length: <int>, + + + Content-Type: <string>, + + + Date: <date>, + + + FSPIOP-Source: <string>, + + + FSPIOP-Destination: <string>, + + + FSPIOP-Encryption: <string>, + + + FSPIOP-Signature: <string>, + + + FSPIOP-URI: <uri>, + + + FSPIOP-HTTP-Method: <string> + + + } + + + Payload - bulkTransferMessage: + + + { + + + bulkTransferState: <bulkTransferState>, + + + completedTimestamp: <completedTimeStamp>, + + + individualTransferResults: + + + [ + + + { + + + transferId: <uuid>, + + + fulfilment: <ilpCondition>, + + + extensionList: { extension: [ + + + { key: <string>, value: <string> } + + + ] } + + + } + + + ], + + + extensionList: { extension: [ + + + { key: <string>, value: <string> } + + + ] } + + + } + + + + 1 + + + PUT - /bulkTransfers/<ID> + + + + + 2 + + + Validate incoming message + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + 3 + + + Persist incoming bulk message to + + + object store: + + + MLOS.individualTransferFulfils + + + + + 4 + + + Return messageId reference to the stored object(s) + + + + + Message: + + + { + + + id: <messageId>, + + + from: <payeeFspName>, + + + to: <payerFspName>, + + + type: "application/json", + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + bulkTransferId: <uuid>, + + + bulkTransferState: "COMPLETED", + + + completedTimestamp: <timestamp>, + + + extensionList: { extension: [ + + + { key: <string>, value: <string> } + + + ] }, + + + count: <int>, + + + hash: <string> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: "bulk-fulfil", + + + action: "bulk-commit", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 5 + + + Route & Publish Bulk Fulfil event for Payee + + + Error code: + + + 2003 + + + + + 6 + + + Ensure event is replicated + + + as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 7 + + + Respond replication acknowledgements + + + have been received + + + + + 8 + + + Respond HTTP - 200 (OK) + + + + + 9 + + + Consume message + + + + + 10 + + + Retrieve individual transfers by key: + + + MLOS.individualTransferFulfils.messageId + + + + + 11 + + + Stream bulk's individual transfers + + + + + ref + + + Bulk Prepare Handler Consume + + + + + alt + + + [Success] + + + + + 12 + + + Produce (stream) single transfer message + + + for each individual transfer [loop] + + + + [Failure] + + + + + 13 + + + Produce single message for the entire bulk + + + + + 14 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (Success) + + + + + alt + + + [Success] + + + + + 15 + + + Produce message + + + + [Failure] + + + + + 16 + + + Produce message + + + + + 17 + + + Consume message + + + + + ref + + + Position Handler Consume (Success) + + + + + 18 + + + Produce message + + + + + 19 + + + Consume message + + + + + ref + + + Bulk Processing Handler Consume (Success) + + + + + 20 + + + Persist bulk message by destination to the + + + object store: + + + MLOS.bulkTransferResults + + + + + 21 + + + Return the reference to the stored + + + notification object(s): + + + messageId + + + + + 22 + + + Send Bulk Commit notification + + + + + 23 + + + Consume message + + + + + 24 + + + Retrieve bulk notification(s) by reference & destination: + + + MLOS.bulkTransferResults.messageId + destination + + + + + 25 + + + Return notification payload + + + + + opt + + + [action == 'bulk-commit'] + + + + + ref + + + Send notification to Participant (Payer) + + + + + 26 + + + Send callback notification + + + + + 27 + + + Consume message + + + + + 28 + + + Retrieve bulk notification(s) by reference & destination: + + + MLOS.bulkTransferResults.messageId + destination + + + + + 29 + + + Return notification payload + + + + + opt + + + [action == 'bulk-commit'] + + + + + ref + + + Send notification to Participant (Payee) + + + + + 30 + + + Send callback notification + + diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.plantuml similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.plantuml rename to legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.plantuml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.svg new file mode 100644 index 000000000..bb328dce5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.svg @@ -0,0 +1,954 @@ + + + + + + + + + + + 2.1.1. Bulk Fulfil Handler Consume + + + + Central Service + + + + + + + + + + + + + + + + + + + mongo- + + + object-store + + + + + mongo- + + + object-store + + + + + topic-bulk- + + + fulfil + + + + + topic-bulk- + + + fulfil + + + Bulk Fulfil + + + Handler + + + + + Bulk Fulfil + + + Handler + + + + + + + topic-transfer- + + + fulfil + + + + + topic-transfer- + + + fulfil + + + + + topic-bulk- + + + processing + + + + + topic-bulk- + + + processing + + + + + topic-event + + + + + topic-event + + + + + topic-notification + + + + + topic-notification + + + Bulk DAO + + + + + Bulk DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Bulk Fulfil Handler Consume + + + + + 1 + + + Consume message + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: + + + type == 'bulk-fulfil' && action == 'bulk-commit' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate FSPIOP-Signature + + + + + ref + + + Validate message.content.headers. + + + FSPIOP-Signature + + + Error codes: + + + 3105/3106 + + + + + Validate Bulk Fulfil Transfer + + + + + 4 + + + Schema validation of the incoming message + + + + + 5 + + + Verify the message's signature + + + (to be confirmed in future requirement) + + + + + The above validation steps are already handled by the + + + Bulk-API-Adapter for the open source implementation. + + + It may need to be added in future for custom adapters. + + + + + Validate Duplicate Check + + + + + 6 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check + + + + + 7 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + break + + + + + 8 + + + Request to retrieve Bulk Transfer state & completedTimestamp + + + Error code: + + + 2003 + + + + + 9 + + + Query database + + + + bulkTransfer + + + bulkTransferFulfilment + + + bulkTransferStateChange + + + + + 10 + + + Return resultset + + + + + 11 + + + Return + + + bulkTransferStateId + + + & + + + completedTimestamp + + + (not null when completed) + + + + + Message: + + + { + + + id: <messageId> + + + from: <ledgerName>, + + + to: <payeeFspName>, + + + type: application/json + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + bulkTransferState: <string>, + + + completedTimestamp: <optional> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "notification", + + + action: "bulk-fulfil-duplicate", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 12 + + + Publish Notification event for Payee + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + { + + + id: <messageId>, + + + from: <ledgerName", + + + to: <payeeFspName>, + + + type: "application/json", + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + errorInformation: { + + + errorCode: "3106", + + + errorDescription: "Modified request", + + + extensionList: { + + + extension: [ + + + { + + + key: "_cause", + + + value: <FSPIOPError> + + + } + + + ] + + + } + + + }, + + + uriParams: { + + + id: <bulkTransferId> + + + } + + + } + + + }, + + + metadata: { + + + correlationId: <uuid>, + + + event: { + + + id: <uuid>, + + + type: "notification", + + + action: "bulk-commit", + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: "3106", + + + description: "Modified request" + + + }, + + + responseTo: <uuid> + + + } + + + } + + + } + + + + + 13 + + + Publish Notification (failure) event for Payer + + + Error codes: + + + 3106 + + + + [hasDuplicateId == FALSE] + + + + + alt + + + [Validate Bulk Transfer Fulfil (success)] + + + + + Persist Bulk Transfer State (with bulktransferState='PROCESSING') + + + + + 14 + + + Request to persist bulk transfer fulfil + + + Error codes: + + + 2003 + + + + + 15 + + + Persist bulkTransferFulfilment + + + + bulkTransferFulfilment + + + bulkTransferStateChange + + + bulkTransferExtension + + + + + 16 + + + Return success + + + + [Validate Bulk Transfer Fulfil (failure)] + + + + + Persist Bulk Transfer State (with bulkTransferState='INVALID/REJECTED') + + + + + 17 + + + Request to persist bulk + + + transfer fulfil failure + + + Error codes: + + + 2003 + + + + + 18 + + + Persist transfer + + + + bulkTransferFulfilment + + + bulkTransferStateChange + + + bulkTransferExtension + + + bulkTransferError + + + + + 19 + + + Return success + + + + + alt + + + [Validate Bulk Transfer Fulfil (success)] + + + + + loop + + + [for every individual transfer in the bulk fulfil list] + + + + + 20 + + + Retrieve individual transfers from the bulk using + + + reference: + + + MLOS.individualTransferFulfils.messageId + + + + + 21 + + + Stream bulk's individual transfer fulfils + + + + + Message: + + + { + + + id: <messageId> + + + from: <payeeFspName>, + + + to: <payerFspName>, + + + type: "application/json" + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "fulfil", + + + action: "bulk-commit", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 22 + + + Route & Publish Prepare event to the Payer for the Individual Transfer + + + Error codes: + + + 2003 + + + + [Validate Bulk Transfer Fulfil (failure)] + + + + + Message: + + + { + + + id: <messageId> + + + from: <ledgerName>, + + + to: <payerFspName>, + + + type: "application/json" + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": <possible codes: [2003, 3100, 3105, 3106, 3202, 3203, 3300, 3301]> + + + "errorDescription": "<refer to section 35.1.3 for description>", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "notification", + + + action: "bulk-abort", + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 23 + + + Publish Notification (failure) event for Payer + + + Error codes: + + + 2003 + + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.plantuml new file mode 100644 index 000000000..b53afd2e5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.plantuml @@ -0,0 +1,236 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Sam Kummary + -------------- + ******'/ + +@startuml +' declate title +title 2.2.1. Fulfil Handler Consume (Success) individual transfers from Bulk + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Handler" as FULF_HANDLER +collections "topic-\nevent" as TOPIC_EVENT +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +entity "Position DAO" as POS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_BULK_PROCESSING + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Success) + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type == 'fulfil' && action == 'bulk-commit'\nError codes: 2001 + end + end + group Persist Event Information + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume\n + end + group Validate FSPIOP-Signature + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Validate message.content.headers.**FSPIOP-Signature**\nError codes: 3105/3106\n + ||| + end + + group Validate Duplicate Check + ||| + FULF_HANDLER -> DB: Request Duplicate Check + ref over FULF_HANDLER, DB: Request Duplicate Check\n + DB --> FULF_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break + FULF_HANDLER -> FULF_HANDLER: stateRecord = await getTransferState(transferId) + alt endStateList.includes(stateRecord.transferStateId) + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: getTransfer callback\n + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else + note right of FULF_HANDLER #lightgrey + Ignore - resend in progress + end note + end + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of FULF_HANDLER #lightgrey + Validate Prepare Transfer (failure) - Modified Request + end note + else hasDuplicateId == FALSE + + end + + group Validate and persist Transfer Fulfilment + FULF_HANDLER -> POS_DAO: Request information for the validate checks\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch from database + activate DB + hnote over DB #lightyellow + transfer + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return transfer + deactivate POS_DAO + FULF_HANDLER ->FULF_HANDLER: Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment)\nError code: 2001 + FULF_HANDLER -> FULF_HANDLER: Validate expirationDate\nError code: 3303 + + opt Transfer.ilpCondition validate successful + group Request current Settlement Window + FULF_HANDLER -> POS_DAO: Request to retrieve current/latest transfer settlement window\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch settlementWindowId + activate DB + hnote over DB #lightyellow + settlementWindow + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return settlementWindowId to be appended during transferFulfilment insert\n**TODO**: During settlement design make sure transfers in 'RECEIVED-FULFIL'\nstate are updated to the next settlement window + deactivate POS_DAO + end + end + + group Persist fulfilment + FULF_HANDLER -> POS_DAO: Persist fulfilment with the result of the above check (transferFulfilment.isValid)\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferFulfilment + transferExtension + end note + FULF_HANDLER <-- POS_DAO: Return success + deactivate POS_DAO + end + + alt Transfer.ilpCondition validate successful + group Persist Transfer State (with transferState='RECEIVED-FULFIL') + FULF_HANDLER -> POS_DAO: Request to persist transfer state\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + POS_DAO --> FULF_HANDLER: Return success + deactivate POS_DAO + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: "application/json", + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "position", + action: "bulk-commit", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Fulfil Transfer not successful + break + FULF_HANDLER -> FULF_HANDLER: Route & Publish Notification event for Payee\nReference: Failure in validation + end + end + end +end + +group Reference: Failure in validation + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: "application/json", + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "bulk-processing", + action: "bulk-commit", + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_BULK_PROCESSING: Publish Notification event for Payee to Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING +end + +deactivate FULF_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.svg new file mode 100644 index 000000000..b89824971 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.svg @@ -0,0 +1,726 @@ + + + + + + + + + + + 2.2.1. Fulfil Handler Consume (Success) individual transfers from Bulk + + + + Central Service + + + + + + + + + + + + + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Handler + + + + + Fulfil Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic- + + + event + + + + + topic- + + + event + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + + + topic- + + + notification + + + + + topic- + + + notification + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Handler Consume (Success) + + + + + 1 + + + Consume Fulfil event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'fulfil' && action == 'bulk-commit' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate FSPIOP-Signature + + + + + ref + + + Validate message.content.headers. + + + FSPIOP-Signature + + + Error codes: + + + 3105/3106 + + + + + Validate Duplicate Check + + + + + 4 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check + + + + + 5 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + break + + + + + 6 + + + stateRecord = await getTransferState(transferId) + + + + + alt + + + [endStateList.includes(stateRecord.transferStateId)] + + + + + ref + + + getTransfer callback + + + + + 7 + + + Produce message + + + + + + Ignore - resend in progress + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + Validate Prepare Transfer (failure) - Modified Request + + + + [hasDuplicateId == FALSE] + + + + + Validate and persist Transfer Fulfilment + + + + + 8 + + + Request information for the validate checks + + + Error code: + + + 2003 + + + + + 9 + + + Fetch from database + + + + transfer + + + + + 10 + + + + + 11 + + + Return transfer + + + + + 12 + + + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + + + Error code: + + + 2001 + + + + + 13 + + + Validate expirationDate + + + Error code: + + + 3303 + + + + + opt + + + [Transfer.ilpCondition validate successful] + + + + + Request current Settlement Window + + + + + 14 + + + Request to retrieve current/latest transfer settlement window + + + Error code: + + + 2003 + + + + + 15 + + + Fetch settlementWindowId + + + + settlementWindow + + + + + 16 + + + + + 17 + + + Return settlementWindowId to be appended during transferFulfilment insert + + + TODO + + + : During settlement design make sure transfers in 'RECEIVED-FULFIL' + + + state are updated to the next settlement window + + + + + Persist fulfilment + + + + + 18 + + + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + + + Error code: + + + 2003 + + + + + 19 + + + Persist to database + + + + transferFulfilment + + + transferExtension + + + + + 20 + + + Return success + + + + + alt + + + [Transfer.ilpCondition validate successful] + + + + + Persist Transfer State (with transferState='RECEIVED-FULFIL') + + + + + 21 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 22 + + + Persist transfer state + + + + transferStateChange + + + + + 23 + + + Return success + + + + + Message: + + + { + + + id: <messageId>, + + + from: <payeeFspName>, + + + to: <payerFspName>, + + + type: "application/json", + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "position", + + + action: "bulk-commit", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 24 + + + Route & Publish Position event for Payee + + + + [Validate Fulfil Transfer not successful] + + + + + break + + + + + 25 + + + Route & Publish Notification event for Payee + + + Reference: Failure in validation + + + + + Reference: Failure in validation + + + + + Message: + + + { + + + id: <messageId>, + + + from: <ledgerName>, + + + to: <payeeFspName>, + + + type: "application/json", + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "bulk-processing", + + + action: "bulk-commit", + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 26 + + + Publish Notification event for Payee to Bulk Processing Topic + + + Error codes: + + + 2003 + + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.plantuml new file mode 100644 index 000000000..a90928354 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.plantuml @@ -0,0 +1,616 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Sam Kummary + -------------- + ******'/ + +@startuml +' declate title +title 2.2.2. Fulfil Handler Consume (Reject/Abort) (single message, includes individual transfers from Bulk) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "topic-\nfulfil" as TOPIC_FULFIL +control "Fulfil Handler" as FULF_HANDLER +collections "topic-\nevent" as TOPIC_EVENT +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +'entity "Transfer Duplicate Facade" as DUP_FACADE +entity "Transfer DAO" as TRANS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_BULK_PROCESSING + participant TOPIC_NOTIFICATIONS + participant TRANS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Failure) + alt Consume Single Message + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type IN ['fulfil','bulk-fulfil'] && ( action IN ['reject','abort'] )\nError codes: 2001 + end + end + group Persist Event Information + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume\n + end + group Validate FSPIOP-Signature + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Validate message.content.headers.**FSPIOP-Signature**\nError codes: 2001 + end + group Validate Transfer Fulfil Duplicate Check + FULF_HANDLER -> FULF_HANDLER: Generate transferFulfilmentId uuid + FULF_HANDLER -> TRANS_DAO: Request to retrieve transfer fulfilment hashes by transferId\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request Transfer fulfilment \nduplicate message hashes + hnote over DB #lightyellow + SELET transferId, hash + FROM **transferFulfilmentDuplicateCheck** + WHERE transferId = request.params.id + end note + activate DB + TRANS_DAO <-- DB: Return existing hashes + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return (list of) transfer fulfil messages hash(es) + deactivate TRANS_DAO + FULF_HANDLER -> FULF_HANDLER: Loop the list of returned hashes & compare \neach entry with the calculated message hash + alt Hash matched + ' Need to check what respond with same results if finalised then resend, else ignore and wait for response + FULF_HANDLER -> TRANS_DAO: Request to retrieve Transfer Fulfilment & Transfer state\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request to retrieve \ntransferFulfilment & transferState + hnote over DB #lightyellow + transferFulfilment + transferStateChange + end note + activate DB + TRANS_DAO <-- DB: Return transferFulfilment & \ntransferState + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return Transfer Fulfilment & Transfer state + deactivate TRANS_DAO + alt transferFulfilment.isValid == 0 + break + alt If type == 'fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: fulfil-duplicate, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event for Payee - Modified Request\nError codes: 3106 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: fulfil-duplicate, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_BULK_PROCESSING: Publish Notification event for Payee - Modified Request \n3106 to Bulk Processing Topic\nError codes: 3106 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + end + else transferState IN ['COMMITTED', 'ABORTED'] + break + alt If type == 'fulfil' + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + else If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: fulfil-duplicate, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_BULK_PROCESSING: Publish Notification event for Payee to Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + end + else transferState NOT 'RESERVED' + break + FULF_HANDLER <-> FULF_HANDLER: Reference: Failure in validation\nError code: 2001 + end + else + break + alt If type == 'fulfil' + FULF_HANDLER <-> FULF_HANDLER: Allow previous request to complete + else If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: fulfil-duplicate, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_BULK_PROCESSING: Publish Notification event for Payee to Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + end + end + else Hash not matched + FULF_HANDLER -> TRANS_DAO: Request to persist transfer hash\nError codes: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist hash + hnote over DB #lightyellow + transferFulfilmentDuplicateCheck + end note + activate DB + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + deactivate TRANS_DAO + end + end + alt action=='reject' call made on PUT /transfers/{ID} + FULF_HANDLER -> TRANS_DAO: Request information for the validate checks\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Fetch from database + activate DB + hnote over DB #lightyellow + transfer + end note + DB --> TRANS_DAO + deactivate DB + FULF_HANDLER <-- TRANS_DAO: Return transfer + deactivate TRANS_DAO + + alt Fulfilment present in the PUT /transfers/{ID} message + FULF_HANDLER ->FULF_HANDLER: Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment)\nError code: 2001 + + group Persist fulfilment + FULF_HANDLER -> TRANS_DAO: Persist fulfilment with the result of the above check (transferFulfilment.isValid)\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferFulfilment + transferExtension + end note + FULF_HANDLER <-- TRANS_DAO: Return success + deactivate TRANS_DAO + end + else Fulfilment NOT present in the PUT /transfers/{ID} message + FULF_HANDLER ->FULF_HANDLER: Validate that transfer fulfilment message to Abort is valid\nError code: 2001 + group Persist extensions + FULF_HANDLER -> TRANS_DAO: Persist extensionList elements\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferExtension + end note + FULF_HANDLER <-- TRANS_DAO: Return success + deactivate TRANS_DAO + end + end + + alt Transfer.ilpCondition validate successful OR generic validation successful + group Persist Transfer State (with transferState='RECEIVED_REJECT') + FULF_HANDLER -> TRANS_DAO: Request to persist transfer state\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + end + + FULF_HANDLER -> FULF_HANDLER: Route & Publish Position event for Payer\nReference: Publish Position Reject event for Payer + + else Validate Fulfil Transfer not successful or Generic validation failed + break + FULF_HANDLER -> FULF_HANDLER: Publish event for Payee\nReference: Failure in validation + end + end + else action=='abort' Error callback + alt Validation successful + group Persist Transfer State (with transferState='RECEIVED_ERROR') + FULF_HANDLER -> TRANS_DAO: Request to persist transfer state & Error\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist transfer state & Error + activate DB + hnote over DB #lightyellow + transferStateChange + transferError + transferExtension + end note + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + end + + FULF_HANDLER -> FULF_HANDLER: Error callback validated\nReference: Produce message for validated error callback + + else Validate Transfer Error Message not successful + break + FULF_HANDLER -> FULF_HANDLER: Notifications for failures\nReference: Validate Transfer Error Message not successful + end + end + end + else Consume Batch Messages + note left of FULF_HANDLER #lightblue + To be delivered by future story + end note + end +end + +group Reference: Validate Transfer Error Message not successful + alt If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_BULK_PROCESSING: Publish Processing event for Payee to Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + else If type == 'fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: fulfil, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Route & Publish Notification event for Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end +end + +group Reference: Produce message for validated error callback + alt If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-position, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else If type == 'fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end +end + +group Reference: Failure in validation + alt If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: reject, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_BULK_PROCESSING: Publish processing event to the Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + else If type == 'fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: fulfil, + action: reject, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Route & Publish Notification event for Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end +end + +group Reference: Publish Position Reject event for Payer + alt If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-position, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else If type == 'fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end +end + +deactivate FULF_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.svg new file mode 100644 index 000000000..1b64285dd --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.svg @@ -0,0 +1,1975 @@ + + + + + + + + + + + 2.2.2. Fulfil Handler Consume (Reject/Abort) (single message, includes individual transfers from Bulk) + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + topic- + + + fulfil + + + + + topic- + + + fulfil + + + Fulfil Handler + + + + + Fulfil Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic- + + + event + + + + + topic- + + + event + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + + + topic- + + + notification + + + + + topic- + + + notification + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + + Fulfil Handler Consume (Failure) + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume Fulfil event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type IN ['fulfil','bulk-fulfil'] && ( action IN ['reject','abort'] ) + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate FSPIOP-Signature + + + + + ref + + + Validate message.content.headers. + + + FSPIOP-Signature + + + Error codes: + + + 2001 + + + + + Validate Transfer Fulfil Duplicate Check + + + + + 4 + + + Generate transferFulfilmentId uuid + + + + + 5 + + + Request to retrieve transfer fulfilment hashes by transferId + + + Error code: + + + 2003 + + + + + 6 + + + Request Transfer fulfilment + + + duplicate message hashes + + + + SELET transferId, hash + + + FROM + + + transferFulfilmentDuplicateCheck + + + WHERE transferId = request.params.id + + + + + 7 + + + Return existing hashes + + + + + 8 + + + Return (list of) transfer fulfil messages hash(es) + + + + + 9 + + + Loop the list of returned hashes & compare + + + each entry with the calculated message hash + + + + + alt + + + [Hash matched] + + + + + 10 + + + Request to retrieve Transfer Fulfilment & Transfer state + + + Error code: + + + 2003 + + + + + 11 + + + Request to retrieve + + + transferFulfilment & transferState + + + + transferFulfilment + + + transferStateChange + + + + + 12 + + + Return transferFulfilment & + + + transferState + + + + + 13 + + + Return Transfer Fulfilment & Transfer state + + + + + alt + + + [transferFulfilment.isValid == 0] + + + + + break + + + + + alt + + + [If type == 'fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: fulfil-duplicate, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 14 + + + Publish Notification event for Payee - Modified Request + + + Error codes: + + + 3106 + + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: fulfil-duplicate, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 15 + + + Publish Notification event for Payee - Modified Request + + + 3106 to Bulk Processing Topic + + + Error codes: + + + 3106 + + + + [transferState IN ['COMMITTED', 'ABORTED']] + + + + + break + + + + + alt + + + [If type == 'fulfil'] + + + + + ref + + + Send notification to Participant (Payee) + + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: fulfil-duplicate, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 16 + + + Publish Notification event for Payee to Bulk Processing Topic + + + Error codes: + + + 2003 + + + + [transferState NOT 'RESERVED'] + + + + + break + + + + + 17 + + + Reference: Failure in validation + + + Error code: + + + 2001 + + + + + + break + + + + + alt + + + [If type == 'fulfil'] + + + + + 18 + + + Allow previous request to complete + + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: fulfil-duplicate, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 19 + + + Publish Notification event for Payee to Bulk Processing Topic + + + Error codes: + + + 2003 + + + + [Hash not matched] + + + + + 20 + + + Request to persist transfer hash + + + Error codes: + + + 2003 + + + + + 21 + + + Persist hash + + + + transferFulfilmentDuplicateCheck + + + + + 22 + + + Return success + + + + + alt + + + [action=='reject' call made on PUT /transfers/{ID}] + + + + + 23 + + + Request information for the validate checks + + + Error code: + + + 2003 + + + + + 24 + + + Fetch from database + + + + transfer + + + + + 25 + + + + + 26 + + + Return transfer + + + + + alt + + + [Fulfilment present in the PUT /transfers/{ID} message] + + + + + 27 + + + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + + + Error code: + + + 2001 + + + + + Persist fulfilment + + + + + 28 + + + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + + + Error code: + + + 2003 + + + + + 29 + + + Persist to database + + + + transferFulfilment + + + transferExtension + + + + + 30 + + + Return success + + + + [Fulfilment NOT present in the PUT /transfers/{ID} message] + + + + + 31 + + + Validate that transfer fulfilment message to Abort is valid + + + Error code: + + + 2001 + + + + + Persist extensions + + + + + 32 + + + Persist extensionList elements + + + Error code: + + + 2003 + + + + + 33 + + + Persist to database + + + + transferExtension + + + + + 34 + + + Return success + + + + + alt + + + [Transfer.ilpCondition validate successful OR generic validation successful] + + + + + Persist Transfer State (with transferState='RECEIVED_REJECT') + + + + + 35 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 36 + + + Persist transfer state + + + + transferStateChange + + + + + 37 + + + Return success + + + + + 38 + + + Route & Publish Position event for Payer + + + Reference: Publish Position Reject event for Payer + + + + [Validate Fulfil Transfer not successful or Generic validation failed] + + + + + break + + + + + 39 + + + Publish event for Payee + + + Reference: Failure in validation + + + + [action=='abort' Error callback] + + + + + alt + + + [Validation successful] + + + + + Persist Transfer State (with transferState='RECEIVED_ERROR') + + + + + 40 + + + Request to persist transfer state & Error + + + Error code: + + + 2003 + + + + + 41 + + + Persist transfer state & Error + + + + transferStateChange + + + transferError + + + transferExtension + + + + + 42 + + + Return success + + + + + 43 + + + Error callback validated + + + Reference: Produce message for validated error callback + + + + [Validate Transfer Error Message not successful] + + + + + break + + + + + 44 + + + Notifications for failures + + + Reference: Validate Transfer Error Message not successful + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + + + + Reference: Validate Transfer Error Message not successful + + + + + alt + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 45 + + + Publish Processing event for Payee to Bulk Processing Topic + + + Error codes: + + + 2003 + + + + [If type == 'fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: fulfil, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 46 + + + Route & Publish Notification event for Payee + + + + + Reference: Produce message for validated error callback + + + + + alt + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 47 + + + Route & Publish Position event for Payer + + + + [If type == 'fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 48 + + + Route & Publish Position event for Payer + + + + + Reference: Failure in validation + + + + + alt + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 49 + + + Publish processing event to the Bulk Processing Topic + + + Error codes: + + + 2003 + + + + [If type == 'fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: fulfil, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 50 + + + Route & Publish Notification event for Payee + + + + + Reference: Publish Position Reject event for Payer + + + + + alt + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-position, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 51 + + + Route & Publish Position event for Payer + + + + [If type == 'fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 52 + + + Route & Publish Position event for Payer + + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.plantuml new file mode 100644 index 000000000..f992f9284 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.plantuml @@ -0,0 +1,176 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Rajiv Mothilal + * Sam Kummary + -------------- + ******'/ + +@startuml +' declate title +title 2.3.1. Fulfil Position Handler Consume (single message, includes individual transfers from Bulk) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER +collections "topic-\nnotifications" as TOPIC_NOTIFICATIONS +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +entity "Position Facade" as POS_FACADE +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant TOPIC_BULK_PROCESSING + participant POS_DAO + participant POS_FACADE + participant DB +end box + +' start flow +activate POS_HANDLER +group Fulfil Position Handler Consume + POS_HANDLER -> POS_DAO: Request current state of transfer from DB \nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferState is 'RECEIVED-FULFIL')\nError code: 2001 + group Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + POS_HANDLER -> POS_FACADE: Request to persist latest position and state to DB\nError code: 2003 + group DB TRANSACTION + activate POS_FACADE + POS_FACADE -> DB: Select participantPosition.value FOR UPDATE from DB for Payee + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_FACADE: Return participantPosition.value from DB for Payee + deactivate DB + POS_FACADE <-> POS_FACADE: **latestPosition** = participantPosition.value - payload.amount.amount + POS_FACADE->DB: Persist latestPosition to DB for Payee + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value = latestPosition + end note + activate DB + deactivate DB + POS_FACADE -> DB: Persist transfer state and participant position change + hnote over DB #lightyellow + INSERT **transferStateChange** transferStateId = 'COMMITTED' + + INSERT **participantPositionChange** + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + end note + activate DB + deactivate DB + deactivate POS_DAO + end + POS_FACADE --> POS_HANDLER: Return success + deactivate POS_FACADE + end + + alt If type == 'bulk-position' + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: bulk-commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_BULK_PROCESSING: Publish Transfer event to Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + else If type == 'position' + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Transfer event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + +end +deactivate POS_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.svg new file mode 100644 index 000000000..a50bd3d57 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.svg @@ -0,0 +1,468 @@ + + + + + + + + + + + 2.3.1. Fulfil Position Handler Consume (single message, includes individual transfers from Bulk) + + + + Central Service + + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + topic- + + + notifications + + + + + topic- + + + notifications + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Position DAO + + + + + Position DAO + + + + + Position Facade + + + + + Position Facade + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Position Handler Consume + + + + + 1 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 2 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + transferParticipant + + + + + 3 + + + Return current state of transfer from DB + + + + + 4 + + + Return current state of transfer from DB + + + + + 5 + + + Validate current state (transferState is 'RECEIVED-FULFIL') + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + + + + + 6 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + DB TRANSACTION + + + + + 7 + + + Select participantPosition.value FOR UPDATE from DB for Payee + + + + participantPosition + + + + + 8 + + + Return participantPosition.value from DB for Payee + + + + + 9 + + + latestPosition + + + = participantPosition.value - payload.amount.amount + + + + + 10 + + + Persist latestPosition to DB for Payee + + + + UPDATE + + + participantPosition + + + SET value = latestPosition + + + + + 11 + + + Persist transfer state and participant position change + + + + INSERT + + + transferStateChange + + + transferStateId = 'COMMITTED' + + + INSERT + + + participantPositionChange + + + SET participantPositionId = participantPosition.participantPositionId, + + + transferStateChangeId = transferStateChange.transferStateChangeId, + + + value = latestPosition, + + + reservedValue = participantPosition.reservedValue + + + createdDate = new Date() + + + + + 12 + + + Return success + + + + + alt + + + [If type == 'bulk-position'] + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: bulk-commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 13 + + + Publish Transfer event to Bulk Processing Topic + + + Error codes: + + + 2003 + + + + [If type == 'position'] + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 14 + + + Publish Transfer event + + + Error code: + + + 2003 + + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.plantuml new file mode 100644 index 000000000..467666a01 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.plantuml @@ -0,0 +1,419 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Sam Kummary + ------------- + ******'/ + +@startuml +' declate title +title 2.3.2. Abort Position Handler Consume (single message, includes individual transfers from Bulk) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER +entity "Position DAO" as POS_DAO +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant TOPIC_BULK_PROCESSING + participant POS_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Abort Position Handler Consume + opt type IN ['position','bulk-position'] && action == 'timeout-reserved' + POS_HANDLER -> POS_DAO: Request current state of transfer from DB\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state \n(transferStateChange.transferStateId == 'RESERVED_TIMEOUT')\nError code: 2001 + + group Persist Position change and Transfer state + POS_HANDLER -> POS_HANDLER: **transferStateId** = 'EXPIRED_RESERVED' + POS_HANDLER -> POS_DAO: Request to persist latest position and state to DB\nError code: 2003 + group DB TRANSACTION IMPLEMENTATION + activate POS_DAO + POS_DAO -> DB: Select participantPosition.value FOR UPDATE for payerCurrencyId + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_DAO: Return participantPosition + deactivate DB + POS_DAO <-> POS_DAO: **latestPosition** = participantPosition - payload.amount.amount + POS_DAO->DB: Persist latestPosition to DB for Payer + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value = latestPosition + end note + activate DB + deactivate DB + POS_DAO -> DB: Persist participant position change and state change + hnote over DB #lightyellow + INSERT **transferStateChange** + VALUES (transferStateId) + + INSERT **participantPositionChange** + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + end note + activate DB + deactivate DB + end + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + alt If type == 'bulk-position' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_BULK_PROCESSING: Publish Transfer event to Bulk Processing Topic (for Payer) \nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + else If type == 'position' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + end + opt type IN ['position','bulk-position'] && (action IN ['reject', 'abort']) + POS_HANDLER -> POS_DAO: Request current state of transfer from DB\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state \n(transferStateChange.transferStateId IN ['RECEIVED_REJECT', 'RECEIVED_ERROR'])\nError code: 2001 + + group Persist Position change and Transfer state + POS_HANDLER -> POS_HANDLER: **transferStateId** = (action == 'reject' ? 'ABORTED_REJECTED' : 'ABORTED_ERROR' ) + POS_HANDLER -> POS_DAO: Request to persist latest position and state to DB\nError code: 2003 + group Refer to DB TRANSACTION IMPLEMENTATION above + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + participantPosition + transferStateChange + participantPositionChange + end note + end + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + alt If action == 'reject' + alt If type == 'position' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: reject, + createdAt: , + state: { + status: "success", + code: 0, + description: "action successful" + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else If type == 'bulk-position' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: reject, + createdAt: , + state: { + status: "success", + code: 0, + description: "action successful" + } + } + } + } + end note + POS_HANDLER -> TOPIC_BULK_PROCESSING: Publish Notification event\nError code: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + else action == 'abort' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + end + + ' TODO: We do not see how this scenario will be triggered + opt type IN ['position','bulk-position'] && action == 'fail' (Unable to currently trigger this scenario) + POS_HANDLER -> POS_DAO: Request current state of transfer from DB\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferStateChange.transferStateId == 'FAILED') + + group Persist Position change and Transfer state + POS_HANDLER -> POS_HANDLER: **transferStateId** = 'FAILED' + POS_HANDLER -> POS_DAO: Request to persist latest position and state to DB\nError code: 2003 + group Refer to DB TRANSACTION IMPLEMENTATION above + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + participantPosition + transferStateChange + participantPositionChange + end note + end + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + alt If type =='position' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3100, + "errorDescription": "Transfer failed", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else If type =='bulk-position' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3100, + "errorDescription": "Transfer failed", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_BULK_PROCESSING: Publish Notification event\nError code: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + end +end +deactivate POS_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.svg new file mode 100644 index 000000000..9ebfd3c26 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.svg @@ -0,0 +1,1297 @@ + + + + + + + + + + + 2.3.2. Abort Position Handler Consume (single message, includes individual transfers from Bulk) + + + + Central Service + + + + + + + + + + + + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Abort Position Handler Consume + + + + + opt + + + [type IN ['position','bulk-position'] && action == 'timeout-reserved'] + + + + + 1 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 2 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + transferParticipant + + + + + 3 + + + Return current state of transfer from DB + + + + + 4 + + + Return current state of transfer from DB + + + + + 5 + + + Validate current state + + + (transferStateChange.transferStateId == 'RESERVED_TIMEOUT') + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer state + + + + + 6 + + + transferStateId + + + = 'EXPIRED_RESERVED' + + + + + 7 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + DB TRANSACTION IMPLEMENTATION + + + + + 8 + + + Select participantPosition.value FOR UPDATE for payerCurrencyId + + + + participantPosition + + + + + 9 + + + Return participantPosition + + + + + 10 + + + latestPosition + + + = participantPosition - payload.amount.amount + + + + + 11 + + + Persist latestPosition to DB for Payer + + + + UPDATE + + + participantPosition + + + SET value = latestPosition + + + + + 12 + + + Persist participant position change and state change + + + + INSERT + + + transferStateChange + + + VALUES (transferStateId) + + + INSERT + + + participantPositionChange + + + SET participantPositionId = participantPosition.participantPositionId, + + + transferStateChangeId = transferStateChange.transferStateChangeId, + + + value = latestPosition, + + + reservedValue = participantPosition.reservedValue + + + createdDate = new Date() + + + + + 13 + + + Return success + + + + + alt + + + [If type == 'bulk-position'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Transfer expired", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 14 + + + Publish Transfer event to Bulk Processing Topic (for Payer) + + + Error codes: + + + 2003 + + + + [If type == 'position'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Transfer expired", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 15 + + + Publish Notification event + + + Error code: + + + 2003 + + + + + opt + + + [type IN ['position','bulk-position'] && (action IN ['reject', 'abort'])] + + + + + 16 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 17 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + + + 18 + + + Return current state of transfer from DB + + + + + 19 + + + Return current state of transfer from DB + + + + + 20 + + + Validate current state + + + (transferStateChange.transferStateId IN ['RECEIVED_REJECT', 'RECEIVED_ERROR']) + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer state + + + + + 21 + + + transferStateId + + + = (action == 'reject' ? 'ABORTED_REJECTED' : 'ABORTED_ERROR' ) + + + + + 22 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + Refer to + + + DB TRANSACTION IMPLEMENTATION + + + above + + + + + 23 + + + Persist to database + + + + participantPosition + + + transferStateChange + + + participantPositionChange + + + + + 24 + + + Return success + + + + + alt + + + [If action == 'reject'] + + + + + alt + + + [If type == 'position'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0, + + + description: "action successful" + + + } + + + } + + + } + + + } + + + + + 25 + + + Publish Notification event + + + Error code: + + + 2003 + + + + [If type == 'bulk-position'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0, + + + description: "action successful" + + + } + + + } + + + } + + + } + + + + + 26 + + + Publish Notification event + + + Error code: + + + 2003 + + + + [action == 'abort'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <payload.errorInformation.errorCode || 5000> + + + description: <payload.errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 27 + + + Publish Notification event + + + Error code: + + + 2003 + + + + + opt + + + [type IN ['position','bulk-position'] && action == 'fail' (Unable to currently trigger this scenario)] + + + + + 28 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 29 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + + + 30 + + + Return current state of transfer from DB + + + + + 31 + + + Return current state of transfer from DB + + + + + 32 + + + Validate current state (transferStateChange.transferStateId == 'FAILED') + + + + + Persist Position change and Transfer state + + + + + 33 + + + transferStateId + + + = 'FAILED' + + + + + 34 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + Refer to + + + DB TRANSACTION IMPLEMENTATION + + + above + + + + + 35 + + + Persist to database + + + + participantPosition + + + transferStateChange + + + participantPositionChange + + + + + 36 + + + Return success + + + + + alt + + + [If type =='position'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3100, + + + "errorDescription": "Transfer failed", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 37 + + + Publish Notification event + + + Error code: + + + 2003 + + + + [If type =='bulk-position'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3100, + + + "errorDescription": "Transfer failed", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 38 + + + Publish Notification event + + + Error code: + + + 2003 + + diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.plantuml similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.plantuml rename to legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.plantuml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.svg new file mode 100644 index 000000000..20faf4b81 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.svg @@ -0,0 +1,406 @@ + + + + + + + + + + + 3.1.0. Transfer Timeout (incl. Bulk Transfer) + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API + + + Adapter + + + + + ML API + + + Adapter + + + + + ML API Notification + + + Event Handler + + + + + ML API Notification + + + Event Handler + + + + + Transfer Timeout + + + Handler + + + + + Transfer Timeout + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic-event + + + + + topic-event + + + Position Event + + + Handler + + + + + Position Event + + + Handler + + + + + + + topic- + + + notification + + + + + topic- + + + notification + + + Bulk Processing + + + Handler + + + + + Bulk Processing + + + Handler + + + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + + + + Transfer Expiry + + + + + ref + + + Timeout Handler Consume + + + + + alt + + + [transferStateId == 'RECEIVED_PREPARE'] + + + + + alt + + + [Regular Transfer] + + + + + 1 + + + Produce message + + + + [Individual Transfer from a Bulk] + + + + + 2 + + + Produce message + + + + [transferStateId == 'RESERVED'] + + + + + 3 + + + Produce message + + + + + 4 + + + Consume message + + + + + ref + + + Position Hander Consume (Timeout) + + + + + alt + + + [Regular Transfer] + + + + + 5 + + + Produce message + + + + [Individual Transfer from a Bulk] + + + + + 6 + + + Produce message + + + + + opt + + + [action IN ['bulk-timeout-received', 'bulk-timeout-reserved']] + + + + + 7 + + + Consume message + + + + + ref + + + Bulk Processing Consume + + + + + 8 + + + Produce message + + + + + opt + + + [action IN ['timeout-received', 'timeout-reserved', 'bulk-timeout-received', 'bulk-timeout-reserved']] + + + + + 9 + + + Consume message + + + + + ref + + + Send notification to Participant (Payer) + + + + + 10 + + + Send callback notification + + + + + opt + + + [action IN ['timeout-reserved', 'bulk-timeout-reserved']] + + + + + 11 + + + Consume message + + + + + ref + + + Send notification to Participant (Payee) + + + + + 12 + + + Send callback notification + + diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.plantuml similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.plantuml rename to legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.plantuml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.svg new file mode 100644 index 000000000..4f687da29 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.svg @@ -0,0 +1,1340 @@ + + + + + + + + + + + 3.1.1. Timeout Handler Consume (incl. Bulk Transfer) + + + + Central Service + + + + + + + + + + + + + + Transfer Timeout + + + Handler + + + + + Transfer Timeout + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + topic-event + + + + + topic-event + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Position DAO + + + + + Position DAO + + + + + Segment DAO + + + + + Segment DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Timeout Handler Consume + + + + + Persist Event Information + + + + + 1 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Get previous checkpoint of last record processed (Lower limit for inclusion) + + + + + 2 + + + Get last segment as @intervalMin + + + + + 3 + + + Get last segment as @intervalMin + + + + SELECT value INTO @intervalMin + + + FROM + + + segment + + + WHERE segmentType = 'timeout' + + + AND enumeration = 0 + + + AND tableName = 'transferStateChange' + + + + + 4 + + + Return @intervalMin + + + + + 5 + + + Return @intervalMin + + + + + opt + + + [@intervalMin IS NULL => segment record NOT FOUND] + + + + + 6 + + + Set @intervalMin = 0 + + + + + Do Cleanup + + + + + 7 + + + Clean up transferTimeout from finalised transfers + + + + + 8 + + + Clean up transferTimeout from finalised transfers + + + + DELETE tt + + + FROM + + + transferTimeout + + + AS tt + + + JOIN (SELECT tsc.transferId, MAX(tsc.transferStateChangeId) maxTransferStateChangeId + + + FROM + + + transferTimeout + + + tt1 + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferId = tt1.transferId + + + GROUP BY transferId) ts + + + ON ts.transferId = tt.transferId + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + + + WHERE tsc.transferStateId IN ('RECEIVED_FULFIL', 'COMMITTED', 'FAILED' + + + , 'EXPIRED', 'REJECTED', 'EXPIRED_PREPARED', 'EXPIRED_RESERVED', 'ABORTED') + + + + + 9 + + + Return success + + + + + Determine IntervalMax (Upper limit for inclusion) + + + + + 10 + + + Get last transferStateChangeId as @intervalMax + + + + + 11 + + + Get last transferStateChangeId as @intervalMax + + + + SELECT MAX(transferStateChangeId) INTO @intervalMax + + + FROM + + + transferStateChange + + + + + 12 + + + Return @intervalMax + + + + + 13 + + + Return @intervalMax + + + + + Prepare data and return the list for expiration + + + + + 14 + + + Prepare data and get transfers to be expired + + + + + DB TRANSACTION + + + + + 15 + + + transactionTimestamp + + + = now() + + + + + 16 + + + Insert all new transfers still in processing state + + + + INSERT INTO + + + transferTimeout + + + (transferId, expirationDate) + + + SELECT t.transferId, t.expirationDate + + + FROM + + + transfer + + + t + + + JOIN (SELECT transferId, MAX(transferStateChangeId) maxTransferStateChangeId + + + FROM + + + transferStateChange + + + WHERE transferStateChangeId > @intervalMin + + + AND transferStateChangeId <= @intervalMax + + + GROUP BY transferId) ts + + + ON ts.transferId = t.transferId + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + + + WHERE tsc.transferStateId IN ('RECEIVED_PREPARE', 'RESERVED') + + + + + 17 + + + Insert transfer state ABORTED for + + + expired RECEIVED_PREPARE transfers + + + + INSERT INTO + + + transferStateChange + + + SELECT tt.transferId, 'EXPIRED_PREPARED' AS transferStateId, 'Aborted by Timeout Handler' AS reason + + + FROM + + + transferTimeout + + + tt + + + JOIN ( + + + -- Following subquery is reused 3 times and may be optimized if needed + + + SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + + + FROM + + + transferStateChange + + + tsc1 + + + JOIN + + + transferTimeout + + + tt1 + + + ON tt1.transferId = tsc1.transferId + + + GROUP BY tsc1.transferId) ts + + + ON ts.transferId = tt.transferId + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + + + WHERE tt.expirationDate < {transactionTimestamp} + + + AND tsc.transferStateId = 'RECEIVED_PREPARE' + + + + + 18 + + + Insert transfer state EXPIRED for + + + expired RESERVED transfers + + + + INSERT INTO + + + transferStateChange + + + SELECT tt.transferId, 'RESERVED_TIMEOUT' AS transferStateId, 'Expired by Timeout Handler' AS reason + + + FROM + + + transferTimeout + + + tt + + + JOIN (SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + + + FROM + + + transferStateChange + + + tsc1 + + + JOIN + + + transferTimeout + + + tt1 + + + ON tt1.transferId = tsc1.transferId + + + GROUP BY tsc1.transferId) ts + + + ON ts.transferId = tt.transferId + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + + + WHERE tt.expirationDate < {transactionTimestamp} + + + AND tsc.transferStateId = 'RESERVED' + + + + + 19 + + + Update segment table to be used for the next run + + + + IF @intervalMin = 0 + + + INSERT + + + INTO + + + segment + + + (segmentType, enumeration, tableName, value) + + + VALUES ('timeout', 0, 'transferStateChange', @intervalMax) + + + ELSE + + + UPDATE + + + segment + + + SET value = @intervalMax + + + WHERE segmentType = 'timeout' + + + AND enumeration = 0 + + + AND tableName = 'transferStateChange' + + + + + 20 + + + Get list of transfers to be expired with current state + + + + SELECT tt.*, tsc.transferStateId, tp1.participantCurrencyId payerParticipantId, + + + tp2.participantCurrencyId payeeParticipantId, bta.bulkTransferId + + + FROM + + + transferTimeout + + + tt + + + JOIN (SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + + + FROM + + + transferStateChange + + + tsc1 + + + JOIN + + + transferTimeout + + + tt1 + + + ON tt1.transferId = tsc1.transferId + + + GROUP BY tsc1.transferId) ts + + + ON ts.transferId = tt.transferId + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + + + JOIN + + + transferParticipant + + + tp1 + + + ON tp1.transferId = tt.transferId + + + AND tp1.transferParticipantRoleTypeId = {PAYER_DFSP} + + + AND tp1.ledgerEntryTypeId = {PRINCIPLE_VALUE} + + + JOIN + + + transferParticipant + + + tp2 + + + ON tp2.transferId = tt.transferId + + + AND tp2.transferParticipantRoleTypeId = {PAYEE_DFSP} + + + AND tp2.ledgerEntryTypeId = {PRINCIPLE_VALUE} + + + LEFT JOIN + + + bulkTransferAssociation + + + bta + + + ON bta.transferId = tt.transferId + + + WHERE tt.expirationDate < {transactionTimestamp} + + + + + 21 + + + Return + + + transferTimeoutList + + + + + 22 + + + Return + + + transferTimeoutList + + + + + loop + + + [for each transfer in the list] + + + + + alt + + + [transferTimeoutList.bulkTransferId == NULL (Regular Transfer)] + + + + + alt + + + [transferStateId == 'RECEIVED_PREPARE'] + + + + + Message: + + + { + + + id: <transferId>, + + + from: <payerParticipantId>, + + + to: <payeeParticipantId>, + + + type: application/json, + + + content: { + + + headers: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + }, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Generic expired error", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: notification, + + + action: timeout-received, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 23 + + + Publish Notification event + + + + [transferStateId == 'RESERVED'] + + + + + Message: + + + { + + + id: <transferId>, + + + from: <payerParticipantId>, + + + to: <payeeParticipantId>, + + + type: application/json, + + + content: { + + + headers: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + }, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Generic expired error", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: position, + + + action: timeout-reserved, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 24 + + + Route & Publish Position event + + + + [Individual Transfer from a Bulk] + + + + + alt + + + [transferStateId == 'RECEIVED_PREPARE'] + + + + + Message: + + + { + + + id + + + : <transferTimeoutList.bulkTransferId>, + + + transferId + + + : <transferTimeoutList.transferId>, + + + from: <payerParticipantId>, + + + to: <payeeParticipantId>, + + + type: application/json, + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Generic expired error", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: bulk-processing, + + + action: bulk-timeout-received, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 25 + + + Publish to Bulk Processing topic + + + + [transferStateId == 'RESERVED'] + + + + + Message: + + + { + + + id + + + : <transferTimeoutList.bulkTransferId>, + + + transferId + + + : <transferTimeoutList.transferId>, + + + from: <payerParticipantId>, + + + to: <payeeParticipantId>, + + + type: application/json, + + + content: { + + + headers: <bulkTransferHeaders>,, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Generic expired error", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: position, + + + action: bulk-timeout-reserved, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 26 + + + Route & Publish Position event + + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.plantuml new file mode 100644 index 000000000..e02a15142 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.plantuml @@ -0,0 +1,233 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- + ******'/ + +@startuml +' declare title +title 4.1.0. Bulk Transfer Abort + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "Bulk API Adapter" as BULKAPI +control "Bulk API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Bulk-Fulfil-Topic" as TOPIC_BULK_FULFIL +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Bulk Fulfil Event Handler" as BULK_FULFIL_HANDLER +control "Fulfil Event Handler" as FULFIL_HANDLER +collections "topic-transfer-position" as TOPIC_POSITION +control "Position Event Handler" as POS_HANDLER +collections "topic-bulk-processing" as TOPIC_BULK_PROCESSING +control "Bulk Processing Event Handler" as BULK_PROCESSING_HANDLER +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE +database "Central Services DB" as DB + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "Bulk API Adapter Service" #LightBlue + participant BULKAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_BULK_FULFIL + participant TOPIC_FULFIL + participant BULK_FULFIL_HANDLER + participant FULFIL_HANDLER + participant TOPIC_POSITION + participant TOPIC_EVENTS + participant POS_HANDLER + participant TOPIC_BULK_PROCESSING + participant BULK_PROCESSING_HANDLER + participant TOPIC_NOTIFICATIONS + participant OBJECT_STORE + participant DB +end box + +' start flow +activate NOTIFY_HANDLER +activate BULK_FULFIL_HANDLER +activate FULFIL_HANDLER +activate FULFIL_HANDLER +activate BULK_PROCESSING_HANDLER +activate POS_HANDLER + +group DFSP2 sends a Fulfil Abort Transfer request + note right of DFSP2 #lightblue + **Note**: In the payload for PUT /bulkTransfers//error + only the **errorInformation** field is **required** + end note + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + Payload - errorMessage: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + } + end note + DFSP2 ->> BULKAPI: **PUT - /bulkTransfers//error** + activate BULKAPI + + BULKAPI -> OBJECT_STORE: Persist request payload with messageId in cache + activate OBJECT_STORE + note right of BULKAPI #yellow + Message: { + messageId: , + bulkTransferId: , + payload: + } + end note + hnote over OBJECT_STORE #lightyellow + individualTransferFulfils + end hnote + BULKAPI <- OBJECT_STORE: Response of save operation + deactivate OBJECT_STORE + note right of BULKAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + BULKAPI -> TOPIC_BULK_FULFIL: Produce bulk-fulfil message + BULKAPI -->> DFSP2: Respond HTTP - 200 (OK) + TOPIC_BULK_FULFIL <- BULK_FULFIL_HANDLER: Consume bulk-fulfil message + BULK_FULFIL_HANDLER -> BULK_FULFIL_HANDLER: Perform duplicate check + BULK_FULFIL_HANDLER -> BULK_FULFIL_HANDLER: Validate request + loop n times, n = number of individual transfers + note right of BULK_FULFIL_HANDLER + Message: { + transferId: , + bulkTransferId< , + bulkTransferAssociationRecord: { + transferId: , + bulkTransferId: , + bulkProcessingStateId: , + errorCode: , + errorDescription: + } + } + end note + BULK_FULFIL_HANDLER -> DB: Update bulkTransferAssociation table + activate DB + hnote over DB #lightyellow + bulkTransferAssociation + end hnote + deactivate DB + BULK_FULFIL_HANDLER -> TOPIC_FULFIL: Produce fulfil message with action bulk-abort for each individual transfer + end + ||| + loop n times, n = number of individual transfers + TOPIC_FULFIL <- FULFIL_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_EVENTS: Fulfil Handler Consume (bulk-abort)\n + FULFIL_HANDLER -> TOPIC_POSITION: Produce message + end + ||| + loop n times, n = number of individual transfers + TOPIC_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_POSITION, BULK_PROCESSING_HANDLER: Position Handler Consume (bulk-abort)\n + POS_HANDLER -> TOPIC_BULK_PROCESSING: Produce message + end + ||| + loop n times, n = number of individual transfers + TOPIC_BULK_PROCESSING <- BULK_PROCESSING_HANDLER: Consume individual transfer message + ref over TOPIC_BULK_PROCESSING, TOPIC_NOTIFICATIONS: Bulk Processing Handler Consume (bulk-abort)\n + end + BULK_PROCESSING_HANDLER -> TOPIC_NOTIFICATIONS: Produce message (Payer) + BULK_PROCESSING_HANDLER -> TOPIC_NOTIFICATIONS: Produce message (Payee) + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message (Payer) + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message (Payee) + opt action == 'bulk-abort' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Notification Handler (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + opt action == 'bulk-abort' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Notification Handler (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +activate POS_HANDLER +activate FULFIL_HANDLER +activate FULFIL_HANDLER +activate NOTIFY_HANDLER +@enduml + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.svg new file mode 100644 index 000000000..65d6a65a7 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.svg @@ -0,0 +1,732 @@ + + + + + + + + + + + 4.1.0. Bulk Transfer Abort + + + + Financial Service Providers + + + + Bulk API Adapter Service + + + + Central Service + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + Bulk API Adapter + + + + + Bulk API Adapter + + + + + Bulk API Notification Event Handler + + + + + Bulk API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Bulk-Fulfil-Topic + + + + + Bulk-Fulfil-Topic + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Bulk Fulfil Event Handler + + + + + Bulk Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + + + Event-Topic + + + + + Event-Topic + + + Position Event Handler + + + + + Position Event Handler + + + + + + + topic-bulk-processing + + + + + topic-bulk-processing + + + Bulk Processing Event Handler + + + + + Bulk Processing Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + Central Services DB + + + + + Central Services DB + + + + + + + + + DFSP2 sends a Fulfil Abort Transfer request + + + + + Note + + + : In the payload for PUT /bulkTransfers/<ID>/error + + + only the + + + errorInformation + + + field is + + + required + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - errorMessage: + + + { + + + "errorInformation": { + + + "errorCode": <string>, + + + "errorDescription": <string>, + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + } + + + + 1 + + + PUT - /bulkTransfers/<ID>/error + + + + + 2 + + + Persist request payload with messageId in cache + + + + + Message: { + + + messageId: <string>, + + + bulkTransferId: <string>, + + + payload: <object> + + + } + + + + individualTransferFulfils + + + + + 3 + + + Response of save operation + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 4 + + + Produce bulk-fulfil message + + + + + 5 + + + Respond HTTP - 200 (OK) + + + + + 6 + + + Consume bulk-fulfil message + + + + + 7 + + + Perform duplicate check + + + + + 8 + + + Validate request + + + + + loop + + + [n times, n = number of individual transfers] + + + + + Message: { + + + transferId: <string>, + + + bulkTransferId< <string>, + + + bulkTransferAssociationRecord: { + + + transferId: <string>, + + + bulkTransferId: <string>, + + + bulkProcessingStateId: <string>, + + + errorCode: <string>, + + + errorDescription: <string> + + + } + + + } + + + + + 9 + + + Update bulkTransferAssociation table + + + + bulkTransferAssociation + + + + + 10 + + + Produce fulfil message with action bulk-abort for each individual transfer + + + + + loop + + + [n times, n = number of individual transfers] + + + + + 11 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (bulk-abort) + + + + + 12 + + + Produce message + + + + + loop + + + [n times, n = number of individual transfers] + + + + + 13 + + + Consume message + + + + + ref + + + Position Handler Consume (bulk-abort) + + + + + 14 + + + Produce message + + + + + loop + + + [n times, n = number of individual transfers] + + + + + 15 + + + Consume individual transfer message + + + + + ref + + + Bulk Processing Handler Consume (bulk-abort) + + + + + 16 + + + Produce message (Payer) + + + + + 17 + + + Produce message (Payee) + + + + + 18 + + + Consume message (Payer) + + + + + 19 + + + Consume message (Payee) + + + + + opt + + + [action == 'bulk-abort'] + + + + + ref + + + Notification Handler (Payer) + + + + + 20 + + + Send callback notification + + + + + opt + + + [action == 'bulk-abort'] + + + + + ref + + + Notification Handler (Payee) + + + + + 21 + + + Send callback notification + + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.plantuml b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.plantuml new file mode 100644 index 000000000..e219f2465 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.plantuml @@ -0,0 +1,209 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- + ******'/ + +@startuml +' declate title +title 5.1.0. Request Bulk Transfer Status + +autonumber + +' declare actors +actor "DFSP(n)\nParticipant" as DFSP +control "Bulk API Notification Event Handler" as NOTIFY_HANDLER +boundary "Bulk API Adapter" as BULKAPI +collections "Topic-Transfer-Get" as TOPIC_GET +control "GET Event Handler" as GET_HANDLER +entity "Bulk Transfer DAO" as BULK_TRANSFER_DAO +database "Central Store" as DB + +box "Financial Service Provider" #lightGray + participant DFSP +end box +box "Bulk API Adapter Service" #LightBlue + participant BULKAPI + participant NOTIFY_HANDLER +end box +box "Central Ledger" #LightYellow + participant TOPIC_GET + participant GET_HANDLER + participant BULK_TRANSFER_DAO + participant DB +end box + +' start flow +group Request Bulk transfer status + activate DFSP + DFSP -> BULKAPI: Request bulk transfer status - GET - /bulkTransfers/{ID} + activate BULKAPI + ||| + BULKAPI -> TOPIC_GET: Publish event information + deactivate BULKAPI + activate TOPIC_GET + ||| + deactivate GET_HANDLER + + DFSP <-- BULKAPI: Respond HTTP - 200 (OK) + deactivate DFSP + deactivate BULKAPI + GET_HANDLER -> TOPIC_GET: Consume message + ||| + ref over TOPIC_GET, GET_HANDLER : GET Handler Consume\n + ||| + deactivate TOPIC_GET + + GET_HANDLER -> BULK_TRANSFER_DAO: Request bulk transfer participants + activate GET_HANDLER + activate BULK_TRANSFER_DAO + BULK_TRANSFER_DAO -> DB: Fetch bulk transfer participants + activate DB + hnote over DB #lightYellow + bulkTransfer + participant + end hnote + BULK_TRANSFER_DAO <-- DB: Return query result + deactivate DB + GET_HANDLER <-- BULK_TRANSFER_DAO: Return bulk transfer participants + deactivate BULK_TRANSFER_DAO + alt Is request not from bulk transfer Payer or Payee FSP? + note left of NOTIFY_HANDLER #yellow + { + "errorInformation": { + "errorCode": 3210, + "errorDescription": "Bulk transfer ID not found" + } + } + end note + GET_HANDLER -> NOTIFY_HANDLER: Publish notification event (404) + deactivate GET_HANDLER + activate NOTIFY_HANDLER + DFSP <- NOTIFY_HANDLER: callback PUT on /bulkTransfers/{ID}/error + deactivate NOTIFY_HANDLER + end + GET_HANDLER -> BULK_TRANSFER_DAO: Request bulk transfer status + activate GET_HANDLER + activate BULK_TRANSFER_DAO + BULK_TRANSFER_DAO -> DB: Fetch bulk transfer status + + activate DB + hnote over DB #lightyellow + bulkTransferStateChange + bulkTransferState + bulkTransferError + bulkTransferExtension + transferStateChange + transferState + transferFulfilment + transferError + transferExtension + ilpPacket + end hnote + BULK_TRANSFER_DAO <-- DB: Return query result + deactivate DB + + GET_HANDLER <-- BULK_TRANSFER_DAO: Return bulk transfer status + deactivate BULK_TRANSFER_DAO + + alt Is there a bulk transfer with the given ID recorded in the system? + alt Bulk Transfer state is **"PROCESSING"** + note left of GET_HANDLER #yellow + { + "bulkTransferState": "PROCESSING" + } + end note + NOTIFY_HANDLER <- GET_HANDLER: Publish notification event + deactivate GET_HANDLER + activate NOTIFY_HANDLER + NOTIFY_HANDLER -> DFSP: Send callback - PUT /bulkTransfers/{ID} + deactivate NOTIFY_HANDLER + end + ||| + alt Request is from Payee FSP? + GET_HANDLER <-> GET_HANDLER: Exclude transfers with **transferStateId** not in \n [ **COMMITTED**, **ABORTED_REJECTED**, **EXPIRED_RESERVED** ] + activate GET_HANDLER + end + + note left of GET_HANDLER #yellow + { + "bulkTransferState": "", + "individualTransferResults": [ + { + "transferId": "", + "fulfilment": "WLctttbu2HvTsa1XWvUoGRcQozHsqeu9Ahl2JW9Bsu8", + "errorInformation": , + "extensionList": { + "extension": + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + ], + "completedTimestamp": "2018-09-24T08:38:08.699-04:00", + "extensionList": + { + "extension": + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + end note + note left of GET_HANDLER #lightGray + NOTE: If transfer is REJECTED, error information may be provided. + Either fulfilment or errorInformation should be set, not both. + end note + NOTIFY_HANDLER <- GET_HANDLER: Publish notification event + deactivate GET_HANDLER + activate NOTIFY_HANDLER + DFSP <- NOTIFY_HANDLER: callback PUT on /bulkTransfers/{ID} + deactivate NOTIFY_HANDLER + note right of NOTIFY_HANDLER #lightgray + Log ERROR event + end note + else A bulk transfer with the given ID is not present in the System or this is an invalid request + note left of NOTIFY_HANDLER #yellow + { + "errorInformation": { + "errorCode": 3210, + "errorDescription": "Bulk transfer ID not found" + } + } + end note + GET_HANDLER -> NOTIFY_HANDLER: Publish notification event (404) + activate NOTIFY_HANDLER + DFSP <- NOTIFY_HANDLER: callback PUT on /bulkTransfers/{ID}/error + deactivate NOTIFY_HANDLER + end + + deactivate GET_HANDLER + deactivate NOTIFY_HANDLER +deactivate DFSP +end +@enduml diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.svg b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.svg new file mode 100644 index 000000000..0c0bb5959 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.svg @@ -0,0 +1,552 @@ + + + + + + + + + + + 5.1.0. Request Bulk Transfer Status + + + + Financial Service Provider + + + + Bulk API Adapter Service + + + + Central Ledger + + + + + + + + + DFSP(n) + + + Participant + + + + + DFSP(n) + + + Participant + + + + + Bulk API Adapter + + + + + Bulk API Adapter + + + + + Bulk API Notification Event Handler + + + + + Bulk API Notification Event Handler + + + + + + + Topic-Transfer-Get + + + + + Topic-Transfer-Get + + + GET Event Handler + + + + + GET Event Handler + + + + + Bulk Transfer DAO + + + + + Bulk Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Request Bulk transfer status + + + + + 1 + + + Request bulk transfer status - GET - /bulkTransfers/{ID} + + + + + 2 + + + Publish event information + + + + + 3 + + + Respond HTTP - 200 (OK) + + + + + 4 + + + Consume message + + + + + ref + + + GET Handler Consume + + + + + 5 + + + Request bulk transfer participants + + + + + 6 + + + Fetch bulk transfer participants + + + + bulkTransfer + + + participant + + + + + 7 + + + Return query result + + + + + 8 + + + Return bulk transfer participants + + + + + alt + + + [Is request not from bulk transfer Payer or Payee FSP?] + + + + + { + + + "errorInformation": { + + + "errorCode": 3210, + + + "errorDescription": "Bulk transfer ID not found" + + + } + + + } + + + + + 9 + + + Publish notification event (404) + + + + + 10 + + + callback PUT on /bulkTransfers/{ID}/error + + + + + 11 + + + Request bulk transfer status + + + + + 12 + + + Fetch bulk transfer status + + + + bulkTransferStateChange + + + bulkTransferState + + + bulkTransferError + + + bulkTransferExtension + + + transferStateChange + + + transferState + + + transferFulfilment + + + transferError + + + transferExtension + + + ilpPacket + + + + + 13 + + + Return query result + + + + + 14 + + + Return bulk transfer status + + + + + alt + + + [Is there a bulk transfer with the given ID recorded in the system?] + + + + + alt + + + [Bulk Transfer state is + + + "PROCESSING" + + + ] + + + + + { + + + "bulkTransferState": "PROCESSING" + + + } + + + + + 15 + + + Publish notification event + + + + + 16 + + + Send callback - PUT /bulkTransfers/{ID} + + + + + alt + + + [Request is from Payee FSP?] + + + + + 17 + + + Exclude transfers with + + + transferStateId + + + not in + + + [ + + + COMMITTED + + + , + + + ABORTED_REJECTED + + + , + + + EXPIRED_RESERVED + + + ] + + + + + { + + + "bulkTransferState": "<BulkTransferState>", + + + "individualTransferResults": [ + + + { + + + "transferId": "<TransferId>", + + + "fulfilment": "WLctttbu2HvTsa1XWvUoGRcQozHsqeu9Ahl2JW9Bsu8", + + + "errorInformation": <ErrorInformationObject>, + + + "extensionList": { + + + "extension": + + + [ + + + { + + + "key": "Description", + + + "value": "This is a more detailed description" + + + } + + + ] + + + } + + + } + + + ], + + + "completedTimestamp": "2018-09-24T08:38:08.699-04:00", + + + "extensionList": + + + { + + + "extension": + + + [ + + + { + + + "key": "Description", + + + "value": "This is a more detailed description" + + + } + + + ] + + + } + + + } + + + + + NOTE: If transfer is REJECTED, error information may be provided. + + + Either fulfilment or errorInformation should be set, not both. + + + + + 18 + + + Publish notification event + + + + + 19 + + + callback PUT on /bulkTransfers/{ID} + + + + + Log ERROR event + + + + [A bulk transfer with the given ID is not present in the System or this is an invalid request] + + + + + { + + + "errorInformation": { + + + "errorCode": 3210, + + + "errorDescription": "Bulk transfer ID not found" + + + } + + + } + + + + + 20 + + + Publish notification event (404) + + + + + 21 + + + callback PUT on /bulkTransfers/{ID}/error + + diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md new file mode 100644 index 000000000..8ad8c6ce7 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md @@ -0,0 +1,15 @@ +# Bulk Prepare Transfer Request [Overview] [includes individual transfers in a bulk] + +Sequence design diagram for Prepare Transfer Request process. + +## References within Sequence Diagram + +* [Bulk Prepare Handler Consume (1.1.1)](1.1.1-bulk-prepare-handler-consume.md) +* [Prepare Handler Consume (1.2.1)](1.2.1-prepare-handler-consume-for-bulk.md) +* [Position Handler Consume (1.3.0)](1.3.0-position-handler-consume-overview.md) +* [Bulk Processing Handler Consume (1.4.1)](1.4.1-bulk-processing-handler.md) +* [Send notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-bulk-1.1.0-bulk-prepare-overview.svg](../assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.svg) diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md new file mode 100644 index 000000000..148656326 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md @@ -0,0 +1,11 @@ +# Bulk Prepare handler consume + +Sequence design diagram for Bulk Prepare Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-bulk-1.1.1-bulk-prepare-handler.svg](../assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md new file mode 100644 index 000000000..56740e2e3 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md @@ -0,0 +1,11 @@ +# Prepare handler consume [that includes individual transfers in a bulk] + +Sequence design diagram for Prepare Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-bulk-1.2.1-prepare-handler.svg](../assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md new file mode 100644 index 000000000..bcd5bf1e1 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md @@ -0,0 +1,14 @@ +# Position Handler Consume [that includes individual transfers in a bulk] + +Sequence design diagram for Position Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [Prepare Position Handler Consume (1.3.1)](1.3.1-prepare-position-handler-consume.md) +* [Fufil Position Handler Consume (2.2.1)](2.2.1-fulfil-commit-for-bulk.md) +* [Abort Position Handler Consume (2.2.2)](2.2.2-fulfil-abort-for-bulk.md) + +## Sequence Diagram + +![seq-bulk-1.3.0-position-overview.svg](../assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md new file mode 100644 index 000000000..31c4c05a4 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md @@ -0,0 +1,7 @@ +# Prepare Position Handler Consume [that includes individual transfers in a bulk] + +Sequence design diagram for Prepare Position Handler Consume process + +## Sequence Diagram + +![seq-bulk-1.3.1-position-prepare.svg](../assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md new file mode 100644 index 000000000..086bfb8b6 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md @@ -0,0 +1,7 @@ +# Bulk Processing Handler Consume + +Sequence design diagram for Bulk Processing Handler Consume process + +## Sequence Diagram + +![seq-bulk-1.4.1-bulk-processing-handler.svg](../assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md new file mode 100644 index 000000000..f08b37d9e --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md @@ -0,0 +1,15 @@ +# Bulk Fulfil Transfer Request Overview + +Sequence design diagram for the Bulk Fulfil Transfer request + +## References within Sequence Diagram + +* [Bulk Fulfil Handler Consume (Success) (2.1.1)](2.1.1-bulk-fulfil-handler-consume.md) +* [Fulfil Handler Consume (Success) (2.2.1)](2.2.1-fulfil-commit-for-bulk.md) +* [Position Handler Consume (Success) (2.3.1)](2.3.1-fulfil-position-handler-consume.md) +* [Bulk Processing Handler Consume (1.4.1)](1.4.1-bulk-processing-handler.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-bulk-2.1.0-bulk-fulfil-overview.svg](../assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.svg) diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md new file mode 100644 index 000000000..ea730d0b8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md @@ -0,0 +1,13 @@ +# Bulk Fulfil Handler Consume + +Sequence design diagram for the Bulk Fulfil Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-bulk-2.1.1-bulk-fulfil-handler.svg](../assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.svg) diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md new file mode 100644 index 000000000..7a2102201 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md @@ -0,0 +1,11 @@ +# Payee sends a Bulk Fulfil Transfer request - Bulk is broken down into individual transfers + +Sequence design diagram for the Bulk Fulfil Transfer for the Commit option + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-bulk-2.2.1-fulfil-handler-commit.svg](../assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.svg) diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md new file mode 100644 index 000000000..ab1c78b39 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md @@ -0,0 +1,13 @@ +# Payee sends a Bulk Fulfil Transfer request - Bulk is broken down into individual transfers + +Sequence design diagram for the Fulfil Handler Consume Reject/Abort process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-bulk-2.2.2-fulfil-handler-abort.svg](../assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md new file mode 100644 index 000000000..c869282ab --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md @@ -0,0 +1,11 @@ +# Fulfil Position Handler Consume [that includes individual transfers in a bulk] + +Sequence design diagram for the Fulfil Position Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-bulk-2.3.1-position-fulfil.svg](../assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md new file mode 100644 index 000000000..ed4d3f9f8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md @@ -0,0 +1,7 @@ +# Position Handler Consume for Fulfil aborts at individual transfer level + +Sequence design diagram for Fulfil Position Handler Consume process + +## Sequence Diagram + +![seq-bulk-2.3.2-position-abort.svg](../assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.svg) diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md new file mode 100644 index 000000000..e2e982791 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md @@ -0,0 +1,7 @@ +# Transfer Timeout [includes individual transfers in a Bulk] + +Sequence design diagram for the Transfer Timeout process. + +## Sequence Diagram + +![seq-bulk-3.1.0-timeout-overview.svg](../assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md new file mode 100644 index 000000000..d8fcefc23 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md @@ -0,0 +1,7 @@ +# TimeOut Handler + +Sequence design diagram for Timeout Handler process + +## Sequence Diagram + +![seq-bulk-3.1.1-timeout-handler.svg](../assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.svg) diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.md new file mode 100644 index 000000000..9a3c04a1d --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.md @@ -0,0 +1,7 @@ +# Bulk Transfer Abort Overview [includes individual transfers in a Bulk] + +Sequence design diagram for the Bulk Transfer Abort process. + +## Sequence Diagram + +![seq-bulk-4.1.0-abort-overview.svg](../assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.md new file mode 100644 index 000000000..f178b7b30 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.md @@ -0,0 +1,7 @@ +# Get Bulk Transfer Overview + +Sequence design diagram for the Get Bulk Transfer process. + +## Sequence Diagram + +![seq-bulk-5.1.0-get-overview.svg](../assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.svg) \ No newline at end of file diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/README.md b/legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/README.md similarity index 100% rename from mojaloop-technical-overview/central-bulk-transfers/transfers/README.md rename to legacy/mojaloop-technical-overview/central-bulk-transfers/transfers/README.md diff --git a/legacy/mojaloop-technical-overview/central-event-processor/5.1.1-notification-handler-for-rejections.md b/legacy/mojaloop-technical-overview/central-event-processor/5.1.1-notification-handler-for-rejections.md new file mode 100644 index 000000000..258ef5fb7 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-event-processor/5.1.1-notification-handler-for-rejections.md @@ -0,0 +1,12 @@ +# Notification Handler for Rejections + +Sequence design diagram for the Notification Handler for Rejections process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](9.1.0-event-handler-placeholder.md) +* [Get Participant Callback Details (3.1.0)](../central-ledger/admin-operations/3.1.0-post-participant-callback-details.md) + +## Sequence Diagram + +![seq-notification-reject-5.1.1.svg](./assets/diagrams/sequence/seq-notification-reject-5.1.1.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-event-processor/9.1.0-event-handler-placeholder.md b/legacy/mojaloop-technical-overview/central-event-processor/9.1.0-event-handler-placeholder.md new file mode 100644 index 000000000..38904e3d2 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-event-processor/9.1.0-event-handler-placeholder.md @@ -0,0 +1,7 @@ +# Event Handler Placeholder + +Sequence design diagram for the Event Handler process. + +## Sequence Diagram + +![seq-event-9.1.0.svg](./assets/diagrams/sequence/seq-event-9.1.0.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-event-processor/README.md b/legacy/mojaloop-technical-overview/central-event-processor/README.md new file mode 100644 index 000000000..45b2203f8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-event-processor/README.md @@ -0,0 +1,13 @@ +# Central Event Processor Service + +The Central Event Processor (CEP) service provides the capability to monitor for a pre-defined/configured set of business rules or patterns. + +In the current iteration, the rules are set to monitor for three criteria: + + 1. Breaching of a threshold on the Limit of Net Debit Cap (which may be set as part of on-boarding), + 2. Adjustment of the limit - Net Debit Cap, + 3. Adjust of position based on a Settlement. + +The CEP can then be integrated with a notifier service, to send out notifications or alerts. In this instance, it integrates with the email-notifier to send out alerts based on the aforementioned criteria. + +![Central Event Processor Architecture](./assets/diagrams/architecture/CEPArchTechOverview.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/architecture/CEPArchTechOverview.svg b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/architecture/CEPArchTechOverview.svg new file mode 100644 index 000000000..40e9f3ae0 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/architecture/CEPArchTechOverview.svg @@ -0,0 +1,2 @@ + +


    Notifiers
    /email, sms, etc./
    [Not supported by viewer]
    ML-Adapter
    [Not supported by viewer]
    prepare 
    [Not supported by viewer]
    fulfil 
    [Not supported by viewer]
    notification 
    <b>notification </b>

    DB
    [Not supported by viewer]
    Central-Services
    Central-Services

    MangoDB
    [Not supported by viewer]
    Central Event
    Processor (CEP)

    [Not supported by viewer]
    RxJS
    RxJS
    json-rule-engine
    json-rule-engine

    Heading

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

    [Not supported by viewer]
    REST admin API
    [Not supported by viewer]
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.plantuml b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.plantuml new file mode 100644 index 000000000..d01340e1f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.plantuml @@ -0,0 +1,94 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declate title +title 9.1.0. Event Handler Placeholder + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +control "Event Handler Placeholder" as EVENT_HANDLER + +box "Event Handler Placeholder" #LightGray + participant EVENT_HANDLER +end box + +collections "Event-Topic" as TOPIC_EVENTS + +' start flow +activate EVENT_HANDLER + +group Event Handler Placeholder + EVENT_HANDLER -> TOPIC_EVENTS: Consume Event message \n Error code: 2001 + note right of EVENT_HANDLER #yellow + Message: + { + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: INFO, + action: AUDIT, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + note right of EVENT_HANDLER #LightGray + The type would be an ENUM with values: + [INFO, DEBUG, ERROR, WARN, FATAL, TRACE] + Possible values for "action" would be + [AUDIT, EXCEPTION] + The event messages can be handled based on the values of these two variables + (when the placeholder is extended). + end note + EVENT_HANDLER -> EVENT_HANDLER: Auto-commit \n Error code: 2001 + note right of EVENT_HANDLER #lightBlue + Currently events to only be published as part of the placeholder. + This can be evolved to add relevant functionality. + end note + activate TOPIC_EVENTS + deactivate TOPIC_EVENTS +end +deactivate EVENT_HANDLER + +@enduml diff --git a/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.svg b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.svg new file mode 100644 index 000000000..3f48ce80a --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.svg @@ -0,0 +1,170 @@ + + + + + + + + + + + 9.1.0. Event Handler Placeholder + + + + Event Handler Placeholder + + + + + + Event Handler Placeholder + + + + + Event Handler Placeholder + + + + + + + Event-Topic + + + + + Event-Topic + + + + + + Event Handler Placeholder + + + + + 1 + + + Consume Event message + + + Error code: + + + 2001 + + + + + Message: + + + { + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: INFO, + + + action: AUDIT, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + The type would be an ENUM with values: + + + [INFO, DEBUG, ERROR, WARN, FATAL, TRACE] + + + Possible values for "action" would be + + + [AUDIT, EXCEPTION] + + + The event messages can be handled based on the values of these two variables + + + (when the placeholder is extended). + + + + + 2 + + + Auto-commit + + + Error code: + + + 2001 + + + + + Currently events to only be published as part of the placeholder. + + + This can be evolved to add relevant functionality. + + diff --git a/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.plantuml b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.plantuml new file mode 100644 index 000000000..38e5e7dd3 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.plantuml @@ -0,0 +1,111 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Henk Kodde + -------------- + ******'/ + +@startuml +' declate title +title 5.1.1. Notification Handler for Rejections + +autonumber + +' Actor Keys: + +' declare actors + +actor "DFSP1\nPayer" as DFSP1 +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Event-Topic" as TOPIC_EVENT +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_EVENT + participant TOPIC_NOTIFICATIONS +end box + +' start flow + +group DFSP Notified of Rejection + activate NOTIFY_HANDLER + NOTIFY_HANDLER -> TOPIC_NOTIFICATIONS: Consume Notification event message \n Error code: 2001 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + group Persist Event Information + NOTIFY_HANDLER -> TOPIC_EVENT: Publish event information \n Error code: 3201 + activate TOPIC_EVENT + ref over TOPIC_EVENT : Event Handler + deactivate TOPIC_EVENT + end + + alt consume a single messages + group Validate Event + NOTIFY_HANDLER <-> NOTIFY_HANDLER: Validate event - Rule: type == 'notification' && [action IN ['reject', 'timeout-received', 'timeout-reserved']] + end + NOTIFY_HANDLER -> CSAPI: Request Participant Callback details \n Error code: 3201 + ref over NOTIFY_HANDLER, CSAPI: Get Participant Callback Details + NOTIFY_HANDLER <-- CSAPI: Return Participant Callback details + note left of NOTIFY_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + payload: + }, + } + end note + NOTIFY_HANDLER --> DFSP1: Send Callback Notification \n Error code: 1000, 1001, 3002 + else Validate rule type != 'notification' / Error + note right of NOTIFY_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + NOTIFY_HANDLER -> TOPIC_EVENT: Invalid messages retrieved from the Notification Topic \n Error code: 3201 + activate TOPIC_EVENT + deactivate TOPIC_EVENT + ref over TOPIC_EVENT: Event Handler + note right of NOTIFY_HANDLER #lightblue + Log ERROR Messages + Update Event log upon ERROR notification + end note +' deactivate TOPIC_NOTIFICATIONS + end +end +@enduml \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.svg b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.svg new file mode 100644 index 000000000..6eb610b07 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + 5.1.1. Notification Handler for Rejections + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + DFSP Notified of Rejection + + + + + 1 + + + Consume Notification event message + + + Error code: + + + 2001 + + + + + Persist Event Information + + + + + 2 + + + Publish event information + + + Error code: + + + 3201 + + + + + ref + + + Event Handler + + + + + alt + + + [consume a single messages] + + + + + Validate Event + + + + + 3 + + + Validate event - Rule: type == 'notification' && [action IN ['reject', 'timeout-received', 'timeout-reserved']] + + + + + 4 + + + Request Participant Callback details + + + Error code: + + + 3201 + + + + + ref + + + Get Participant Callback Details + + + + + 5 + + + Return Participant Callback details + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + payload: <transferMessage> + + + }, + + + } + + + + + 6 + + + Send Callback Notification + + + Error code: + + + 1000, 1001, 3002 + + + + [Validate rule type != 'notification' / Error] + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <errorCode>, + + + "errorDescription": <ErrorMessage>, + + + } + + + } + + + + + 7 + + + Invalid messages retrieved from the Notification Topic + + + Error code: + + + 3201 + + + + + ref + + + Event Handler + + + + + Log ERROR Messages + + + Update Event log upon ERROR notification + + diff --git a/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-signature-validation.plantuml b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-signature-validation.plantuml new file mode 100644 index 000000000..03a932865 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-signature-validation.plantuml @@ -0,0 +1,35 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + * Rajiv Mothilal + -------------- + ******'/ + +@startuml +' declare title +title Signature Validation + +Alice -> Bob: Authentication Request +Bob --> Alice: Authentication Response + +Alice -> Bob: Another authentication Request +Alice <-- Bob: another authentication Response +@enduml \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-signature-validation.svg b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-signature-validation.svg new file mode 100644 index 000000000..4e80c45ca --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-signature-validation.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + Signature Validation + + + + + Alice + + + + Alice + + + + Bob + + + + Bob + + + + + Authentication Request + + + + + Authentication Response + + + + + Another authentication Request + + + + + another authentication Response + + diff --git a/legacy/mojaloop-technical-overview/central-event-processor/signature-validation.md b/legacy/mojaloop-technical-overview/central-event-processor/signature-validation.md new file mode 100644 index 000000000..e4aabbbe7 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-event-processor/signature-validation.md @@ -0,0 +1,7 @@ +# Signature Validation + +Sequence design diagram for the Signature Validation process. + +## Sequence Diagram + +![seq-signature-validation.svg](./assets/diagrams/sequence/seq-signature-validation.svg) \ No newline at end of file diff --git a/mojaloop-technical-overview/central-settlements/assets/.gitkeep b/legacy/mojaloop-technical-overview/central-ledger/.gitkeep similarity index 100% rename from mojaloop-technical-overview/central-settlements/assets/.gitkeep rename to legacy/mojaloop-technical-overview/central-ledger/.gitkeep diff --git a/legacy/mojaloop-technical-overview/central-ledger/README.md b/legacy/mojaloop-technical-overview/central-ledger/README.md new file mode 100644 index 000000000..4d5089388 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/README.md @@ -0,0 +1,52 @@ +# Central-Ledger Services + +The central ledger is a series of services that facilitate clearing and settlement of transfers between DFSPs, including the following functions: + +* Brokering real-time messaging for funds clearing +* Maintaining net positions for a deferred net settlement +* Propagating scheme-level and off-transfer fees + +## 1. Central Ledger Process Design + +### 1.1 Architecture overview + +![Central-Ledger Architecture](assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg) + +## 2. Transfers End-to-End Architecture + + +### 2.1 Transfers End-to-End Architecture for v1.1 +![Transfers Architecture for Mojaloop FSP Interoperability API v1.1](assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.1.svg) + +### 2.2 Transfers End-to-End Architecture for v1.0 +![Transfers Architecture for Mojaloop FSP Interoperability API v1.0](assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0.svg) + +## 3. Database Design + +### Note + +The tables *Grey* colored tables are specific to the transfer process. The *Blue* and *Green* color tables are used for reference purposes during the Transfer process. + +Summary of the tables specific to the transfer process; + +- `transfer` - stores data related to the transfer; +- `transferDuplicateCheck` - used to identify duplication during the transfer requests process; +- `transferError` - stores information on transfer errors encountered during the transfer process; +- `transferErrorDuplicateCheck` - used to identify duplication error transfer processes; +- `transferExtensions` - stores information on the transfer extension data; +- `transferFulfilment` - stores data for transfers that have completed the prepare transfer process; +- `transferFulfilmentDuplicateCheck` - used the identify duplicate transfer fulfil requests; +- `transferParticipant` - participant information related to the transfer process; +- `transferStateChange` - use to track state changes of each individual transfer, creating and audit trail for a specific transfer request; +- `transferTimeout` - stores information of transfers that encountered a timeout exception during the process; +- `ilpPacket` - stores the ilp package for the transfer; + +The remaining tables in the below ERD are either lookup (blue) or settlement-specific (red) and are included as direct or indirect dependencies to depict the relation between the transfer specific entities and the transfer tables. + +The **Central Ledger** database schema definition [Central-Ledger Database Schema Definition](assets/database/central-ledger-ddl-MySQLWorkbench.sql). + +![Central-Ledger Database Diagram](assets/database/central-ledger-schema.png) + +## 4. API Specification + +Refer to **Central Ledger API** in the [API Specifications](../../api/README.md#central-ledger-api) section. diff --git a/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-health-check.md b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-health-check.md new file mode 100644 index 000000000..021204219 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-health-check.md @@ -0,0 +1,265 @@ +# GET Health Check + +Design discussion for new Health Check implementation. + + +## Objectives + +The goal for this design is to implement a new Health check for mojaloop switch services that allows for a greater level of detail. + +It Features: +- Clear HTTP Statuses (no need to inspect the response to know there are no issues) +- ~Backwards compatibility with existing health checks~ - No longer a requirement. See [this discussion](https://github.com/mojaloop/project/issues/796#issuecomment-498350828). +- Information about the version of the API, and how long it has been running for +- Information about sub-service (kafka, logging sidecar and mysql) connections + +## Request Format +`/health` + +Uses the newly implemented health check. As discussed [here](https://github.com/mojaloop/project/issues/796#issuecomment-498350828) since there will be no added connection overhead (e.g. pinging a database) as part of implementing the health check, there is no need to complicate things with a simple and detailed version. + +Responses Codes: +- `200` - Success. The API is up and running, and is sucessfully connected to necessary services. +- `502` - Bad Gateway. The API is up and running, but the API cannot connect to necessary service (eg. `kafka`). +- `503` - Service Unavailable. This response is not implemented in this design, but will be the default if the api is not and running + +## Response Format + +| Name | Type | Description | Example | +| --- | --- | --- | --- | +| `status` | `statusEnum` | The status of the service. Options are `OK` and `DOWN`. _See `statusEnum` below_. | `"OK"` | +| `uptime` | `number` | How long (in seconds) the service has been alive for. | `123456` | +| `started` | `string` (ISO formatted date-time) | When the service was started (UTC) | `"2019-05-31T05:09:25.409Z"` | +| `versionNumber` | `string` (semver) | The current version of the service. | `"5.2.5"` | +| `services` | `Array` | A list of services this service depends on, and their connection status | _see below_ | + +### serviceHealth + +| Name | Type | Description | Example | +| --- | --- | --- | --- | +| `name` | `subServiceEnum` | The sub-service name. _See `subServiceEnum` below_. | `"broker"` | +| `status` | `enum` | The status of the service. Options are `OK` and `DOWN` | `"OK"` | + +### subServiceEnum + +The subServiceEnum enum describes a name of the subservice: + +Options: +- `datastore` -> The database for this service (typically a MySQL Database). +- `broker` -> The message broker for this service (typically Kafka). +- `sidecar` -> The logging sidecar sub-service this service attaches to. +- `cache` -> The caching sub-service this services attaches to. + + +### statusEnum + +The status enum represents status of the system or sub-service. + +It has two options: +- `OK` -> The service or sub-service is healthy. +- `DOWN` -> The service or sub-service is unhealthy. + +When a service is `OK`: the API is considered healthy, and all sub-services are also considered healthy. + +If __any__ sub-service is `DOWN`, then the entire health check will fail, and the API will be considered `DOWN`. + +## Defining Sub-Service health + +It is not enough to simply ping a sub-service to know if it is healthy, we want to go one step further. These criteria will change with each sub-service. + +### `datastore` + +For `datastore`, a status of `OK` means: +- An existing connection to the database +- The database is not empty (contains more than 1 table) + + +### `broker` + +For `broker`, a status of `OK` means: +- An existing connection to the kafka broker +- The necessary topics exist. This will change depending on which service the health check is running for. + +For example, for the `central-ledger` service to be considered healthy, the following topics need to be found: +``` +topic-admin-transfer +topic-transfer-prepare +topic-transfer-position +topic-transfer-fulfil +``` + +### `sidecar` + +For `sidecar`, a status of `OK` means: +- An existing connection to the sidecar + + +### `cache` + +For `cache`, a status of `OK` means: +- An existing connection to the cache + + +## Swagger Definition + +>_Note: These will be added to the existing swagger definitions for the following services:_ +> - `ml-api-adapter` +> - `central-ledger` +> - `central-settlement` +> - `central-event-processor` +> - `email-notifier` + +```json +{ + /// . . . + "/health": { + "get": { + "operationId": "getHealth", + "tags": [ + "health" + ], + "responses": { + "default": { + "schema": { + "$ref": "#/definitions/health" + }, + "description": "Successful" + } + } + } + }, + // . . . + "definitions": { + "health": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "OK", + "DOWN" + ] + }, + "uptime": { + "description": "How long (in seconds) the service has been alive for.", + "type": "number", + }, + "started": { + "description": "When the service was started (UTC)", + "type": "string", + "format": "date-time" + }, + "versionNumber": { + "description": "The current version of the service.", + "type": "string", + "example": "5.2.3", + }, + "services": { + "description": "A list of services this service depends on, and their connection status", + "type": "array", + "items": { + "$ref": "#/definitions/serviceHealth" + } + }, + }, + }, + "serviceHealth": { + "type": "object", + "properties": { + "name": { + "description": "The sub-service name.", + "type": "string", + "enum": [ + "datastore", + "broker", + "sidecar", + "cache" + ] + }, + "status": { + "description": "The connection status with the service.", + "type": "string", + "enum": [ + "OK", + "DOWN" + ] + } + } + } + } +} +``` + + +### Example Requests and Responses: + +__Successful Legacy Health Check:__ + +```bash +GET /health HTTP/1.1 +Content-Type: application/json + +200 SUCCESS +{ + "status": "OK" +} +``` + + +__Successful New Health Check:__ + +``` +GET /health?detailed=true HTTP/1.1 +Content-Type: application/json + +200 SUCCESS +{ + "status": "OK", + "uptime": 0, + "started": "2019-05-31T05:09:25.409Z", + "versionNumber": "5.2.3", + "services": [ + { + "name": "broker", + "status": "OK", + } + ] +} +``` + +__Failed Health Check, but API is up:__ + +``` +GET /health?detailed=true HTTP/1.1 +Content-Type: application/json + +502 BAD GATEWAY +{ + "status": "DOWN", + "uptime": 0, + "started": "2019-05-31T05:09:25.409Z", + "versionNumber": "5.2.3", + "services": [ + { + "name": "broker", + "status": "DOWN", + } + ] +} +``` + +__Failed Health Check:__ + +``` +GET /health?detailed=true HTTP/1.1 +Content-Type: application/json + +503 SERVICE UNAVAILABLE +``` + + +## Sequence Diagram + +Sequence design diagram for the GET Health + +![seq-get-health-1.0.0.svg](../assets/diagrams/sequence/seq-get-health-1.0.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md new file mode 100644 index 000000000..7a1c5e933 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md @@ -0,0 +1,7 @@ +# GET Participant Limit Details For All Participants + +Sequence design diagram for the GET Participant Limit Details For All Participants process. + +## Sequence Diagram + +![seq-get-all-participant-limit-1.0.0.svg](../assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md new file mode 100644 index 000000000..6fda674e3 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md @@ -0,0 +1,7 @@ +# Create initial position and limits for Participant + +Sequence design diagram for the POST (create) Participant Initial Position and Limit process. + +## Sequence Diagram + +![seq-participant-position-limits-1.0.0.svg](../assets/diagrams/sequence/seq-participant-position-limits-1.0.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md new file mode 100644 index 000000000..2419df6fe --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md @@ -0,0 +1,7 @@ +# Request Participant Position and Limit Details + +Sequence design diagram for the Request Participant Position and Limit Details process. + +## Sequence Diagram + +![seq-get-participant-position-limit-1.1.0.svg](../assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-post-participant-limits.md b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-post-participant-limits.md new file mode 100644 index 000000000..99fb44d05 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-post-participant-limits.md @@ -0,0 +1,7 @@ +# Adjust Participant Limit for a certain Currency + +Sequence design diagram for the POST (manage) Participant Limit Details process. + +## Sequence Diagram + +![seq-manage-participant-limit-1.1.0.svg](../assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.5-get-transfer-status.md b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.5-get-transfer-status.md new file mode 100644 index 000000000..b5c1f6734 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/1.1.5-get-transfer-status.md @@ -0,0 +1,7 @@ +# Request transfer status + +Sequence design diagram for the GET Transfer Status process. + +## Sequence Diagram + +![seq-get-transfer-1.1.5-phase2.svg](../assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md new file mode 100644 index 000000000..72020a489 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md @@ -0,0 +1,7 @@ +# 3.1.0 Get Participant Callback Details + +Sequence design diagram for the GET Participant Callback Details process. + +## Sequence Diagram + +![seq-callback-3.1.0.svg](../assets/diagrams/sequence/seq-callback-3.1.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md new file mode 100644 index 000000000..2b9afae31 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md @@ -0,0 +1,7 @@ +# 3.1.0 Add Participant Callback Details + +Sequence design diagram for the POST (Add) Participant Callback Details process. + +## Sequence Diagram + +![seq-callback-add-3.1.0.svg](../assets/diagrams/sequence/seq-callback-add-3.1.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/admin-operations/4.1.0-get-participant-position-details.md b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/4.1.0-get-participant-position-details.md new file mode 100644 index 000000000..1153ef409 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/4.1.0-get-participant-position-details.md @@ -0,0 +1,7 @@ +# Get Participant Position Details + +Sequence design diagram for the GET Participant Position Details process. + +## Sequence Diagram + +![seq-participants-positions-query-4.1.0.svg](../assets/diagrams/sequence/seq-participants-positions-query-4.1.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md new file mode 100644 index 000000000..176494d61 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md @@ -0,0 +1,7 @@ +# Get Position Details for all Participants + +Sequence design diagram for the Get Positions of all Participants process. + +## Sequence Diagram + +![seq-participants-positions-query-all-4.2.0.svg](../assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/admin-operations/README.md b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/README.md new file mode 100644 index 000000000..ebdb6ac1d --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/admin-operations/README.md @@ -0,0 +1,3 @@ +# Mojaloop HUB/Switch operations + +Operational processes normally initiated by a HUB/Switch operator. diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/database/README.md b/legacy/mojaloop-technical-overview/central-ledger/assets/database/README.md new file mode 100644 index 000000000..77d71d79d --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/database/README.md @@ -0,0 +1,17 @@ +# How to EDIT the central-ledger-schema-DBeaver.erd file + +This is a basic guide on how to successfully view/update the central-ledger-schema-DBeaver.erd file. + +## Prerequisites +* Download and install the DBeaver Community DB Manager +* The Mojaloop Central-Ledger MySQL Database needs to be up and running, and connectable by the DBeaver +* You'll also need a text editor +## Steps to follow +* Create a new db connection in DBeaver under Database Navigator tab for the MySQL instance running. +* Under the Projects tab right click and create a New ER Diagram. +* Give the diagram a name and select central-ledger db in the wizard. + +* Copy the `central-ledger-schema-DBeaver.erd` file from the documentation module to `DBeaverData/workspace/General/Diagrams` in your DBeaver storage location +* Navigate to the newly created erd file using a text editor, search for `data-source id` and copy its value which looks like `mysql5-171ea991174-1218b6e1bf273693`. +* Navigate with a text editor to the `central-ledger-schema-DBeaver.erd` file in the ER Diagrams directory and replace its `data-source id` value with the one copied from the newly created erd file. +* The `central-ledger-schema-DBeaver.erd` should now show the tables as per the `central-ledger-schema.png` \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-ddl-MySQLWorkbench.sql b/legacy/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-ddl-MySQLWorkbench.sql new file mode 100644 index 000000000..280962173 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-ddl-MySQLWorkbench.sql @@ -0,0 +1,1820 @@ +-- MySQL dump 10.13 Distrib 8.0.18, for macos10.14 (x86_64) +-- +-- Host: localhost Database: central_ledger +-- ------------------------------------------------------ +-- Server version 8.0.13 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!50503 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `amountType` +-- + +DROP TABLE IF EXISTS `amountType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `amountType` ( + `amountTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`amountTypeId`), + UNIQUE KEY `amounttype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `balanceOfPayments` +-- + +DROP TABLE IF EXISTS `balanceOfPayments`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `balanceOfPayments` ( + `balanceOfPaymentsId` int(10) unsigned NOT NULL, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL COMMENT 'Possible values and meaning are defined in https://www.imf.org/external/np/sta/bopcode/', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`balanceOfPaymentsId`), + UNIQUE KEY `balanceofpayments_name_unique` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='See https://www.imf.org/external/np/sta/bopcode/guide.htm'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkProcessingState` +-- + +DROP TABLE IF EXISTS `bulkProcessingState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkProcessingState` ( + `bulkProcessingStateId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkProcessingStateId`), + UNIQUE KEY `bulkprocessingstate_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransfer` +-- + +DROP TABLE IF EXISTS `bulkTransfer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransfer` ( + `bulkTransferId` varchar(36) NOT NULL, + `bulkQuoteId` varchar(36) DEFAULT NULL, + `payerParticipantId` int(10) unsigned DEFAULT NULL, + `payeeParticipantId` int(10) unsigned DEFAULT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`), + KEY `bulktransfer_payerparticipantid_index` (`payerParticipantId`), + KEY `bulktransfer_payeeparticipantid_index` (`payeeParticipantId`), + CONSTRAINT `bulktransfer_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransferDuplicateCheck` (`bulktransferid`), + CONSTRAINT `bulktransfer_payeeparticipantid_foreign` FOREIGN KEY (`payeeParticipantId`) REFERENCES `participant` (`participantid`), + CONSTRAINT `bulktransfer_payerparticipantid_foreign` FOREIGN KEY (`payerParticipantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferAssociation` +-- + +DROP TABLE IF EXISTS `bulkTransferAssociation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferAssociation` ( + `bulkTransferAssociationId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `bulkTransferId` varchar(36) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `bulkProcessingStateId` int(10) unsigned NOT NULL, + `lastProcessedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `errorCode` int(10) unsigned DEFAULT NULL, + `errorDescription` varchar(128) DEFAULT NULL, + PRIMARY KEY (`bulkTransferAssociationId`), + UNIQUE KEY `bulktransferassociation_transferid_bulktransferid_unique` (`transferId`,`bulkTransferId`), + KEY `bulktransferassociation_bulktransferid_foreign` (`bulkTransferId`), + KEY `bulktransferassociation_bulkprocessingstateid_foreign` (`bulkProcessingStateId`), + CONSTRAINT `bulktransferassociation_bulkprocessingstateid_foreign` FOREIGN KEY (`bulkProcessingStateId`) REFERENCES `bulkProcessingState` (`bulkprocessingstateid`), + CONSTRAINT `bulktransferassociation_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferDuplicateCheck` +-- + +DROP TABLE IF EXISTS `bulkTransferDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferDuplicateCheck` ( + `bulkTransferId` varchar(36) NOT NULL, + `hash` varchar(256) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferError` +-- + +DROP TABLE IF EXISTS `bulkTransferError`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferError` ( + `bulkTransferErrorId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `bulkTransferStateChangeId` bigint(20) unsigned NOT NULL, + `errorCode` int(10) unsigned NOT NULL, + `errorDescription` varchar(128) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferErrorId`), + KEY `bulktransfererror_bulktransferstatechangeid_index` (`bulkTransferStateChangeId`), + CONSTRAINT `bulktransfererror_bulktransferstatechangeid_foreign` FOREIGN KEY (`bulkTransferStateChangeId`) REFERENCES `bulkTransferStateChange` (`bulktransferstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferExtension` +-- + +DROP TABLE IF EXISTS `bulkTransferExtension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferExtension` ( + `bulkTransferExtensionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `bulkTransferId` varchar(36) NOT NULL, + `isFulfilment` tinyint(1) NOT NULL DEFAULT '0', + `key` varchar(128) NOT NULL, + `value` text NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferExtensionId`), + KEY `bulktransferextension_bulktransferid_index` (`bulkTransferId`), + CONSTRAINT `bulktransferextension_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferFulfilment` +-- + +DROP TABLE IF EXISTS `bulkTransferFulfilment`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferFulfilment` ( + `bulkTransferId` varchar(36) NOT NULL, + `completedDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`), + CONSTRAINT `bulktransferfulfilment_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransferFulfilmentDuplicateCheck` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferFulfilmentDuplicateCheck` +-- + +DROP TABLE IF EXISTS `bulkTransferFulfilmentDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferFulfilmentDuplicateCheck` ( + `bulkTransferId` varchar(36) NOT NULL, + `hash` varchar(256) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`), + CONSTRAINT `bulktransferfulfilmentduplicatecheck_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferState` +-- + +DROP TABLE IF EXISTS `bulkTransferState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferState` ( + `bulkTransferStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL COMMENT 'bulkTransferState associated to the Mojaloop API', + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferStateChange` +-- + +DROP TABLE IF EXISTS `bulkTransferStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferStateChange` ( + `bulkTransferStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `bulkTransferId` varchar(36) NOT NULL, + `bulkTransferStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferStateChangeId`), + KEY `bulktransferstatechange_bulktransferid_index` (`bulkTransferId`), + KEY `bulktransferstatechange_bulktransferstateid_index` (`bulkTransferStateId`), + CONSTRAINT `bulktransferstatechange_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`), + CONSTRAINT `bulktransferstatechange_bulktransferstateid_foreign` FOREIGN KEY (`bulkTransferStateId`) REFERENCES `bulkTransferState` (`bulktransferstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `contactType` +-- + +DROP TABLE IF EXISTS `contactType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `contactType` ( + `contactTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`contactTypeId`), + UNIQUE KEY `contacttype_name_unique` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `currency` +-- + +DROP TABLE IF EXISTS `currency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `currency` ( + `currencyId` varchar(3) NOT NULL, + `name` varchar(128) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `scale` int(10) unsigned NOT NULL DEFAULT '4', + PRIMARY KEY (`currencyId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `endpointType` +-- + +DROP TABLE IF EXISTS `endpointType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `endpointType` ( + `endpointTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`endpointTypeId`), + UNIQUE KEY `endpointtype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `event` +-- + +DROP TABLE IF EXISTS `event`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `event` ( + `eventId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`eventId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `expiringTransfer` +-- + +DROP TABLE IF EXISTS `expiringTransfer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `expiringTransfer` ( + `expiringTransferId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`expiringTransferId`), + UNIQUE KEY `expiringtransfer_transferid_unique` (`transferId`), + KEY `expiringtransfer_expirationdate_index` (`expirationDate`), + CONSTRAINT `expiringtransfer_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `geoCode` +-- + +DROP TABLE IF EXISTS `geoCode`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `geoCode` ( + `geoCodeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `quotePartyId` bigint(20) unsigned NOT NULL COMMENT 'Optionally the GeoCode for the Payer/Payee may have been provided. If the Quote Response has the GeoCode for the Payee, an additional row is added', + `latitude` varchar(50) NOT NULL COMMENT 'Latitude of the initiating Party', + `longitude` varchar(50) NOT NULL COMMENT 'Longitude of the initiating Party', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`geoCodeId`), + KEY `geocode_quotepartyid_foreign` (`quotePartyId`), + CONSTRAINT `geocode_quotepartyid_foreign` FOREIGN KEY (`quotePartyId`) REFERENCES `quoteParty` (`quotepartyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ilpPacket` +-- + +DROP TABLE IF EXISTS `ilpPacket`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `ilpPacket` ( + `transferId` varchar(36) NOT NULL, + `value` text NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + CONSTRAINT `ilppacket_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ledgerAccountType` +-- + +DROP TABLE IF EXISTS `ledgerAccountType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `ledgerAccountType` ( + `ledgerAccountTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `isSettleable` tinyint(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`ledgerAccountTypeId`), + UNIQUE KEY `ledgeraccounttype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ledgerEntryType` +-- + +DROP TABLE IF EXISTS `ledgerEntryType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `ledgerEntryType` ( + `ledgerEntryTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `ledgerAccountTypeId` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`ledgerEntryTypeId`), + UNIQUE KEY `ledgerentrytype_name_unique` (`name`), + KEY `ledgerentrytype_ledgeraccounttypeid_foreign` (`ledgerAccountTypeId`), + CONSTRAINT `ledgerentrytype_ledgeraccounttypeid_foreign` FOREIGN KEY (`ledgerAccountTypeId`) REFERENCES `ledgerAccountType` (`ledgeraccounttypeid`) +) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `migration` +-- + +DROP TABLE IF EXISTS `migration`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `migration` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `batch` int(11) DEFAULT NULL, + `migration_time` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=157 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `migration_lock` +-- + +DROP TABLE IF EXISTS `migration_lock`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `migration_lock` ( + `index` int(10) unsigned NOT NULL AUTO_INCREMENT, + `is_locked` int(11) DEFAULT NULL, + PRIMARY KEY (`index`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participant` +-- + +DROP TABLE IF EXISTS `participant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participant` ( + `participantId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantId`), + UNIQUE KEY `participant_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantContact` +-- + +DROP TABLE IF EXISTS `participantContact`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantContact` ( + `participantContactId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `contactTypeId` int(10) unsigned NOT NULL, + `value` varchar(256) NOT NULL, + `priorityPreference` int(11) NOT NULL DEFAULT '9', + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantContactId`), + KEY `participantcontact_participantid_index` (`participantId`), + KEY `participantcontact_contacttypeid_index` (`contactTypeId`), + CONSTRAINT `participantcontact_contacttypeid_foreign` FOREIGN KEY (`contactTypeId`) REFERENCES `contactType` (`contacttypeid`), + CONSTRAINT `participantcontact_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantCurrency` +-- + +DROP TABLE IF EXISTS `participantCurrency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantCurrency` ( + `participantCurrencyId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `currencyId` varchar(3) NOT NULL, + `ledgerAccountTypeId` int(10) unsigned NOT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantCurrencyId`), + UNIQUE KEY `participantcurrency_pcl_unique` (`participantId`,`currencyId`,`ledgerAccountTypeId`), + KEY `participantcurrency_ledgeraccounttypeid_foreign` (`ledgerAccountTypeId`), + KEY `participantcurrency_participantid_index` (`participantId`), + KEY `participantcurrency_currencyid_index` (`currencyId`), + CONSTRAINT `participantcurrency_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `participantcurrency_ledgeraccounttypeid_foreign` FOREIGN KEY (`ledgerAccountTypeId`) REFERENCES `ledgerAccountType` (`ledgeraccounttypeid`), + CONSTRAINT `participantcurrency_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantEndpoint` +-- + +DROP TABLE IF EXISTS `participantEndpoint`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantEndpoint` ( + `participantEndpointId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `endpointTypeId` int(10) unsigned NOT NULL, + `value` varchar(512) NOT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantEndpointId`), + KEY `participantendpoint_participantid_index` (`participantId`), + KEY `participantendpoint_endpointtypeid_index` (`endpointTypeId`), + CONSTRAINT `participantendpoint_endpointtypeid_foreign` FOREIGN KEY (`endpointTypeId`) REFERENCES `endpointType` (`endpointtypeid`), + CONSTRAINT `participantendpoint_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantLimit` +-- + +DROP TABLE IF EXISTS `participantLimit`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantLimit` ( + `participantLimitId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantCurrencyId` int(10) unsigned NOT NULL, + `participantLimitTypeId` int(10) unsigned NOT NULL, + `value` decimal(18,4) NOT NULL DEFAULT '0.0000', + `thresholdAlarmPercentage` decimal(5,2) NOT NULL DEFAULT '10.00', + `startAfterParticipantPositionChangeId` bigint(20) unsigned DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantLimitId`), + KEY `participantlimit_participantcurrencyid_index` (`participantCurrencyId`), + KEY `participantlimit_participantlimittypeid_index` (`participantLimitTypeId`), + KEY `participantlimit_startafterparticipantpositionchangeid_index` (`startAfterParticipantPositionChangeId`), + CONSTRAINT `participantlimit_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `participantlimit_participantlimittypeid_foreign` FOREIGN KEY (`participantLimitTypeId`) REFERENCES `participantLimitType` (`participantlimittypeid`), + CONSTRAINT `participantlimit_startafterparticipantpositionchangeid_foreign` FOREIGN KEY (`startAfterParticipantPositionChangeId`) REFERENCES `participantPositionChange` (`participantpositionchangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantLimitType` +-- + +DROP TABLE IF EXISTS `participantLimitType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantLimitType` ( + `participantLimitTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`participantLimitTypeId`), + UNIQUE KEY `participantlimittype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantParty` +-- + +DROP TABLE IF EXISTS `participantParty`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantParty` ( + `participantPartyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `partyId` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`participantPartyId`), + UNIQUE KEY `participantparty_participantid_partyid_unique` (`participantId`,`partyId`), + KEY `participantparty_participantid_index` (`participantId`), + CONSTRAINT `participantparty_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantPosition` +-- + +DROP TABLE IF EXISTS `participantPosition`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantPosition` ( + `participantPositionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `participantCurrencyId` int(10) unsigned NOT NULL, + `value` decimal(18,4) NOT NULL, + `reservedValue` decimal(18,4) NOT NULL, + `changedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`participantPositionId`), + KEY `participantposition_participantcurrencyid_index` (`participantCurrencyId`), + CONSTRAINT `participantposition_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantPositionChange` +-- + +DROP TABLE IF EXISTS `participantPositionChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantPositionChange` ( + `participantPositionChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `participantPositionId` bigint(20) unsigned NOT NULL, + `transferStateChangeId` bigint(20) unsigned NOT NULL, + `value` decimal(18,4) NOT NULL, + `reservedValue` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`participantPositionChangeId`), + KEY `participantpositionchange_participantpositionid_index` (`participantPositionId`), + KEY `participantpositionchange_transferstatechangeid_index` (`transferStateChangeId`), + CONSTRAINT `participantpositionchange_participantpositionid_foreign` FOREIGN KEY (`participantPositionId`) REFERENCES `participantPosition` (`participantpositionid`), + CONSTRAINT `participantpositionchange_transferstatechangeid_foreign` FOREIGN KEY (`transferStateChangeId`) REFERENCES `transferStateChange` (`transferstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `party` +-- + +DROP TABLE IF EXISTS `party`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `party` ( + `partyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quotePartyId` bigint(20) unsigned NOT NULL, + `firstName` varchar(128) DEFAULT NULL, + `middleName` varchar(128) DEFAULT NULL, + `lastName` varchar(128) DEFAULT NULL, + `dateOfBirth` datetime DEFAULT NULL, + PRIMARY KEY (`partyId`), + KEY `party_quotepartyid_foreign` (`quotePartyId`), + CONSTRAINT `party_quotepartyid_foreign` FOREIGN KEY (`quotePartyId`) REFERENCES `quoteParty` (`quotepartyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Optional pers. data provided during Quote Request & Response'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `partyIdentifierType` +-- + +DROP TABLE IF EXISTS `partyIdentifierType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `partyIdentifierType` ( + `partyIdentifierTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) NOT NULL, + PRIMARY KEY (`partyIdentifierTypeId`), + UNIQUE KEY `partyidentifiertype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `partyType` +-- + +DROP TABLE IF EXISTS `partyType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `partyType` ( + `partyTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL, + `description` varchar(256) NOT NULL, + PRIMARY KEY (`partyTypeId`), + UNIQUE KEY `partytype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quote` +-- + +DROP TABLE IF EXISTS `quote`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quote` ( + `quoteId` varchar(36) NOT NULL, + `transactionReferenceId` varchar(36) NOT NULL COMMENT 'Common ID (decided by the Payer FSP) between the FSPs for the future transaction object', + `transactionRequestId` varchar(36) DEFAULT NULL COMMENT 'Optional previously-sent transaction request', + `note` text COMMENT 'A memo that will be attached to the transaction', + `expirationDate` datetime DEFAULT NULL COMMENT 'Optional expiration for the requested transaction', + `transactionInitiatorId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction initiator', + `transactionInitiatorTypeId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction initiator type', + `transactionScenarioId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction scenario', + `balanceOfPaymentsId` int(10) unsigned DEFAULT NULL COMMENT 'This is part of the transaction type that contains the elements- balance of payment', + `transactionSubScenarioId` int(10) unsigned DEFAULT NULL COMMENT 'This is part of the transaction type sub scenario as defined by the local scheme', + `amountTypeId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction type that contains valid elements for - Amount Type', + `amount` decimal(18,4) NOT NULL DEFAULT '0.0000' COMMENT 'The amount that the quote is being requested for. Need to be interpert in accordance with the amount type', + `currencyId` varchar(255) DEFAULT NULL COMMENT 'Trading currency pertaining to the Amount', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteId`), + KEY `quote_transactionreferenceid_foreign` (`transactionReferenceId`), + KEY `quote_transactionrequestid_foreign` (`transactionRequestId`), + KEY `quote_transactioninitiatorid_foreign` (`transactionInitiatorId`), + KEY `quote_transactioninitiatortypeid_foreign` (`transactionInitiatorTypeId`), + KEY `quote_transactionscenarioid_foreign` (`transactionScenarioId`), + KEY `quote_balanceofpaymentsid_foreign` (`balanceOfPaymentsId`), + KEY `quote_transactionsubscenarioid_foreign` (`transactionSubScenarioId`), + KEY `quote_amounttypeid_foreign` (`amountTypeId`), + KEY `quote_currencyid_foreign` (`currencyId`), + CONSTRAINT `quote_amounttypeid_foreign` FOREIGN KEY (`amountTypeId`) REFERENCES `amountType` (`amounttypeid`), + CONSTRAINT `quote_balanceofpaymentsid_foreign` FOREIGN KEY (`balanceOfPaymentsId`) REFERENCES `balanceOfPayments` (`balanceofpaymentsid`), + CONSTRAINT `quote_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quote_transactioninitiatorid_foreign` FOREIGN KEY (`transactionInitiatorId`) REFERENCES `transactionInitiator` (`transactioninitiatorid`), + CONSTRAINT `quote_transactioninitiatortypeid_foreign` FOREIGN KEY (`transactionInitiatorTypeId`) REFERENCES `transactionInitiatorType` (`transactioninitiatortypeid`), + CONSTRAINT `quote_transactionreferenceid_foreign` FOREIGN KEY (`transactionReferenceId`) REFERENCES `transactionReference` (`transactionreferenceid`), + CONSTRAINT `quote_transactionrequestid_foreign` FOREIGN KEY (`transactionRequestId`) REFERENCES `transactionReference` (`transactionreferenceid`), + CONSTRAINT `quote_transactionscenarioid_foreign` FOREIGN KEY (`transactionScenarioId`) REFERENCES `transactionScenario` (`transactionscenarioid`), + CONSTRAINT `quote_transactionsubscenarioid_foreign` FOREIGN KEY (`transactionSubScenarioId`) REFERENCES `transactionSubScenario` (`transactionsubscenarioid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteDuplicateCheck` +-- + +DROP TABLE IF EXISTS `quoteDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteDuplicateCheck` ( + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `hash` varchar(1024) DEFAULT NULL COMMENT 'hash value received for the quote request', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteError` +-- + +DROP TABLE IF EXISTS `quoteError`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteError` ( + `quoteErrorId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `quoteResponseId` bigint(20) unsigned DEFAULT NULL COMMENT 'The response to the intial quote', + `errorCode` int(10) unsigned NOT NULL, + `errorDescription` varchar(128) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`quoteErrorId`), + KEY `quoteerror_quoteid_foreign` (`quoteId`), + KEY `quoteerror_quoteresponseid_foreign` (`quoteResponseId`), + CONSTRAINT `quoteerror_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteerror_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteExtension` +-- + +DROP TABLE IF EXISTS `quoteExtension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteExtension` ( + `quoteExtensionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `quoteResponseId` bigint(20) unsigned NOT NULL COMMENT 'The response to the intial quote', + `transactionId` varchar(36) NOT NULL COMMENT 'The transaction reference that is part of the initial quote', + `key` varchar(128) NOT NULL, + `value` text NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteExtensionId`), + KEY `quoteextension_quoteid_foreign` (`quoteId`), + KEY `quoteextension_quoteresponseid_foreign` (`quoteResponseId`), + KEY `quoteextension_transactionid_foreign` (`transactionId`), + CONSTRAINT `quoteextension_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteextension_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`), + CONSTRAINT `quoteextension_transactionid_foreign` FOREIGN KEY (`transactionId`) REFERENCES `transactionReference` (`transactionreferenceid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteParty` +-- + +DROP TABLE IF EXISTS `quoteParty`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteParty` ( + `quotePartyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `partyTypeId` int(10) unsigned NOT NULL COMMENT 'Specifies the type of party this row relates to; typically PAYER or PAYEE', + `partyIdentifierTypeId` int(10) unsigned NOT NULL COMMENT 'Specifies the type of identifier used to identify this party e.g. MSISDN, IBAN etc...', + `partyIdentifierValue` varchar(128) NOT NULL COMMENT 'The value of the identifier used to identify this party', + `partySubIdOrTypeId` int(10) unsigned DEFAULT NULL COMMENT 'A sub-identifier or sub-type for the Party', + `fspId` varchar(255) DEFAULT NULL COMMENT 'This is the FSP ID as provided in the quote. For the switch between multi-parties it is required', + `participantId` int(10) unsigned DEFAULT NULL COMMENT 'Reference to the resolved FSP ID (if supplied/known). If not an error will be reported', + `merchantClassificationCode` varchar(4) DEFAULT NULL COMMENT 'Used in the context of Payee Information, where the Payee happens to be a merchant accepting merchant payments', + `partyName` varchar(128) DEFAULT NULL COMMENT 'Display name of the Party, could be a real name or a nick name', + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL COMMENT 'The role this Party is playing in the transaction', + `ledgerEntryTypeId` int(10) unsigned NOT NULL COMMENT 'The type of financial entry this Party is presenting', + `amount` decimal(18,4) NOT NULL, + `currencyId` varchar(3) NOT NULL COMMENT 'Trading currency pertaining to the party amount', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quotePartyId`), + KEY `quoteparty_quoteid_foreign` (`quoteId`), + KEY `quoteparty_partytypeid_foreign` (`partyTypeId`), + KEY `quoteparty_partyidentifiertypeid_foreign` (`partyIdentifierTypeId`), + KEY `quoteparty_partysubidortypeid_foreign` (`partySubIdOrTypeId`), + KEY `quoteparty_participantid_foreign` (`participantId`), + KEY `quoteparty_transferparticipantroletypeid_foreign` (`transferParticipantRoleTypeId`), + KEY `quoteparty_ledgerentrytypeid_foreign` (`ledgerEntryTypeId`), + KEY `quoteparty_currencyid_foreign` (`currencyId`), + CONSTRAINT `quoteparty_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quoteparty_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `quoteparty_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`), + CONSTRAINT `quoteparty_partyidentifiertypeid_foreign` FOREIGN KEY (`partyIdentifierTypeId`) REFERENCES `partyIdentifierType` (`partyidentifiertypeid`), + CONSTRAINT `quoteparty_partysubidortypeid_foreign` FOREIGN KEY (`partySubIdOrTypeId`) REFERENCES `partyIdentifierType` (`partyidentifiertypeid`), + CONSTRAINT `quoteparty_partytypeid_foreign` FOREIGN KEY (`partyTypeId`) REFERENCES `partyType` (`partytypeid`), + CONSTRAINT `quoteparty_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteparty_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Temporary view structure for view `quotePartyView` +-- + +DROP TABLE IF EXISTS `quotePartyView`; +/*!50001 DROP VIEW IF EXISTS `quotePartyView`*/; +SET @saved_cs_client = @@character_set_client; +/*!50503 SET character_set_client = utf8mb4 */; +/*!50001 CREATE VIEW `quotePartyView` AS SELECT + 1 AS `quoteId`, + 1 AS `quotePartyId`, + 1 AS `partyType`, + 1 AS `identifierType`, + 1 AS `partyIdentifierValue`, + 1 AS `partySubIdOrType`, + 1 AS `fspId`, + 1 AS `merchantClassificationCode`, + 1 AS `partyName`, + 1 AS `firstName`, + 1 AS `lastName`, + 1 AS `middleName`, + 1 AS `dateOfBirth`, + 1 AS `longitude`, + 1 AS `latitude`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `quoteResponse` +-- + +DROP TABLE IF EXISTS `quoteResponse`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteResponse` ( + `quoteResponseId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `transferAmountCurrencyId` varchar(3) NOT NULL COMMENT 'CurrencyId of the transfer amount', + `transferAmount` decimal(18,4) NOT NULL COMMENT 'The amount of money that the Payer FSP should transfer to the Payee FSP', + `payeeReceiveAmountCurrencyId` varchar(3) DEFAULT NULL COMMENT 'CurrencyId of the payee receive amount', + `payeeReceiveAmount` decimal(18,4) DEFAULT NULL COMMENT 'The amount of Money that the Payee should receive in the end-to-end transaction. Optional as the Payee FSP might not want to disclose any optional Payee fees', + `payeeFspFeeCurrencyId` varchar(3) DEFAULT NULL COMMENT 'CurrencyId of the payee fsp fee amount', + `payeeFspFeeAmount` decimal(18,4) DEFAULT NULL COMMENT 'Payee FSP’s part of the transaction fee', + `payeeFspCommissionCurrencyId` varchar(3) DEFAULT NULL COMMENT 'CurrencyId of the payee fsp commission amount', + `payeeFspCommissionAmount` decimal(18,4) DEFAULT NULL COMMENT 'Transaction commission from the Payee FSP', + `ilpCondition` varchar(256) NOT NULL, + `responseExpirationDate` datetime DEFAULT NULL COMMENT 'Optional expiration for the requested transaction', + `isValid` tinyint(1) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteResponseId`), + KEY `quoteresponse_quoteid_foreign` (`quoteId`), + KEY `quoteresponse_transferamountcurrencyid_foreign` (`transferAmountCurrencyId`), + KEY `quoteresponse_payeereceiveamountcurrencyid_foreign` (`payeeReceiveAmountCurrencyId`), + KEY `quoteresponse_payeefspcommissioncurrencyid_foreign` (`payeeFspCommissionCurrencyId`), + CONSTRAINT `quoteresponse_payeefspcommissioncurrencyid_foreign` FOREIGN KEY (`payeeFspCommissionCurrencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quoteresponse_payeereceiveamountcurrencyid_foreign` FOREIGN KEY (`payeeReceiveAmountCurrencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quoteresponse_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteresponse_transferamountcurrencyid_foreign` FOREIGN KEY (`transferAmountCurrencyId`) REFERENCES `currency` (`currencyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='This table is the primary store for quote responses'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteResponseDuplicateCheck` +-- + +DROP TABLE IF EXISTS `quoteResponseDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteResponseDuplicateCheck` ( + `quoteResponseId` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'The response to the intial quote', + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `hash` varchar(255) DEFAULT NULL COMMENT 'hash value received for the quote response', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteResponseId`), + KEY `quoteresponseduplicatecheck_quoteid_foreign` (`quoteId`), + CONSTRAINT `quoteresponseduplicatecheck_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteresponseduplicatecheck_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteResponseIlpPacket` +-- + +DROP TABLE IF EXISTS `quoteResponseIlpPacket`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteResponseIlpPacket` ( + `quoteResponseId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `value` text NOT NULL COMMENT 'ilpPacket returned from Payee in response to a quote request', + PRIMARY KEY (`quoteResponseId`), + CONSTRAINT `quoteresponseilppacket_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Temporary view structure for view `quoteResponseView` +-- + +DROP TABLE IF EXISTS `quoteResponseView`; +/*!50001 DROP VIEW IF EXISTS `quoteResponseView`*/; +SET @saved_cs_client = @@character_set_client; +/*!50503 SET character_set_client = utf8mb4 */; +/*!50001 CREATE VIEW `quoteResponseView` AS SELECT + 1 AS `quoteResponseId`, + 1 AS `quoteId`, + 1 AS `transferAmountCurrencyId`, + 1 AS `transferAmount`, + 1 AS `payeeReceiveAmountCurrencyId`, + 1 AS `payeeReceiveAmount`, + 1 AS `payeeFspFeeCurrencyId`, + 1 AS `payeeFspFeeAmount`, + 1 AS `payeeFspCommissionCurrencyId`, + 1 AS `payeeFspCommissionAmount`, + 1 AS `ilpCondition`, + 1 AS `responseExpirationDate`, + 1 AS `isValid`, + 1 AS `createdDate`, + 1 AS `ilpPacket`, + 1 AS `longitude`, + 1 AS `latitude`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Temporary view structure for view `quoteView` +-- + +DROP TABLE IF EXISTS `quoteView`; +/*!50001 DROP VIEW IF EXISTS `quoteView`*/; +SET @saved_cs_client = @@character_set_client; +/*!50503 SET character_set_client = utf8mb4 */; +/*!50001 CREATE VIEW `quoteView` AS SELECT + 1 AS `quoteId`, + 1 AS `transactionReferenceId`, + 1 AS `transactionRequestId`, + 1 AS `note`, + 1 AS `expirationDate`, + 1 AS `transactionInitiator`, + 1 AS `transactionInitiatorType`, + 1 AS `transactionScenario`, + 1 AS `balanceOfPaymentsId`, + 1 AS `transactionSubScenario`, + 1 AS `amountType`, + 1 AS `amount`, + 1 AS `currency`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `segment` +-- + +DROP TABLE IF EXISTS `segment`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `segment` ( + `segmentId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `segmentType` varchar(50) NOT NULL, + `enumeration` int(11) NOT NULL DEFAULT '0', + `tableName` varchar(50) NOT NULL, + `value` bigint(20) NOT NULL, + `changedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`segmentId`), + KEY `segment_keys_index` (`segmentType`,`enumeration`,`tableName`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlement` +-- + +DROP TABLE IF EXISTS `settlement`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlement` ( + `settlementId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + `settlementModelId` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`settlementId`), + KEY `settlement_currentstatechangeid_foreign` (`currentStateChangeId`), + KEY `settlement_settlementmodelid_foreign` (`settlementModelId`), + CONSTRAINT `settlement_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementStateChange` (`settlementstatechangeid`), + CONSTRAINT `settlement_settlementmodelid_foreign` FOREIGN KEY (`settlementModelId`) REFERENCES `settlementModel` (`settlementmodelid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementContentAggregation` +-- + +DROP TABLE IF EXISTS `settlementContentAggregation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementContentAggregation` ( + `settlementContentAggregationId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementWindowContentId` bigint(20) unsigned NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL, + `ledgerEntryTypeId` int(10) unsigned NOT NULL, + `amount` decimal(18,2) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateId` varchar(50) NOT NULL, + `settlementId` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`settlementContentAggregationId`), + KEY `settlementcontentaggregation_settlementwindowcontentid_index` (`settlementWindowContentId`), + KEY `settlementcontentaggregation_participantcurrencyid_index` (`participantCurrencyId`), + KEY `settlementcontentaggregation_transferparticipantroletypeid_index` (`transferParticipantRoleTypeId`), + KEY `settlementcontentaggregation_ledgerentrytypeid_index` (`ledgerEntryTypeId`), + KEY `settlementcontentaggregation_currentstateid_index` (`currentStateId`), + KEY `settlementcontentaggregation_settlementid_index` (`settlementId`), + CONSTRAINT `sca_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`), + CONSTRAINT `settlementcontentaggregation_currentstateid_foreign` FOREIGN KEY (`currentStateId`) REFERENCES `settlementWindowState` (`settlementwindowstateid`), + CONSTRAINT `settlementcontentaggregation_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `settlementcontentaggregation_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `settlementcontentaggregation_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementcontentaggregation_settlementwindowcontentid_foreign` FOREIGN KEY (`settlementWindowContentId`) REFERENCES `settlementWindowContent` (`settlementwindowcontentid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementDelay` +-- + +DROP TABLE IF EXISTS `settlementDelay`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementDelay` ( + `settlementDelayId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`settlementDelayId`), + UNIQUE KEY `settlementdelay_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementGranularity` +-- + +DROP TABLE IF EXISTS `settlementGranularity`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementGranularity` ( + `settlementGranularityId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`settlementGranularityId`), + UNIQUE KEY `settlementgranularity_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementInterchange` +-- + +DROP TABLE IF EXISTS `settlementInterchange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementInterchange` ( + `settlementInterchangeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`settlementInterchangeId`), + UNIQUE KEY `settlementinterchange_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementModel` +-- + +DROP TABLE IF EXISTS `settlementModel`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementModel` ( + `settlementModelId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `settlementGranularityId` int(10) unsigned NOT NULL, + `settlementInterchangeId` int(10) unsigned NOT NULL, + `settlementDelayId` int(10) unsigned NOT NULL, + `currencyId` varchar(3) DEFAULT NULL, + `requireLiquidityCheck` tinyint(1) NOT NULL DEFAULT '1', + `ledgerAccountTypeId` int(10) unsigned NOT NULL, + `autoPositionReset` tinyint(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`settlementModelId`), + UNIQUE KEY `settlementmodel_name_unique` (`name`), + KEY `settlementmodel_settlementgranularityid_index` (`settlementGranularityId`), + KEY `settlementmodel_settlementinterchangeid_index` (`settlementInterchangeId`), + KEY `settlementmodel_settlementdelayid_index` (`settlementDelayId`), + KEY `settlementmodel_currencyid_index` (`currencyId`), + KEY `settlementmodel_ledgeraccounttypeid_index` (`ledgerAccountTypeId`), + CONSTRAINT `settlementmodel_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `settlementmodel_ledgeraccounttypeid_foreign` FOREIGN KEY (`ledgerAccountTypeId`) REFERENCES `ledgerAccountType` (`ledgeraccounttypeid`), + CONSTRAINT `settlementmodel_settlementdelayid_foreign` FOREIGN KEY (`settlementDelayId`) REFERENCES `settlementDelay` (`settlementdelayid`), + CONSTRAINT `settlementmodel_settlementgranularityid_foreign` FOREIGN KEY (`settlementGranularityId`) REFERENCES `settlementGranularity` (`settlementgranularityid`), + CONSTRAINT `settlementmodel_settlementinterchangeid_foreign` FOREIGN KEY (`settlementInterchangeId`) REFERENCES `settlementInterchange` (`settlementinterchangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementParticipantCurrency` +-- + +DROP TABLE IF EXISTS `settlementParticipantCurrency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementParticipantCurrency` ( + `settlementParticipantCurrencyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `netAmount` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + `settlementTransferId` varchar(36) DEFAULT NULL, + PRIMARY KEY (`settlementParticipantCurrencyId`), + KEY `settlementparticipantcurrency_settlementid_index` (`settlementId`), + KEY `settlementparticipantcurrency_participantcurrencyid_index` (`participantCurrencyId`), + KEY `settlementparticipantcurrency_settlementtransferid_index` (`settlementTransferId`), + KEY `spc_currentstatechangeid_foreign` (`currentStateChangeId`), + CONSTRAINT `settlementparticipantcurrency_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `settlementparticipantcurrency_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `spc_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementParticipantCurrencyStateChange` (`settlementparticipantcurrencystatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementParticipantCurrencyStateChange` +-- + +DROP TABLE IF EXISTS `settlementParticipantCurrencyStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementParticipantCurrencyStateChange` ( + `settlementParticipantCurrencyStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementParticipantCurrencyId` bigint(20) unsigned NOT NULL, + `settlementStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `externalReference` varchar(50) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementParticipantCurrencyStateChangeId`), + KEY `spcsc_settlementparticipantcurrencyid_index` (`settlementParticipantCurrencyId`), + KEY `spcsc_settlementstateid_index` (`settlementStateId`), + CONSTRAINT `spcsc_settlementparticipantcurrencyid_foreign` FOREIGN KEY (`settlementParticipantCurrencyId`) REFERENCES `settlementParticipantCurrency` (`settlementparticipantcurrencyid`), + CONSTRAINT `spcsc_settlementstateid_foreign` FOREIGN KEY (`settlementStateId`) REFERENCES `settlementState` (`settlementstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementSettlementWindow` +-- + +DROP TABLE IF EXISTS `settlementSettlementWindow`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementSettlementWindow` ( + `settlementSettlementWindowId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementSettlementWindowId`), + UNIQUE KEY `settlementsettlementwindow_unique` (`settlementId`,`settlementWindowId`), + KEY `settlementsettlementwindow_settlementid_index` (`settlementId`), + KEY `settlementsettlementwindow_settlementwindowid_index` (`settlementWindowId`), + CONSTRAINT `settlementsettlementwindow_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementsettlementwindow_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementState` +-- + +DROP TABLE IF EXISTS `settlementState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementState` ( + `settlementStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementStateChange` +-- + +DROP TABLE IF EXISTS `settlementStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementStateChange` ( + `settlementStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `settlementStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementStateChangeId`), + KEY `settlementstatechange_settlementid_index` (`settlementId`), + KEY `settlementstatechange_settlementstateid_index` (`settlementStateId`), + CONSTRAINT `settlementstatechange_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementstatechange_settlementstateid_foreign` FOREIGN KEY (`settlementStateId`) REFERENCES `settlementState` (`settlementstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementTransferParticipant` +-- + +DROP TABLE IF EXISTS `settlementTransferParticipant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementTransferParticipant` ( + `settlementTransferParticipantId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL, + `ledgerEntryTypeId` int(10) unsigned NOT NULL, + `amount` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementTransferParticipantId`), + KEY `settlementtransferparticipant_settlementid_index` (`settlementId`), + KEY `settlementtransferparticipant_settlementwindowid_index` (`settlementWindowId`), + KEY `settlementtransferparticipant_participantcurrencyid_index` (`participantCurrencyId`), + KEY `stp_transferparticipantroletypeid_index` (`transferParticipantRoleTypeId`), + KEY `settlementtransferparticipant_ledgerentrytypeid_index` (`ledgerEntryTypeId`), + CONSTRAINT `settlementtransferparticipant_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `settlementtransferparticipant_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `settlementtransferparticipant_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementtransferparticipant_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`), + CONSTRAINT `stp_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindow` +-- + +DROP TABLE IF EXISTS `settlementWindow`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementWindow` ( + `settlementWindowId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`settlementWindowId`), + KEY `settlementwindow_currentstatechangeid_foreign` (`currentStateChangeId`), + CONSTRAINT `settlementwindow_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementWindowStateChange` (`settlementwindowstatechangeid`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindowContent` +-- + +DROP TABLE IF EXISTS `settlementWindowContent`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementWindowContent` ( + `settlementWindowContentId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `ledgerAccountTypeId` int(10) unsigned NOT NULL, + `currencyId` varchar(3) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + `settlementId` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`settlementWindowContentId`), + KEY `settlementwindowcontent_settlementwindowid_index` (`settlementWindowId`), + KEY `settlementwindowcontent_ledgeraccounttypeid_index` (`ledgerAccountTypeId`), + KEY `settlementwindowcontent_currencyid_index` (`currencyId`), + KEY `settlementwindowcontent_currentstatechangeid_index` (`currentStateChangeId`), + KEY `settlementwindowcontent_settlementid_index` (`settlementId`), + CONSTRAINT `settlementwindowcontent_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `settlementwindowcontent_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementWindowContentStateChange` (`settlementwindowcontentstatechangeid`), + CONSTRAINT `settlementwindowcontent_ledgeraccounttypeid_foreign` FOREIGN KEY (`ledgerAccountTypeId`) REFERENCES `ledgerAccountType` (`ledgeraccounttypeid`), + CONSTRAINT `settlementwindowcontent_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementwindowcontent_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindowContentStateChange` +-- + +DROP TABLE IF EXISTS `settlementWindowContentStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementWindowContentStateChange` ( + `settlementWindowContentStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementWindowContentId` bigint(20) unsigned NOT NULL, + `settlementWindowStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementWindowContentStateChangeId`), + KEY `swcsc_settlementwindowcontentid_index` (`settlementWindowContentId`), + KEY `swcsc_settlementwindowstateid_index` (`settlementWindowStateId`), + CONSTRAINT `swc_settlementwindowcontentid_foreign` FOREIGN KEY (`settlementWindowContentId`) REFERENCES `settlementWindowContent` (`settlementwindowcontentid`), + CONSTRAINT `sws1_settlementwindowstateid_foreign` FOREIGN KEY (`settlementWindowStateId`) REFERENCES `settlementWindowState` (`settlementwindowstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindowState` +-- + +DROP TABLE IF EXISTS `settlementWindowState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementWindowState` ( + `settlementWindowStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementWindowStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindowStateChange` +-- + +DROP TABLE IF EXISTS `settlementWindowStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementWindowStateChange` ( + `settlementWindowStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `settlementWindowStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementWindowStateChangeId`), + KEY `settlementwindowstatechange_settlementwindowid_index` (`settlementWindowId`), + KEY `settlementwindowstatechange_settlementwindowstateid_index` (`settlementWindowStateId`), + CONSTRAINT `settlementwindowstatechange_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`), + CONSTRAINT `settlementwindowstatechange_settlementwindowstateid_foreign` FOREIGN KEY (`settlementWindowStateId`) REFERENCES `settlementWindowState` (`settlementwindowstateid`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `token` +-- + +DROP TABLE IF EXISTS `token`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `token` ( + `tokenId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `value` varchar(256) NOT NULL, + `expiration` bigint(20) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`tokenId`), + UNIQUE KEY `token_value_unique` (`value`), + KEY `token_participantid_index` (`participantId`), + CONSTRAINT `token_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionInitiator` +-- + +DROP TABLE IF EXISTS `transactionInitiator`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transactionInitiator` ( + `transactionInitiatorId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionInitiatorId`), + UNIQUE KEY `transactioninitiator_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionInitiatorType` +-- + +DROP TABLE IF EXISTS `transactionInitiatorType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transactionInitiatorType` ( + `transactionInitiatorTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionInitiatorTypeId`), + UNIQUE KEY `transactioninitiatortype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionReference` +-- + +DROP TABLE IF EXISTS `transactionReference`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transactionReference` ( + `transactionReferenceId` varchar(36) NOT NULL COMMENT 'Common ID (decided by the Payer FSP) between the FSPs for the future transaction object', + `quoteId` varchar(36) DEFAULT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System row creation timestamp', + PRIMARY KEY (`transactionReferenceId`), + KEY `transactionreference_quoteid_index` (`quoteId`), + CONSTRAINT `transactionreference_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quoteDuplicateCheck` (`quoteid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionScenario` +-- + +DROP TABLE IF EXISTS `transactionScenario`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transactionScenario` ( + `transactionScenarioId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionScenarioId`), + UNIQUE KEY `transactionscenario_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionSubScenario` +-- + +DROP TABLE IF EXISTS `transactionSubScenario`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transactionSubScenario` ( + `transactionSubScenarioId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL COMMENT 'Possible sub-scenario, defined locally within the scheme', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionSubScenarioId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transfer` +-- + +DROP TABLE IF EXISTS `transfer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transfer` ( + `transferId` varchar(36) NOT NULL, + `amount` decimal(18,4) NOT NULL, + `currencyId` varchar(3) NOT NULL, + `ilpCondition` varchar(256) NOT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + KEY `transfer_currencyid_index` (`currencyId`), + CONSTRAINT `transfer_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `transfer_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transferDuplicateCheck` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferDuplicateCheck` +-- + +DROP TABLE IF EXISTS `transferDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferDuplicateCheck` ( + `transferId` varchar(36) NOT NULL, + `hash` varchar(256) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferError` +-- + +DROP TABLE IF EXISTS `transferError`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferError` ( + `transferId` varchar(36) NOT NULL, + `transferStateChangeId` bigint(20) unsigned NOT NULL, + `errorCode` int(10) unsigned NOT NULL, + `errorDescription` varchar(128) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + KEY `transfererror_transferstatechangeid_foreign` (`transferStateChangeId`), + CONSTRAINT `transfererror_transferstatechangeid_foreign` FOREIGN KEY (`transferStateChangeId`) REFERENCES `transferStateChange` (`transferstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferErrorDuplicateCheck` +-- + +DROP TABLE IF EXISTS `transferErrorDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferErrorDuplicateCheck` ( + `transferId` varchar(36) NOT NULL, + `hash` varchar(256) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + CONSTRAINT `transfererrorduplicatecheck_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferExtension` +-- + +DROP TABLE IF EXISTS `transferExtension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferExtension` ( + `transferExtensionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `key` varchar(128) NOT NULL, + `value` text NOT NULL, + `isFulfilment` tinyint(1) NOT NULL DEFAULT '0', + `isError` tinyint(1) NOT NULL DEFAULT '0', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferExtensionId`), + KEY `transferextension_transferid_foreign` (`transferId`), + CONSTRAINT `transferextension_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferFulfilment` +-- + +DROP TABLE IF EXISTS `transferFulfilment`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferFulfilment` ( + `transferId` varchar(36) NOT NULL, + `ilpFulfilment` varchar(256) DEFAULT NULL, + `completedDate` datetime NOT NULL, + `isValid` tinyint(1) DEFAULT NULL, + `settlementWindowId` bigint(20) unsigned DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + KEY `transferfulfilment_settlementwindowid_foreign` (`settlementWindowId`), + CONSTRAINT `transferfulfilment_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`), + CONSTRAINT `transferfulfilment_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transferFulfilmentDuplicateCheck` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferFulfilmentDuplicateCheck` +-- + +DROP TABLE IF EXISTS `transferFulfilmentDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferFulfilmentDuplicateCheck` ( + `transferId` varchar(36) NOT NULL, + `hash` varchar(256) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + CONSTRAINT `transferfulfilmentduplicatecheck_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferParticipant` +-- + +DROP TABLE IF EXISTS `transferParticipant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferParticipant` ( + `transferParticipantId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL, + `ledgerEntryTypeId` int(10) unsigned NOT NULL, + `amount` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`transferParticipantId`), + KEY `transferparticipant_transferid_index` (`transferId`), + KEY `transferparticipant_participantcurrencyid_index` (`participantCurrencyId`), + KEY `transferparticipant_transferparticipantroletypeid_index` (`transferParticipantRoleTypeId`), + KEY `transferparticipant_ledgerentrytypeid_index` (`ledgerEntryTypeId`), + KEY `transferparticipant_currentstatechangeid_foreign` (`currentStateChangeId`), + CONSTRAINT `transferparticipant_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `transferParticipantStateChange` (`transferparticipantstatechangeid`), + CONSTRAINT `transferparticipant_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `transferparticipant_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `transferparticipant_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`), + CONSTRAINT `transferparticipant_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferParticipantRoleType` +-- + +DROP TABLE IF EXISTS `transferParticipantRoleType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferParticipantRoleType` ( + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferParticipantRoleTypeId`), + UNIQUE KEY `transferparticipantroletype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferParticipantStateChange` +-- + +DROP TABLE IF EXISTS `transferParticipantStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferParticipantStateChange` ( + `transferParticipantStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferParticipantId` bigint(20) unsigned NOT NULL, + `settlementWindowStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferParticipantStateChangeId`), + KEY `transferparticipantstatechange_transferparticipantid_index` (`transferParticipantId`), + KEY `transferparticipantstatechange_settlementwindowstateid_index` (`settlementWindowStateId`), + CONSTRAINT `transferparticipantstatechange_settlementwindowstateid_foreign` FOREIGN KEY (`settlementWindowStateId`) REFERENCES `settlementWindowState` (`settlementwindowstateid`), + CONSTRAINT `transferparticipantstatechange_transferparticipantid_foreign` FOREIGN KEY (`transferParticipantId`) REFERENCES `transferParticipant` (`transferparticipantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferRules` +-- + +DROP TABLE IF EXISTS `transferRules`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferRules` ( + `transferRulesId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `rule` text NOT NULL, + `enabled` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferRulesId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferState` +-- + +DROP TABLE IF EXISTS `transferState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferState` ( + `transferStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL COMMENT 'transferState associated to the Mojaloop API', + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferStateChange` +-- + +DROP TABLE IF EXISTS `transferStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferStateChange` ( + `transferStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `transferStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferStateChangeId`), + KEY `transferstatechange_transferid_index` (`transferId`), + KEY `transferstatechange_transferstateid_index` (`transferStateId`), + CONSTRAINT `transferstatechange_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`), + CONSTRAINT `transferstatechange_transferstateid_foreign` FOREIGN KEY (`transferStateId`) REFERENCES `transferState` (`transferstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferTimeout` +-- + +DROP TABLE IF EXISTS `transferTimeout`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferTimeout` ( + `transferTimeoutId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferTimeoutId`), + UNIQUE KEY `transfertimeout_transferid_unique` (`transferId`), + CONSTRAINT `transfertimeout_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Final view structure for view `quotePartyView` +-- + +/*!50001 DROP VIEW IF EXISTS `quotePartyView`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`central_ledger`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `quotePartyView` AS select `qp`.`quoteId` AS `quoteId`,`qp`.`quotePartyId` AS `quotePartyId`,`pt`.`name` AS `partyType`,`pit`.`name` AS `identifierType`,`qp`.`partyIdentifierValue` AS `partyIdentifierValue`,`spit`.`name` AS `partySubIdOrType`,`qp`.`fspId` AS `fspId`,`qp`.`merchantClassificationCode` AS `merchantClassificationCode`,`qp`.`partyName` AS `partyName`,`p`.`firstName` AS `firstName`,`p`.`lastName` AS `lastName`,`p`.`middleName` AS `middleName`,`p`.`dateOfBirth` AS `dateOfBirth`,`gc`.`longitude` AS `longitude`,`gc`.`latitude` AS `latitude` from (((((`quoteParty` `qp` join `partyType` `pt` on((`pt`.`partyTypeId` = `qp`.`partyTypeId`))) join `partyIdentifierType` `pit` on((`pit`.`partyIdentifierTypeId` = `qp`.`partyIdentifierTypeId`))) left join `party` `p` on((`p`.`quotePartyId` = `qp`.`quotePartyId`))) left join `partyIdentifierType` `spit` on((`spit`.`partyIdentifierTypeId` = `qp`.`partySubIdOrTypeId`))) left join `geoCode` `gc` on((`gc`.`quotePartyId` = `qp`.`quotePartyId`))) */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; + +-- +-- Final view structure for view `quoteResponseView` +-- + +/*!50001 DROP VIEW IF EXISTS `quoteResponseView`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`central_ledger`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `quoteResponseView` AS select `qr`.`quoteResponseId` AS `quoteResponseId`,`qr`.`quoteId` AS `quoteId`,`qr`.`transferAmountCurrencyId` AS `transferAmountCurrencyId`,`qr`.`transferAmount` AS `transferAmount`,`qr`.`payeeReceiveAmountCurrencyId` AS `payeeReceiveAmountCurrencyId`,`qr`.`payeeReceiveAmount` AS `payeeReceiveAmount`,`qr`.`payeeFspFeeCurrencyId` AS `payeeFspFeeCurrencyId`,`qr`.`payeeFspFeeAmount` AS `payeeFspFeeAmount`,`qr`.`payeeFspCommissionCurrencyId` AS `payeeFspCommissionCurrencyId`,`qr`.`payeeFspCommissionAmount` AS `payeeFspCommissionAmount`,`qr`.`ilpCondition` AS `ilpCondition`,`qr`.`responseExpirationDate` AS `responseExpirationDate`,`qr`.`isValid` AS `isValid`,`qr`.`createdDate` AS `createdDate`,`qrilp`.`value` AS `ilpPacket`,`gc`.`longitude` AS `longitude`,`gc`.`latitude` AS `latitude` from ((((`quoteResponse` `qr` join `quoteResponseIlpPacket` `qrilp` on((`qrilp`.`quoteResponseId` = `qr`.`quoteResponseId`))) join `quoteParty` `qp` on((`qp`.`quoteId` = `qr`.`quoteId`))) join `partyType` `pt` on((`pt`.`partyTypeId` = `qp`.`partyTypeId`))) left join `geoCode` `gc` on((`gc`.`quotePartyId` = `qp`.`quotePartyId`))) where (`pt`.`name` = 'PAYEE') */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; + +-- +-- Final view structure for view `quoteView` +-- + +/*!50001 DROP VIEW IF EXISTS `quoteView`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`central_ledger`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `quoteView` AS select `q`.`quoteId` AS `quoteId`,`q`.`transactionReferenceId` AS `transactionReferenceId`,`q`.`transactionRequestId` AS `transactionRequestId`,`q`.`note` AS `note`,`q`.`expirationDate` AS `expirationDate`,`ti`.`name` AS `transactionInitiator`,`tit`.`name` AS `transactionInitiatorType`,`ts`.`name` AS `transactionScenario`,`q`.`balanceOfPaymentsId` AS `balanceOfPaymentsId`,`tss`.`name` AS `transactionSubScenario`,`amt`.`name` AS `amountType`,`q`.`amount` AS `amount`,`q`.`currencyId` AS `currency` from (((((`quote` `q` join `transactionInitiator` `ti` on((`ti`.`transactionInitiatorId` = `q`.`transactionInitiatorId`))) join `transactionInitiatorType` `tit` on((`tit`.`transactionInitiatorTypeId` = `q`.`transactionInitiatorTypeId`))) join `transactionScenario` `ts` on((`ts`.`transactionScenarioId` = `q`.`transactionScenarioId`))) join `amountType` `amt` on((`amt`.`amountTypeId` = `q`.`amountTypeId`))) left join `transactionSubScenario` `tss` on((`tss`.`transactionSubScenarioId` = `q`.`transactionSubScenarioId`))) */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2020-02-20 22:51:43 diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-schema-DBeaver.erd b/legacy/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-schema-DBeaver.erd new file mode 100644 index 000000000..303fa1534 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-schema-DBeaver.erd @@ -0,0 +1,612 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-schema.png b/legacy/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-schema.png new file mode 100644 index 000000000..62b4a1a1e Binary files /dev/null and b/legacy/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-schema.png differ diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg new file mode 100644 index 000000000..d91178975 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg @@ -0,0 +1,3 @@ + + +
    Mojaloop Adapter
    Mojaloop Adapter
    Ledger
    Ledger
    Mojaloop
    Adapter
    [Not supported by viewer]
    C 1. Transfer
    C 1. Transfer
    request_to_prepare
    request_to_prepare
    C 1.2
    [Not supported by viewer]
    C 1.3
    [Not supported by viewer]
    prepared.notification
    prepared.notification
    C 1.4
    C 1.4
    fulfiled.notification
    fulfiled.notification
    request_to_fulfil
    request_to_fulfil
    Fulfil Transfer
    Fulfil Transfer
    C 1.8
    C 1.8
    C 1.9
    [Not supported by viewer]
    C 1.10
    [Not supported by viewer]
    C 1.11
    C 1.11
    C 1.12 Fulfil Notify
    C 1.12 Fulfil Notify
    C 1.1
    C 1.1
    C 1.5
    C 1.5
    DB
    DB
    Central Services
    [Not supported by viewer]
    positions
    positions
    Account-Lookup-Service
    [Not supported by viewer]
    Pathfinder
    Pathfinder
    FSP
    Backend

    (Does not natively speak Mojaloop API)



    [Not supported by viewer]
    Scheme-Adapter

    (Converts from Mojaloop API to backend FSP API)
    [Not supported by viewer]
    A 2. MSISDN
    based lookup
    A 2. MSISDN <br>based lookup
    DB
    DB
     Database
     Database
    FSP
    Backend
      

    (Natively speaks Mojaloop API)



    [Not supported by viewer]
    A
    A
    A 1. User Lookup
    A 1. User Lookup
    A 3. Receiver Details
    A 3. Receiver Details
    B
    B
    B 1. Quote
    B 1. Quote
    Mojaloop Hub
    [Not supported by viewer]
    Payer FSP
    [Not supported by viewer]
    Payee FSP
    [Not supported by viewer]
    Ledger
    Ledger<br>
    Ledger
    Ledger<br>
    C
    C
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    C 1.6
    Prepare
    Transfer
    [Not supported by viewer]
    C 1.7
    C 1.7
    C 1.11
    C 1.11
    C 1.12
    C 1.12
    Fulfil Notify
    Fulfil Notify
    C 1.13
    Fulfil Notify
    [Not supported by viewer]
    B 2. Fee /
    Commission
    [Not supported by viewer]
    A 4. Get 
    receiver 
    details
    [Not supported by viewer]
    B 1. Quote
    B 1. Quote
    D 6.
    D 6.
    Settlements
    Settlements
    D 5. Update Positions
    [Not supported by viewer]
    settlement.notifications
    settlement.notifications
    Scheme Settlement Processor
    <span>Scheme Settlement Processor</span><br>
    Hub Operator
    Hub Operator
    D 1. Create
    Settlement
    [Not supported by viewer]
    D
    D
    D 2. Query
    Settlement
    Report
    (Pull)
    [Not supported by viewer]
    D 4. Send
    Acks
    (Push)
    [Not supported by viewer]
    Settlement
    Bank
    Settlement<br>Bank<br>
    D 3. Process Settlements
    [Not supported by viewer]
    Bank
    [Not supported by viewer]
    D 7. Position Notifications Change result
    D 7. Position Notifications Change result
    D 7. Settlement Notification
    D 7. Settlement Notification
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0-old.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0-old.svg new file mode 100644 index 000000000..73c49765f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0-old.svg @@ -0,0 +1,3 @@ + + +
    1.5 Increment Position (fsp1)
    [Not supported by viewer]
    1.4 Increment
    Position (fsp1)

    [Not supported by viewer]
    PrepareHandler
    PrepareHandler
    PositionHandler
    PositionHandler
    Fulfil
    Sucess
    [Not supported by viewer]
    2.4 Fulfil
    Success
    [Not supported by viewer]
    <alt> 2.4 
    Fulfil Reject

    [Not supported by viewer]
    Fulfil
    Reject
    [Not supported by viewer]
    <alt> 2.5 Decrement
    Position (fsp1)

    [Not supported by viewer]
    <alt>1.6 Reject Notification
    (Not enough position)

    [Not supported by viewer]
    Central - Services
    <font style="font-size: 18px">Central - Services</font>
    3.0 Reject
    [Not supported by viewer]
    2.6 Fulfil Notification /
     <alt> 2.6 Reject Notification (Fulfil) /
    3.2 Reject Notification (Timeout)

    [Not supported by viewer]
    1.0 Transfer 
    Request

    [Not supported by viewer]
    3.1 Decrement
    Position (fsp1)

    [Not supported by viewer]
    1.6 Prepare Notification
    [Not supported by viewer]
    ML-Adapter
    [Not supported by viewer]
    Transfer
    API
    [Not supported by viewer]
    Notification
    Event Handler
    [Not supported by viewer]
    fsp prepare
    fsp prepare
    1.3 Prepare Consume
    [Not supported by viewer]
    notifications
    notifications
    FSP1
    (Payer)

    [Not supported by viewer]
    FSP2
    (Payee)
    [Not supported by viewer]
    1.1
    Prepare Request
    [Not supported by viewer]
    1.2 Accpeted
    (202)
    [Not supported by viewer]
    Transfer
    API
    [Not supported by viewer]
    2.0 Fulfil 
    Success / 
    Reject

    [Not supported by viewer]
    fulfils
    fulfils
    FulfilHandler
    FulfilHandler
    Success/
    Reject
    [Not supported by viewer]
    2.5 Decrement
    Position (fsp2)

    [Not supported by viewer]
    2.1 Fulfil 
    Success / Reject

    [Not supported by viewer]
    2.2 OK
    (200)
    [Not supported by viewer]
    2.3 Fulfil
    Success /
    Reject
    Consume
    [Not supported by viewer]
    OK (200)
    [Not supported by viewer]
    OK (200)
    [Not supported by viewer]
    Transfer Timeout
    Handler
    [Not supported by viewer]
    <alt> 1.4 Prepare Failure
    [Not supported by viewer]
    <alt> 2.4 Fulfil Failure
    [Not supported by viewer]
    2.7 Fulfil Notify Callback /
    <alt> 2.7 Reject Response (Fulfil reject) /
    3.1, 3.3 Reject Response (Timeout) /
    <alt> 1.7 Reject Response (Not enough position)
    <alt> 1.5 Prepare Failure 

    [Not supported by viewer]
    1.7 Prepare Notify /
    2.8 Fulfil Notify /
    <alt> 2.7 Reject Response (Fulfil reject)
    3.3 Reject Response (Timeout)
    <alt> 2.5 Fulfil Failure

    [Not supported by viewer]
    position
    position<br>
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0.svg new file mode 100644 index 000000000..02658b83d --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0.svg @@ -0,0 +1,3 @@ + + +
    1.5 Increment Position (fsp1)
    1.5 Increment Position (fsp1)
    1.4 Increment
    Position (fsp1)

    1.4 Increment...
    PrepareHandler
    PrepareHandler
    PositionHandler
    PositionHandler
    Fulfil
    Sucess
    Fulfil...
    2.4 Fulfil
    Success
    2.4 Fulfil...
    <alt> 2.4 
    Fulfil Reject

    <alt> 2.4...
    Fulfil
    Reject
    Fulfil...
    <alt> 2.5 Decrement
    Position (fsp1)

    <alt> 2.5 Decrement...
    <alt>1.6 Reject Notification
    (Not enough position)

    <alt>1.6...
    Central - Services
    Central - Services
    3.0 Reject
    3.0 Reject
    2.6 Fulfil Notification /
     <alt> 2.6 Reject Notification (Fulfil) /
    3.2 Reject Notification (Timeout)

    2.6 Fulfil Notification /...
    1.0 Transfer 
    Request

    1.0 Transfer...
    3.1 Decrement
    Position (fsp1)

    3.1 Decrement...
    1.6 Prepare Notification
    1.6 Prepare Notification
    ML-Adapter
    ML-Adapter
    Transfer
    API
    Transfer...
    Notification
    Event Handler
    Notification...
    fsp prepare
    fsp prep...
    1.3 Prepare Consume
    1.3 Prepare Consume
    notifications
    notificati...
    FSP1
    (Payer)

    FSP1...
    FSP2
    (Payee)
    FSP2...
    1.1
    Prepare Request
    1.1...
    1.2 Accpeted
    (202)
    1.2 Accpeted...
    Transfer
    API
    Transfer...
    2.0 Fulfil 
    Success / 
    Reject

    2...
    fulfils
    fulfils
    FulfilHandler
    FulfilHandler
    Success/
    Reject
    Success/...
    2.5 Decrement
    Position (fsp2)

    2.5 Decrement...
    2.1 Fulfil 
    Success / Reject

    2.1 Fulfil...
    2.2 OK
    (200)
    2.2 OK...
    2.3 Fulfil
    Success /
    Reject
    Consume
    2.3 Fulfil...
    OK (200)
    OK (200)
    OK (200)
    OK (200)
    Transfer Timeout
    Handler
    Transfer Timeout...
    <alt> 1.4 Prepare Failure
    <alt> 1.4 Prepare Failure
    <alt> 2.4 Fulfil Failure
    <alt>...
    2.7 Fulfil Notify Callback /
    <alt> 2.7 Reject Response (Fulfil reject) /
    3.1, 3.3 Reject Response (Timeout) /
    <alt> 1.7 Reject Response (Not enough position)
    <alt> 1.5 Prepare Failure 

    2.7 Fulfil Notify Callback /...
    1.7 Prepare Notify /
    2.8 Commit Notify (optional) /
    <alt> 2.7 Reject Response (Fulfil reject)
    3.3 Reject Response (Timeout)
    <alt> 2.5 Fulfil Failure

    1.7 Prepare Notify /...
    position
    position
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.1.svg new file mode 100644 index 000000000..e9a1460c8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.1.svg @@ -0,0 +1,3 @@ + + +
    1.5 Increment Position (fsp1)
    1.5 Increment Position (fsp1)
    1.4 Increment
    Position (fsp1)

    1.4 Increment...
    PrepareHandler
    PrepareHandler
    PositionHandler
    PositionHandler
    Fulfil
    Sucess
    Fulfil...
    2.4 Fulfil
    Success
    2.4 Fulfil...
    <alt> 2.4 
    Fulfil Reject

    <alt> 2.4...
    Fulfil
    Reject
    Fulfil...
    <alt> 2.5 Decrement
    Position (fsp1)

    <alt> 2.5 Decrement...
    <alt>1.6 Reject Notification
    (Not enough position)

    <alt>1.6...
    Central - Services
    Central - Services
    3.0 Reject
    3.0 Reject
    2.6 Fulfil Notification /
     <alt> 2.6 Reject Notification (Fulfil) /
    3.2 Reject Notification (Timeout)

    2.6 Fulfil Notification /...
    1.0 Transfer 
    Request

    1.0 Transfer...
    3.1 Decrement
    Position (fsp1)

    3.1 Decrement...
    1.6 Prepare Notification
    1.6 Prepare Notification
    ML-Adapter
    ML-Adapter
    Transfer
    API
    Transfer...
    Notification
    Event Handler
    Notification...
    fsp prepare
    fsp prep...
    1.3 Prepare Consume
    1.3 Prepare Consume
    notifications
    notificati...
    FSP1
    (Payer)

    FSP1...
    FSP2
    (Payee)
    FSP2...
    1.1
    Prepare Request
    1.1...
    1.2 Accpeted
    (202)
    1.2 Accpeted...
    Transfer
    API
    Transfer...
    2.0 Fulfil 
    Success / 
    Reject

    2...
    fulfils
    fulfils
    FulfilHandler
    FulfilHandler
    Success/
    Reject
    Success/...
    2.5 Decrement
    Position (fsp2)

    2.5 Decrement...
    2.1 Fulfil 
    Success / Reject

    2.1 Fulfil...
    2.2 OK
    (200)
    2.2 OK...
    2.3 Fulfil
    Success /
    Reject
    Consume
    2.3 Fulfil...
    OK (200)
    OK (200)
    OK (200)
    OK (200)
    Transfer Timeout
    Handler
    Transfer Timeout...
    <alt> 1.4 Prepare Failure
    <alt> 1.4 Prepare Failure
    <alt> 2.4 Fulfil Failure
    <alt>...
    2.7 Fulfil Notify Callback /
    <alt> 2.7 Reject Response (Fulfil reject) /
    3.1, 3.3 Reject Response (Timeout) /
    <alt> 1.7 Reject Response (Not enough position)
    <alt> 1.5 Prepare Failure 

    2.7 Fulfil Notify Callback /...
    1.7 Prepare Notify /
    2.8 Commit Notify (if transfer reserved) /
    <alt> 2.7 Reject Response (Fulfil reject)
    3.3 Reject Response (Timeout)
    <alt> 2.5 Fulfil Failure

    1.7 Prepare Notify /...
    position
    position
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.plantuml new file mode 100644 index 000000000..461a64c23 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.plantuml @@ -0,0 +1,160 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declate title +title 3.1.0 Get Participant Callback Details + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +entity "ML-API-ADAPTER" as MLAPI +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB +box "ML API Adapter Service" #LightBlue +participant MLAPI +end box + +box "Central Services" #LightYellow +participant CSAPI +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant DB +end box + +' start flow + +activate MLAPI +group Get Callback Details + MLAPI -> CSAPI: Request to get callback details - GET - /participants/{name}/endpoints?type={typeValue} + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Fetch Callback details for Participant + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant \nError code: 3200 + + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Participant + activate DB + hnote over DB #lightyellow + participant + end note + DB --> PARTICIPANT_DAO: Retrieved Participant + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Participant + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Validate DFSP + alt Validate participant (success) + PARTICIPANT_HANDLER -> PARTICIPANT_HANDLER: check if "type" parameter is sent + alt Check if "type" parameter is sent (Sent) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Callback details for Participant and type \nError code: 3000 + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Callback details for Participant and type + note right of PARTICIPANT_DAO #lightgrey + Condition: + isActive = 1 + [endpointTypeId = ] + end note + + activate DB + hnote over DB #lightyellow + participantEndpoint + end note + DB --> PARTICIPANT_DAO: Retrieved Callback details for Participant and type + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Callback details for Participant and type + deactivate PARTICIPANT_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + { + endpoints: {type: , value: } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Callback details for Participant + deactivate PARTICIPANT_HANDLER + CSAPI -->MLAPI: Return Callback details for Participant + else Check if "type" parameter is sent (Not Sent) + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Callback details for Participant \nError code: 3000 + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Callback details for Participant + note right of PARTICIPANT_DAO #lightgrey + Condition: + isActive = 1 + end note + + activate DB + hnote over DB #lightyellow + participantEndpoint + end note + DB --> PARTICIPANT_DAO: Retrieved Callback details for Participant + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Callback details for Participant + deactivate PARTICIPANT_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + { + endpoints: [ + {type: , value: }, + {type: , value: } + ] + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Callback details for Participant + ' deactivate PARTICIPANT_HANDLER + CSAPI -->MLAPI: Return Callback details for Participant + end + + + else Validate participant (failure)/ Error + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #red: Validation failure/ Error! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3000, 3200 + deactivate PARTICIPANT_HANDLER + CSAPI -->MLAPI: Return Error code: 3000, 3200 + + end + deactivate CSAPI + deactivate MLAPI +end + +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.svg new file mode 100644 index 000000000..c7acd7bd0 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.svg @@ -0,0 +1,409 @@ + + + + + + + + + + + 3.1.0 Get Participant Callback Details + + + + ML API Adapter Service + + + + Central Services + + + + + + + + + ML-API-ADAPTER + + + + + ML-API-ADAPTER + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Get Callback Details + + + + + 1 + + + Request to get callback details - GET - /participants/{name}/endpoints?type={typeValue} + + + + + 2 + + + Fetch Callback details for Participant + + + + + 3 + + + Fetch Participant + + + Error code: + + + 3200 + + + + + 4 + + + Fetch Participant + + + + participant + + + + + 5 + + + Retrieved Participant + + + + + 6 + + + Return Participant + + + + + 7 + + + Validate DFSP + + + + + alt + + + [Validate participant (success)] + + + + + 8 + + + check if "type" parameter is sent + + + + + alt + + + [Check if "type" parameter is sent (Sent)] + + + + + 9 + + + Fetch Callback details for Participant and type + + + Error code: + + + 3000 + + + + + 10 + + + Fetch Callback details for Participant and type + + + + + Condition: + + + isActive = 1 + + + [endpointTypeId = <type>] + + + + participantEndpoint + + + + + 11 + + + Retrieved Callback details for Participant and type + + + + + 12 + + + Return Callback details for Participant and type + + + + + Message: + + + { + + + endpoints: {type: <type>, value: <value>} + + + } + + + + + 13 + + + Return Callback details for Participant + + + + + 14 + + + Return Callback details for Participant + + + + [Check if "type" parameter is sent (Not Sent)] + + + + + 15 + + + Fetch Callback details for Participant + + + Error code: + + + 3000 + + + + + 16 + + + Fetch Callback details for Participant + + + + + Condition: + + + isActive = 1 + + + + participantEndpoint + + + + + 17 + + + Retrieved Callback details for Participant + + + + + 18 + + + Return Callback details for Participant + + + + + Message: + + + { + + + endpoints: [ + + + {type: <type>, value: <value>}, + + + {type: <type>, value: <value>} + + + ] + + + } + + + + + 19 + + + Return Callback details for Participant + + + + + 20 + + + Return Callback details for Participant + + + + [Validate participant (failure)/ Error] + + + + + Validation failure/ Error! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <errorCode>, + + + "errorDescription": <ErrorMessage>, + + + } + + + } + + + + + 21 + + + Return + + + Error code: + + + 3000, 3200 + + + + + 22 + + + Return + + + Error code: + + + 3000, 3200 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.plantuml new file mode 100644 index 000000000..dd4849343 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.plantuml @@ -0,0 +1,149 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + -------------- + ******'/ + + +@startuml +' declate title +title 3.1.0 Add Participant Callback Details + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Services" #LightYellow +participant CSAPI +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant DB +end box + +' start flow + +activate OPERATOR +group Add Callback Details + OPERATOR -> CSAPI: Request to add callback details - POST - /paticipants/{name}/endpoints + note right of OPERATOR #yellow + Message: + { + payload: { + endpoint: { + type: , + value: + } + } + } + end note + + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Add Callback details for Participant + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant \nError code: 3200 + + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch Participant + activate DB + hnote over DB #lightyellow + participant + end note + DB --> PARTICIPANT_DAO: Retrieved Participant + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return Participant + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Validate DFSP + alt Validate participant (success) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Add Callback details for Participant \nError code: 2003/Msg: Service unavailable \nError code: 2001/Msg: Internal Server Error + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Persist Participant Endpoint + activate DB + hnote over DB #lightyellow + participantEndpoint + end note + deactivate DB + note right of PARTICIPANT_DAO #lightgrey + If (endpoint exists && isActive = 1) + oldEndpoint.isActive = 0 + insert endpoint + Else + insert endpoint + End + + end note + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return status + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER -> PARTICIPANT_HANDLER: Validate status + alt Validate status (success) + PARTICIPANT_HANDLER -->CSAPI: Return Status Code 201 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Status Code 201 + else Validate status (failure) / Error + note right of PARTICIPANT_HANDLER #red: Error! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code + ' deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code + + end + + else Validate participant (failure) + note right of PARTICIPANT_HANDLER #red: Validation failure! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "FSP id Not Found", + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3200 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3200 + + end + deactivate CSAPI + deactivate OPERATOR +end +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.svg new file mode 100644 index 000000000..975978ddb --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.svg @@ -0,0 +1,400 @@ + + + + + + + + + + + 3.1.0 Add Participant Callback Details + + + + Central Services + + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Add Callback Details + + + + + 1 + + + Request to add callback details - POST - /paticipants/{name}/endpoints + + + + + Message: + + + { + + + payload: { + + + endpoint: { + + + type: <typeValue>, + + + value: <endpointValue> + + + } + + + } + + + } + + + + + 2 + + + Add Callback details for Participant + + + + + 3 + + + Fetch Participant + + + Error code: + + + 3200 + + + + + 4 + + + Fetch Participant + + + + participant + + + + + 5 + + + Retrieved Participant + + + + + 6 + + + Return Participant + + + + + 7 + + + Validate DFSP + + + + + alt + + + [Validate participant (success)] + + + + + 8 + + + Add Callback details for Participant + + + Error code: + + + 2003/ + + + Msg: + + + Service unavailable + + + Error code: + + + 2001/ + + + Msg: + + + Internal Server Error + + + + + 9 + + + Persist Participant Endpoint + + + + participantEndpoint + + + + + If (endpoint exists && isActive = 1) + + + oldEndpoint.isActive = 0 + + + insert endpoint + + + Else + + + insert endpoint + + + End + + + + + 10 + + + Return status + + + + + 11 + + + Validate status + + + + + alt + + + [Validate status (success)] + + + + + 12 + + + Return Status Code 201 + + + + + 13 + + + Return Status Code 201 + + + + [Validate status (failure) / Error] + + + + + Error! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 14 + + + Return + + + Error code + + + + + 15 + + + Return + + + Error code + + + + [Validate participant (failure)] + + + + + Validation failure! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": 3200, + + + "errorDescription": "FSP id Not Found", + + + } + + + } + + + + + 16 + + + Return + + + Error code: + + + 3200 + + + + + 17 + + + Return + + + Error code: + + + 3200 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.plantuml new file mode 100644 index 000000000..c24ae484b --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.plantuml @@ -0,0 +1,207 @@ +/' + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Valentin Genev + -------------- + '/ + + +@startuml +' declate title +title 2.1.0. DFSP2 sends a Fulfil Success Transfer request v1.1 + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "topic-fulfil" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +control "Settlement Model\nHandler" as SETMODEL_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_SETMODEL + participant SETMODEL_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate SETMODEL_HANDLER +activate POS_HANDLER +group DFSP2 sends a request for notification after tranfer is being committed in the Switch + DFSP2 <-> DFSP2: Retrieve fulfilment string generated during\nthe quoting process or regenerate it using\n**Local secret** and **ILP Packet** as inputs + alt Send back notification reserve request + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "fulfilment": , + "transferState": "RESERVED" + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + end note + else Send back commit request + + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "fulfilment": , + "completedTimestamp": , + "transferState": "COMMITTED" + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + end note + end + DFSP2 ->> MLAPI: PUT - /transfers/ + activate MLAPI + MLAPI -> MLAPI: Validate incoming token and originator matching Payee\nError codes: 3000-3002, 3100-3107 + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: reserve || commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Fulfil event for Payee\nError code: 2003 + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Success) {[[https://github.com/mojaloop/documentation/tree/master/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg 2.1.1-v1.1]]} \n + FULF_HANDLER -> TOPIC_SETMODEL: Produce message + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_SETMODEL <- SETMODEL_HANDLER: Consume message + ref over TOPIC_SETMODEL, SETMODEL_HANDLER: Settlement Model Handler Consume (Success)\n + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Success)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'commit' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'reserve' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +deactivate POS_HANDLER +deactivate FULF_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.svg new file mode 100644 index 000000000..1a04bdb4a --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.svg @@ -0,0 +1,665 @@ + + + + + + + + + + + 2.1.0. DFSP2 sends a Fulfil Success Transfer request v1.1 + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + topic-fulfil + + + + + topic-fulfil + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic- + + + settlement-model + + + + + topic- + + + settlement-model + + + Settlement Model + + + Handler + + + + + Settlement Model + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + Position Handler + + + + + Position Handler + + + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + + DFSP2 sends a request for notification after tranfer is being committed in the Switch + + + + + 1 + + + Retrieve fulfilment string generated during + + + the quoting process or regenerate it using + + + Local secret + + + and + + + ILP Packet + + + as inputs + + + + + alt + + + [Send back notification reserve request] + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - transferMessage: + + + { + + + "fulfilment": <IlpFulfilment>, + + + "transferState": "RESERVED" + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + + [Send back commit request] + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - transferMessage: + + + { + + + "fulfilment": <IlpFulfilment>, + + + "completedTimestamp": <DateTime>, + + + "transferState": "COMMITTED" + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + + 2 + + + PUT - /transfers/<ID> + + + + + 3 + + + Validate incoming token and originator matching Payee + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: reserve || commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 4 + + + Route & Publish Fulfil event for Payee + + + Error code: + + + 2003 + + + + + 5 + + + Ensure event is replicated as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 6 + + + Respond replication acknowledgements have been received + + + + + 7 + + + Respond HTTP - 200 (OK) + + + + + 8 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (Success) { + + + + 2.1.1-v1.1 + + + + } + + + + + 9 + + + Produce message + + + + + 10 + + + Produce message + + + + + 11 + + + Consume message + + + + + ref + + + Settlement Model Handler Consume (Success) + + + + + 12 + + + Consume message + + + + + ref + + + Position Handler Consume (Success) + + + + + 13 + + + Produce message + + + + + 14 + + + Consume message + + + + + opt + + + [action == 'commit'] + + + + + ref + + + Send notification to Participant (Payer) + + + + + 15 + + + Send callback notification + + + + + 16 + + + Consume message + + + + + opt + + + [action == 'reserve'] + + + + + ref + + + Send notification to Participant (Payee) + + + + + 17 + + + Send callback notification + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.plantuml new file mode 100644 index 000000000..08c71eb9f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.plantuml @@ -0,0 +1,174 @@ +/' + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + -------------- + '/ + + +@startuml +' declate title +title 2.1.0. DFSP2 sends a Fulfil Success Transfer request + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "topic-fulfil" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +control "Settlement Model\nHandler" as SETMODEL_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_SETMODEL + participant SETMODEL_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate SETMODEL_HANDLER +activate POS_HANDLER +group DFSP2 sends a Fulfil Success Transfer request + DFSP2 <-> DFSP2: Retrieve fulfilment string generated during\nthe quoting process or regenerate it using\n**Local secret** and **ILP Packet** as inputs + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "fulfilment": , + "completedTimestamp": , + "transferState": "COMMITTED", + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + end note + DFSP2 ->> MLAPI: PUT - /transfers/ + activate MLAPI + MLAPI -> MLAPI: Validate incoming token and originator matching Payee\nError codes: 3000-3002, 3100-3107 + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Fulfil event for Payee\nError code: 2003 + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Success) {[[https://github.com/mojaloop/documentation/tree/master/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.svg 2.1.1]]} \n + FULF_HANDLER -> TOPIC_SETMODEL: Produce message + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_SETMODEL <- SETMODEL_HANDLER: Consume message + ref over TOPIC_SETMODEL, SETMODEL_HANDLER: Settlement Model Handler Consume (Success)\n + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Success)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'commit' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'commit' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +deactivate POS_HANDLER +deactivate FULF_HANDLER +deactivate NOTIFY_HANDLER +@enduml \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.svg new file mode 100644 index 000000000..052c40891 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.svg @@ -0,0 +1,574 @@ + + + + + + + + + + + 2.1.0. DFSP2 sends a Fulfil Success Transfer request + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + topic-fulfil + + + + + topic-fulfil + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic- + + + settlement-model + + + + + topic- + + + settlement-model + + + Settlement Model + + + Handler + + + + + Settlement Model + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + Position Handler + + + + + Position Handler + + + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + + DFSP2 sends a Fulfil Success Transfer request + + + + + 1 + + + Retrieve fulfilment string generated during + + + the quoting process or regenerate it using + + + Local secret + + + and + + + ILP Packet + + + as inputs + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - transferMessage: + + + { + + + "fulfilment": <IlpFulfilment>, + + + "completedTimestamp": <DateTime>, + + + "transferState": "COMMITTED", + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + + 2 + + + PUT - /transfers/<ID> + + + + + 3 + + + Validate incoming token and originator matching Payee + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 4 + + + Route & Publish Fulfil event for Payee + + + Error code: + + + 2003 + + + + + 5 + + + Ensure event is replicated as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 6 + + + Respond replication acknowledgements have been received + + + + + 7 + + + Respond HTTP - 200 (OK) + + + + + 8 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (Success) { + + + + 2.1.1 + + + + } + + + + + 9 + + + Produce message + + + + + 10 + + + Produce message + + + + + 11 + + + Consume message + + + + + ref + + + Settlement Model Handler Consume (Success) + + + + + 12 + + + Consume message + + + + + ref + + + Position Handler Consume (Success) + + + + + 13 + + + Produce message + + + + + 14 + + + Consume message + + + + + opt + + + [action == 'commit'] + + + + + ref + + + Send notification to Participant (Payer) + + + + + 15 + + + Send callback notification + + + + + 16 + + + Consume message + + + + + opt + + + [action == 'commit'] + + + + + ref + + + Send notification to Participant (Payee) + + + + + 17 + + + Send callback notification + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.plantuml new file mode 100644 index 000000000..9f2523d6d --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.plantuml @@ -0,0 +1,273 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title 2.1.1. Fulfil Handler Consume (Success) v1.1 +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "topic-fulfil" as TOPIC_FULFIL +control "Fulfil Event\nHandler" as FULF_HANDLER +collections "topic-event" as TOPIC_EVENT +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +entity "Position DAO" as POS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_SETMODEL + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Success) + alt Consume Single Message + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type == 'fulfil' && action IN ['commit', 'reserve']\nError codes: 2001 + end + end + group Persist Event Information + ||| + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume\n + ||| + end + + group Validate Duplicate Check + ||| + FULF_HANDLER -> DB: Request Duplicate Check + ref over FULF_HANDLER, DB: Request Duplicate Check\n + DB --> FULF_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break + FULF_HANDLER -> FULF_HANDLER: stateRecord = await getTransferState(transferId) + alt endStateList.includes(stateRecord.transferStateId) + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: getTransfer callback\n + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else + note right of FULF_HANDLER #lightgrey + Ignore - resend in progress + end note + end + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of FULF_HANDLER #lightgrey + Validate Prepare Transfer (failure) - Modified Request + end note + else hasDuplicateId == FALSE + group Validate and persist Transfer Fulfilment + FULF_HANDLER -> POS_DAO: Request information for the validate checks\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch from database + activate DB + hnote over DB #lightyellow + transfer + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return transfer + deactivate POS_DAO + FULF_HANDLER ->FULF_HANDLER: Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment)\nError code: 2001 + FULF_HANDLER -> FULF_HANDLER: Validate expirationDate\nError code: 3303 + + opt Transfer.ilpCondition validate successful + group Request current Settlement Window + FULF_HANDLER -> POS_DAO: Request to retrieve current/latest transfer settlement window\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch settlementWindowId + activate DB + hnote over DB #lightyellow + settlementWindow + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return settlementWindowId to be appended during transferFulfilment insert\n**TODO**: During settlement design make sure transfers in 'RECEIVED-FULFIL'\nstate are updated to the next settlement window + deactivate POS_DAO + end + end + + group Persist fulfilment + FULF_HANDLER -> POS_DAO: Persist fulfilment with the result of the above check (transferFulfilment.isValid)\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferFulfilment + transferExtension + end note + FULF_HANDLER <-- POS_DAO: Return success + deactivate POS_DAO + end + + alt Transfer.ilpCondition validate successful + group Persist Transfer State (with transferState='RECEIVED-FULFIL') + FULF_HANDLER -> POS_DAO: Request to persist transfer state\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + POS_DAO --> FULF_HANDLER: Return success + deactivate POS_DAO + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: switch, + to: switch, + type: application/json + content: { + payload: { + transferId: {id} + } + }, + metadata: { + event: { + id: , + responseTo: , + type: setmodel, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_SETMODEL: Route & Publish settlement model event + activate TOPIC_SETMODEL + deactivate TOPIC_SETMODEL + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: commit || reserve, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Fulfil Transfer not successful + group Persist Transfer State (with transferState='ABORTED') + FULF_HANDLER -> POS_DAO: Request to persist transfer state\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + POS_DAO --> FULF_HANDLER: Return success + deactivate POS_DAO + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end + end + end + else Consume Batch Messages + note left of FULF_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate FULF_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg new file mode 100644 index 000000000..9d931dc0c --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg @@ -0,0 +1,821 @@ + + + + + + + + + + + 2.1.1. Fulfil Handler Consume (Success) v1.1 + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + topic-fulfil + + + + + topic-fulfil + + + Fulfil Event + + + Handler + + + + + Fulfil Event + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic-event + + + + + topic-event + + + + + topic- + + + settlement-model + + + + + topic- + + + settlement-model + + + + + topic- + + + notification + + + + + topic- + + + notification + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Handler Consume (Success) + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume Fulfil event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'fulfil' && action IN ['commit', 'reserve'] + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate Duplicate Check + + + + + 4 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check + + + + + 5 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + break + + + + + 6 + + + stateRecord = await getTransferState(transferId) + + + + + alt + + + [endStateList.includes(stateRecord.transferStateId)] + + + + + ref + + + getTransfer callback + + + + + 7 + + + Produce message + + + + + + Ignore - resend in progress + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + Validate Prepare Transfer (failure) - Modified Request + + + + [hasDuplicateId == FALSE] + + + + + Validate and persist Transfer Fulfilment + + + + + 8 + + + Request information for the validate checks + + + Error code: + + + 2003 + + + + + 9 + + + Fetch from database + + + + transfer + + + + + 10 + + + + + 11 + + + Return transfer + + + + + 12 + + + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + + + Error code: + + + 2001 + + + + + 13 + + + Validate expirationDate + + + Error code: + + + 3303 + + + + + opt + + + [Transfer.ilpCondition validate successful] + + + + + Request current Settlement Window + + + + + 14 + + + Request to retrieve current/latest transfer settlement window + + + Error code: + + + 2003 + + + + + 15 + + + Fetch settlementWindowId + + + + settlementWindow + + + + + 16 + + + + + 17 + + + Return settlementWindowId to be appended during transferFulfilment insert + + + TODO + + + : During settlement design make sure transfers in 'RECEIVED-FULFIL' + + + state are updated to the next settlement window + + + + + Persist fulfilment + + + + + 18 + + + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + + + Error code: + + + 2003 + + + + + 19 + + + Persist to database + + + + transferFulfilment + + + transferExtension + + + + + 20 + + + Return success + + + + + alt + + + [Transfer.ilpCondition validate successful] + + + + + Persist Transfer State (with transferState='RECEIVED-FULFIL') + + + + + 21 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 22 + + + Persist transfer state + + + + transferStateChange + + + + + 23 + + + Return success + + + + + Message: + + + { + + + id: <id>, + + + from: switch, + + + to: switch, + + + type: application/json + + + content: { + + + payload: { + + + transferId: {id} + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: setmodel, + + + action: commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 24 + + + Route & Publish settlement model event + + + + + Message: + + + { + + + id: <id>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: commit || reserve, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 25 + + + Route & Publish Position event for Payee + + + + [Validate Fulfil Transfer not successful] + + + + + Persist Transfer State (with transferState='ABORTED') + + + + + 26 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 27 + + + Persist transfer state + + + + transferStateChange + + + + + 28 + + + Return success + + + + + Message: + + + { + + + id: <id>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 29 + + + Route & Publish Position event for Payer + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.plantuml new file mode 100644 index 000000000..42f281ef6 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.plantuml @@ -0,0 +1,272 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.1.1. Fulfil Handler Consume (Success) +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "topic-fulfil" as TOPIC_FULFIL +control "Fulfil Event\nHandler" as FULF_HANDLER +collections "topic-event" as TOPIC_EVENT +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +entity "Position DAO" as POS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_SETMODEL + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Success) + alt Consume Single Message + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type == 'fulfil' && action == 'commit'\nError codes: 2001 + end + end + group Persist Event Information + ||| + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume\n + ||| + end + + group Validate Duplicate Check + ||| + FULF_HANDLER -> DB: Request Duplicate Check + ref over FULF_HANDLER, DB: Request Duplicate Check\n + DB --> FULF_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break + FULF_HANDLER -> FULF_HANDLER: stateRecord = await getTransferState(transferId) + alt endStateList.includes(stateRecord.transferStateId) + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: getTransfer callback\n + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else + note right of FULF_HANDLER #lightgrey + Ignore - resend in progress + end note + end + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of FULF_HANDLER #lightgrey + Validate Prepare Transfer (failure) - Modified Request + end note + else hasDuplicateId == FALSE + group Validate and persist Transfer Fulfilment + FULF_HANDLER -> POS_DAO: Request information for the validate checks\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch from database + activate DB + hnote over DB #lightyellow + transfer + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return transfer + deactivate POS_DAO + FULF_HANDLER ->FULF_HANDLER: Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment)\nError code: 2001 + FULF_HANDLER -> FULF_HANDLER: Validate expirationDate\nError code: 3303 + + opt Transfer.ilpCondition validate successful + group Request current Settlement Window + FULF_HANDLER -> POS_DAO: Request to retrieve current/latest transfer settlement window\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch settlementWindowId + activate DB + hnote over DB #lightyellow + settlementWindow + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return settlementWindowId to be appended during transferFulfilment insert\n**TODO**: During settlement design make sure transfers in 'RECEIVED-FULFIL'\nstate are updated to the next settlement window + deactivate POS_DAO + end + end + + group Persist fulfilment + FULF_HANDLER -> POS_DAO: Persist fulfilment with the result of the above check (transferFulfilment.isValid)\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferFulfilment + transferExtension + end note + FULF_HANDLER <-- POS_DAO: Return success + deactivate POS_DAO + end + + alt Transfer.ilpCondition validate successful + group Persist Transfer State (with transferState='RECEIVED-FULFIL') + FULF_HANDLER -> POS_DAO: Request to persist transfer state\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + POS_DAO --> FULF_HANDLER: Return success + deactivate POS_DAO + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: switch, + to: switch, + type: application/json + content: { + payload: { + transferId: {id} + } + }, + metadata: { + event: { + id: , + responseTo: , + type: setmodel, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_SETMODEL: Route & Publish settlement model event + activate TOPIC_SETMODEL + deactivate TOPIC_SETMODEL + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Fulfil Transfer not successful + group Persist Transfer State (with transferState='ABORTED') + FULF_HANDLER -> POS_DAO: Request to persist transfer state\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + POS_DAO --> FULF_HANDLER: Return success + deactivate POS_DAO + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end + end + end + else Consume Batch Messages + note left of FULF_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate FULF_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.svg new file mode 100644 index 000000000..de1888f4f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.svg @@ -0,0 +1,821 @@ + + + + + + + + + + + 2.1.1. Fulfil Handler Consume (Success) + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + topic-fulfil + + + + + topic-fulfil + + + Fulfil Event + + + Handler + + + + + Fulfil Event + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic-event + + + + + topic-event + + + + + topic- + + + settlement-model + + + + + topic- + + + settlement-model + + + + + topic- + + + notification + + + + + topic- + + + notification + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Handler Consume (Success) + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume Fulfil event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'fulfil' && action == 'commit' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate Duplicate Check + + + + + 4 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check + + + + + 5 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + break + + + + + 6 + + + stateRecord = await getTransferState(transferId) + + + + + alt + + + [endStateList.includes(stateRecord.transferStateId)] + + + + + ref + + + getTransfer callback + + + + + 7 + + + Produce message + + + + + + Ignore - resend in progress + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + Validate Prepare Transfer (failure) - Modified Request + + + + [hasDuplicateId == FALSE] + + + + + Validate and persist Transfer Fulfilment + + + + + 8 + + + Request information for the validate checks + + + Error code: + + + 2003 + + + + + 9 + + + Fetch from database + + + + transfer + + + + + 10 + + + + + 11 + + + Return transfer + + + + + 12 + + + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + + + Error code: + + + 2001 + + + + + 13 + + + Validate expirationDate + + + Error code: + + + 3303 + + + + + opt + + + [Transfer.ilpCondition validate successful] + + + + + Request current Settlement Window + + + + + 14 + + + Request to retrieve current/latest transfer settlement window + + + Error code: + + + 2003 + + + + + 15 + + + Fetch settlementWindowId + + + + settlementWindow + + + + + 16 + + + + + 17 + + + Return settlementWindowId to be appended during transferFulfilment insert + + + TODO + + + : During settlement design make sure transfers in 'RECEIVED-FULFIL' + + + state are updated to the next settlement window + + + + + Persist fulfilment + + + + + 18 + + + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + + + Error code: + + + 2003 + + + + + 19 + + + Persist to database + + + + transferFulfilment + + + transferExtension + + + + + 20 + + + Return success + + + + + alt + + + [Transfer.ilpCondition validate successful] + + + + + Persist Transfer State (with transferState='RECEIVED-FULFIL') + + + + + 21 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 22 + + + Persist transfer state + + + + transferStateChange + + + + + 23 + + + Return success + + + + + Message: + + + { + + + id: <id>, + + + from: switch, + + + to: switch, + + + type: application/json + + + content: { + + + payload: { + + + transferId: {id} + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: setmodel, + + + action: commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 24 + + + Route & Publish settlement model event + + + + + Message: + + + { + + + id: <id>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 25 + + + Route & Publish Position event for Payee + + + + [Validate Fulfil Transfer not successful] + + + + + Persist Transfer State (with transferState='ABORTED') + + + + + 26 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 27 + + + Persist transfer state + + + + transferStateChange + + + + + 28 + + + Return success + + + + + Message: + + + { + + + id: <id>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 29 + + + Route & Publish Position event for Payer + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.plantuml new file mode 100644 index 000000000..d3d86084c --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.plantuml @@ -0,0 +1,111 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declate title +title 1.0.0 Get Participant Limit Details For All Participants + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant Facade" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Services" #LightYellow +participant CSAPI +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant DB +end box + +' start flow + +activate OPERATOR +group Get Limits for all Participants + OPERATOR -> CSAPI: Request to get Limits - GET - /participants/limits?type={typeValue}¤cy={currencyType} + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Fetch Limits for all Participants + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Limits for all participants with currency and type \nError code: 3000 + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Limits for currencyId and type(if passed) + note right of PARTICIPANT_DAO #lightgrey + Condition: + participantCurrency.participantCurrencyId = participant.participantCurrencyId + participantLimit.isActive = 1 + participantLimit.participantCurrencyId = participantCurrency.participantCurrencyId + [ + participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + participantLimit.participantCurrencyId = + participantLimitType.name = + ] + end note + + activate DB + hnote over DB #lightyellow + participant + participantCurrency + participantLimit + participantLimitType + end note + DB --> PARTICIPANT_DAO: Retrieved Participant Limits for currencyId and type + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Limits for all participants + deactivate PARTICIPANT_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + [ + { + name: + currency: , + limit: {type: , value: } + }, + { + name: + currency: , + limit: {type: , value: } + } + ] + end note + PARTICIPANT_HANDLER -->CSAPI: Return Limits for all participants \nError code: 3000 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Limits for all participants \nError code: 3000 + + deactivate CSAPI + deactivate OPERATOR +end + +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.svg new file mode 100644 index 000000000..3f24665cc --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.svg @@ -0,0 +1,241 @@ + + + + + + + + + + + 1.0.0 Get Participant Limit Details For All Participants + + + + Central Services + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant Facade + + + + + Participant Facade + + + + + Central Store + + + + + Central Store + + + + + + + + Get Limits for all Participants + + + + + 1 + + + Request to get Limits - GET - /participants/limits?type={typeValue}&currency={currencyType} + + + + + 2 + + + Fetch Limits for all Participants + + + + + 3 + + + Fetch Limits for all participants with currency and type + + + Error code: + + + 3000 + + + + + 4 + + + Fetch Limits for currencyId and type(if passed) + + + + + Condition: + + + participantCurrency.participantCurrencyId = participant.participantCurrencyId + + + participantLimit.isActive = 1 + + + participantLimit.participantCurrencyId = participantCurrency.participantCurrencyId + + + [ + + + participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + + + participantLimit.participantCurrencyId = <currencyId> + + + participantLimitType.name = <type> + + + ] + + + + participant + + + participantCurrency + + + participantLimit + + + participantLimitType + + + + + 5 + + + Retrieved Participant Limits for currencyId and type + + + + + 6 + + + Return Limits for all participants + + + + + Message: + + + [ + + + { + + + name: <fsp> + + + currency: <currencyId>, + + + limit: {type: <type>, value: <value>} + + + }, + + + { + + + name: <fsp> + + + currency: <currencyId>, + + + limit: {type: <type>, value: <value>} + + + } + + + ] + + + + + 7 + + + Return Limits for all participants + + + Error code: + + + 3000 + + + + + 8 + + + Return Limits for all participants + + + Error code: + + + 3000 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.plantuml new file mode 100644 index 000000000..b8a7ba51b --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.plantuml @@ -0,0 +1,203 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Lewis Daly + -------------- + ******'/ + + +@startuml +' declare title +title 1.0.0 Get Health Check + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Metadata Handler" as METADATA_HANDLER +entity "Central Service API" as CSAPI +database "Central Store" as DB +collections "Kafka Store" as KAFKA +collections "Logging Sidecar" as SIDECAR + +box "Central Services" #LightYellow +participant CSAPI +participant METADATA_HANDLER +participant DB +participant KAFKA +participant SIDECAR +end box + +' start flow + +activate OPERATOR +group Get Detailed Health Check + OPERATOR -> CSAPI: Request to getHealth - GET /health?detailed=true + activate CSAPI + + CSAPI -> METADATA_HANDLER: Fetch health status for all sub services + activate METADATA_HANDLER + + METADATA_HANDLER -> METADATA_HANDLER: Fetch Service Metadata + note right of METADATA_HANDLER #yellow + - versionNumber + - uptime + - time service started + end note + + + METADATA_HANDLER -> DB: Check connection status + activate DB + DB --> METADATA_HANDLER: Report connection status + deactivate DB + + + METADATA_HANDLER -> KAFKA: Check connection status + activate KAFKA + KAFKA --> METADATA_HANDLER: Report connection status + deactivate KAFKA + + + METADATA_HANDLER -> SIDECAR: Check connection status + activate SIDECAR + SIDECAR --> METADATA_HANDLER: Report connection status + deactivate SIDECAR + + alt Validate Status (success) + METADATA_HANDLER --> CSAPI: Return status response + deactivate METADATA_HANDLER + note right of OPERATOR #yellow + **Example Message:** + ""200 Success"" + { + "status": "UP", + "uptime": 1234, + "started": "2019-05-31T05:09:25.409Z", + "versionNumber": "5.2.3", + "services": [ + { + "name": "kafka", + "status": "UP", + "latency": 10 + } + ] + } + end note + + CSAPI --> OPERATOR: Return HTTP Status: 200 + + deactivate CSAPI + deactivate OPERATOR + end + + alt Validate Status (service failure) + METADATA_HANDLER --> CSAPI: Return status response + deactivate METADATA_HANDLER + note right of OPERATOR #yellow + **Example Message:** + ""502 Bad Gateway"" + { + "status": "DOWN", + "uptime": 1234, + "started": "2019-05-31T05:09:25.409Z", + "versionNumber": "5.2.3", + "services": [ + { + "name": "kafka", + "status": "DOWN", + "latency": 1111111 + } + ] + } + end note + + CSAPI --> OPERATOR: Return HTTP Status: 502 + + deactivate CSAPI + deactivate OPERATOR + + + end + + +' group Get Limits for all Participants +' OPERATOR -> CSAPI: Request to get Limits - GET - /participants/limits?type={typeValue}¤cy={currencyType} +' activate CSAPI +' CSAPI -> PARTICIPANT_HANDLER: Fetch Limits for all Participants +' activate PARTICIPANT_HANDLER +' PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Limits for all participants with currency and type \nError code: 3000 +' activate PARTICIPANT_DAO +' PARTICIPANT_DAO ->DB: Fetch Limits for currencyId and type(if passed) +' note right of PARTICIPANT_DAO #lightgrey +' Condition: +' participantCurrency.participantCurrencyId = participant.participantCurrencyId +' participantLimit.isActive = 1 +' participantLimit.participantCurrencyId = participantCurrency.participantCurrencyId +' [ +' participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId +' participantLimit.participantCurrencyId = +' participantLimitType.name = +' ] +' end note + +' activate DB +' hnote over DB #lightyellow +' participant +' participantCurrency +' participantLimit +' participantLimitType +' end note +' DB --> PARTICIPANT_DAO: Retrieved Participant Limits for currencyId and type +' deactivate DB +' PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Limits for all participants +' deactivate PARTICIPANT_DAO +' note right of PARTICIPANT_HANDLER #yellow +' Message: +' [ +' { +' name: +' currency: , +' limit: {type: , value: } +' }, +' { +' name: +' currency: , +' limit: {type: , value: } +' } +' ] +' end note +' PARTICIPANT_HANDLER -->CSAPI: Return Limits for all participants \nError code: 3000 +' deactivate PARTICIPANT_HANDLER +' CSAPI -->OPERATOR: Return Limits for all participants \nError code: 3000 + +' deactivate CSAPI +' deactivate OPERATOR +end + +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.svg new file mode 100644 index 000000000..aff440cd5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.svg @@ -0,0 +1,324 @@ + + + + + + + + + + + 1.0.0 Get Health Check + + + + Central Services + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Metadata Handler + + + + + Metadata Handler + + + + + Central Store + + + + + Central Store + + + + + + + Kafka Store + + + + + Kafka Store + + + + + Logging Sidecar + + + + + Logging Sidecar + + + + + + Get Detailed Health Check + + + + + 1 + + + Request to getHealth - GET /health?detailed=true + + + + + 2 + + + Fetch health status for all sub services + + + + + 3 + + + Fetch Service Metadata + + + + + - versionNumber + + + - uptime + + + - time service started + + + + + 4 + + + Check connection status + + + + + 5 + + + Report connection status + + + + + 6 + + + Check connection status + + + + + 7 + + + Report connection status + + + + + 8 + + + Check connection status + + + + + 9 + + + Report connection status + + + + + alt + + + [Validate Status (success)] + + + + + 10 + + + Return status response + + + + + Example Message: + + + 200 Success + + + { + + + "status": "UP", + + + "uptime": 1234, + + + "started": "2019-05-31T05:09:25.409Z", + + + "versionNumber": "5.2.3", + + + "services": [ + + + { + + + "name": "kafka", + + + "status": "UP", + + + "latency": 10 + + + } + + + ] + + + } + + + + + 11 + + + Return + + + HTTP Status: + + + 200 + + + + + alt + + + [Validate Status (service failure)] + + + + + 12 + + + Return status response + + + + + Example Message: + + + 502 Bad Gateway + + + { + + + "status": "DOWN", + + + "uptime": 1234, + + + "started": "2019-05-31T05:09:25.409Z", + + + "versionNumber": "5.2.3", + + + "services": [ + + + { + + + "name": "kafka", + + + "status": "DOWN", + + + "latency": 1111111 + + + } + + + ] + + + } + + + + + 13 + + + Return + + + HTTP Status: + + + 502 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.plantuml new file mode 100644 index 000000000..0c0fbfff9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.plantuml @@ -0,0 +1,206 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declate title +title 1.1.0 Request Participant Position and Limit Details + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant Facade" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Services" #LightYellow +participant CSAPI +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant DB +end box + +' start flow + +activate OPERATOR +group Get Callback Details + OPERATOR -> CSAPI: Request to get Limits - GET - /participants/{name}/limits?type={typeValue}¤cy={currencyValue} + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Fetch Limits for Participant + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER -> PARTICIPANT_HANDLER: check if "currency" parameter is sent + alt Check if "currency" parameter is sent (Sent) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant/currency id \nError code: 3200 + + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Participant/currency id + activate DB + hnote over DB #lightyellow + participant + participantCurrency + end note + DB --> PARTICIPANT_DAO: Retrieved Participant + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Participant/currency id + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Validate DFSP + alt Validate participant (success) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant Limits for currency and type \nError code: 3000 + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Participant Limit for currencyId and type(if passed) + note right of PARTICIPANT_DAO #lightgrey + Condition: + participantLimit.isActive = 1 + participantLimit.participantCurrencyId = + [ participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + participantLimitType.name = + ] + end note + + activate DB + hnote over DB #lightyellow + participantLimit + participantLimitType + end note + DB --> PARTICIPANT_DAO: Retrieved Participant Limits for currencyId and type + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Participant Limits for currencyId and type + deactivate PARTICIPANT_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + [ + { currency: , + limit: {type: , value: } + } + ] + end note + PARTICIPANT_HANDLER -->CSAPI: Return Participant Limits + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Participant Limits + + + else Validate participant (failure)/ Error + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #red: Validation failure/ Error! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3000, 3200 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3000, 3200 + end + + else Check if "currency" parameter is sent (Not Sent) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant \nError code: 3200 + + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Participant + activate DB + hnote over DB #lightyellow + participant + end note + DB --> PARTICIPANT_DAO: Retrieved Participant + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Participant + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Validate DFSP + alt Validate participant (success) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant Limits for all currencies and type \nError code: 3000 + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Participant Limit for all currencies and type(if passed) + note right of PARTICIPANT_DAO #lightgrey + Condition: + participantCurrency.participantId = + participantLimit.participantCurrencyId = participantCurrency.participantCurrencyId + participantLimit.isActive = 1 + [ participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + participantLimitType.name = + ] + end note + + activate DB + hnote over DB #lightyellow + participantCurrency + participantLimit + participantLimitType + end note + DB --> PARTICIPANT_DAO: Retrieved Participant Limits for all currencies and type + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Participant Limits for all currencies and type + deactivate PARTICIPANT_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + [ + { currency: , + limit: {type: , value: } + } + ] + end note + PARTICIPANT_HANDLER -->CSAPI: Return Participant Limits + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Participant Limits + + + else Validate participant (failure)/ Error + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #red: Validation failure/ Error! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3000, 3200 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3000, 3200 + end + end + + + deactivate CSAPI + deactivate OPERATOR +end + +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.svg new file mode 100644 index 000000000..e017a501e --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.svg @@ -0,0 +1,568 @@ + + + + + + + + + + + 1.1.0 Request Participant Position and Limit Details + + + + Central Services + + + + + + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant Facade + + + + + Participant Facade + + + + + Central Store + + + + + Central Store + + + + + + + + + + Get Callback Details + + + + + 1 + + + Request to get Limits - GET - /participants/{name}/limits?type={typeValue}&currency={currencyValue} + + + + + 2 + + + Fetch Limits for Participant + + + + + 3 + + + check if "currency" parameter is sent + + + + + alt + + + [Check if "currency" parameter is sent (Sent)] + + + + + 4 + + + Fetch Participant/currency id + + + Error code: + + + 3200 + + + + + 5 + + + Fetch Participant/currency id + + + + participant + + + participantCurrency + + + + + 6 + + + Retrieved Participant + + + + + 7 + + + Return Participant/currency id + + + + + 8 + + + Validate DFSP + + + + + alt + + + [Validate participant (success)] + + + + + 9 + + + Fetch Participant Limits for currency and type + + + Error code: + + + 3000 + + + + + 10 + + + Fetch Participant Limit for currencyId and type(if passed) + + + + + Condition: + + + participantLimit.isActive = 1 + + + participantLimit.participantCurrencyId = <currencyId> + + + [ participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + + + participantLimitType.name = <type> + + + ] + + + + participantLimit + + + participantLimitType + + + + + 11 + + + Retrieved Participant Limits for currencyId and type + + + + + 12 + + + Return Participant Limits for currencyId and type + + + + + Message: + + + [ + + + { currency: <currencyId>, + + + limit: {type: <type>, value: <value>} + + + } + + + ] + + + + + 13 + + + Return Participant Limits + + + + + 14 + + + Return Participant Limits + + + + [Validate participant (failure)/ Error] + + + + + Validation failure/ Error! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <errorCode>, + + + "errorDescription": <ErrorMessage>, + + + } + + + } + + + + + 15 + + + Return + + + Error code: + + + 3000, 3200 + + + + + 16 + + + Return + + + Error code: + + + 3000, 3200 + + + + [Check if "currency" parameter is sent (Not Sent)] + + + + + 17 + + + Fetch Participant + + + Error code: + + + 3200 + + + + + 18 + + + Fetch Participant + + + + participant + + + + + 19 + + + Retrieved Participant + + + + + 20 + + + Return Participant + + + + + 21 + + + Validate DFSP + + + + + alt + + + [Validate participant (success)] + + + + + 22 + + + Fetch Participant Limits for all currencies and type + + + Error code: + + + 3000 + + + + + 23 + + + Fetch Participant Limit for all currencies and type(if passed) + + + + + Condition: + + + participantCurrency.participantId = <participantId> + + + participantLimit.participantCurrencyId = participantCurrency.participantCurrencyId + + + participantLimit.isActive = 1 + + + [ participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + + + participantLimitType.name = <type> + + + ] + + + + participantCurrency + + + participantLimit + + + participantLimitType + + + + + 24 + + + Retrieved Participant Limits for all currencies and type + + + + + 25 + + + Return Participant Limits for all currencies and type + + + + + Message: + + + [ + + + { currency: <currencyId>, + + + limit: {type: <type>, value: <value>} + + + } + + + ] + + + + + 26 + + + Return Participant Limits + + + + + 27 + + + Return Participant Limits + + + + [Validate participant (failure)/ Error] + + + + + Validation failure/ Error! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <errorCode>, + + + "errorDescription": <ErrorMessage>, + + + } + + + } + + + + + 28 + + + Return + + + Error code: + + + 3000, 3200 + + + + + 29 + + + Return + + + Error code: + + + 3000, 3200 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.plantuml new file mode 100644 index 000000000..06f4689fb --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.plantuml @@ -0,0 +1,167 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declate title +title 1.1.5. Request transfer status (getTransferStatusById) - Phase2 version + +autonumber + +' declare actors +actor "DFSP(n)\nParticipant" as DFSP +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Event-Topic" as TOPIC_EVENTS +entity "Transfer-DAO" as TRANSFER_DAO +database "Central Store" as DB + +box "Financial Service Provider" #lightGray + participant DFSP +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_EVENTS + participant TRANSFER_DAO + participant DB +end box + +' start flow +group Request transfer status + activate DFSP + DFSP -> NOTIFY_HANDLER: Callback transfer status request URL - GET - /transfers/{ID} +'alt invalid tansferId +' activate NOTIFY_HANDLER +' NOTIFY_HANDLER -> NOTIFY_HANDLER: Validate TransferId +' break +' note right of NOTIFY_HANDLER #yellow +' { +' "errorInformation": { +' "errorCode": , +' "errorDescription": "Invalid payload or state" +' } +' } +' end note +' DFSP <-- NOTIFY_HANDLER: Respond HTTP - 4xx (Bad Request) +' end +'else valid transfer + ||| + group Persist Event Information +' hnote over NOTIFY_HANDLER #Pink +' Do we need to write the event to the Event-Topic? +' Not transaction related. +' end hnote + NOTIFY_HANDLER -> CSAPI: Request transfer information - GET - /transfers/{ID} + activate CSAPI + + activate TOPIC_EVENTS + CSAPI -> TOPIC_EVENTS: Publish event information + ||| + ref over TOPIC_EVENTS : Event Handler Consume\n + ||| + CSAPI <-- TOPIC_EVENTS: Return success + deactivate TOPIC_EVENTS + CSAPI --> NOTIFY_HANDLER: Return success + deactivate CSAPI + end + DFSP <-- NOTIFY_HANDLER: Respond HTTP - 200 (OK) +'end + NOTIFY_HANDLER -> CSAPI: Request details for Transfer - GET - /transfers/{ID}\nError code: 2003 + activate CSAPI + CSAPI -> TRANSFER_DAO: Request transfer status\nError code: 2003 + activate TRANSFER_DAO + TRANSFER_DAO -> DB: Fetch transfer status + activate DB + hnote over DB #lightyellow + SELECT transferId, transferStateId + FROM **transferStateChange** + WHERE transferId = {ID} + ORDER BY transferStateChangeId desc limit 1 + end note + deactivate DB + CSAPI <-- TRANSFER_DAO: Return transfer status + deactivate TRANSFER_DAO + NOTIFY_HANDLER <-- CSAPI: Return transfer status\nError codes: 3202, 3203 + deactivate CSAPI + + alt Is there a transfer with the given ID recorded in the system? + alt Yes AND transferState is COMMITTED \nThis implies that a succesful transfer with the given ID is recorded in the system + note left of NOTIFY_HANDLER #yellow + { + "fulfilment": "WLctttbu2HvTsa1XWvUoGRcQozHsqeu9Ahl2JW9Bsu8", + "completedTimestamp": "2018-09-24T08:38:08.699-04:00", + "transferState": "COMMITTED", + extensionList: + { + extension: + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + end note + DFSP <- NOTIFY_HANDLER: callback PUT on /transfers/{ID} + else transferState in [RECEIVED, RESERVED, ABORTED] + note left of NOTIFY_HANDLER #yellow + { + "transferState": "RECEIVED", + extensionList: + { + extension: + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + end note + DFSP <- NOTIFY_HANDLER: callback PUT on /transfers/{ID} + end + note right of NOTIFY_HANDLER #lightgray + Log ERROR event + end note + else A transfer with the given ID is not present in the System or this is an invalid request + note left of NOTIFY_HANDLER #yellow + { + "errorInformation": { + "errorCode": , + "errorDescription": "Client error description" + } + } + end note + DFSP <- NOTIFY_HANDLER: callback PUT on /transfers/{ID}/error + end + deactivate NOTIFY_HANDLER +deactivate DFSP +end +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.svg new file mode 100644 index 000000000..8ad873bd3 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.svg @@ -0,0 +1,402 @@ + + + + + + + + + + + 1.1.5. Request transfer status (getTransferStatusById) - Phase2 version + + + + Financial Service Provider + + + + ML API Adapter Service + + + + Central Service + + + + + + + + + DFSP(n) + + + Participant + + + + + DFSP(n) + + + Participant + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Event-Topic + + + + + Event-Topic + + + Transfer-DAO + + + + + Transfer-DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Request transfer status + + + + + 1 + + + Callback transfer status request URL - GET - /transfers/{ID} + + + + + Persist Event Information + + + + + 2 + + + Request transfer information - GET - /transfers/{ID} + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + 4 + + + Return success + + + + + 5 + + + Return success + + + + + 6 + + + Respond HTTP - 200 (OK) + + + + + 7 + + + Request details for Transfer - GET - /transfers/{ID} + + + Error code: + + + 2003 + + + + + 8 + + + Request transfer status + + + Error code: + + + 2003 + + + + + 9 + + + Fetch transfer status + + + + SELECT transferId, transferStateId + + + FROM + + + transferStateChange + + + WHERE transferId = {ID} + + + ORDER BY transferStateChangeId desc limit 1 + + + + + 10 + + + Return transfer status + + + + + 11 + + + Return transfer status + + + Error codes: + + + 3202, 3203 + + + + + alt + + + [Is there a transfer with the given ID recorded in the system?] + + + + + alt + + + [Yes AND transferState is COMMITTED + + + This implies that a succesful transfer with the given ID is recorded in the system] + + + + + { + + + "fulfilment": "WLctttbu2HvTsa1XWvUoGRcQozHsqeu9Ahl2JW9Bsu8", + + + "completedTimestamp": "2018-09-24T08:38:08.699-04:00", + + + "transferState": "COMMITTED", + + + extensionList: + + + { + + + extension: + + + [ + + + { + + + "key": "Description", + + + "value": "This is a more detailed description" + + + } + + + ] + + + } + + + } + + + + + 12 + + + callback PUT on /transfers/{ID} + + + + [transferState in [RECEIVED, RESERVED, ABORTED]] + + + + + { + + + "transferState": "RECEIVED", + + + extensionList: + + + { + + + extension: + + + [ + + + { + + + "key": "Description", + + + "value": "This is a more detailed description" + + + } + + + ] + + + } + + + } + + + + + 13 + + + callback PUT on /transfers/{ID} + + + + + Log ERROR event + + + + [A transfer with the given ID is not present in the System or this is an invalid request] + + + + + { + + + "errorInformation": { + + + "errorCode": <integer>, + + + "errorDescription": "Client error description" + + + } + + + } + + + + + 14 + + + callback PUT on /transfers/{ID}/error + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.plantuml new file mode 100644 index 000000000..0d42f4d94 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.plantuml @@ -0,0 +1,174 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declare title +title 1.1.0 Manage Participant Limits + +autonumber + +' declare actors +actor "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Services" #LightYellow +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant DB +end box + +' start flow + +activate OPERATOR +group Manage Net Debit Cap + OPERATOR -> CSAPI: Request to adjust Participant Limit for a certain Currency - POST - /participants/{name}/limits + note right of OPERATOR #yellow + Message: + { + payload: { + currency: , + limit: { + type: , + value: + } + } + } + end note + + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Adjust Limit for Participant + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant/currency \nError code: 3200 + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch Participant/currency + activate DB + hnote over DB #lightyellow + participant + participantCurrency + end note + DB --> PARTICIPANT_DAO: Retrieved Participant/currency + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return Participant/currency + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER -> PARTICIPANT_HANDLER: Validate DFSP + alt Validate participant (success) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: (for ParticipantCurrency) Fetch ParticipantLimit \nError code: 3200 + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch ParticipantLimit + activate DB + hnote over DB #lightyellow + participantLimit + end note + DB --> PARTICIPANT_DAO: Retrieved ParticipantLimit + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return ParticipantLimit + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER -> PARTICIPANT_HANDLER: Validate ParticipantLimit + alt Validate participantLimit (success) + Group DB TRANSACTION IMPLEMENTATION - Lock on ParticipantLimit table with UPDATE + note right of PARTICIPANT_DAO #lightgrey + If (record exists && isActive = 1) + oldIsActive.isActive = 0 + insert Record + Else + insert Record + End + + end note + + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: (for ParticipantLimit) Insert new ParticipantLimit \nError code: 3200 + + activate PARTICIPANT_DAO + + PARTICIPANT_DAO -> DB: Insert ParticipantLimit + activate DB + hnote over DB #lightyellow + participantLimit + end note + DB --> PARTICIPANT_DAO: Inserted ParticipantLimit + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return ParticipantLimit + + + deactivate PARTICIPANT_DAO + ' Release Lock on ParticipantLimit table + End + + else Validate participantLimit (failure) + note right of PARTICIPANT_HANDLER #red: Validation failure! + + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "ParticipantLimit Not Found", + } + } + end note + end + PARTICIPANT_HANDLER --> CSAPI: Return new Limit values and status 200 + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "currency": "EUR", + "limit": { + "participantLimitId": , + "participantLimitTypeId": , + "type": , + "value": , + "isActive": 1 + } + } + end note + CSAPI --> OPERATOR: Return new Limit values and status 200 + + else Validate participant (failure) + note right of PARTICIPANT_HANDLER #red: Validation failure! + + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "FSP id Not Found", + } + } + end note + + end + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3200 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3200 + + deactivate PARTICIPANT_HANDLER + deactivate CSAPI + deactivate OPERATOR +end +@enduml \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.svg new file mode 100644 index 000000000..a640cdb01 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.svg @@ -0,0 +1,457 @@ + + + + + + + + + + + 1.1.0 Manage Participant Limits + + + + Central Services + + + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Manage Net Debit Cap + + + + + 1 + + + Request to adjust Participant Limit for a certain Currency - POST - /participants/{name}/limits + + + + + Message: + + + { + + + payload: { + + + currency: <string>, + + + limit: { + + + type: <string>, + + + value: <Id> + + + } + + + } + + + } + + + + + 2 + + + Adjust Limit for Participant + + + + + 3 + + + Fetch Participant/currency + + + Error code: + + + 3200 + + + + + 4 + + + Fetch Participant/currency + + + + participant + + + participantCurrency + + + + + 5 + + + Retrieved Participant/currency + + + + + 6 + + + Return Participant/currency + + + + + 7 + + + Validate DFSP + + + + + alt + + + [Validate participant (success)] + + + + + 8 + + + (for ParticipantCurrency) Fetch ParticipantLimit + + + Error code: + + + 3200 + + + + + 9 + + + Fetch ParticipantLimit + + + + participantLimit + + + + + 10 + + + Retrieved ParticipantLimit + + + + + 11 + + + Return ParticipantLimit + + + + + 12 + + + Validate ParticipantLimit + + + + + alt + + + [Validate participantLimit (success)] + + + + + DB TRANSACTION IMPLEMENTATION - Lock on ParticipantLimit table with UPDATE + + + + + If (record exists && isActive = 1) + + + oldIsActive.isActive = 0 + + + insert Record + + + Else + + + insert Record + + + End + + + + + 13 + + + (for ParticipantLimit) Insert new ParticipantLimit + + + Error code: + + + 3200 + + + + + 14 + + + Insert ParticipantLimit + + + + participantLimit + + + + + 15 + + + Inserted ParticipantLimit + + + + + 16 + + + Return ParticipantLimit + + + + [Validate participantLimit (failure)] + + + + + Validation failure! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": 3200, + + + "errorDescription": "ParticipantLimit Not Found", + + + } + + + } + + + + + 17 + + + Return new Limit values and status 200 + + + + + Message: + + + { + + + "currency": "EUR", + + + "limit": { + + + "participantLimitId": <number>, + + + "participantLimitTypeId": <number>, + + + "type": <string>, + + + "value": <string>, + + + "isActive": 1 + + + } + + + } + + + + + 18 + + + Return new Limit values and status 200 + + + + [Validate participant (failure)] + + + + + Validation failure! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": 3200, + + + "errorDescription": "FSP id Not Found", + + + } + + + } + + + + + 19 + + + Return + + + Error code: + + + 3200 + + + + + 20 + + + Return + + + Error code: + + + 3200 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.plantuml new file mode 100644 index 000000000..79bb20553 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.plantuml @@ -0,0 +1,187 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declate title +title 1.0.0 Create initial position and limits for Participant + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant FACADE" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Services" #LightYellow +participant CSAPI +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant DB +end box + +' start flow + +activate OPERATOR +group Create initial position and limits + OPERATOR -> CSAPI: Request to Create initial position and limits - POST - /paticipants/{name}/initialPositionAndLimits + note right of OPERATOR #yellow + Message: + { + currency: , + limit: { + type: , + value: + }, + initialPosition: + } + end note + + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Create initial position and limits for Participant + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant/ Currency Id \nError code: 3200 + + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch Participant/Currency Id + activate DB + hnote over DB #lightyellow + participant + participantCurrency + end note + DB --> PARTICIPANT_DAO: Retrieved Participant/Currency Id + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return Participant/Currency Id + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Validate DFSP + alt Validate participant (success) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch limit for participantCurrencyId + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch limit for participantCurrencyId + activate DB + hnote over DB #lightyellow + participantLimit + end note + DB --> PARTICIPANT_DAO: Retrieved participant limit + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return participant limit + deactivate PARTICIPANT_DAO + + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch position for participantCurrencyId + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch position for participantCurrencyId + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> PARTICIPANT_DAO: Retrieved participant position + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return participant position + deactivate PARTICIPANT_DAO + + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Participant position or limit exists check + + alt position or limit does not exist (success) + + + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: create initial position and limits for Participantt \nError code: 2003/Msg: Service unavailable \nError code: 2001/Msg: Internal Server Error + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Persist Participant limits/position + activate DB + hnote over DB #lightyellow + participantPosition + participantLimit + end note + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return status + deactivate PARTICIPANT_DAO + alt Details persisted successfully + PARTICIPANT_HANDLER -->CSAPI: Return Status Code 201 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Status Code 201 + else Details not persisted/Error + note right of PARTICIPANT_HANDLER #red: Error! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code + ' deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code + + end + + else position or limit exists (failure) + note right of PARTICIPANT_HANDLER #red: Error! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "Participant Limit or Initial Position already set", + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3200 + ' deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3200 + + end + + else Validate participant (failure) + note right of PARTICIPANT_HANDLER #red: Validation failure! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "FSP id Not Found", + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3200 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3200 + + end + deactivate CSAPI + deactivate OPERATOR +end +@enduml \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.svg new file mode 100644 index 000000000..fcfca97c7 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.svg @@ -0,0 +1,527 @@ + + + + + + + + + + + 1.0.0 Create initial position and limits for Participant + + + + Central Services + + + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant FACADE + + + + + Participant FACADE + + + + + Central Store + + + + + Central Store + + + + + + + + Create initial position and limits + + + + + 1 + + + Request to Create initial position and limits - POST - /paticipants/{name}/initialPositionAndLimits + + + + + Message: + + + { + + + currency: <currencyId>, + + + limit: { + + + type: <limitType>, + + + value: <limitValue> + + + }, + + + initialPosition: <positionValue> + + + } + + + + + 2 + + + Create initial position and limits for Participant + + + + + 3 + + + Fetch Participant/ Currency Id + + + Error code: + + + 3200 + + + + + 4 + + + Fetch Participant/Currency Id + + + + participant + + + participantCurrency + + + + + 5 + + + Retrieved Participant/Currency Id + + + + + 6 + + + Return Participant/Currency Id + + + + + 7 + + + Validate DFSP + + + + + alt + + + [Validate participant (success)] + + + + + 8 + + + Fetch limit for participantCurrencyId + + + + + 9 + + + Fetch limit for participantCurrencyId + + + + participantLimit + + + + + 10 + + + Retrieved participant limit + + + + + 11 + + + Return participant limit + + + + + 12 + + + Fetch position for participantCurrencyId + + + + + 13 + + + Fetch position for participantCurrencyId + + + + participantPosition + + + + + 14 + + + Retrieved participant position + + + + + 15 + + + Return participant position + + + + + 16 + + + Participant position or limit exists check + + + + + alt + + + [position or limit does not exist (success)] + + + + + 17 + + + create initial position and limits for Participantt + + + Error code: + + + 2003/ + + + Msg: + + + Service unavailable + + + Error code: + + + 2001/ + + + Msg: + + + Internal Server Error + + + + + 18 + + + Persist Participant limits/position + + + + participantPosition + + + participantLimit + + + + + 19 + + + Return status + + + + + alt + + + [Details persisted successfully] + + + + + 20 + + + Return Status Code 201 + + + + + 21 + + + Return Status Code 201 + + + + [Details not persisted/Error] + + + + + Error! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 22 + + + Return + + + Error code + + + + + 23 + + + Return + + + Error code + + + + [position or limit exists (failure)] + + + + + Error! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": 3200, + + + "errorDescription": "Participant Limit or Initial Position already set", + + + } + + + } + + + + + 24 + + + Return + + + Error code: + + + 3200 + + + + + 25 + + + Return + + + Error code: + + + 3200 + + + + [Validate participant (failure)] + + + + + Validation failure! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": 3200, + + + "errorDescription": "FSP id Not Found", + + + } + + + } + + + + + 26 + + + Return + + + Error code: + + + 3200 + + + + + 27 + + + Return + + + Error code: + + + 3200 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.plantuml new file mode 100644 index 000000000..2bab529fe --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.plantuml @@ -0,0 +1,164 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declate title +title 4.1.0 Get Participant Position Details + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant DAO" as PARTICIPANT_DAO +entity "Position Facade" as POSITION_DAO +database "Central Store" as DB +box "HUB Operator" #LightBlue +participant OPERATOR +end box + +box "Central Service" #LightYellow +participant CSAPI +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant POSITION_DAO +participant DB +end box + +' start flow + +activate OPERATOR +group Get Position Details + OPERATOR -> CSAPI: Request to get positions - GET - /participants/{name}/positions?currency={currencyId} + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Fetch Positions for Participant + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant \nError code: 2003,3201 + + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Participant + activate DB + hnote over DB #lightyellow + participant + end note + DB --> PARTICIPANT_DAO: Retrieved Participant + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Participant + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Validate DFSP \nError code: 3201 + alt Validate participant (success) + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: currency parameter passed ? + + alt currency parameter passed + + PARTICIPANT_HANDLER ->POSITION_DAO: Fetch Participant position for a currency id\nError code: 2003 + activate POSITION_DAO + POSITION_DAO ->DB: Fetch Participant position for a currency id + activate DB + hnote over DB #lightyellow + participantCurrency + participantPosition + end note + DB --> POSITION_DAO: Retrieved Participant position for a currency id + deactivate DB + POSITION_DAO -->PARTICIPANT_HANDLER: Return Positions for Participant + deactivate POSITION_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + { + { + currency: , + value: , + updatedTime: + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Participant position for a currency id + CSAPI -->OPERATOR: Return Participant position for a currency id + else currency parameter not passed + PARTICIPANT_HANDLER ->POSITION_DAO: Fetch Participant Positions for all currencies\nError code: 2003 + activate POSITION_DAO + POSITION_DAO ->DB: Fetch Participant Positions for all currencies + activate DB + hnote over DB #lightyellow + participantCurrency + participantPosition + end note + DB --> POSITION_DAO: Retrieved Participant Positions for all currencies + deactivate DB + POSITION_DAO -->PARTICIPANT_HANDLER: Return Participant Positions for all currencies + deactivate POSITION_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + { + [ + { + currency: , + value: , + updatedTime: + }, + { + currency: , + value: , + updatedTime: + } + ] + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Participant Positions for all currencies + CSAPI -->OPERATOR: Return Participant Positions for all currencies + end + else Validate participant (failure) + note right of PARTICIPANT_HANDLER #red: Validation failure! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": 3201, + "errorDescription": "FSP id does not exist or not found", + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3201 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3201 + end + +end + +deactivate CSAPI +deactivate OPERATOR + +@enduml \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.svg new file mode 100644 index 000000000..b623ef955 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.svg @@ -0,0 +1,448 @@ + + + + + + + + + + + 4.1.0 Get Participant Position Details + + + + HUB Operator + + + + Central Service + + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant DAO + + + + + Participant DAO + + + + + Position Facade + + + + + Position Facade + + + + + Central Store + + + + + Central Store + + + + + + + + Get Position Details + + + + + 1 + + + Request to get positions - GET - /participants/{name}/positions?currency={currencyId} + + + + + 2 + + + Fetch Positions for Participant + + + + + 3 + + + Fetch Participant + + + Error code: + + + 2003,3201 + + + + + 4 + + + Fetch Participant + + + + participant + + + + + 5 + + + Retrieved Participant + + + + + 6 + + + Return Participant + + + + + 7 + + + Validate DFSP + + + Error code: + + + 3201 + + + + + alt + + + [Validate participant (success)] + + + + + 8 + + + currency parameter passed ? + + + + + alt + + + [currency parameter passed] + + + + + 9 + + + Fetch Participant position for a currency id + + + Error code: + + + 2003 + + + + + 10 + + + Fetch Participant position for a currency id + + + + participantCurrency + + + participantPosition + + + + + 11 + + + Retrieved Participant position for a currency id + + + + + 12 + + + Return Positions for Participant + + + + + Message: + + + { + + + { + + + currency: <currencyId>, + + + value: <positionValue>, + + + updatedTime: <timeStamp1> + + + } + + + } + + + + + 13 + + + Return Participant position for a currency id + + + + + 14 + + + Return Participant position for a currency id + + + + [currency parameter not passed] + + + + + 15 + + + Fetch Participant Positions for all currencies + + + Error code: + + + 2003 + + + + + 16 + + + Fetch Participant Positions for all currencies + + + + participantCurrency + + + participantPosition + + + + + 17 + + + Retrieved Participant Positions for all currencies + + + + + 18 + + + Return Participant Positions for all currencies + + + + + Message: + + + { + + + [ + + + { + + + currency: <currencyId1>, + + + value: <positionValue1>, + + + updatedTime: <timeStamp1> + + + }, + + + { + + + currency: <currencyId2>, + + + value: <positionValue2>, + + + updatedTime: <timeStamp2> + + + } + + + ] + + + } + + + + + 19 + + + Return Participant Positions for all currencies + + + + + 20 + + + Return Participant Positions for all currencies + + + + [Validate participant (failure)] + + + + + Validation failure! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": 3201, + + + "errorDescription": "FSP id does not exist or not found", + + + } + + + } + + + + + 21 + + + Return + + + Error code: + + + 3201 + + + + + 22 + + + Return + + + Error code: + + + 3201 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.plantuml new file mode 100644 index 000000000..753a7e850 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.plantuml @@ -0,0 +1,139 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declate title +title 4.2.0 Get Positions of all Participants + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +entity "ML-API-ADAPTER" as MLAPI +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB +box "ML API Adapter Service" #LightBlue + participant MLAPI +end box + +box "Central Service" #LightYellow + participant CSAPI + participant PARTICIPANT_HANDLER + participant PARTICIPANT_DAO + participant DB +end box + +' start flow + +activate MLAPI +group Get Position Details +MLAPI -> CSAPI: Request to get positions - GET - /participants/positions + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Fetch Positions for all Participants + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Positions for all active Participants \nError code: 2003,3200 + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Positions for: \n all active Participants \n with all active Currencies for each Participant + activate DB + hnote over DB #lightyellow + participant + participantPosition + participantCurrency + end note + DB --> PARTICIPANT_DAO: Retrieved Positions for Participants + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Positions for Participants + deactivate PARTICIPANT_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + { + snapshotAt: , + positions: + [ + { + participantId: , + participantPositions: + [ + { + currentPosition: { + currency: , + value: , + reservedValue: , + lastUpdated: + } + }, + { + currentPosition: { + currency: , + value: , + reservedValue: , + lastUpdated: + } + } + ] + }, + { + participantId: , + participantPositions: + [ + { + currentPosition: { + currency: , + value: , + reservedValue: , + lastUpdated: + } + }, + { + currentPosition: { + currency: , + value: , + reservedValue: , + lastUpdated: + } + } + ] + } + ] + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Positions for Participants + deactivate PARTICIPANT_HANDLER +CSAPI -->MLAPI: Return Positions for Participants + +end + deactivate CSAPI +deactivate MLAPI + +@enduml \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.svg new file mode 100644 index 000000000..76b9e95a5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.svg @@ -0,0 +1,321 @@ + + + + + + + + + + + 4.2.0 Get Positions of all Participants + + + + ML API Adapter Service + + + + Central Service + + + + + + ML-API-ADAPTER + + + + + ML-API-ADAPTER + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Get Position Details + + + + + 1 + + + Request to get positions - GET - /participants/positions + + + + + 2 + + + Fetch Positions for all Participants + + + + + 3 + + + Fetch Positions for all active Participants + + + Error code: + + + 2003,3200 + + + + + 4 + + + Fetch Positions for: + + + all active Participants + + + with all active Currencies for each Participant + + + + participant + + + participantPosition + + + participantCurrency + + + + + 5 + + + Retrieved Positions for Participants + + + + + 6 + + + Return Positions for Participants + + + + + Message: + + + { + + + snapshotAt: <timestamp0>, + + + positions: + + + [ + + + { + + + participantId: <dfsp1>, + + + participantPositions: + + + [ + + + { + + + currentPosition: { + + + currency: <currency1>, + + + value: <amount1>, + + + reservedValue: <amount2>, + + + lastUpdated: <timeStamp1> + + + } + + + }, + + + { + + + currentPosition: { + + + currency: <currency2>, + + + value: <amount3>, + + + reservedValue: <amount4>, + + + lastUpdated: <timeStamp2> + + + } + + + } + + + ] + + + }, + + + { + + + participantId: <dfsp2>, + + + participantPositions: + + + [ + + + { + + + currentPosition: { + + + currency: <currency1>, + + + value: <amount1>, + + + reservedValue: <amount2>, + + + lastUpdated: <timeStamp1> + + + } + + + }, + + + { + + + currentPosition: { + + + currency: <currency2>, + + + value: <amount3>, + + + reservedValue: <amount4>, + + + lastUpdated: <timeStamp2> + + + } + + + } + + + ] + + + } + + + ] + + + } + + + + + 7 + + + Return Positions for Participants + + + + + 8 + + + Return Positions for Participants + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.plantuml new file mode 100644 index 000000000..04d4356c9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.plantuml @@ -0,0 +1,116 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title 1.3.0. Position Handler Consume (single message) v1.1 + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + alt Consume Prepare message for Payer + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'prepare'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Prepare Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Fulfil message for Payee + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action IN ['commit', 'reserve']\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Fulfil Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Abort message + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' &&\naction IN ['timeout-reserved', 'reject', 'fail']\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Abort Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + end + +end +deactivate POS_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.svg new file mode 100644 index 000000000..6829d68ff --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.svg @@ -0,0 +1,301 @@ + + + + + + + + + + + 1.3.0. Position Handler Consume (single message) v1.1 + + + + Central Service + + + + + + + + + + + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Handler + + + + + Position Handler + + + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + Position Handler Consume + + + + + alt + + + [Consume Prepare message for Payer] + + + + + 1 + + + Consume Position event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'position' && action == 'prepare' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Prepare Position Handler Consume + + + + + 4 + + + Produce message + + + + [Consume Fulfil message for Payee] + + + + + 5 + + + Consume Position event message for Payee + + + + + break + + + + + Validate Event + + + + + 6 + + + Validate event - Rule: type == 'position' && action IN ['commit', 'reserve'] + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 7 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Fulfil Position Handler Consume + + + + + 8 + + + Produce message + + + + [Consume Abort message] + + + + + 9 + + + Consume Position event message + + + + + break + + + + + Validate Event + + + + + 10 + + + Validate event - Rule: type == 'position' && + + + action IN ['timeout-reserved', 'reject', 'fail'] + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 11 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Abort Position Handler Consume + + + + + 12 + + + Produce message + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.plantuml new file mode 100644 index 000000000..963700067 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.plantuml @@ -0,0 +1,115 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.3.0. Position Handler Consume (single message) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + alt Consume Prepare message for Payer + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'prepare'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Prepare Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Fulfil message for Payee + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'commit'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Fulfil Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Abort message + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' &&\naction IN ['timeout-reserved', 'reject', 'fail']\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Abort Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + end + +end +deactivate POS_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.svg new file mode 100644 index 000000000..f03e043a8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.svg @@ -0,0 +1,301 @@ + + + + + + + + + + + 1.3.0. Position Handler Consume (single message) + + + + Central Service + + + + + + + + + + + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Handler + + + + + Position Handler + + + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + Position Handler Consume + + + + + alt + + + [Consume Prepare message for Payer] + + + + + 1 + + + Consume Position event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'position' && action == 'prepare' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Prepare Position Handler Consume + + + + + 4 + + + Produce message + + + + [Consume Fulfil message for Payee] + + + + + 5 + + + Consume Position event message for Payee + + + + + break + + + + + Validate Event + + + + + 6 + + + Validate event - Rule: type == 'position' && action == 'commit' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 7 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Fulfil Position Handler Consume + + + + + 8 + + + Produce message + + + + [Consume Abort message] + + + + + 9 + + + Consume Position event message + + + + + break + + + + + Validate Event + + + + + 10 + + + Validate event - Rule: type == 'position' && + + + action IN ['timeout-reserved', 'reject', 'fail'] + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 11 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Abort Position Handler Consume + + + + + 12 + + + Produce message + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml new file mode 100644 index 000000000..2e420c3b3 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml @@ -0,0 +1,283 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.3.1. Prepare Position Handler Consume + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER + +entity "Position\nManagement\nFacade" as POS_MGMT +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant POS_MGMT + participant POS_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Prepare Position Handler Consume + POS_HANDLER -> POS_MGMT: Request transfers to be processed + activate POS_MGMT + POS_MGMT -> POS_MGMT: Check 1st transfer to select the Participant and Currency + group DB TRANSACTION + ' DB Trans: This is where 1st DB Transaction would start in 2 DB transacation future model for horizontal scaling + POS_MGMT -> POS_MGMT: Loop through batch and build list of transferIds and calculate sumTransfersInBatch,\nchecking all in Batch are for the correct Paricipant and Currency\nError code: 2001, 3100 + POS_MGMT -> DB: Retrieve current state of all transfers in array from DB with select whereIn\n(FYI: The two DB transaction model needs to add a mini-state step here (RECEIVED_PREPARE => RECEIVDED_PREPARE_PROCESSING) so that the transfers are left alone if processing has started) + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_MGMT: Return current state of all selected transfers from DB + deactivate DB + POS_MGMT <-> POS_MGMT: Validate current state (transferStateChange.transferStateId == 'RECEIVED_PREPARE')\nError code: 2001 against failing transfers\nBatch is not rejected as a whole. + + note right of POS_MGMT #lightgray + List of transfers used during processing + **reservedTransfers** is list of transfers to be processed in the batch + **abortedTransfers** is the list of transfers in the incorrect state going into the process. Currently the transferStateChange is set to ABORTED - this should only be done if not already in a final state (idempotency) + **processedTransfers** is the list of transfers that have gone through the position management algorithm. Both successful and failed trasnfers appear here as the order and "running position" against each is necessary for reconciliation + + Scalar intermidate values used in the algorithm + **transferAmount** = payload.amount.amount + **sumTransfersInBatch** = SUM amount against each Transfer in batch + **currentPosition** = participantPosition.value + **reservedPosition** = participantPosition.{original}reservedValue + **effectivePosition** = currentPosition + reservedPosition + **heldPosition** = effectivePosition + sumTransfersInBatch + **availablePosition** = //if settlement model delay is IMMEDIATE then:// settlementBalance + participantLimit(NetDebitCap) - effectivePosition, //otherwise:// participantLimit(NetDebitCap) - effectivePosition + **sumReserved** = SUM of transfers that have met rule criteria and processed + end note + note over POS_MGMT,DB + Going to reserve the sum of the valid transfers in the batch against the Participants Positon in the Currency of this batch + and calculate the available position for the Participant to use + end note + POS_MGMT -> DB: Select effectivePosition FOR UPDATE from DB for Payer + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_MGMT: Return effectivePosition (currentPosition and reservedPosition) from DB for Payer + deactivate DB + POS_MGMT -> POS_MGMT: Increment reservedValue to heldPosition\n(reservedValue = reservedPosition + sumTransfersInBatch) + POS_MGMT -> DB: Persist reservedValue + activate DB + hnote over DB #lightyellow + UPDATE **participantPosition** + SET reservedValue += sumTransfersInBatch + end note + deactivate DB + ' DB Trans: This is where 1st DB Transaction would end in 2 DB transacation future model for horizontal scaling + + + POS_MGMT -> DB: Request position limits for Payer Participant + activate DB + hnote over DB #lightyellow + FROM **participantLimit** + WHERE participantLimit.limitTypeId = 'NET-DEBIT-CAP' + AND participantLimit.participantId = payload.payerFsp + AND participantLimit.currencyId = payload.amount.currency + end note + DB --> POS_MGMT: Return position limits + deactivate DB + POS_MGMT <-> POS_MGMT: **availablePosition** = //if settlement model delay is IMMEDIATE then://\n settlementBalance + participantLimit(NetDebitCap) - effectivePosition\n //otherwise://\n participantLimit(NetDebitCap) - effectivePosition\n(same as = (settlementBalance?) + netDebitCap - currentPosition - reservedPosition) + note over POS_MGMT,DB + For each transfer in the batch, validate the availablility of position to meet the transfer amount + this will be as per the position algorithm documented below + end note + POS_MGMT <-> POS_MGMT: Validate availablePosition for each tranfser (see algorithm below)\nError code: 4001 + note right of POS_MGMT #lightgray + 01: sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED + 02: sumProcessed =0 // Record the sum of the transfers already processed in this batch + 03: processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position + 04: foreach transfer in reservedTransfers + 05: sumProcessed += transfer.amount // the total processed so far **(NEED TO UPDATE IN CODE)** + 06: if availablePosition >= transfer.amount + 07: transfer.state = "RESERVED" + 08: availablePosition -= preparedTransfer.amount + 09: sumRESERVED += preparedTransfer.amount + 10: else + 11: preparedTransfer.state = "ABORTED" + 12: preparedTransfer.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + 13: end if + 14: runningPosition = currentPosition + sumReserved // the initial value of the Participants position plus the total value that has been accepted in the batch so far + 15: runningReservedValue = sumTransfersInBatch - sumProcessed + reservedPosition **(NEED TO UPDATE IN CODE)** // the running down of the total reserved value at the begining of the batch. + 16: Add transfer to the processedTransfer list recording the transfer state and running position and reserved values { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue } + 16: end foreach + end note + note over POS_MGMT,DB + Once the outcome for all transfers is known,update the Participant's position and remove the reserved amount associated with the batch + (If there are any alarm limits, process those returning limits in which the threshold has been breached) + Do a bulk insert of the trasnferStateChanges associated with processing, using the result to complete the participantPositionChange and bulk insert of these to persist the running position + end note + POS_MGMT->POS_MGMT: Assess any limit thresholds on the final position\nadding to alarm list if triggered + + ' DB Trans: This is where 2nd DB Transaction would start in 2 DB transacation future model for horizontal scaling + POS_MGMT->DB: Persist latest position **value** and **reservedValue** to DB for Payer + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value += sumRESERVED, + reservedValue -= sumTransfersInBatch + end note + activate DB + deactivate DB + + POS_MGMT -> DB: Bulk persist transferStateChange for all processedTransfers + hnote over DB #lightyellow + batch INSERT **transferStateChange** + select for update from transfer table where transferId in ([transferBatch.transferId,...]) + build list of transferStateChanges from transferBatch + + end note + activate DB + deactivate DB + + POS_MGMT->POS_MGMT: Populate batchParticipantPositionChange from the resultant transferStateChange and the earlier processedTransfer list + + note right of POS_MGMT #lightgray + Effectively: + SET transferStateChangeId = processedTransfer.transferStateChangeId, + participantPositionId = preparedTransfer.participantPositionId, + value = preparedTransfer.positionValue, + reservedValue = preparedTransfer.positionReservedValue + end note + POS_MGMT -> DB: Bulk persist the participant position change for all processedTransfers + hnote over DB #lightyellow + batch INSERT **participantPositionChange** + end note + activate DB + deactivate DB + ' DB Trans: This is where 2nd DB Transaction would end in 2 DB transacation future model for horizontal scaling + end + POS_MGMT --> POS_HANDLER: Return a map of transferIds and their transferStateChanges + deactivate POS_MGMT + alt Calculate & Validate Latest Position Prepare (success) + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else Calculate & Validate Latest Position Prepare (failure) + note right of POS_HANDLER #red: Validation failure! + + group Persist Transfer State (with transferState='ABORTED' on position check fail) + POS_HANDLER -> POS_DAO: Request to persist transfer\nError code: 2003 + activate POS_DAO + note right of POS_HANDLER #lightgray + transferStateChange.state = "ABORTED", + transferStateChange.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + end note + POS_DAO -> DB: Persist transfer state + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: prepare, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + deactivate POS_HANDLER + end +end +deactivate POS_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.svg new file mode 100644 index 000000000..0e6b46ec3 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.svg @@ -0,0 +1,842 @@ + + + + + + + + + + + 1.3.1. Prepare Position Handler Consume + + + + Central Service + + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + Position + + + Management + + + Facade + + + + + Position + + + Management + + + Facade + + + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Prepare Position Handler Consume + + + + + 1 + + + Request transfers to be processed + + + + + 2 + + + Check 1st transfer to select the Participant and Currency + + + + + DB TRANSACTION + + + + + 3 + + + Loop through batch and build list of transferIds and calculate sumTransfersInBatch, + + + checking all in Batch are for the correct Paricipant and Currency + + + Error code: + + + 2001, 3100 + + + + + 4 + + + Retrieve current state of all transfers in array from DB with select whereIn + + + (FYI: The two DB transaction model needs to add a mini-state step here (RECEIVED_PREPARE => RECEIVDED_PREPARE_PROCESSING) so that the transfers are left alone if processing has started) + + + + transferStateChange + + + transferParticipant + + + + + 5 + + + Return current state of all selected transfers from DB + + + + + 6 + + + Validate current state (transferStateChange.transferStateId == 'RECEIVED_PREPARE') + + + Error code: + + + 2001 + + + against failing transfers + + + Batch is not rejected as a whole. + + + + + List of transfers used during processing + + + reservedTransfers + + + is list of transfers to be processed in the batch + + + abortedTransfers + + + is the list of transfers in the incorrect state going into the process. Currently the transferStateChange is set to ABORTED - this should only be done if not already in a final state (idempotency) + + + processedTransfers + + + is the list of transfers that have gone through the position management algorithm. Both successful and failed trasnfers appear here as the order and "running position" against each is necessary for reconciliation + + + Scalar intermidate values used in the algorithm + + + transferAmount + + + = payload.amount.amount + + + sumTransfersInBatch + + + = SUM amount against each Transfer in batch + + + currentPosition + + + = participantPosition.value + + + reservedPosition + + + = participantPosition.{original}reservedValue + + + effectivePosition + + + = currentPosition + reservedPosition + + + heldPosition + + + = effectivePosition + sumTransfersInBatch + + + availablePosition + + + = + + + if settlement model delay is IMMEDIATE then: + + + settlementBalance + participantLimit(NetDebitCap) - effectivePosition, + + + otherwise: + + + participantLimit(NetDebitCap) - effectivePosition + + + sumReserved + + + = SUM of transfers that have met rule criteria and processed + + + + + Going to reserve the sum of the valid transfers in the batch against the Participants Positon in the Currency of this batch + + + and calculate the available position for the Participant to use + + + + + 7 + + + Select effectivePosition FOR UPDATE from DB for Payer + + + + participantPosition + + + + + 8 + + + Return effectivePosition (currentPosition and reservedPosition) from DB for Payer + + + + + 9 + + + Increment reservedValue to heldPosition + + + (reservedValue = reservedPosition + sumTransfersInBatch) + + + + + 10 + + + Persist reservedValue + + + + UPDATE + + + participantPosition + + + SET reservedValue += sumTransfersInBatch + + + + + 11 + + + Request position limits for Payer Participant + + + + FROM + + + participantLimit + + + WHERE participantLimit.limitTypeId = 'NET-DEBIT-CAP' + + + AND participantLimit.participantId = payload.payerFsp + + + AND participantLimit.currencyId = payload.amount.currency + + + + + 12 + + + Return position limits + + + + + 13 + + + availablePosition + + + = + + + if settlement model delay is IMMEDIATE then: + + + settlementBalance + participantLimit(NetDebitCap) - effectivePosition + + + otherwise: + + + participantLimit(NetDebitCap) - effectivePosition + + + (same as = (settlementBalance?) + netDebitCap - currentPosition - reservedPosition) + + + + + For each transfer in the batch, validate the availablility of position to meet the transfer amount + + + this will be as per the position algorithm documented below + + + + + 14 + + + Validate availablePosition for each tranfser (see algorithm below) + + + Error code: + + + 4001 + + + + + 01: sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED + + + 02: sumProcessed =0 // Record the sum of the transfers already processed in this batch + + + 03: processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position + + + 04: foreach transfer in reservedTransfers + + + 05: sumProcessed += transfer.amount // the total processed so far + + + (NEED TO UPDATE IN CODE) + + + 06: if availablePosition >= transfer.amount + + + 07: transfer.state = "RESERVED" + + + 08: availablePosition -= preparedTransfer.amount + + + 09: sumRESERVED += preparedTransfer.amount + + + 10: else + + + 11: preparedTransfer.state = "ABORTED" + + + 12: preparedTransfer.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + + + 13: end if + + + 14: runningPosition = currentPosition + sumReserved // the initial value of the Participants position plus the total value that has been accepted in the batch so far + + + 15: runningReservedValue = sumTransfersInBatch - sumProcessed + reservedPosition + + + (NEED TO UPDATE IN CODE) + + + // the running down of the total reserved value at the begining of the batch. + + + 16: Add transfer to the processedTransfer list recording the transfer state and running position and reserved values { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue } + + + 16: end foreach + + + + + Once the outcome for all transfers is known,update the Participant's position and remove the reserved amount associated with the batch + + + (If there are any alarm limits, process those returning limits in which the threshold has been breached) + + + Do a bulk insert of the trasnferStateChanges associated with processing, using the result to complete the participantPositionChange and bulk insert of these to persist the running position + + + + + 15 + + + Assess any limit thresholds on the final position + + + adding to alarm list if triggered + + + + + 16 + + + Persist latest position + + + value + + + and + + + reservedValue + + + to DB for Payer + + + + UPDATE + + + participantPosition + + + SET value += sumRESERVED, + + + reservedValue -= sumTransfersInBatch + + + + + 17 + + + Bulk persist transferStateChange for all processedTransfers + + + + batch INSERT + + + transferStateChange + + + select for update from transfer table where transferId in ([transferBatch.transferId,...]) + + + build list of transferStateChanges from transferBatch + + + + + 18 + + + Populate batchParticipantPositionChange from the resultant transferStateChange and the earlier processedTransfer list + + + + + Effectively: + + + SET transferStateChangeId = processedTransfer.transferStateChangeId, + + + participantPositionId = preparedTransfer.participantPositionId, + + + value = preparedTransfer.positionValue, + + + reservedValue = preparedTransfer.positionReservedValue + + + + + 19 + + + Bulk persist the participant position change for all processedTransfers + + + + batch INSERT + + + participantPositionChange + + + + + 20 + + + Return a map of transferIds and their transferStateChanges + + + + + alt + + + [Calculate & Validate Latest Position Prepare (success)] + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: transfer, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 21 + + + Publish Notification event + + + Error code: + + + 2003 + + + + [Calculate & Validate Latest Position Prepare (failure)] + + + + + Validation failure! + + + + + Persist Transfer State (with transferState='ABORTED' on position check fail) + + + + + 22 + + + Request to persist transfer + + + Error code: + + + 2003 + + + + + transferStateChange.state = "ABORTED", + + + transferStateChange.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + + + + + 23 + + + Persist transfer state + + + + transferStateChange + + + + + 24 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <ledgerName>, + + + to: <transferMessage.payerFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 4001, + + + "errorDescription": "Payer FSP insufficient liquidity", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 25 + + + Publish Notification (failure) event for Payer + + + Error code: + + + 2003 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.plantuml new file mode 100644 index 000000000..fab0fbf38 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.plantuml @@ -0,0 +1,141 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title 1.3.2. Fulfil Position Handler Consume v1.1 + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER +collections "Notifications-Topic" as TOPIC_NOTIFICATIONS +entity "Position Facade" as POS_FACADE +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant POS_FACADE + participant DB +end box + +' start flow +activate POS_HANDLER +group Fulfil Position Handler Consume + POS_HANDLER -> POS_DAO: Request current state of transfer from DB \nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferState is 'RECEIVED-FULFIL')\nError code: 2001 + group Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + POS_HANDLER -> POS_FACADE: Request to persist latest position and state to DB\nError code: 2003 + group DB TRANSACTION + activate POS_FACADE + POS_FACADE -> DB: Select participantPosition.value FOR UPDATE from DB for Payee + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_FACADE: Return participantPosition.value from DB for Payee + deactivate DB + POS_FACADE <-> POS_FACADE: **latestPosition** = participantPosition.value - payload.amount.amount + POS_FACADE->DB: Persist latestPosition to DB for Payee + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value = latestPosition + end note + activate DB + deactivate DB + POS_FACADE -> DB: Persist transfer state and participant position change + hnote over DB #lightyellow + INSERT **transferStateChange** transferStateId = 'COMMITTED' + + INSERT **participantPositionChange** + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + end note + activate DB + deactivate DB + deactivate POS_DAO + end + POS_FACADE --> POS_HANDLER: Return success + deactivate POS_FACADE + end + + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: commit || reserve, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Transfer event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS +end +deactivate POS_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.svg new file mode 100644 index 000000000..de29ad2c9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.svg @@ -0,0 +1,345 @@ + + + + + + + + + + + 1.3.2. Fulfil Position Handler Consume v1.1 + + + + Central Service + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + Notifications-Topic + + + + + Notifications-Topic + + + Position DAO + + + + + Position DAO + + + + + Position Facade + + + + + Position Facade + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Position Handler Consume + + + + + 1 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 2 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + transferParticipant + + + + + 3 + + + Return current state of transfer from DB + + + + + 4 + + + Return current state of transfer from DB + + + + + 5 + + + Validate current state (transferState is 'RECEIVED-FULFIL') + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + + + + + 6 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + DB TRANSACTION + + + + + 7 + + + Select participantPosition.value FOR UPDATE from DB for Payee + + + + participantPosition + + + + + 8 + + + Return participantPosition.value from DB for Payee + + + + + 9 + + + latestPosition + + + = participantPosition.value - payload.amount.amount + + + + + 10 + + + Persist latestPosition to DB for Payee + + + + UPDATE + + + participantPosition + + + SET value = latestPosition + + + + + 11 + + + Persist transfer state and participant position change + + + + INSERT + + + transferStateChange + + + transferStateId = 'COMMITTED' + + + INSERT + + + participantPositionChange + + + SET participantPositionId = participantPosition.participantPositionId, + + + transferStateChangeId = transferStateChange.transferStateChangeId, + + + value = latestPosition, + + + reservedValue = participantPosition.reservedValue + + + createdDate = new Date() + + + + + 12 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: transfer, + + + action: commit || reserve, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 13 + + + Publish Transfer event + + + Error code: + + + 2003 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.plantuml new file mode 100644 index 000000000..091fd6adf --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.plantuml @@ -0,0 +1,140 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.3.2. Fulfil Position Handler Consume + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER +collections "Notifications-Topic" as TOPIC_NOTIFICATIONS +entity "Position Facade" as POS_FACADE +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant POS_FACADE + participant DB +end box + +' start flow +activate POS_HANDLER +group Fulfil Position Handler Consume + POS_HANDLER -> POS_DAO: Request current state of transfer from DB \nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferState is 'RECEIVED-FULFIL')\nError code: 2001 + group Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + POS_HANDLER -> POS_FACADE: Request to persist latest position and state to DB\nError code: 2003 + group DB TRANSACTION + activate POS_FACADE + POS_FACADE -> DB: Select participantPosition.value FOR UPDATE from DB for Payee + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_FACADE: Return participantPosition.value from DB for Payee + deactivate DB + POS_FACADE <-> POS_FACADE: **latestPosition** = participantPosition.value - payload.amount.amount + POS_FACADE->DB: Persist latestPosition to DB for Payee + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value = latestPosition + end note + activate DB + deactivate DB + POS_FACADE -> DB: Persist transfer state and participant position change + hnote over DB #lightyellow + INSERT **transferStateChange** transferStateId = 'COMMITTED' + + INSERT **participantPositionChange** + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + end note + activate DB + deactivate DB + deactivate POS_DAO + end + POS_FACADE --> POS_HANDLER: Return success + deactivate POS_FACADE + end + + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Transfer event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS +end +deactivate POS_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.svg new file mode 100644 index 000000000..89ddaffd3 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.svg @@ -0,0 +1,345 @@ + + + + + + + + + + + 1.3.2. Fulfil Position Handler Consume + + + + Central Service + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + Notifications-Topic + + + + + Notifications-Topic + + + Position DAO + + + + + Position DAO + + + + + Position Facade + + + + + Position Facade + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Position Handler Consume + + + + + 1 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 2 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + transferParticipant + + + + + 3 + + + Return current state of transfer from DB + + + + + 4 + + + Return current state of transfer from DB + + + + + 5 + + + Validate current state (transferState is 'RECEIVED-FULFIL') + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + + + + + 6 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + DB TRANSACTION + + + + + 7 + + + Select participantPosition.value FOR UPDATE from DB for Payee + + + + participantPosition + + + + + 8 + + + Return participantPosition.value from DB for Payee + + + + + 9 + + + latestPosition + + + = participantPosition.value - payload.amount.amount + + + + + 10 + + + Persist latestPosition to DB for Payee + + + + UPDATE + + + participantPosition + + + SET value = latestPosition + + + + + 11 + + + Persist transfer state and participant position change + + + + INSERT + + + transferStateChange + + + transferStateId = 'COMMITTED' + + + INSERT + + + participantPositionChange + + + SET participantPositionId = participantPosition.participantPositionId, + + + transferStateChangeId = transferStateChange.transferStateChangeId, + + + value = latestPosition, + + + reservedValue = participantPosition.reservedValue + + + createdDate = new Date() + + + + + 12 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: transfer, + + + action: commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 13 + + + Publish Transfer event + + + Error code: + + + 2003 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.plantuml new file mode 100644 index 000000000..3301874a4 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.plantuml @@ -0,0 +1,306 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + * Sam Kummary + ------------- + ******'/ + +@startuml +' declate title +title 1.3.3. Abort Position Handler Consume + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER +entity "Position DAO" as POS_DAO +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Abort Position Handler Consume + opt type == 'position' && action == 'timeout-reserved' + POS_HANDLER -> POS_DAO: Request current state of transfer from DB\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferStateChange.transferStateId == 'RESERVED_TIMEOUT')\nError code: 2001 + + group Persist Position change and Transfer state + POS_HANDLER -> POS_HANDLER: **transferStateId** = 'EXPIRED_RESERVED' + POS_HANDLER -> POS_DAO: Request to persist latest position and state to DB\nError code: 2003 + group DB TRANSACTION IMPLEMENTATION + activate POS_DAO + POS_DAO -> DB: Select participantPosition.value FOR UPDATE for payerCurrencyId + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_DAO: Return participantPosition + deactivate DB + POS_DAO <-> POS_DAO: **latestPosition** = participantPosition - payload.amount.amount + POS_DAO->DB: Persist latestPosition to DB for Payer + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value = latestPosition + end note + activate DB + deactivate DB + POS_DAO -> DB: Persist participant position change and state change + hnote over DB #lightyellow + INSERT **transferStateChange** + VALUES (transferStateId) + + INSERT **participantPositionChange** + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + end note + activate DB + deactivate DB + end + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + opt type == 'position' && (action IN ['reject', 'abort']) + POS_HANDLER -> POS_DAO: Request current state of transfer from DB\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferStateChange.transferStateId IN ['RECEIVED_REJECT', 'RECEIVED_ERROR'])\nError code: 2001 + + group Persist Position change and Transfer state + POS_HANDLER -> POS_HANDLER: **transferStateId** = (action == 'reject' ? 'ABORTED_REJECTED' : 'ABORTED_ERROR' ) + POS_HANDLER -> POS_DAO: Request to persist latest position and state to DB\nError code: 2003 + group Refer to DB TRANSACTION IMPLEMENTATION above + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + participantPosition + transferStateChange + participantPositionChange + end note + end + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + alt action == 'reject' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: reject, + createdAt: , + state: { + status: "success", + code: 0, + description: "action successful" + } + } + } + } + end note + else action == 'abort' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + end + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + + ' TODO: We do not see how this scenario will be triggered + opt type == 'position' && action == 'fail' (Unable to currently trigger this scenario) + POS_HANDLER -> POS_DAO: Request current state of transfer from DB\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferStateChange.transferStateId == 'FAILED') + + group Persist Position change and Transfer state + POS_HANDLER -> POS_HANDLER: **transferStateId** = 'FAILED' + POS_HANDLER -> POS_DAO: Request to persist latest position and state to DB\nError code: 2003 + group Refer to DB TRANSACTION IMPLEMENTATION above + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + participantPosition + transferStateChange + participantPositionChange + end note + end + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3100, + "errorDescription": "Transfer failed", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end +end +deactivate POS_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.svg new file mode 100644 index 000000000..57c541a8c --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.svg @@ -0,0 +1,915 @@ + + + + + + + + + + + 1.3.3. Abort Position Handler Consume + + + + Central Service + + + + + + + + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Abort Position Handler Consume + + + + + opt + + + [type == 'position' && action == 'timeout-reserved'] + + + + + 1 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 2 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + transferParticipant + + + + + 3 + + + Return current state of transfer from DB + + + + + 4 + + + Return current state of transfer from DB + + + + + 5 + + + Validate current state (transferStateChange.transferStateId == 'RESERVED_TIMEOUT') + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer state + + + + + 6 + + + transferStateId + + + = 'EXPIRED_RESERVED' + + + + + 7 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + DB TRANSACTION IMPLEMENTATION + + + + + 8 + + + Select participantPosition.value FOR UPDATE for payerCurrencyId + + + + participantPosition + + + + + 9 + + + Return participantPosition + + + + + 10 + + + latestPosition + + + = participantPosition - payload.amount.amount + + + + + 11 + + + Persist latestPosition to DB for Payer + + + + UPDATE + + + participantPosition + + + SET value = latestPosition + + + + + 12 + + + Persist participant position change and state change + + + + INSERT + + + transferStateChange + + + VALUES (transferStateId) + + + INSERT + + + participantPositionChange + + + SET participantPositionId = participantPosition.participantPositionId, + + + transferStateChangeId = transferStateChange.transferStateChangeId, + + + value = latestPosition, + + + reservedValue = participantPosition.reservedValue + + + createdDate = new Date() + + + + + 13 + + + Return success + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Transfer expired", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 14 + + + Publish Notification event + + + Error code: + + + 2003 + + + + + opt + + + [type == 'position' && (action IN ['reject', 'abort'])] + + + + + 15 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 16 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + + + 17 + + + Return current state of transfer from DB + + + + + 18 + + + Return current state of transfer from DB + + + + + 19 + + + Validate current state (transferStateChange.transferStateId IN ['RECEIVED_REJECT', 'RECEIVED_ERROR']) + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer state + + + + + 20 + + + transferStateId + + + = (action == 'reject' ? 'ABORTED_REJECTED' : 'ABORTED_ERROR' ) + + + + + 21 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + Refer to + + + DB TRANSACTION IMPLEMENTATION + + + above + + + + + 22 + + + Persist to database + + + + participantPosition + + + transferStateChange + + + participantPositionChange + + + + + 23 + + + Return success + + + + + alt + + + [action == 'reject'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0, + + + description: "action successful" + + + } + + + } + + + } + + + } + + + + [action == 'abort'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <payload.errorInformation.errorCode || 5000> + + + description: <payload.errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 24 + + + Publish Notification event + + + Error code: + + + 2003 + + + + + opt + + + [type == 'position' && action == 'fail' (Unable to currently trigger this scenario)] + + + + + 25 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 26 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + + + 27 + + + Return current state of transfer from DB + + + + + 28 + + + Return current state of transfer from DB + + + + + 29 + + + Validate current state (transferStateChange.transferStateId == 'FAILED') + + + + + Persist Position change and Transfer state + + + + + 30 + + + transferStateId + + + = 'FAILED' + + + + + 31 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + Refer to + + + DB TRANSACTION IMPLEMENTATION + + + above + + + + + 32 + + + Persist to database + + + + participantPosition + + + transferStateChange + + + participantPositionChange + + + + + 33 + + + Return success + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3100, + + + "errorDescription": "Transfer failed", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 34 + + + Publish Notification event + + + Error code: + + + 2003 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.plantuml new file mode 100644 index 000000000..5b530af7b --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.plantuml @@ -0,0 +1,163 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.0. DFSP1 sends a Prepare Transfer request to DFSP2 + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "topic-transfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Event Handler" as PREP_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate PREP_HANDLER +activate POS_HANDLER +group DFSP1 sends a Prepare Transfer request to DFSP2 + note right of DFSP1 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "transferId": , + "payeeFsp": dfsp2, + "payerFsp": dfsp1, + "amount": { + "currency": "AED", + "amount": "string" + }, + "ilpPacket": "string", + "condition": "string", + "expiration": "string", + "extensionList": { + "extension": [ + { + "key": "string", + "value": "string" + } + ] + } + } + end note + DFSP1 ->> MLAPI: POST - /transfers + activate MLAPI + MLAPI -> MLAPI: Validate incoming token and originator matching Payer\nError codes: 3000-3002, 3100-3107 + note right of MLAPI #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: prepare, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_TRANSFER_PREPARE: Route & Publish Prepare event for Payer\nError code: 2003 + activate TOPIC_TRANSFER_PREPARE + TOPIC_TRANSFER_PREPARE <-> TOPIC_TRANSFER_PREPARE: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_TRANSFER_PREPARE --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_TRANSFER_PREPARE + MLAPI -->> DFSP1: Respond HTTP - 202 (Accepted) + deactivate MLAPI + ||| + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume message + ref over TOPIC_TRANSFER_PREPARE, PREP_HANDLER, TOPIC_TRANSFER_POSITION : Prepare Handler Consume\n + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, POS_HANDLER : Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + ref over DFSP2, TOPIC_NOTIFICATIONS : Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + ||| +end +deactivate POS_HANDLER +deactivate PREP_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.svg new file mode 100644 index 000000000..597c20f74 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.svg @@ -0,0 +1,455 @@ + + + + + + + + + + + 1.1.0. DFSP1 sends a Prepare Transfer request to DFSP2 + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + topic-transfer-prepare + + + + + topic-transfer-prepare + + + Prepare Event Handler + + + + + Prepare Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Event Handler + + + + + Position Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + DFSP1 sends a Prepare Transfer request to DFSP2 + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - transferMessage: + + + { + + + "transferId": <uuid>, + + + "payeeFsp": dfsp2, + + + "payerFsp": dfsp1, + + + "amount": { + + + "currency": "AED", + + + "amount": "string" + + + }, + + + "ilpPacket": "string", + + + "condition": "string", + + + "expiration": "string", + + + "extensionList": { + + + "extension": [ + + + { + + + "key": "string", + + + "value": "string" + + + } + + + ] + + + } + + + } + + + + 1 + + + POST - /transfers + + + + + 2 + + + Validate incoming token and originator matching Payer + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: prepare, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 3 + + + Route & Publish Prepare event for Payer + + + Error code: + + + 2003 + + + + + 4 + + + Ensure event is replicated as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 5 + + + Respond replication acknowledgements have been received + + + + + 6 + + + Respond HTTP - 202 (Accepted) + + + + + 7 + + + Consume message + + + + + ref + + + Prepare Handler Consume + + + + + 8 + + + Produce message + + + + + 9 + + + Consume message + + + + + ref + + + Position Handler Consume + + + + + 10 + + + Produce message + + + + + 11 + + + Consume message + + + + + ref + + + Send notification to Participant (Payee) + + + + + 12 + + + Send callback notification + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.plantuml new file mode 100644 index 000000000..4df26eef9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.plantuml @@ -0,0 +1,257 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + * Georgi Georgiev + * Rajiv Mothilal + * Samuel Kummary + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.1.a. Prepare Handler Consume (single message) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Event Handler" as PREP_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Position DAO" as POS_DAO +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate PREP_HANDLER +group Prepare Handler Consume + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume Prepare event message + activate TOPIC_TRANSFER_PREPARE + deactivate TOPIC_TRANSFER_PREPARE + + break + group Validate Event + PREP_HANDLER <-> PREP_HANDLER: Validate event - Rule: type == 'prepare' && action == 'prepare'\nError codes: 2001 + end + end + + group Persist Event Information + ||| + PREP_HANDLER -> TOPIC_EVENTS: Publish event information + ref over PREP_HANDLER, TOPIC_EVENTS: Event Handler Consume\n + ||| + end + + group Validate Prepare Transfer + PREP_HANDLER <-> PREP_HANDLER: Schema validation of the incoming message + PREP_HANDLER <-> PREP_HANDLER: Verify the message's signature (to be confirmed in future requirement) + note right of PREP_HANDLER #lightgrey + The above validation steps are already handled by + the ML-Adapter for the open source implementation. + It may need to be added in future for custom adapters. + end note + + group Validate Duplicate Check + ||| + PREP_HANDLER -> DB: Request Duplicate Check + ref over PREP_HANDLER, DB: Request Duplicate Check\n + DB --> PREP_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break + PREP_HANDLER -> PREP_HANDLER: stateRecord = await getTransferState(transferId) + alt endStateList.includes(stateRecord.transferStateId) + ||| + ref over PREP_HANDLER, TOPIC_NOTIFICATIONS: getTransfer callback\n + PREP_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else + note right of PREP_HANDLER #lightgrey + Ignore - resend in progress + end note + end + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of PREP_HANDLER #lightgrey + Validate Prepare Transfer (failure) - Modified Request + end note + else hasDuplicateId == FALSE + group Validate Payer + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payer Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payer\nError codes: 3202 + end + group Validate Payee + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payee Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payee\nError codes: 3203 + end + + alt Validate Prepare Transfer (success) + group Persist Transfer State (with transferState='RECEIVED-PREPARE') + PREP_HANDLER -> POS_DAO: Request to persist transfer\nError codes: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer + hnote over DB #lightyellow + transfer + transferParticipant + transferStateChange + transferExtension + ilpPacket + end note + activate DB + deactivate DB + POS_DAO --> PREP_HANDLER: Return success + deactivate POS_DAO + end + else Validate Prepare Transfer (failure) + group Persist Transfer State (with transferState='INVALID') (Introducing a new status INVALID to mark these entries) + PREP_HANDLER -> POS_DAO: Request to persist transfer\n(when Payee/Payer/crypto-condition validation fails)\nError codes: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer + hnote over DB #lightyellow + transfer + transferParticipant + transferStateChange + transferExtension + transferError + ilpPacket + end note + activate DB + deactivate DB + POS_DAO --> PREP_HANDLER: Return success + deactivate POS_DAO + end + end + end + end + + alt Validate Prepare Transfer (success) + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer\nError codes: 2003 + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Prepare Transfer (failure) + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": + "errorDescription": "", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: prepare, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + PREP_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError codes: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end +end +deactivate PREP_HANDLER +@enduml + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.svg new file mode 100644 index 000000000..65895c97b --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.svg @@ -0,0 +1,738 @@ + + + + + + + + + + + 1.1.1.a. Prepare Handler Consume (single message) + + + + Central Service + + + + + + + + + + + + + + + + + + + + topic-transfer-prepare + + + + + topic-transfer-prepare + + + Prepare Event Handler + + + + + Prepare Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + Position DAO + + + + + Position DAO + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Prepare Handler Consume + + + + + 1 + + + Consume Prepare event message + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'prepare' && action == 'prepare' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate Prepare Transfer + + + + + 4 + + + Schema validation of the incoming message + + + + + 5 + + + Verify the message's signature (to be confirmed in future requirement) + + + + + The above validation steps are already handled by + + + the ML-Adapter for the open source implementation. + + + It may need to be added in future for custom adapters. + + + + + Validate Duplicate Check + + + + + 6 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check + + + + + 7 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + break + + + + + 8 + + + stateRecord = await getTransferState(transferId) + + + + + alt + + + [endStateList.includes(stateRecord.transferStateId)] + + + + + ref + + + getTransfer callback + + + + + 9 + + + Produce message + + + + + + Ignore - resend in progress + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + Validate Prepare Transfer (failure) - Modified Request + + + + [hasDuplicateId == FALSE] + + + + + Validate Payer + + + + + 10 + + + Request to retrieve Payer Participant details (if it exists) + + + + + 11 + + + Request Participant details + + + + participant + + + participantCurrency + + + + + 12 + + + Return Participant details if it exists + + + + + 13 + + + Return Participant details if it exists + + + + + 14 + + + Validate Payer + + + Error codes: + + + 3202 + + + + + Validate Payee + + + + + 15 + + + Request to retrieve Payee Participant details (if it exists) + + + + + 16 + + + Request Participant details + + + + participant + + + participantCurrency + + + + + 17 + + + Return Participant details if it exists + + + + + 18 + + + Return Participant details if it exists + + + + + 19 + + + Validate Payee + + + Error codes: + + + 3203 + + + + + alt + + + [Validate Prepare Transfer (success)] + + + + + Persist Transfer State (with transferState='RECEIVED-PREPARE') + + + + + 20 + + + Request to persist transfer + + + Error codes: + + + 2003 + + + + + 21 + + + Persist transfer + + + + transfer + + + transferParticipant + + + transferStateChange + + + transferExtension + + + ilpPacket + + + + + 22 + + + Return success + + + + [Validate Prepare Transfer (failure)] + + + + + Persist Transfer State (with transferState='INVALID') (Introducing a new status INVALID to mark these entries) + + + + + 23 + + + Request to persist transfer + + + (when Payee/Payer/crypto-condition validation fails) + + + Error codes: + + + 2003 + + + + + 24 + + + Persist transfer + + + + transfer + + + transferParticipant + + + transferStateChange + + + transferExtension + + + transferError + + + ilpPacket + + + + + 25 + + + Return success + + + + + alt + + + [Validate Prepare Transfer (success)] + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 26 + + + Route & Publish Position event for Payer + + + Error codes: + + + 2003 + + + + [Validate Prepare Transfer (failure)] + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <ledgerName>, + + + to: <transferMessage.payerFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": <possible codes: [2003, 3100, 3105, 3106, 3202, 3203, 3300, 3301]> + + + "errorDescription": "<refer to section 35.1.3 for description>", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 27 + + + Publish Notification (failure) event for Payer + + + Error codes: + + + 2003 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml new file mode 100644 index 000000000..1b01ef9c5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml @@ -0,0 +1,186 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.1.b. Prepare Handler Consume (batch messages) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Event Handler" as PREP_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Position DAO" as POS_DAO +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate PREP_HANDLER +group Prepare Handler Consume + note over TOPIC_TRANSFER_PREPARE #LightSalmon + This flow has not been implemented + end note + + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume Prepare event batch of messages for Payer + activate TOPIC_TRANSFER_PREPARE + deactivate TOPIC_TRANSFER_PREPARE + group Persist Event Information + ||| + PREP_HANDLER -> TOPIC_EVENTS: Publish event information + ref over PREP_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + + group Fetch batch Payer information + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve batch of Payer Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payer + PREP_HANDLER -> PREP_HANDLER: store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYER + end + + group Fetch batch Payee information + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve batch of Payee Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payee + PREP_HANDLER -> PREP_HANDLER: store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYEE + end + + group Fetch batch of transfers + PREP_HANDLER -> POS_DAO: Request to retrieve batch of Transfers (if it exists) + activate POS_DAO + POS_DAO -> DB: Request batch of Transfers + hnote over DB #lightyellow + transfer + end note + activate DB + POS_DAO <-- DB: Return batch of Transfers (if it exists) + deactivate DB + POS_DAO --> PREP_HANDLER: Return batch of Transfer (if it exists) + deactivate POS_DAO + PREP_HANDLER -> PREP_HANDLER: store result set in var: $LIST_TRANSFERS + end + + loop for each message in batch + + group Validate Prepare Transfer + group Validate Payer + PREP_HANDLER <-> PREP_HANDLER: Validate Payer against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYER + end + group Validate Payee + PREP_HANDLER <-> PREP_HANDLER: Validate Payee against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYEE + end + group Duplicate check + PREP_HANDLER <-> PREP_HANDLER: Validate duplicate Check against in-memory var $LIST_TRANSFERS + end + PREP_HANDLER <-> PREP_HANDLER: Validate amount + PREP_HANDLER <-> PREP_HANDLER: Validate crypto-condition + PREP_HANDLER <-> PREP_HANDLER: Validate message signature (to be confirmed in future requirement) + end + + group Persist Transfer State (with transferState='RECEIVED' on validation pass) + PREP_HANDLER -> POS_DAO: Request to persist transfer + activate POS_DAO + POS_DAO -> DB: Persist transfer + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + POS_DAO --> PREP_HANDLER: Return success + deactivate POS_DAO + end + + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end +end +deactivate PREP_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.svg new file mode 100644 index 000000000..13489faa8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.svg @@ -0,0 +1,497 @@ + + + + + + + + + + + 1.1.1.b. Prepare Handler Consume (batch messages) + + + + Central Service + + + + + + + + + + + topic-transfer-prepare + + + + + topic-transfer-prepare + + + Prepare Event Handler + + + + + Prepare Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + Position DAO + + + + + Position DAO + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Prepare Handler Consume + + + + + This flow has not been implemented + + + + + 1 + + + Consume Prepare event batch of messages for Payer + + + + + Persist Event Information + + + + + 2 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Fetch batch Payer information + + + + + 3 + + + Request to retrieve batch of Payer Participant details (if it exists) + + + + + 4 + + + Request Participant details + + + + participant + + + + + 5 + + + Return Participant details if it exists + + + + + 6 + + + Return Participant details if it exists + + + + + 7 + + + Validate Payer + + + + + 8 + + + store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYER + + + + + Fetch batch Payee information + + + + + 9 + + + Request to retrieve batch of Payee Participant details (if it exists) + + + + + 10 + + + Request Participant details + + + + participant + + + + + 11 + + + Return Participant details if it exists + + + + + 12 + + + Return Participant details if it exists + + + + + 13 + + + Validate Payee + + + + + 14 + + + store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYEE + + + + + Fetch batch of transfers + + + + + 15 + + + Request to retrieve batch of Transfers (if it exists) + + + + + 16 + + + Request batch of Transfers + + + + transfer + + + + + 17 + + + Return batch of Transfers (if it exists) + + + + + 18 + + + Return batch of Transfer (if it exists) + + + + + 19 + + + store result set in var: $LIST_TRANSFERS + + + + + loop + + + [for each message in batch] + + + + + Validate Prepare Transfer + + + + + Validate Payer + + + + + 20 + + + Validate Payer against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYER + + + + + Validate Payee + + + + + 21 + + + Validate Payee against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYEE + + + + + Duplicate check + + + + + 22 + + + Validate duplicate Check against in-memory var $LIST_TRANSFERS + + + + + 23 + + + Validate amount + + + + + 24 + + + Validate crypto-condition + + + + + 25 + + + Validate message signature (to be confirmed in future requirement) + + + + + Persist Transfer State (with transferState='RECEIVED' on validation pass) + + + + + 26 + + + Request to persist transfer + + + + + 27 + + + Persist transfer + + + + transferStateChange + + + + + 28 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 29 + + + Route & Publish Position event for Payer + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.plantuml new file mode 100644 index 000000000..abec38aa9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.plantuml @@ -0,0 +1,249 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.2.a. Position Handler Consume (single message) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +entity "Position DAO" as POS_DAO +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'prepare' + end + end + + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + + alt Calulate & Validate Latest Position (success) + group Calculate position and persist change + POS_HANDLER -> POS_DAO: Request latest position from DB for Payer + activate POS_DAO + POS_DAO -> DB: Retrieve latest position from DB for Payer + activate DB + hnote over DB #lightyellow + transferPosition + end note + DB --> POS_DAO: Retrieve latest position from DB for Payer + deactivate DB + POS_DAO --> POS_HANDLER: Return latest position + deactivate POS_DAO + + POS_HANDLER -> PARTICIPANT_DAO: Request position limits for Payer Participant + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request position limits for Payer Participant + activate DB + hnote over DB #lightyellow + participant + participantLimit + end note + DB --> PARTICIPANT_DAO: Return position limits + deactivate DB + deactivate DB + PARTICIPANT_DAO --> POS_HANDLER: Return position limits + deactivate PARTICIPANT_DAO + + POS_HANDLER <-> POS_HANDLER: Calculate latest position (lpos) for prepare + POS_HANDLER <-> POS_HANDLER: Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + POS_HANDLER -> POS_DAO: Request to persist latest position for Payer + activate POS_DAO + POS_DAO -> DB: Persist latest position to DB for Payer + hnote over DB #lightyellow + transferPosition + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + + group Persist Transfer State (with transferState='RESERVED' on position check pass) + POS_HANDLER -> POS_DAO: Request to persist transfer + activate POS_DAO + POS_DAO -> DB: Persist transfer state + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event to Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else Calculate & Validate Latest Position (failure) + group Calculate position and persist change + POS_HANDLER -> POS_DAO: Request latest position from DB for Payer + activate POS_DAO + POS_DAO -> DB: Retrieve latest position from DB for Payer + activate DB + hnote over DB #lightyellow + transferPosition + end note + DB --> POS_DAO: Retrieve latest position from DB for Payer + deactivate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return latest position + deactivate POS_DAO + + POS_HANDLER -> PARTICIPANT_DAO: Request position limits for Payer Participant + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request position limits for Payer Participant + activate DB + hnote over DB #lightyellow + participant + participantLimit + end note + DB --> PARTICIPANT_DAO: Return position limits + deactivate DB + deactivate DB + PARTICIPANT_DAO --> POS_HANDLER: Return position limits + deactivate PARTICIPANT_DAO + + POS_HANDLER <-> POS_HANDLER: Calculate latest position (lpos) for prepare + POS_HANDLER <-> POS_HANDLER: Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + note right of POS_HANDLER #red: Validation failure! + end + + group Persist Transfer State (with transferState='ABORTED' on position check pass) + POS_HANDLER -> POS_DAO: Request to persist transfer + activate POS_DAO + POS_DAO -> DB: Persist transfer state + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: prepare, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + deactivate POS_HANDLER + end +end +deactivate POS_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.svg new file mode 100644 index 000000000..2a0857acf --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.svg @@ -0,0 +1,633 @@ + + + + + + + + + + + 1.1.2.a. Position Handler Consume (single message) + + + + Central Service + + + + + + + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Event Handler + + + + + Position Event Handler + + + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + Position DAO + + + + + Position DAO + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Position Handler Consume + + + + + 1 + + + Consume Position event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'position' && action == 'prepare' + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + alt + + + [Calulate & Validate Latest Position (success)] + + + + + Calculate position and persist change + + + + + 4 + + + Request latest position from DB for Payer + + + + + 5 + + + Retrieve latest position from DB for Payer + + + + transferPosition + + + + + 6 + + + Retrieve latest position from DB for Payer + + + + + 7 + + + Return latest position + + + + + 8 + + + Request position limits for Payer Participant + + + + + 9 + + + Request position limits for Payer Participant + + + + participant + + + participantLimit + + + + + 10 + + + Return position limits + + + + + 11 + + + Return position limits + + + + + 12 + + + Calculate latest position (lpos) for prepare + + + + + 13 + + + Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + + + + 14 + + + Request to persist latest position for Payer + + + + + 15 + + + Persist latest position to DB for Payer + + + + transferPosition + + + + + 16 + + + Return success + + + + + Persist Transfer State (with transferState='RESERVED' on position check pass) + + + + + 17 + + + Request to persist transfer + + + + + 18 + + + Persist transfer state + + + + transferStateChange + + + + + 19 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: transfer, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 20 + + + Publish Notification event to Payee + + + + [Calculate & Validate Latest Position (failure)] + + + + + Calculate position and persist change + + + + + 21 + + + Request latest position from DB for Payer + + + + + 22 + + + Retrieve latest position from DB for Payer + + + + transferPosition + + + + + 23 + + + Retrieve latest position from DB for Payer + + + + + 24 + + + Return latest position + + + + + 25 + + + Request position limits for Payer Participant + + + + + 26 + + + Request position limits for Payer Participant + + + + participant + + + participantLimit + + + + + 27 + + + Return position limits + + + + + 28 + + + Return position limits + + + + + 29 + + + Calculate latest position (lpos) for prepare + + + + + 30 + + + Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + + + + Validation failure! + + + + + Persist Transfer State (with transferState='ABORTED' on position check pass) + + + + + 31 + + + Request to persist transfer + + + + + 32 + + + Persist transfer state + + + + transferStateChange + + + + + 33 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <ledgerName>, + + + to: <transferMessage.payerFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 4001, + + + "errorDescription": "Payer FSP insufficient liquidity", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 34 + + + Publish Notification (failure) event for Payer + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml new file mode 100644 index 000000000..9e9bc1ff9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml @@ -0,0 +1,148 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.2.b. Position Handler Consume (batch messages) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Transfer-Topic" as TOPIC_TRANSFERS +entity "Position DAO" as POS_DAO +entity "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Transfer DAO" as TRANS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_TRANSFERS + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant TRANS_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + note over TOPIC_TRANSFER_POSITION #LightSalmon + This flow has not been implemented + end note + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event batch of messages for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + + loop for each message in batch + group Calculate position and persist change + POS_HANDLER -> POS_DAO: Request latest position from DB for Payer + activate POS_DAO + POS_DAO -> DB: Retrieve latest position from DB for Payer + hnote over DB #lightyellow + transferPosition + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return latest position + deactivate POS_DAO + + POS_HANDLER <-> POS_HANDLER: Calculate latest position (lpos) by incrementing transfer for prepare + POS_HANDLER <-> POS_HANDLER: Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + POS_HANDLER -> POS_DAO: Request to persist latest position for Payer + activate POS_DAO + POS_DAO -> DB: Persist latest position to DB for Payer + hnote over DB #lightyellow + transferPosition + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + group Persist Transfer State (with transferState='RESERVED' on position check pass) + POS_HANDLER -> TRANS_DAO: Request to persist batch transfer + activate TRANS_DAO + TRANS_DAO -> DB: Persist batch transfer + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + TRANS_DAO --> POS_HANDLER: Return success + deactivate TRANS_DAO + end + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_TRANSFERS: Publish Transfer event + activate TOPIC_TRANSFERS + deactivate TOPIC_TRANSFERS + end +end +deactivate POS_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.svg new file mode 100644 index 000000000..3b1dd63b4 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.svg @@ -0,0 +1,342 @@ + + + + + + + + + + + 1.1.2.b. Position Handler Consume (batch messages) + + + + Central Service + + + + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Event Handler + + + + + Position Event Handler + + + + + + + Transfer-Topic + + + + + Transfer-Topic + + + Event-Topic + + + + + Event-Topic + + + + + + + Notification-Topic + + + + + Notification-Topic + + + Position DAO + + + + + Position DAO + + + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Position Handler Consume + + + + + This flow has not been implemented + + + + + 1 + + + Consume Position event batch of messages for Payer + + + + + Persist Event Information + + + + + 2 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + loop + + + [for each message in batch] + + + + + Calculate position and persist change + + + + + 3 + + + Request latest position from DB for Payer + + + + + 4 + + + Retrieve latest position from DB for Payer + + + + transferPosition + + + + + 5 + + + Return latest position + + + + + 6 + + + Calculate latest position (lpos) by incrementing transfer for prepare + + + + + 7 + + + Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + + + + 8 + + + Request to persist latest position for Payer + + + + + 9 + + + Persist latest position to DB for Payer + + + + transferPosition + + + + + 10 + + + Return success + + + + + Persist Transfer State (with transferState='RESERVED' on position check pass) + + + + + 11 + + + Request to persist batch transfer + + + + + 12 + + + Persist batch transfer + + + + transferStateChange + + + + + 13 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: transfer, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 14 + + + Publish Transfer event + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.plantuml new file mode 100644 index 000000000..fc35e5b8b --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.plantuml @@ -0,0 +1,123 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Shashikant Hirugade + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) v1.1 + +autonumber + +' Actor Keys: +' actor - Payer DFSP, Payee DFSP +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "Payer DFSP\nParticipant" as PAYER_DFSP +actor "Payee DFSP\nParticipant" as PAYEE_DFSP +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +collections "Event-Topic" as TOPIC_EVENTS +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Financial Service Provider (Payer)" #lightGray + participant PAYER_DFSP +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant TOPIC_NOTIFICATIONS + participant CSAPI + participant TOPIC_EVENTS + participant PARTICIPANT_DAO + participant DB +end box + +box "Financial Service Provider (Payee)" #lightGray + participant PAYEE_DFSP +end box + +' start flow +activate NOTIFY_HANDLER +group Send notification to Participants + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume Notification event + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + + group Persist Event Information + NOTIFY_HANDLER -> CSAPI: Request to persist event information - POST - /events + activate CSAPI + CSAPI -> TOPIC_EVENTS: Publish event information + activate TOPIC_EVENTS + ||| + ref over TOPIC_EVENTS : Event Handler Consume\n + ||| + TOPIC_EVENTS --> CSAPI: Return success + deactivate TOPIC_EVENTS + CSAPI --> NOTIFY_HANDLER: Return success + deactivate CSAPI + end + note right of NOTIFY_HANDLER #lightgray + The endpoint details are cached, when the cache + expires, the details are fetched again + end note + NOTIFY_HANDLER -> CSAPI: Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints\nError code: 2003 + + activate CSAPI + CSAPI -> PARTICIPANT_DAO: Fetch Endpoint details for Participant\nError code: 2003 + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch Endpoint details for Participant + activate DB + hnote over DB #lightyellow + participantEndpoint + end note + DB -> PARTICIPANT_DAO: Retrieved Endpoint details for Participant + deactivate DB + PARTICIPANT_DAO --> CSAPI: Return Endpoint details for Participant + deactivate PARTICIPANT_DAO + CSAPI --> NOTIFY_HANDLER: Return Endpoint details for Participant\nError codes: 3202, 3203 + deactivate CSAPI + NOTIFY_HANDLER -> PAYER_DFSP: Notification with Prepare/fulfil result/error to \nPayer DFSP to specified Endpoint - PUT \nError code: 1001 + NOTIFY_HANDLER <-- PAYER_DFSP: HTTP 200 OK + alt event.action === 'reserve' + alt event.status === 'success' + NOTIFY_HANDLER -> PAYEE_DFSP: Notification to with succesful fulfil result (committed) to Payee DFSP to specified Endpoint - PATCH \nError code: 1001 + ||| + NOTIFY_HANDLER <-- PAYEE_DFSP: HTTP 200 OK + end + end +end +deactivate NOTIFY_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.svg new file mode 100644 index 000000000..7461e0ab9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.svg @@ -0,0 +1,326 @@ + + + + + + + + + + + 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) v1.1 + + + + Financial Service Provider (Payer) + + + + ML API Adapter Service + + + + Central Service + + + + Financial Service Provider (Payee) + + + + + + + + Payer DFSP + + + Participant + + + + + Payer DFSP + + + Participant + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + Central Service API + + + + + Central Service API + + + + + + + Event-Topic + + + + + Event-Topic + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + Payee DFSP + + + Participant + + + + + Payee DFSP + + + Participant + + + + + + + + Send notification to Participants + + + + + 1 + + + Consume Notification event + + + + + Persist Event Information + + + + + 2 + + + Request to persist event information - POST - /events + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + 4 + + + Return success + + + + + 5 + + + Return success + + + + + The endpoint details are cached, when the cache + + + expires, the details are fetched again + + + + + 6 + + + Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints + + + Error code: + + + 2003 + + + + + 7 + + + Fetch Endpoint details for Participant + + + Error code: + + + 2003 + + + + + 8 + + + Fetch Endpoint details for Participant + + + + participantEndpoint + + + + + 9 + + + Retrieved Endpoint details for Participant + + + + + 10 + + + Return Endpoint details for Participant + + + + + 11 + + + Return Endpoint details for Participant + + + Error codes: + + + 3202, 3203 + + + + + 12 + + + Notification with Prepare/fulfil result/error to + + + Payer DFSP to specified Endpoint - PUT + + + Error code: + + + 1001 + + + + + 13 + + + HTTP 200 OK + + + + + alt + + + [event.action === 'reserve'] + + + + + alt + + + [event.status === 'success'] + + + + + 14 + + + Notification to with succesful fulfil result (committed) to Payee DFSP to specified Endpoint - PATCH + + + Error code: + + + 1001 + + + + + 15 + + + HTTP 200 OK + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.plantuml new file mode 100644 index 000000000..b96130bf1 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.plantuml @@ -0,0 +1,120 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declate title +title 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) + +autonumber + +' Actor Keys: +' actor - Payer DFSP, Payee DFSP +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "Payer DFSP\nParticipant" as PAYER_DFSP +actor "Payee DFSP\nParticipant" as PAYEE_DFSP +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +collections "Event-Topic" as TOPIC_EVENTS +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Financial Service Provider (Payer)" #lightGray + participant PAYER_DFSP +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant TOPIC_NOTIFICATIONS + participant CSAPI + participant TOPIC_EVENTS + participant PARTICIPANT_DAO + participant DB +end box + +box "Financial Service Provider (Payee)" #lightGray + participant PAYEE_DFSP +end box + +' start flow +activate NOTIFY_HANDLER +group Send notification to Participants + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume Notification event + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + + group Persist Event Information + NOTIFY_HANDLER -> CSAPI: Request to persist event information - POST - /events + activate CSAPI + CSAPI -> TOPIC_EVENTS: Publish event information + activate TOPIC_EVENTS + ||| + ref over TOPIC_EVENTS : Event Handler Consume\n + ||| + TOPIC_EVENTS --> CSAPI: Return success + deactivate TOPIC_EVENTS + CSAPI --> NOTIFY_HANDLER: Return success + deactivate CSAPI + end + note right of NOTIFY_HANDLER #lightgray + The endpoint details are cached, when the cache + expires, the details are fetched again + end note + NOTIFY_HANDLER -> CSAPI: Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints\nError code: 2003 + + activate CSAPI + CSAPI -> PARTICIPANT_DAO: Fetch Endpoint details for Participant\nError code: 2003 + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch Endpoint details for Participant + activate DB + hnote over DB #lightyellow + participantEndpoint + end note + DB -> PARTICIPANT_DAO: Retrieved Endpoint details for Participant + deactivate DB + PARTICIPANT_DAO --> CSAPI: Return Endpoint details for Participant + deactivate PARTICIPANT_DAO + CSAPI --> NOTIFY_HANDLER: Return Endpoint details for Participant\nError codes: 3202, 3203 + deactivate CSAPI + NOTIFY_HANDLER -> PAYER_DFSP: Notification with Prepare/fulfil result/error to \nPayer DFSP to specified Endpoint - PUT \nError code: 1001 + NOTIFY_HANDLER <-- PAYER_DFSP: HTTP 200 OK + alt Config.SEND_TRANSFER_CONFIRMATION_TO_PAYEE === true + NOTIFY_HANDLER -> PAYEE_DFSP: Notification to with fulfil result (committed/aborted/rejected) to Payee DFSP to specified Endpoint - PUT \nError code: 1001 + ||| + NOTIFY_HANDLER <-- PAYEE_DFSP: HTTP 200 OK + end +end +deactivate NOTIFY_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.svg new file mode 100644 index 000000000..de654e47e --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.svg @@ -0,0 +1,317 @@ + + + + + + + + + + + 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) + + + + Financial Service Provider (Payer) + + + + ML API Adapter Service + + + + Central Service + + + + Financial Service Provider (Payee) + + + + + + + Payer DFSP + + + Participant + + + + + Payer DFSP + + + Participant + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + Central Service API + + + + + Central Service API + + + + + + + Event-Topic + + + + + Event-Topic + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + Payee DFSP + + + Participant + + + + + Payee DFSP + + + Participant + + + + + + + + Send notification to Participants + + + + + 1 + + + Consume Notification event + + + + + Persist Event Information + + + + + 2 + + + Request to persist event information - POST - /events + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + 4 + + + Return success + + + + + 5 + + + Return success + + + + + The endpoint details are cached, when the cache + + + expires, the details are fetched again + + + + + 6 + + + Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints + + + Error code: + + + 2003 + + + + + 7 + + + Fetch Endpoint details for Participant + + + Error code: + + + 2003 + + + + + 8 + + + Fetch Endpoint details for Participant + + + + participantEndpoint + + + + + 9 + + + Retrieved Endpoint details for Participant + + + + + 10 + + + Return Endpoint details for Participant + + + + + 11 + + + Return Endpoint details for Participant + + + Error codes: + + + 3202, 3203 + + + + + 12 + + + Notification with Prepare/fulfil result/error to + + + Payer DFSP to specified Endpoint - PUT + + + Error code: + + + 1001 + + + + + 13 + + + HTTP 200 OK + + + + + alt + + + [Config.SEND_TRANSFER_CONFIRMATION_TO_PAYEE === true] + + + + + 14 + + + Notification to with fulfil result (committed/aborted/rejected) to Payee DFSP to specified Endpoint - PUT + + + Error code: + + + 1001 + + + + + 15 + + + HTTP 200 OK + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml new file mode 100644 index 000000000..0c5c5fb5d --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml @@ -0,0 +1,108 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.4.b. Send notification to Participant (Payer/Payee) (batch messages) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP(n)\nParticipant" as DFSP +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +collections "Event-Topic" as TOPIC_EVENTS +entity "Notification DAO" as NOTIFY_DAO +database "Central Store" as DB + +box "Financial Service Provider" #lightGray + participant DFSP +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow +participant TOPIC_NOTIFICATIONS + participant CSAPI + participant TOPIC_EVENTS + participant EVENT_DAO + participant NOTIFY_DAO + participant DB +end box + +' start flow +activate NOTIFY_HANDLER +group Send notification to Participant + note over DFSP #LightSalmon + This flow has not been implemented + end note + + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: **Consume Notifications event batch of messages for Participant** + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + loop for each message in batch + group Persist Event Information + NOTIFY_HANDLER -> CSAPI: Request to persist event information - POST - /events + activate CSAPI + CSAPI -> TOPIC_EVENTS: Publish event information + activate TOPIC_EVENTS + ||| + ref over TOPIC_EVENTS : Event Handler Consume\n + ||| + TOPIC_EVENTS --> CSAPI: Return success + deactivate TOPIC_EVENTS + CSAPI --> NOTIFY_HANDLER: Return success + deactivate CSAPI + end + NOTIFY_HANDLER -> CSAPI: Request Notifications details for Participant - GET - /notifications/DFPS(n) + activate CSAPI + CSAPI -> NOTIFY_DAO: Fetch Notifications details for Participant + activate NOTIFY_DAO + NOTIFY_DAO -> DB: Fetch Notifications details for Participant + activate DB + hnote over DB #lightyellow + transferPosition + end note + DB --> NOTIFY_DAO: Retrieved Notification details for Participant + 'deactivate DB + NOTIFY_DAO --> CSAPI: Return Notifications details for Participant + deactivate NOTIFY_DAO + CSAPI --> NOTIFY_HANDLER: Return Notifications details for Participant + deactivate CSAPI + NOTIFY_HANDLER --> DFSP: Callback with Prepare result to Participant to specified URL - PUT - />/transfers + end +end +deactivate NOTIFY_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.svg new file mode 100644 index 000000000..6e972084c --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.svg @@ -0,0 +1,246 @@ + + + + + + + + + + + 1.1.4.b. Send notification to Participant (Payer/Payee) (batch messages) + + + + Financial Service Provider + + + + ML API Adapter Service + + + + Central Service + + + + + + + + DFSP(n) + + + Participant + + + + + DFSP(n) + + + Participant + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + Central Service API + + + + + Central Service API + + + + + + + Event-Topic + + + + + Event-Topic + + + + EVENT_DAO + + + + EVENT_DAO + + + Notification DAO + + + + + Notification DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Send notification to Participant + + + + + This flow has not been implemented + + + + + 1 + + + Consume Notifications event batch of messages for Participant + + + + + loop + + + [for each message in batch] + + + + + Persist Event Information + + + + + 2 + + + Request to persist event information - POST - /events + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + 4 + + + Return success + + + + + 5 + + + Return success + + + + + 6 + + + Request Notifications details for Participant - GET - /notifications/DFPS(n) + + + + + 7 + + + Fetch Notifications details for Participant + + + + + 8 + + + Fetch Notifications details for Participant + + + + transferPosition + + + + + 9 + + + Retrieved Notification details for Participant + + + + + 10 + + + Return Notifications details for Participant + + + + + 11 + + + Return Notifications details for Participant + + + + + 12 + + + Callback with Prepare result to Participant to specified URL - PUT - /<dfsp-host>>/transfers + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.plantuml new file mode 100644 index 000000000..45f7fd524 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.plantuml @@ -0,0 +1,143 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER + +' collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +' control "Position Event Handler" as POS_HANDLER +' collections "Event-Topic" as TOPIC_EVENTS +' collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +group DFSP2 sends an error callback to reject a transfer with an errorCode and description + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + } + end note + DFSP2 ->> MLAPI: **PUT - /transfers//error** + + activate MLAPI + MLAPI -> MLAPI: Validate incoming token and originator matching Payee + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Fulfil event for Payee + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all) + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + FULF_HANDLER -> FULF_HANDLER: Log error message + note right of FULF_HANDLER: (corresponding to a Fulfil message with transferState='ABORTED')\naction REJECT is not allowed into fulfil handler +end +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.svg new file mode 100644 index 000000000..d00bef23e --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.svg @@ -0,0 +1,341 @@ + + + + + + + + + + + 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + + DFSP2 sends an error callback to reject a transfer with an errorCode and description + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - transferMessage: + + + { + + + "errorInformation": { + + + "errorCode": <errorCode>, + + + "errorDescription": <errorDescription>, + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + } + + + + 1 + + + PUT - /transfers/<ID>/error + + + + + 2 + + + Validate incoming token and originator matching Payee + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 3 + + + Route & Publish Fulfil event for Payee + + + + + 4 + + + Ensure event is replicated as configured (ACKS=all) + + + + + 5 + + + Respond replication acknowledgements have been received + + + + + 6 + + + Respond HTTP - 200 (OK) + + + + + 7 + + + Consume message + + + + + 8 + + + Log error message + + + + + (corresponding to a Fulfil message with transferState='ABORTED') + + + action REJECT is not allowed into fulfil handler + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.plantuml new file mode 100644 index 000000000..ec02b5318 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.plantuml @@ -0,0 +1,166 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- +******'/ + +@startuml +' declate title +title 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate POS_HANDLER +group DFSP2 sends a Fulfil Success Transfer request + DFSP2 <-> DFSP2: During processing of an incoming\nPOST /transfers request, some processing\nerror occurred and an Error callback is made + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - errorMessage: + { + errorInformation + { + "errorCode": , + "errorDescription": + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + } + end note + DFSP2 ->> MLAPI: PUT - /transfers//error + activate MLAPI + MLAPI -> MLAPI: Validate incoming originator matching Payee\nError codes: 3000-3002, 3100-3107 + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Abort event for Payee\nError code: 2003 + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Abort)\n + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Abort)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'abort' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'abort' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +deactivate POS_HANDLER +deactivate FULF_HANDLER +deactivate NOTIFY_HANDLER +@enduml \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.svg new file mode 100644 index 000000000..dd1fc3063 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.svg @@ -0,0 +1,495 @@ + + + + + + + + + + + 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Event Handler + + + + + Position Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + DFSP2 sends a Fulfil Success Transfer request + + + + + 1 + + + During processing of an incoming + + + POST /transfers request, some processing + + + error occurred and an Error callback is made + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - errorMessage: + + + { + + + errorInformation + + + { + + + "errorCode": <errorCode>, + + + "errorDescription": <errorDescription> + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + } + + + + 2 + + + PUT - /transfers/<ID>/error + + + + + 3 + + + Validate incoming originator matching Payee + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <errorMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 4 + + + Route & Publish Abort event for Payee + + + Error code: + + + 2003 + + + + + 5 + + + Ensure event is replicated as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 6 + + + Respond replication acknowledgements have been received + + + + + 7 + + + Respond HTTP - 200 (OK) + + + + + 8 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (Abort) + + + + + 9 + + + Produce message + + + + + 10 + + + Consume message + + + + + ref + + + Position Handler Consume (Abort) + + + + + 11 + + + Produce message + + + + + 12 + + + Consume message + + + + + opt + + + [action == 'abort'] + + + + + ref + + + Send notification to Participant (Payer) + + + + + 13 + + + Send callback notification + + + + + 14 + + + Consume message + + + + + opt + + + [action == 'abort'] + + + + + ref + + + Send notification to Participant (Payee) + + + + + 15 + + + Send callback notification + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.plantuml new file mode 100644 index 000000000..f7c9c3c06 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.plantuml @@ -0,0 +1,166 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- +******'/ + +@startuml +' declate title +title 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate POS_HANDLER +group DFSP2 sends a Fulfil Success Transfer request + DFSP2 <-> DFSP2: During processing of an incoming\nPOST /transfers request, some processing\nerror occurred and an Error callback is made + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - errorMessage: + { + errorInformation + { + "errorCode": , + "errorDescription": + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + } + end note + DFSP2 ->> MLAPI: PUT - /transfers//error + activate MLAPI + MLAPI -> MLAPI: Validate incoming originator matching Payee\nError codes: 3000-3002, 3100-3107 + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Abort/Reject event for Payee\nError code: 2003 + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Reject/Abort)\n + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Abort)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'abort' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'abort' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +deactivate POS_HANDLER +deactivate FULF_HANDLER +deactivate NOTIFY_HANDLER +@enduml \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.svg new file mode 100644 index 000000000..7ac9606f1 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.svg @@ -0,0 +1,495 @@ + + + + + + + + + + + 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Event Handler + + + + + Position Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + DFSP2 sends a Fulfil Success Transfer request + + + + + 1 + + + During processing of an incoming + + + POST /transfers request, some processing + + + error occurred and an Error callback is made + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - errorMessage: + + + { + + + errorInformation + + + { + + + "errorCode": <errorCode>, + + + "errorDescription": <errorDescription> + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + } + + + + 2 + + + PUT - /transfers/<ID>/error + + + + + 3 + + + Validate incoming originator matching Payee + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <errorMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 4 + + + Route & Publish Abort/Reject event for Payee + + + Error code: + + + 2003 + + + + + 5 + + + Ensure event is replicated as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 6 + + + Respond replication acknowledgements have been received + + + + + 7 + + + Respond HTTP - 200 (OK) + + + + + 8 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (Reject/Abort) + + + + + 9 + + + Produce message + + + + + 10 + + + Consume message + + + + + ref + + + Position Handler Consume (Abort) + + + + + 11 + + + Produce message + + + + + 12 + + + Consume message + + + + + opt + + + [action == 'abort'] + + + + + ref + + + Send notification to Participant (Payer) + + + + + 13 + + + Send callback notification + + + + + 14 + + + Consume message + + + + + opt + + + [action == 'abort'] + + + + + ref + + + Send notification to Participant (Payee) + + + + + 15 + + + Send callback notification + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.plantuml new file mode 100644 index 000000000..9c88eb8cb --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.plantuml @@ -0,0 +1,170 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENTS + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate POS_HANDLER +group DFSP2 sends a Fulfil Reject Transfer request + DFSP2 <-> DFSP2: Retrieve fulfilment string generated during\nthe quoting process or regenerate it using\n**Local secret** and **ILP Packet** as inputs + note right of DFSP2 #lightblue + **Note**: In the payload for PUT /transfers/ + only the **transferState** field is **required** + end note + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "fulfilment": , + "completedTimestamp": , + "transferState": "ABORTED", + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + end note + note right of DFSP2 #lightgray + **Note**: Payee rejection reason should be captured + in the extensionList within the payload. + end note + DFSP2 ->> MLAPI: **PUT - /transfers/** + + activate MLAPI + MLAPI -> MLAPI: Validate incoming token and originator matching Payee + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Fulfil event for Payee + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all) + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_EVENTS: Fulfil Handler Consume (Reject/Abort)\n + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Reject)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'reject' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| +end +activate POS_HANDLER +activate FULF_HANDLER +activate NOTIFY_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.svg new file mode 100644 index 000000000..a2cbf7626 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.svg @@ -0,0 +1,489 @@ + + + + + + + + + + + 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + + + Event-Topic + + + + + Event-Topic + + + Position Event Handler + + + + + Position Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + DFSP2 sends a Fulfil Reject Transfer request + + + + + 1 + + + Retrieve fulfilment string generated during + + + the quoting process or regenerate it using + + + Local secret + + + and + + + ILP Packet + + + as inputs + + + + + Note + + + : In the payload for PUT /transfers/<ID> + + + only the + + + transferState + + + field is + + + required + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - transferMessage: + + + { + + + "fulfilment": <IlpFulfilment>, + + + "completedTimestamp": <DateTime>, + + + "transferState": "ABORTED", + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + + + Note + + + : Payee rejection reason should be captured + + + in the extensionList within the payload. + + + + 2 + + + PUT - /transfers/<ID> + + + + + 3 + + + Validate incoming token and originator matching Payee + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 4 + + + Route & Publish Fulfil event for Payee + + + + + 5 + + + Ensure event is replicated as configured (ACKS=all) + + + + + 6 + + + Respond replication acknowledgements have been received + + + + + 7 + + + Respond HTTP - 200 (OK) + + + + + 8 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (Reject/Abort) + + + + + 9 + + + Produce message + + + + + 10 + + + Consume message + + + + + ref + + + Position Handler Consume (Reject) + + + + + 11 + + + Produce message + + + + + 12 + + + Consume message + + + + + opt + + + [action == 'reject'] + + + + + ref + + + Send notification to Participant (Payer) + + + + + 13 + + + Send callback notification + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.plantuml new file mode 100644 index 000000000..3c390db71 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.plantuml @@ -0,0 +1,225 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + * Sam Kummary + -------------- + ******'/ + +@startuml +' declate title +title 2.2.1. Fulfil Handler Consume (Abort/Reject) +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "Event-Topic" as TOPIC_EVENT +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +'entity "Transfer Duplicate Facade" as DUP_FACADE +entity "Transfer DAO" as TRANS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_NOTIFICATIONS + participant TRANS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Failure) + alt Consume Single Message + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type == 'fulfil' && ( action IN ['reject','abort'] )\nError codes: 2001 + end + end + group Persist Event Information + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume + end + group Validate FSPIOP-Signature + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Validate message.content.headers.**FSPIOP-Signature**\nError codes: 2001 + end + group Validate Transfer Fulfil Duplicate Check + FULF_HANDLER -> FULF_HANDLER: Generate transferFulfilmentId uuid + FULF_HANDLER -> TRANS_DAO: Request to retrieve transfer fulfilment hashes by transferId\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request Transfer fulfilment duplicate message hashes + hnote over DB #lightyellow + SELET transferId, hash + FROM **transferFulfilmentDuplicateCheck** + WHERE transferId = request.params.id + end note + activate DB + TRANS_DAO <-- DB: Return existing hashes + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return (list of) transfer fulfil messages hash(es) + deactivate TRANS_DAO + FULF_HANDLER -> FULF_HANDLER: Loop the list of returned hashes and compare each entry with the calculated message hash + alt Hash matched + ' Need to check what respond with same results if finalised then resend, else ignore and wait for response + FULF_HANDLER -> TRANS_DAO: Request to retrieve Transfer Fulfilment and Transfer state\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request to retrieve Transfer Fulfilment and Transfer state + hnote over DB #lightyellow + transferFulfilment + transferStateChange + end note + activate DB + TRANS_DAO <-- DB: Return Transfer Fulfilment and Transfer state + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return Transfer Fulfilment and Transfer state + deactivate TRANS_DAO + alt transferFulfilment.isValid == 0 + break + FULF_HANDLER <-> FULF_HANDLER: Error handling: 3105 + end + else transferState IN ['COMMITTED', 'ABORTED'] + break + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + end + else transferState NOT 'RESERVED' + break + FULF_HANDLER <-> FULF_HANDLER: Error code: 2001 + end + else + break + FULF_HANDLER <-> FULF_HANDLER: Allow previous request to complete + end + end + else Hash not matched + FULF_HANDLER -> TRANS_DAO: Request to persist transfer hash\nError codes: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist hash + hnote over DB #lightyellow + transferFulfilmentDuplicateCheck + end note + activate DB + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + deactivate TRANS_DAO + end + end + alt action=='reject' call made on PUT /transfers/{ID} + FULF_HANDLER -> FULF_HANDLER: Log error message + note right of FULF_HANDLER: action REJECT is not allowed into fulfil handler + else action=='abort' Error callback + alt Validation successful + group Persist Transfer State (with transferState='RECEIVED_ERROR') + FULF_HANDLER -> TRANS_DAO: Request to persist transfer state and Error\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist transfer state and error information + activate DB + hnote over DB #lightyellow + transferStateChange + transferError + transferExtension + end note + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Transfer Error Message not successful + break + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Route & Publish Notification event for Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + end + end + else Consume Batch Messages + note left of FULF_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate FULF_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.svg new file mode 100644 index 000000000..7b61b6711 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.svg @@ -0,0 +1,697 @@ + + + + + + + + + + + 2.2.1. Fulfil Handler Consume (Abort/Reject) + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Handler Consume (Failure) + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume Fulfil event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'fulfil' && ( action IN ['reject','abort'] ) + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate FSPIOP-Signature + + + + + ref + + + Validate message.content.headers. + + + FSPIOP-Signature + + + Error codes: + + + 2001 + + + + + Validate Transfer Fulfil Duplicate Check + + + + + 4 + + + Generate transferFulfilmentId uuid + + + + + 5 + + + Request to retrieve transfer fulfilment hashes by transferId + + + Error code: + + + 2003 + + + + + 6 + + + Request Transfer fulfilment duplicate message hashes + + + + SELET transferId, hash + + + FROM + + + transferFulfilmentDuplicateCheck + + + WHERE transferId = request.params.id + + + + + 7 + + + Return existing hashes + + + + + 8 + + + Return (list of) transfer fulfil messages hash(es) + + + + + 9 + + + Loop the list of returned hashes and compare each entry with the calculated message hash + + + + + alt + + + [Hash matched] + + + + + 10 + + + Request to retrieve Transfer Fulfilment and Transfer state + + + Error code: + + + 2003 + + + + + 11 + + + Request to retrieve Transfer Fulfilment and Transfer state + + + + transferFulfilment + + + transferStateChange + + + + + 12 + + + Return Transfer Fulfilment and Transfer state + + + + + 13 + + + Return Transfer Fulfilment and Transfer state + + + + + alt + + + [transferFulfilment.isValid == 0] + + + + + break + + + + + 14 + + + Error handling: + + + 3105 + + + + [transferState IN ['COMMITTED', 'ABORTED']] + + + + + break + + + + + ref + + + Send notification to Participant (Payee) + + + + [transferState NOT 'RESERVED'] + + + + + break + + + + + 15 + + + Error code: + + + 2001 + + + + + + break + + + + + 16 + + + Allow previous request to complete + + + + [Hash not matched] + + + + + 17 + + + Request to persist transfer hash + + + Error codes: + + + 2003 + + + + + 18 + + + Persist hash + + + + transferFulfilmentDuplicateCheck + + + + + 19 + + + Return success + + + + + alt + + + [action=='reject' call made on PUT /transfers/{ID}] + + + + + 20 + + + Log error message + + + + + action REJECT is not allowed into fulfil handler + + + + [action=='abort' Error callback] + + + + + alt + + + [Validation successful] + + + + + Persist Transfer State (with transferState='RECEIVED_ERROR') + + + + + 21 + + + Request to persist transfer state and Error + + + Error code: + + + 2003 + + + + + 22 + + + Persist transfer state and error information + + + + transferStateChange + + + transferError + + + transferExtension + + + + + 23 + + + Return success + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 24 + + + Route & Publish Position event for Payer + + + + [Validate Transfer Error Message not successful] + + + + + break + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 25 + + + Route & Publish Notification event for Payee + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.plantuml new file mode 100644 index 000000000..1cd1e4b68 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.plantuml @@ -0,0 +1,343 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + * Sam Kummary + -------------- + ******'/ + +@startuml +' declate title +title 2.2.1. Fulfil Handler Consume (Reject/Abort) +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "Event-Topic" as TOPIC_EVENT +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +'entity "Transfer Duplicate Facade" as DUP_FACADE +entity "Transfer DAO" as TRANS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_NOTIFICATIONS + participant TRANS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Failure) + alt Consume Single Message + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type == 'fulfil' && ( action IN ['reject','abort'] )\nError codes: 2001 + end + end + group Persist Event Information + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume + end + group Validate FSPIOP-Signature + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Validate message.content.headers.**FSPIOP-Signature**\nError codes: 2001 + end + group Validate Transfer Fulfil Duplicate Check + FULF_HANDLER -> FULF_HANDLER: Generate transferFulfilmentId uuid + FULF_HANDLER -> TRANS_DAO: Request to retrieve transfer fulfilment hashes by transferId\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request Transfer fulfilment duplicate message hashes + hnote over DB #lightyellow + SELET transferId, hash + FROM **transferFulfilmentDuplicateCheck** + WHERE transferId = request.params.id + end note + activate DB + TRANS_DAO <-- DB: Return existing hashes + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return (list of) transfer fulfil messages hash(es) + deactivate TRANS_DAO + FULF_HANDLER -> FULF_HANDLER: Loop the list of returned hashes and compare each entry with the calculated message hash + alt Hash matched + ' Need to check what respond with same results if finalised then resend, else ignore and wait for response + FULF_HANDLER -> TRANS_DAO: Request to retrieve Transfer Fulfilment and Transfer state\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request to retrieve Transfer Fulfilment and Transfer state + hnote over DB #lightyellow + transferFulfilment + transferStateChange + end note + activate DB + TRANS_DAO <-- DB: Return Transfer Fulfilment and Transfer state + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return Transfer Fulfilment and Transfer state + deactivate TRANS_DAO + alt transferFulfilment.isValid == 0 + break + FULF_HANDLER <-> FULF_HANDLER: Error handling: 3105 + end + else transferState IN ['COMMITTED', 'ABORTED'] + break + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + end + else transferState NOT 'RESERVED' + break + FULF_HANDLER <-> FULF_HANDLER: Error code: 2001 + end + else + break + FULF_HANDLER <-> FULF_HANDLER: Allow previous request to complete + end + end + else Hash not matched + FULF_HANDLER -> TRANS_DAO: Request to persist transfer hash\nError codes: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist hash + hnote over DB #lightyellow + transferFulfilmentDuplicateCheck + end note + activate DB + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + deactivate TRANS_DAO + end + end + alt action=='reject' call made on PUT /transfers/{ID} + FULF_HANDLER -> TRANS_DAO: Request information for the validate checks\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Fetch from database + activate DB + hnote over DB #lightyellow + transfer + end note + DB --> TRANS_DAO + deactivate DB + FULF_HANDLER <-- TRANS_DAO: Return transfer + deactivate TRANS_DAO + + alt Fulfilment present in the PUT /transfers/{ID} message + FULF_HANDLER ->FULF_HANDLER: Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment)\nError code: 2001 + + group Persist fulfilment + FULF_HANDLER -> TRANS_DAO: Persist fulfilment with the result of the above check (transferFulfilment.isValid)\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferFulfilment + transferExtension + end note + FULF_HANDLER <-- TRANS_DAO: Return success + deactivate TRANS_DAO + end + else Fulfilment NOT present in the PUT /transfers/{ID} message + FULF_HANDLER ->FULF_HANDLER: Validate that transfer fulfilment message to Abort is valid\nError code: 2001 + group Persist extensions + FULF_HANDLER -> TRANS_DAO: Persist extensionList elements\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferExtension + end note + FULF_HANDLER <-- TRANS_DAO: Return success + deactivate TRANS_DAO + end + end + + alt Transfer.ilpCondition validate successful OR generic validation successful + group Persist Transfer State (with transferState='RECEIVED_REJECT') + FULF_HANDLER -> TRANS_DAO: Request to persist transfer state\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Fulfil Transfer not successful or Generic validation failed + break + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: reject, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Route & Publish Notification event for Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + end + else action=='abort' Error callback + alt Validation successful + group Persist Transfer State (with transferState='RECEIVED_ERROR') + FULF_HANDLER -> TRANS_DAO: Request to persist transfer state and Error\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist transfer state and error information + activate DB + hnote over DB #lightyellow + transferStateChange + transferError + transferExtension + end note + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Transfer Error Message not successful + break + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Route & Publish Notification event for Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + end + end + else Consume Batch Messages + note left of FULF_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate FULF_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.svg new file mode 100644 index 000000000..ad8d40a03 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.svg @@ -0,0 +1,1073 @@ + + + + + + + + + + + 2.2.1. Fulfil Handler Consume (Reject/Abort) + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + + Fulfil Handler Consume (Failure) + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume Fulfil event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'fulfil' && ( action IN ['reject','abort'] ) + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate FSPIOP-Signature + + + + + ref + + + Validate message.content.headers. + + + FSPIOP-Signature + + + Error codes: + + + 2001 + + + + + Validate Transfer Fulfil Duplicate Check + + + + + 4 + + + Generate transferFulfilmentId uuid + + + + + 5 + + + Request to retrieve transfer fulfilment hashes by transferId + + + Error code: + + + 2003 + + + + + 6 + + + Request Transfer fulfilment duplicate message hashes + + + + SELET transferId, hash + + + FROM + + + transferFulfilmentDuplicateCheck + + + WHERE transferId = request.params.id + + + + + 7 + + + Return existing hashes + + + + + 8 + + + Return (list of) transfer fulfil messages hash(es) + + + + + 9 + + + Loop the list of returned hashes and compare each entry with the calculated message hash + + + + + alt + + + [Hash matched] + + + + + 10 + + + Request to retrieve Transfer Fulfilment and Transfer state + + + Error code: + + + 2003 + + + + + 11 + + + Request to retrieve Transfer Fulfilment and Transfer state + + + + transferFulfilment + + + transferStateChange + + + + + 12 + + + Return Transfer Fulfilment and Transfer state + + + + + 13 + + + Return Transfer Fulfilment and Transfer state + + + + + alt + + + [transferFulfilment.isValid == 0] + + + + + break + + + + + 14 + + + Error handling: + + + 3105 + + + + [transferState IN ['COMMITTED', 'ABORTED']] + + + + + break + + + + + ref + + + Send notification to Participant (Payee) + + + + [transferState NOT 'RESERVED'] + + + + + break + + + + + 15 + + + Error code: + + + 2001 + + + + + + break + + + + + 16 + + + Allow previous request to complete + + + + [Hash not matched] + + + + + 17 + + + Request to persist transfer hash + + + Error codes: + + + 2003 + + + + + 18 + + + Persist hash + + + + transferFulfilmentDuplicateCheck + + + + + 19 + + + Return success + + + + + alt + + + [action=='reject' call made on PUT /transfers/{ID}] + + + + + 20 + + + Request information for the validate checks + + + Error code: + + + 2003 + + + + + 21 + + + Fetch from database + + + + transfer + + + + + 22 + + + + + 23 + + + Return transfer + + + + + alt + + + [Fulfilment present in the PUT /transfers/{ID} message] + + + + + 24 + + + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + + + Error code: + + + 2001 + + + + + Persist fulfilment + + + + + 25 + + + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + + + Error code: + + + 2003 + + + + + 26 + + + Persist to database + + + + transferFulfilment + + + transferExtension + + + + + 27 + + + Return success + + + + [Fulfilment NOT present in the PUT /transfers/{ID} message] + + + + + 28 + + + Validate that transfer fulfilment message to Abort is valid + + + Error code: + + + 2001 + + + + + Persist extensions + + + + + 29 + + + Persist extensionList elements + + + Error code: + + + 2003 + + + + + 30 + + + Persist to database + + + + transferExtension + + + + + 31 + + + Return success + + + + + alt + + + [Transfer.ilpCondition validate successful OR generic validation successful] + + + + + Persist Transfer State (with transferState='RECEIVED_REJECT') + + + + + 32 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 33 + + + Persist transfer state + + + + transferStateChange + + + + + 34 + + + Return success + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 35 + + + Route & Publish Position event for Payer + + + + [Validate Fulfil Transfer not successful or Generic validation failed] + + + + + break + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 36 + + + Route & Publish Notification event for Payee + + + + [action=='abort' Error callback] + + + + + alt + + + [Validation successful] + + + + + Persist Transfer State (with transferState='RECEIVED_ERROR') + + + + + 37 + + + Request to persist transfer state and Error + + + Error code: + + + 2003 + + + + + 38 + + + Persist transfer state and error information + + + + transferStateChange + + + transferError + + + transferExtension + + + + + 39 + + + Return success + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 40 + + + Route & Publish Position event for Payer + + + + [Validate Transfer Error Message not successful] + + + + + break + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 41 + + + Route & Publish Notification event for Payee + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.plantuml new file mode 100644 index 000000000..99fd990f9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.plantuml @@ -0,0 +1,114 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 9.1.1. Request Duplicate Check (incl. Transfers, Quotes, Bulk Transfers, Bulk Quotes) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-source" as TOPIC_SOURCE +control "Processing\nHandler" as HANDLER +collections "topic-event" as TOPIC_EVENTS +collections "topic-notifcation" as TOPIC_NOTIFICATION +entity "Request DAO" as DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_SOURCE + participant HANDLER + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATION + participant DAO + participant DB +end box + +' start flow +activate HANDLER + +group Request Duplicate Check + TOPIC_SOURCE <- HANDLER: Consume message + activate TOPIC_SOURCE + deactivate TOPIC_SOURCE + + HANDLER -> HANDLER: Generate hash: **generatedHash** + group UUID Check (compareById) + HANDLER -> DAO: Query hash using getDuplicateDataFuncOverride(id)\nError code: 2003 + activate DAO + note right of DAO #lightgrey + //request// keyword to be replaced by + **transfer**, **transferFulfilment**, + **bulkTransfer** or other depending + on the override + end note + DAO -> DB: getDuplicateDataFuncOverride + hnote over DB #lightyellow + //request//DuplicateCheck + end note + activate DB + DB --> DAO: Return **duplicateHashRecord** + deactivate DB + DAO --> HANDLER: Return **hasDuplicateId** + deactivate DAO + end + + alt hasDuplicateId == TRUE + group Hash Check (compareByHash) + note right of HANDLER #lightgrey + generatedHash == duplicateHashRecord.hash + end note + HANDLER -> HANDLER: Return **hasDuplicateHash** + end + else hasDuplicateId == FALSE + group Store Message Hash + HANDLER -> DAO: Persist hash using saveHashFuncOverride(id, generatedHash)\nError code: 2003 + activate DAO + DAO -> DB: Persist **generatedHash** + activate DB + deactivate DB + hnote over DB #lightyellow + //request//DuplicateCheck + end note + DAO --> HANDLER: Return success + deactivate DAO + end + end + + note right of HANDLER #yellow + return { + hasDuplicateId: Boolean, + hasDuplicateHash: Boolean + } + end note +end + +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.svg new file mode 100644 index 000000000..988ffd39a --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.svg @@ -0,0 +1,292 @@ + + + + + + + + + + + 9.1.1. Request Duplicate Check (incl. Transfers, Quotes, Bulk Transfers, Bulk Quotes) + + + + Central Service + + + + + + + + + + + + topic-source + + + + + topic-source + + + Processing + + + Handler + + + + + Processing + + + Handler + + + + + + + topic-event + + + + + topic-event + + + + + topic-notifcation + + + + + topic-notifcation + + + Request DAO + + + + + Request DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Request Duplicate Check + + + + + 1 + + + Consume message + + + + + 2 + + + Generate hash: + + + generatedHash + + + + + UUID Check (compareById) + + + + + 3 + + + Query hash using getDuplicateDataFuncOverride(id) + + + Error code: + + + 2003 + + + + + request + + + keyword to be replaced by + + + transfer + + + , + + + transferFulfilment + + + , + + + bulkTransfer + + + or other depending + + + on the override + + + + + 4 + + + getDuplicateDataFuncOverride + + + + request + + + DuplicateCheck + + + + + 5 + + + Return + + + duplicateHashRecord + + + + + 6 + + + Return + + + hasDuplicateId + + + + + alt + + + [hasDuplicateId == TRUE] + + + + + Hash Check (compareByHash) + + + + + generatedHash == duplicateHashRecord.hash + + + + + 7 + + + Return + + + hasDuplicateHash + + + + [hasDuplicateId == FALSE] + + + + + Store Message Hash + + + + + 8 + + + Persist hash using saveHashFuncOverride(id, generatedHash) + + + Error code: + + + 2003 + + + + + 9 + + + Persist + + + generatedHash + + + + request + + + DuplicateCheck + + + + + 10 + + + Return success + + + + + return { + + + hasDuplicateId: Boolean, + + + hasDuplicateHash: Boolean + + + } + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.plantuml new file mode 100644 index 000000000..3d8209299 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.plantuml @@ -0,0 +1,122 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * ModusBox + - Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.1.2. Settlement Model Handler Consume +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +control "Settlement Model\nHandler" as SETMODEL_HANDLER +collections "topic-event" as TOPIC_EVENT +entity "Settlement DAO" as SET_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_SETMODEL + participant SETMODEL_HANDLER + participant TOPIC_EVENT + participant SET_DAO + participant DB +end box + +' start flow +activate SETMODEL_HANDLER +group Settlement Model Handler Consume + alt Consume Single Message + TOPIC_SETMODEL <- SETMODEL_HANDLER: Consume settlement model\nevent message + activate TOPIC_SETMODEL + deactivate TOPIC_SETMODEL + break + group Validate Event + SETMODEL_HANDLER <-> SETMODEL_HANDLER: Validate event - Rule: type == 'setmodel' && action == 'commit'\nError codes: 2001 + end + end + group Persist Event Information + ||| + SETMODEL_HANDLER -> TOPIC_EVENT: Publish event information + ref over SETMODEL_HANDLER, TOPIC_EVENT: Event Handler Consume\n + ||| + end + + SETMODEL_HANDLER -> SET_DAO: Assign transferParicipant state(s)\nError code: 2003 + activate SET_DAO + group DB TRANSACTION + SET_DAO -> DB: Fetch transfer participant entries + activate DB + hnote over DB #lightyellow + transferParticipant + end note + DB --> SET_DAO: Return **transferParticipantRecords** + deactivate DB + + loop for each transferParticipant + note right of SET_DAO #lightgrey + Settlement models caching to be considered + end note + SET_DAO -> DB: Get settlement model by currency and ledger entry + activate DB + hnote over DB #lightyellow + settlementModel + end note + DB --> SET_DAO: Return **settlementModel** + deactivate DB + + opt settlementModel.delay == 'IMMEDIATE' && settlementModel.granularity == 'GROSS' + SET_DAO -> DB: Set states: CLOSED->PENDING_SETTLEMENT->SETTLED + activate DB + hnote over DB #lightyellow + transferParticipantStateChange + transferParticipant + end note + deactivate DB + else + SET_DAO -> DB: Set state: OPEN + activate DB + hnote over DB #lightyellow + transferParticipantStateChange + transferParticipant + end note + deactivate DB + end + + end + end + SETMODEL_HANDLER <-- SET_DAO: Return success + deactivate SET_DAO + else Consume Batch Messages + note left of SETMODEL_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate SETMODEL_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.svg new file mode 100644 index 000000000..50323963f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.svg @@ -0,0 +1,292 @@ + + + + + + + + + + + 2.1.2. Settlement Model Handler Consume + + + + Central Service + + + + + + + + + + + + + + topic- + + + settlement-model + + + + + topic- + + + settlement-model + + + Settlement Model + + + Handler + + + + + Settlement Model + + + Handler + + + + + + + topic-event + + + + + topic-event + + + Settlement DAO + + + + + Settlement DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Settlement Model Handler Consume + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume settlement model + + + event message + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'setmodel' && action == 'commit' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + 4 + + + Assign transferParicipant state(s) + + + Error code: + + + 2003 + + + + + DB TRANSACTION + + + + + 5 + + + Fetch transfer participant entries + + + + transferParticipant + + + + + 6 + + + Return + + + transferParticipantRecords + + + + + loop + + + [for each transferParticipant] + + + + + Settlement models caching to be considered + + + + + 7 + + + Get settlement model by currency and ledger entry + + + + settlementModel + + + + + 8 + + + Return + + + settlementModel + + + + + opt + + + [settlementModel.delay == 'IMMEDIATE' && settlementModel.granularity == 'GROSS'] + + + + + 9 + + + Set states: CLOSED->PENDING_SETTLEMENT->SETTLED + + + + transferParticipantStateChange + + + transferParticipant + + + + + + 10 + + + Set state: OPEN + + + + transferParticipantStateChange + + + transferParticipant + + + + + 11 + + + Return success + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.plantuml new file mode 100644 index 000000000..a1ee95a55 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.plantuml @@ -0,0 +1,107 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * ModusBox + - Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.3.0. Transfer Timeout + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API\nAdapter" as MLAPI +control "Notification\nHandler" as NOTIFY_HANDLER +control "Timeout Prepare\nHandler" as TIMEOUT_PREP_HANDLER +collections "topic-\ntransfer-timeout" as TOPIC_TRANSFER_TIMEOUT +control "Timeout\nHandler" as TIMEOUT_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position\nHandler" as POS_HANDLER +collections "topic-notification" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightgray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #lightblue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #lightyellow + participant TIMEOUT_PREP_HANDLER + participant TOPIC_TRANSFER_TIMEOUT + participant TIMEOUT_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate TIMEOUT_PREP_HANDLER +activate NOTIFY_HANDLER +activate TIMEOUT_HANDLER +activate POS_HANDLER +group Transfer Expiry + ||| + ref over TIMEOUT_PREP_HANDLER, TOPIC_TRANSFER_TIMEOUT: Timeout Processing Handler Consume\n + TIMEOUT_PREP_HANDLER -> TOPIC_TRANSFER_TIMEOUT: Produce message + ||| + TOPIC_TRANSFER_TIMEOUT <- TIMEOUT_HANDLER: Consume message + ref over TOPIC_TRANSFER_TIMEOUT, TIMEOUT_HANDLER: Timeout Processing Handler Consume\n + alt transferStateId == 'RECEIVED_PREPARE' + TIMEOUT_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else transferStateId == 'RESERVED' + TIMEOUT_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Hander Consume (Timeout)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + end + opt action IN ['timeout-received', 'timeout-reserved'] + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + ref over DFSP1, TOPIC_NOTIFICATIONS : Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'timeout-reserved' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS : Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end +end +deactivate POS_HANDLER +deactivate TIMEOUT_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.svg new file mode 100644 index 000000000..b35a96686 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.svg @@ -0,0 +1,339 @@ + + + + + + + + + + + 2.3.0. Transfer Timeout + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API + + + Adapter + + + + + ML API + + + Adapter + + + + + Notification + + + Handler + + + + + Notification + + + Handler + + + + + Timeout Prepare + + + Handler + + + + + Timeout Prepare + + + Handler + + + + + + + topic- + + + transfer-timeout + + + + + topic- + + + transfer-timeout + + + Timeout + + + Handler + + + + + Timeout + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + Position + + + Handler + + + + + Position + + + Handler + + + + + + + topic-notification + + + + + topic-notification + + + + + + Transfer Expiry + + + + + ref + + + Timeout Processing Handler Consume + + + + + 1 + + + Produce message + + + + + 2 + + + Consume message + + + + + ref + + + Timeout Processing Handler Consume + + + + + alt + + + [transferStateId == 'RECEIVED_PREPARE'] + + + + + 3 + + + Produce message + + + + [transferStateId == 'RESERVED'] + + + + + 4 + + + Produce message + + + + + 5 + + + Consume message + + + + + ref + + + Position Hander Consume (Timeout) + + + + + 6 + + + Produce message + + + + + opt + + + [action IN ['timeout-received', 'timeout-reserved']] + + + + + 7 + + + Consume message + + + + + ref + + + Send notification to Participant (Payer) + + + + + 8 + + + Send callback notification + + + + + 9 + + + Consume message + + + + + opt + + + [action == 'timeout-reserved'] + + + + + ref + + + Send notification to Participant (Payee) + + + + + 10 + + + Send callback notification + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.plantuml new file mode 100644 index 000000000..c51976758 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.plantuml @@ -0,0 +1,132 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * ModusBox + - Georgi Georgiev + -------------- + ******'/ + +@startuml +' declare title +title 2.3.1. Timeout Prepare Handler + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +control "Timeout Prepare\nHandler" as TIMEOUT_PREP_HANDLER +collections "topic-\ntransfer-timeout" as TOPIC_TRANSFER_TIMEOUT +collections "topic-event" as EVENT_TOPIC +entity "Timeout DAO" as TIMEOUT_DAO +database "Central Store" as DB + +box "Central Service" #lightyellow + participant TIMEOUT_PREP_HANDLER + participant TOPIC_TRANSFER_TIMEOUT + participant EVENT_TOPIC + participant TIMEOUT_DAO + participant DB +end box + +' start flow + +group Timeout Prepare Handler + activate TIMEOUT_PREP_HANDLER + group Persist Event Information + TIMEOUT_PREP_HANDLER -> EVENT_TOPIC: Publish event information + ref over TIMEOUT_PREP_HANDLER, EVENT_TOPIC : Event Handler Consume\n + end + + group Cleanup + TIMEOUT_PREP_HANDLER -> TIMEOUT_DAO: Cleanup Fulfilled Transfers\nError code: 2003 + activate TIMEOUT_DAO + TIMEOUT_DAO -> DB: Delete fuflfilled transfers records + activate DB + deactivate DB + hnote over DB #lightyellow + DELETE et + FROM **expiringTransfer** et + JOIN **transferFulfilment** tf + ON tf.transferId = et.transferId + end note + TIMEOUT_DAO --> TIMEOUT_PREP_HANDLER: Return success + deactivate TIMEOUT_DAO + end + + group List Expired + TIMEOUT_PREP_HANDLER -> TIMEOUT_DAO: Retrieve Expired Transfers\nError code: 2003 + activate TIMEOUT_DAO + TIMEOUT_DAO -> DB: Select using index + activate DB + hnote over DB #lightyellow + SELECT * + FROM **expiringTransfer** + WHERE expirationDate < currentTimestamp + end note + TIMEOUT_DAO <-- DB: Return expired transfers + deactivate DB + TIMEOUT_DAO --> TIMEOUT_PREP_HANDLER: Return **expiredTransfersList** + deactivate TIMEOUT_DAO + end + + + + loop for each transfer in the list + ||| + note right of TIMEOUT_PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: null, + payload: + }, + metadata: { + event: { + id: , + responseTo: null, + type: transfer, + action: timeout, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + TIMEOUT_PREP_HANDLER -> TOPIC_TRANSFER_TIMEOUT: Publish Timeout event\nError code: 2003 + activate TOPIC_TRANSFER_TIMEOUT + deactivate TOPIC_TRANSFER_TIMEOUT + end + + deactivate TIMEOUT_PREP_HANDLER +end +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.svg new file mode 100644 index 000000000..08083d7e3 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.svg @@ -0,0 +1,325 @@ + + + + + + + + + + + 2.3.1. Timeout Prepare Handler + + + + Central Service + + + + + + + Timeout Prepare + + + Handler + + + + + Timeout Prepare + + + Handler + + + + + + + topic- + + + transfer-timeout + + + + + topic- + + + transfer-timeout + + + + + topic-event + + + + + topic-event + + + Timeout DAO + + + + + Timeout DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Timeout Prepare Handler + + + + + Persist Event Information + + + + + 1 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Cleanup + + + + + 2 + + + Cleanup Fulfilled Transfers + + + Error code: + + + 2003 + + + + + 3 + + + Delete fuflfilled transfers records + + + + DELETE et + + + FROM + + + expiringTransfer + + + et + + + JOIN + + + transferFulfilment + + + tf + + + ON tf.transferId = et.transferId + + + + + 4 + + + Return success + + + + + List Expired + + + + + 5 + + + Retrieve Expired Transfers + + + Error code: + + + 2003 + + + + + 6 + + + Select using index + + + + SELECT * + + + FROM + + + expiringTransfer + + + WHERE expirationDate < currentTimestamp + + + + + 7 + + + Return expired transfers + + + + + 8 + + + Return + + + expiredTransfersList + + + + + loop + + + [for each transfer in the list] + + + + + Message: + + + { + + + id: <uuid> + + + from: <switch>, + + + to: <payerFsp>, + + + type: application/json + + + content: { + + + headers: null, + + + payload: <transfer> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: null, + + + type: transfer, + + + action: timeout, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 9 + + + Publish Timeout event + + + Error code: + + + 2003 + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.plantuml b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.plantuml new file mode 100644 index 000000000..42132c116 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.plantuml @@ -0,0 +1,227 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * ModusBox + - Georgi Georgiev + - Rajiv Mothilal + -------------- + ******'/ + +@startuml +' declare title +title 2.3.2. Timeout Handler + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +control "Transfer Timeout Handler" as TIMEOUT_HANDLER +collections "topic-\ntransfer-timeout" as TOPIC_TRANSFER_TIMEOUT +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nnotification" as NOTIFICATIONS_TOPIC +collections "topic-event" as EVENT_TOPIC +entity "Timeout DAO" as TIMEOUT_DAO +database "Central Store" as DB + +box "Central Service" #lightyellow + participant TOPIC_TRANSFER_TIMEOUT + participant TIMEOUT_HANDLER + participant TOPIC_TRANSFER_POSITION + participant NOTIFICATIONS_TOPIC + participant EVENT_TOPIC + participant TIMEOUT_DAO + participant DB +end box + +' start flow + +group Timeout Handler Consume + activate TIMEOUT_HANDLER + TOPIC_TRANSFER_TIMEOUT <- TIMEOUT_HANDLER: Consume message + activate TOPIC_TRANSFER_TIMEOUT + deactivate TOPIC_TRANSFER_TIMEOUT + + group Persist Event Information + TIMEOUT_HANDLER -> EVENT_TOPIC: Publish event information + ref over TIMEOUT_HANDLER, EVENT_TOPIC: Event Handler Consume\n + end + + group Get transfer info + TIMEOUT_HANDLER -> TIMEOUT_DAO: Acquire transfer information\nError code: 2003 + activate TIMEOUT_DAO + TIMEOUT_DAO -> DB: Get transfer data and state + activate DB + hnote over DB #lightyellow + transfer + transferParticipant + participantCurrency + participant + transferStateChange + end note + TIMEOUT_DAO <-- DB: Return **transferInfo** + deactivate DB + TIMEOUT_HANDLER <-- TIMEOUT_DAO: Return **transferInfo** + deactivate TIMEOUT_DAO + end + + alt transferInfo.transferStateId == 'RECEIVED_PREPARE' + TIMEOUT_HANDLER -> TIMEOUT_DAO: Set EXPIRED_PREPARED state\nError code: 2003 + activate TIMEOUT_DAO + TIMEOUT_DAO -> DB: Insert state change + activate DB + deactivate DB + hnote over DB #lightyellow + transferStateChange + end note + TIMEOUT_HANDLER <-- TIMEOUT_DAO: Return success + deactivate TIMEOUT_DAO + + note right of TIMEOUT_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + }, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + type: notification, + action: timeout-received, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + TIMEOUT_HANDLER -> NOTIFICATIONS_TOPIC: Publish Notification event + activate NOTIFICATIONS_TOPIC + deactivate NOTIFICATIONS_TOPIC + else transferInfo.transferStateId == 'RESERVED' + TIMEOUT_HANDLER -> TIMEOUT_DAO: Set RESERVED_TIMEOUT state\nError code: 2003 + activate TIMEOUT_DAO + TIMEOUT_DAO -> DB: Insert state change + activate DB + deactivate DB + hnote over DB #lightyellow + transferStateChange + end note + TIMEOUT_HANDLER <-- TIMEOUT_DAO: Return success + deactivate TIMEOUT_DAO + + note right of TIMEOUT_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + }, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + type: position, + action: timeout-reserved, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + TIMEOUT_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event\nError code: 2003 + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else + note right of TIMEOUT_HANDLER #lightgrey + Any other state is ignored + end note + end + + group Cleanup + TIMEOUT_HANDLER -> TIMEOUT_DAO: Cleanup handled expiring transfer\nError code: 2003 + activate TIMEOUT_DAO + TIMEOUT_DAO -> DB: Delete record + activate DB + deactivate DB + hnote over DB #lightyellow + expiringTransfer + end note + TIMEOUT_HANDLER <-- TIMEOUT_DAO: Return success + deactivate TIMEOUT_DAO + end + + deactivate TIMEOUT_HANDLER +end +@enduml diff --git a/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.svg b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.svg new file mode 100644 index 000000000..0103f7ba9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.svg @@ -0,0 +1,614 @@ + + + + + + + + + + + 2.3.2. Timeout Handler + + + + Central Service + + + + + + + + + + + topic- + + + transfer-timeout + + + + + topic- + + + transfer-timeout + + + Transfer Timeout Handler + + + + + Transfer Timeout Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + topic-event + + + + + topic-event + + + Timeout DAO + + + + + Timeout DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Timeout Handler Consume + + + + + 1 + + + Consume message + + + + + Persist Event Information + + + + + 2 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Get transfer info + + + + + 3 + + + Acquire transfer information + + + Error code: + + + 2003 + + + + + 4 + + + Get transfer data and state + + + + transfer + + + transferParticipant + + + participantCurrency + + + participant + + + transferStateChange + + + + + 5 + + + Return + + + transferInfo + + + + + 6 + + + Return + + + transferInfo + + + + + alt + + + [transferInfo.transferStateId == 'RECEIVED_PREPARE'] + + + + + 7 + + + Set EXPIRED_PREPARED state + + + Error code: + + + 2003 + + + + + 8 + + + Insert state change + + + + transferStateChange + + + + + 9 + + + Return success + + + + + Message: + + + { + + + id: <transferId>, + + + from: <payerParticipantId>, + + + to: <payeeParticipantId>, + + + type: application/json, + + + content: { + + + headers: + + + { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + }, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3303, + + + "errorDescription": "Transfer expired", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: notification, + + + action: timeout-received, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 10 + + + Publish Notification event + + + + [transferInfo.transferStateId == 'RESERVED'] + + + + + 11 + + + Set RESERVED_TIMEOUT state + + + Error code: + + + 2003 + + + + + 12 + + + Insert state change + + + + transferStateChange + + + + + 13 + + + Return success + + + + + Message: + + + { + + + id: <transferId>, + + + from: <payerParticipantId>, + + + to: <payeeParticipantId>, + + + type: application/json, + + + content: { + + + headers: + + + { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + }, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3303, + + + "errorDescription": "Transfer expired", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: position, + + + action: timeout-reserved, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 14 + + + Route & Publish Position event + + + Error code: + + + 2003 + + + + + + Any other state is ignored + + + + + Cleanup + + + + + 15 + + + Cleanup handled expiring transfer + + + Error code: + + + 2003 + + + + + 16 + + + Delete record + + + + expiringTransfer + + + + + 17 + + + Return success + + diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.0-prepare-transfer-request.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.0-prepare-transfer-request.md new file mode 100644 index 000000000..e98c606e8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.0-prepare-transfer-request.md @@ -0,0 +1,16 @@ +# Prepare Transfer Request + +Sequence design diagram for Prepare Transfer Request process. + +## References within Sequence Diagram + +* [Prepare Handler Consume (1.1.1.a)](1.1.1.a-prepare-handler-consume.md) +* **Not Implemented** [Prepare Handler Consume (1.1.1.b)](1.1.1.b-prepare-handler-consume.md) +* [Position Handler Consume (1.1.2.a)](1.1.2.a-position-handler-consume.md) +* **Not Implemented** [Position Handler Consume (1.1.2.b)](1.1.2.b-position-handler-consume.md) +* [Send notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) +* **Not Implemented** [Send notification to Participant (1.1.4.b)](1.1.4.b-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-prepare-1.1.0.svg](../assets/diagrams/sequence/seq-prepare-1.1.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md new file mode 100644 index 000000000..b0a401b5f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md @@ -0,0 +1,11 @@ +# Prepare handler consume + +Sequence design diagram for Prepare Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.1.a.svg](../assets/diagrams/sequence/seq-prepare-1.1.1.a.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md new file mode 100644 index 000000000..72e6784d5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md @@ -0,0 +1,11 @@ +# Prepare handler consume + +Sequence design diagram for Prepare Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.1.b.svg](../assets/diagrams/sequence/seq-prepare-1.1.1.b.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.2.a-position-handler-consume.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.2.a-position-handler-consume.md new file mode 100644 index 000000000..d091e6223 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.2.a-position-handler-consume.md @@ -0,0 +1,11 @@ +# Position handler consume + +Sequence design diagram for Position Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.2.a.svg](../assets/diagrams/sequence/seq-prepare-1.1.2.a.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.2.b-position-handler-consume.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.2.b-position-handler-consume.md new file mode 100644 index 000000000..161bea8d9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.2.b-position-handler-consume.md @@ -0,0 +1,11 @@ +# Position handler consume + +Sequence design diagram for Position Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.2.b.svg](../assets/diagrams/sequence/seq-prepare-1.1.2.b.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.md new file mode 100644 index 000000000..9fd4fb1c5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.md @@ -0,0 +1,11 @@ +# Send Notification to Participant v1.1 + +Sequence design diagram for the Send Notification to Participant request. + +## References within Sequence Diagram + +* [9.1.0-event-handler-consume](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.4.a-v1.1.svg](../assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md new file mode 100644 index 000000000..12b1972d6 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md @@ -0,0 +1,11 @@ +# Send Notification to Participant + +Sequence design diagram for the Send Notification to Participant request. + +## References within Sequence Diagram + +* [9.1.0-event-handler-consume](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.4.a.svg](../assets/diagrams/sequence/seq-prepare-1.1.4.a.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md new file mode 100644 index 000000000..c22b6c94f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md @@ -0,0 +1,11 @@ +# Send Notification to Participant + +Sequence design diagram for the Send Notification to Participant request. + +## References within Sequence Diagram + +* [9.1.0-event-handler-consume](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.4.b.svg](../assets/diagrams/sequence/seq-prepare-1.1.4.b.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.md new file mode 100644 index 000000000..3f12ab0b1 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.md @@ -0,0 +1,14 @@ +# Position Handler Consume v1.1 + +Sequence design diagram for Position Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [Prepare Position Handler Consume (1.3.1)](1.3.1-prepare-position-handler-consume.md) +* [Fufil Position Handler Consume (1.3.2)](1.3.2-fulfil-position-handler-consume-v1.1.md) +* [Abort Position Handler Consume (1.3.3)](1.3.3-abort-position-handler-consume.md) + +## Sequence Diagram + +![seq-position-1.3.0-v1.1.svg](../assets/diagrams/sequence/seq-position-1.3.0-v1.1.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.md new file mode 100644 index 000000000..a3942172f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.md @@ -0,0 +1,14 @@ +# Position Handler Consume + +Sequence design diagram for Position Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [Prepare Position Handler Consume (1.3.1)](1.3.1-prepare-position-handler-consume.md) +* [Fufil Position Handler Consume (1.3.2)](1.3.2-fulfil-position-handler-consume.md) +* [Abort Position Handler Consume (1.3.3)](1.3.3-abort-position-handler-consume.md) + +## Sequence Diagram + +![seq-position-1.3.0.svg](../assets/diagrams/sequence/seq-position-1.3.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md new file mode 100644 index 000000000..2ab39456e --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md @@ -0,0 +1,7 @@ +# Prepare Position Handler Consume + +Sequence design diagram for Prepare Position Handler Consume process. + +## Sequence Diagram + +![seq-position-1.3.1-prepare.svg](../assets/diagrams/sequence/seq-position-1.3.1-prepare.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.md new file mode 100644 index 000000000..fff28f156 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.md @@ -0,0 +1,8 @@ +# Fulfil Position Handler Consume v1.1 + +Sequence design diagram for Fulfil Position Handler Consume process. + +## Sequence Diagram + +![seq-position-1.3.2-fulfil-v1.1.svg](../assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.svg) + diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md new file mode 100644 index 000000000..25e5b2774 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md @@ -0,0 +1,7 @@ +# Fulfil Position Handler Consume + +Sequence design diagram for Fulfil Position Handler Consume process. + +## Sequence Diagram + +![seq-position-1.3.2-fulfil.svg](../assets/diagrams/sequence/seq-position-1.3.2-fulfil.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.3-abort-position-handler-consume.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.3-abort-position-handler-consume.md new file mode 100644 index 000000000..9ab80dc75 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/1.3.3-abort-position-handler-consume.md @@ -0,0 +1,7 @@ +# Abort Position Handler Consume + +Sequence design diagram for Abort Position Handler Consume process. + +## Sequence Diagram + +![seq-position-1.3.3-abort.svg](../assets/diagrams/sequence/seq-position-1.3.3-abort.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.md new file mode 100644 index 000000000..d7a71954f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.md @@ -0,0 +1,13 @@ +# Fulfil Transfer Request success v1.1 + +Sequence design diagram for the Fulfil Success Transfer request. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Success) (2.1.1)](2.1.1-fulfil-handler-consume-v1.1.md) +* [Position Handler Consume (Success) (1.3.2)](1.3.2-fulfil-position-handler-consume-v1.1.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v1.1-v1.1.md) + +## Sequence Diagram + +![seq-fulfil-2.1.0-v1.1.svg](../assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request.md new file mode 100644 index 000000000..c552a057a --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request.md @@ -0,0 +1,13 @@ +# Fulfil Transfer Request success + +Sequence design diagram for the Fulfil Success Transfer request. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Success) (2.1.1)](2.1.1-fulfil-handler-consume.md) +* [Position Handler Consume (Success) (1.3.2)](1.3.2-fulfil-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-fulfil-2.1.0.svg](../assets/diagrams/sequence/seq-fulfil-2.1.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.md new file mode 100644 index 000000000..69f2afa87 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.md @@ -0,0 +1,13 @@ +# Fulfil Handler Consume (Success) v1.1 + +Sequence design diagram for the Fulfil Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v1.1.md) + +## Sequence Diagram + +![seq-fulfil-2.1.1-v1.1.svg](../assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume.md new file mode 100644 index 000000000..05f7e38f0 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume.md @@ -0,0 +1,13 @@ +# Fulfil Handler Consume (Success) + +Sequence design diagram for the Fulfil Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-fulfil-2.1.1.svg](../assets/diagrams/sequence/seq-fulfil-2.1.1.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.md new file mode 100644 index 000000000..ede9acee1 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.md @@ -0,0 +1,7 @@ +# Payee sends a Fulfil Abort Transfer request v1.1 + +Sequence design diagram for the Fulfil Reject Transfer process for version 1.1. of the API. + +## Sequence Diagram + +![seq-reject-2.2.0-v1.1.svg](../assets/diagrams/sequence/seq-reject-2.2.0-v1.1.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md new file mode 100644 index 000000000..fc193a59d --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md @@ -0,0 +1,13 @@ +# [Outdated] Payee sends a Fulfil Reject Transfer request + +Sequence design diagram for the Fulfil Reject Transfer process. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Reject/Abort)(2.2.1)](2.2.1-fulfil-reject-handler.md) +* [Position Handler Consume (Reject)(1.3.3)](1.3.3-abort-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v1.1.md) + +## Sequence Diagram + +![seq-reject-2.2.0.svg](../assets/diagrams/sequence/seq-reject-2.2.0.svg) diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.md new file mode 100644 index 000000000..74303e5e5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.md @@ -0,0 +1,13 @@ +# Payee sends a PUT call on /error end-point for a Transfer request v1.1 + +Sequence design diagram for the Fulfil Reject Transfer process for version 1.1. of the API. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Abort)(2.2.1)](2.2.1-fulfil-reject-handler-v1.1.md) +* [Position Handler Consume (Reject)(1.3.3)](1.3.3-abort-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v1.1.md) + +## Sequence Diagram + +![seq-reject-2.2.0.a-v1.1.svg](../assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md new file mode 100644 index 000000000..91d635f5e --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md @@ -0,0 +1,13 @@ +# Payee sends a PUT call on /error end-point for a Transfer request + +Sequence design diagram for the Fulfil Reject Transfer process. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Reject/Abort)(2.2.1)](2.2.1-fulfil-reject-handler.md) +* [Position Handler Consume (Reject)(1.3.3)](1.3.3-abort-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-reject-2.2.0.a.svg](../assets/diagrams/sequence/seq-reject-2.2.0.a.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.md new file mode 100644 index 000000000..c3b5939f2 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.md @@ -0,0 +1,7 @@ +## Fulfil Handler Consume (Reject/Abort) + +Sequence design diagram for the Fulfil Handler Consume Reject/Abort process for version 1.1. of the API. + +## Sequence Diagram + +![seq-reject-2.2.1-v1.1.svg](../assets/diagrams/sequence/seq-reject-2.2.1-v1.1.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler.md new file mode 100644 index 000000000..c83982b0d --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler.md @@ -0,0 +1,13 @@ +## Fulfil Handler Consume (Reject/Abort) + +Sequence design diagram for the Fulfil Handler Consume Reject/Abort process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-reject-2.2.1.svg](../assets/diagrams/sequence/seq-reject-2.2.1.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/2.3.0-transfer-timeout.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.3.0-transfer-timeout.md new file mode 100644 index 000000000..874561f3d --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.3.0-transfer-timeout.md @@ -0,0 +1,13 @@ +## Transfer Timeout + +Sequence design diagram for the Transfer Timeout process. + +## References within Sequence Diagram + +* [Timeout Handler Consume (2.3.1)](2.3.1-timeout-handler-consume.md) +* [Position Handler Consume (Timeout)(1.3.3)](1.3.3-abort-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-timeout-2.3.0.svg](../assets/diagrams/sequence/seq-timeout-2.3.0.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/2.3.1-timeout-handler-consume.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.3.1-timeout-handler-consume.md new file mode 100644 index 000000000..9d96ccf69 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/2.3.1-timeout-handler-consume.md @@ -0,0 +1,11 @@ +## Timeout Handler Consume + +Sequence design diagram for the Timeout Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-timeout-2.3.1.svg](../assets/diagrams/sequence/seq-timeout-2.3.1.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-ledger/transfers/README.md b/legacy/mojaloop-technical-overview/central-ledger/transfers/README.md new file mode 100644 index 000000000..ba8fc02cf --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-ledger/transfers/README.md @@ -0,0 +1,8 @@ +# Mojaloop Transfer operations + +Operational processes that is the core of the transfer operational process; + +- Prepare process +- Fulfil process +- Notifications process +- Reject/Abort process diff --git a/legacy/mojaloop-technical-overview/central-settlements/.gitkeep b/legacy/mojaloop-technical-overview/central-settlements/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/legacy/mojaloop-technical-overview/central-settlements/README.md b/legacy/mojaloop-technical-overview/central-settlements/README.md new file mode 100644 index 000000000..596744601 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/README.md @@ -0,0 +1,24 @@ +# Central-Settlements Service + +The Central Settlements service is part of the Mojaloop project and deployment. + +* The central settlements service exposes Settlement API to manage the settlements between FSPs and the Central Hub. +* The service manages Settlement Windows and Settlements Event Triggers and provides information about FSPs accounts and settlements. + +## 1. Settlement Process Design + +### 1.1. Architecture overview + +![The Settlements Architecture](./assets/diagrams/architecture/Arch-Mojaloop-Settlements-PI4.svg) + +## 2. Funds In/Out + +Record Funds In and Record Funds Out operations are used respectively to deposit and withdraw funds into participant SETTLEMENT ledgers. The balance of the SETTLEMENT account relates to the NET_DEBIT_CAP set by the switch for every participant of the scheme. NET_DEBIT_CAP value is always lower or equal to the SETTLEMENT value. On the other side, the balance of the participant's POSITION account is limited to the value of the NET_DEBIT_CAP. + +## 3. API Specification + +Refer to **Central Settlements API** in the [API Specifications](../../api/README.md#central-settlements-api) section. + +## 4. Rules Engine + +The rules engine is separate handler within the Central-Settlement handler, that can be deployed if needed. Rules format and way of operation can be found on [Rules Handler . Interchange fees example. File format.](./settlement-process/rules-handler-consume.md) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-settlements/assets/.gitkeep b/legacy/mojaloop-technical-overview/central-settlements/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/mojaloop-technical-overview/central-settlements/assets/diagrams/Settlement_ERD.png b/legacy/mojaloop-technical-overview/central-settlements/assets/diagrams/Settlement_ERD.png similarity index 100% rename from mojaloop-technical-overview/central-settlements/assets/diagrams/Settlement_ERD.png rename to legacy/mojaloop-technical-overview/central-settlements/assets/diagrams/Settlement_ERD.png diff --git a/mojaloop-technical-overview/central-settlements/assets/diagrams/architecture/Arch-Mojaloop-Settlements-PI4.svg b/legacy/mojaloop-technical-overview/central-settlements/assets/diagrams/architecture/Arch-Mojaloop-Settlements-PI4.svg similarity index 100% rename from mojaloop-technical-overview/central-settlements/assets/diagrams/architecture/Arch-Mojaloop-Settlements-PI4.svg rename to legacy/mojaloop-technical-overview/central-settlements/assets/diagrams/architecture/Arch-Mojaloop-Settlements-PI4.svg diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/README.md b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/README.md similarity index 100% rename from mojaloop-technical-overview/central-settlements/funds-in-out/README.md rename to legacy/mojaloop-technical-overview/central-settlements/funds-in-out/README.md diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.a-reconciliationTransferPrepare.plantuml b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.a-reconciliationTransferPrepare.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.a-reconciliationTransferPrepare.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.a-reconciliationTransferPrepare.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.a-reconciliationTransferPrepare.svg b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.a-reconciliationTransferPrepare.svg new file mode 100644 index 000000000..56512040f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.a-reconciliationTransferPrepare.svg @@ -0,0 +1,267 @@ + + + + + + + + + + + 5.1.0.a. Reconciliation transfer prepare (reconciliationTransferPrepare) + + + + Central Service + + + + + + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + reconciliationTransferPrepare (payload, trx) + + + + + 1 + + + Insert transferDuplicateCheck + + + + INSERT INTO + + + transferDuplicateCheck + + + (transferId, hash, createdDate) + + + VALUES ({payload.transferId}, hashCode({payload.transferId}), {transactionTimestamp}) + + + + + 2 + + + Insert transfer + + + + INSERT INTO + + + transfer + + + (transferId, amount, currencyId, + + + ilpCondition, expirationDate, createdDate) + + + VALUES ({payload.transferId}, {payload.amount.amount}, + + + {payload.amount.curency}, 0, + + + {new Date()+Config.INTERNAL_TRANSFER_VALIDITY_SECONDS}, + + + {transactionTimestamp}) + + + + + 3 + + + Retrieve hub reconciliation account + + + + SELECT participantCurrencyId AS reconciliationAccountId + + + FROM + + + participantCurrency + + + WHERE participantId = 1 + + + AND currencyId = {payload.amount.currency} + + + LIMIT 1 + + + + + 4 + + + Return + + + reconciliationAccountId + + + + + alt + + + [payload.action == 'RECORD_FUNDS_IN'] + + + + + ledgerEntryTypeId + + + = 'RECORD_FUNDS_IN' + + + amount + + + = + + + payload.amount.amount + + + + [payload.action == 'RECORD_FUNDS_OUT_PREPARE'] + + + + + ledgerEntryTypeId + + + = 'RECORD_FUNDS_OUT' + + + amount + + + = + + + -payload.amount.amount + + + + + 5 + + + Insert transferParticipant records + + + + INSERT INTO + + + transferParticipant + + + (transferId, participantCurrencyId, transferParticipantRoleTypeId, + + + ledgerEntryTypeId, amount, createdDate) + + + VALUES (payload.transferId, reconciliationAccountId, 'HUB', + + + {ledgerEntryTypeId}, {amount}, {transactionTimestamp}) + + + INSERT INTO + + + transferParticipant + + + (transferId, participantCurrencyId, transferParticipantRoleTypeId, + + + ledgerEntryTypeId, amount, createdDate) + + + VALUES ({payload.transferId}, {payload.participantCurrencyId}, 'DFSP_SETTLEMENT', + + + {ledgerEntryTypeId}, {-amount}, {transactionTimestamp}) + + + + + 6 + + + Insert transferStateChange record + + + + INSERT INTO + + + transferStateChange + + + (transferId, transferStateId, reason, createdDate) + + + VALUES ({payload.transferId}, 'RECEIVED_PREPARE', + + + {payload.reason}, {transactionTimestamp}) + + + + + 7 + + + Save externalReference and extensions + + + + transferExtension + + diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.b-transferStateAndPositionChange.plantuml b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.b-transferStateAndPositionChange.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.b-transferStateAndPositionChange.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.b-transferStateAndPositionChange.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.b-transferStateAndPositionChange.svg b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.b-transferStateAndPositionChange.svg new file mode 100644 index 000000000..57ab88b3f --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.b-transferStateAndPositionChange.svg @@ -0,0 +1,473 @@ + + + + + + + + + + + 5.1.0.b. Transfer state and position change (transferStateAndPositionChange) + + + + Central Service + + + + + + + + + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + transferStateAndPositionUpdate (param1, trx) + + + + + param1 + + + = { + + + transferId: {payload.transferId}, + + + transferStateId: "enum", + + + reason: {payload.reason}, + + + createdDate: {transactionTimestamp}, + + + drUpdated: "boolean", + + + crUpdated: "boolean" + + + } + + + + + 1 + + + Select all required info + + + + SELECT dr.participantCurrencyId AS drAccountId, + + + dr.amount AS drAmount, drp.participantPositionId AS drPositionId, + + + drp.value AS drPositionValue, drp.reservedValue AS drReservedValue, + + + cr.participantCurrencyId AS crAccountId, + + + cr.amount AS crAmount, crp.participantPositionId AS crPositionId, + + + crp.value AS crPositionValue, crp.reservedValue AS crReservedValue, + + + tsc.transferStateId + + + FROM + + + transfer + + + t + + + JOIN + + + transferParticipant + + + dr + + + ON dr.transferId = t.transferId + + + AND dr.amount > 0 + + + JOIN + + + participantCurrency + + + drpc + + + ON drpc.participantCurrencyId = dr.participantCurrencyId + + + JOIN + + + participantPosition + + + drp + + + ON drp.participantCurrencyId = dr.participantCurrencyId + + + JOIN + + + transferParticipant + + + cr + + + ON cr.transferId = t.transferId + + + AND cr.amount < 0 + + + JOIN + + + participantCurrency + + + crpc + + + ON crpc.participantCurrencyId = dr.participantCurrencyId + + + JOIN + + + participantPosition + + + crp + + + ON crp.participantCurrencyId = cr.participantCurrencyId + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferId = t.transferId + + + WHERE t.transferId = param1.tranferId + + + AND drpc.ledgerAccountTypeId IN('POSITION', 'SETTLEMENT', ' + + + HUB_RECONCILIATION', 'HUB_MULTILATERAL_SETTLEMENT') + + + AND crpc.ledgerAccountTypeId IN('POSITION', 'SETTLEMENT', ' + + + HUB_RECONCILIATION', 'HUB_MULTILATERAL_SETTLEMENT') + + + ORDER BY transferStateChangeId DESC + + + LIMIT 1 + + + + + 2 + + + Return + + + info + + + + + opt + + + [param1.transferStateId == 'COMMITTED'] + + + + + 3 + + + Change transfer state + + + + INSERT INTO + + + transferStateChange + + + (transferId, transferStateId, reason, createdDate) + + + VALUES ({param1.transferId, 'RECEIVED_FULFIL', {param1.reason}, {param1.createdDate}) + + + + [param1.transferStateId == 'ABORTED'] + + + + + 4 + + + Change transfer state + + + + INSERT INTO + + + transferStateChange + + + (transferId, transferStateId, reason, createdDate) + + + VALUES ({param1.transferId, 'REJECTED', {param1.reason}, {param1.createdDate}) + + + + + 5 + + + Change transfer state + + + + INSERT INTO + + + transferStateChange + + + (transferId, transferStateId, reason, createdDate) + + + VALUES ({param1.transferId, {param1.transferStateId}, {param1.reason}, {param1.createdDate}) + + + + + 6 + + + Return + + + transferStateChangeId + + + + + opt + + + [param1.drUpdated == true] + + + + + opt + + + [param1.transferStateId == 'ABORTED'] + + + + + info.drAmount = -info.drAmount + + + + + 7 + + + Change DR position + + + + UPDATE + + + participantPosition + + + SET value = {info.drPositionValue + info.drAmount} + + + WHERE participantPositionId = {info.drPositionId} + + + INSERT INTO + + + participantPositionChange + + + (participantPositionId, + + + transferStateChangeId, value, reservedValue, createdDate) + + + VALUES ({info.drPositionId}, {transferStateChangeId}, + + + {info.drPositionValue + info.drAmount}, {info.drReservedValue}, + + + {param1.createdDate}) + + + + + opt + + + [param1.crUpdated == true] + + + + + opt + + + [param1.transferStateId == 'ABORTED'] + + + + + info.crAmount = -info.crAmount + + + + + 8 + + + Change CR position + + + + UPDATE + + + participantPosition + + + SET value = {info.crPositionValue + info.crAmount} + + + WHERE participantPositionId = {info.crPositionId} + + + INSERT INTO + + + participantPositionChange + + + (participantPositionId, + + + transferStateChangeId, value, reservedValue, createdDate) + + + VALUES ({info.crPositionId}, {transferStateChangeId}, + + + {info.crPositionValue + info.crAmount}, {info.crReservedValue}, + + + {param1.createdDate}) + + + + + return + + + { + + + transferStateChangeId, + + + drPositionValue: {info.drPositionValue + info.drAmount} + + + crPositionValue: {info.crPositionValue + info.crAmount} + + + } + + diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.1-in.plantuml b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.1-in.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.1-in.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.1-in.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.1-in.svg b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.1-in.svg new file mode 100644 index 000000000..c83a1ab9b --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.1-in.svg @@ -0,0 +1,426 @@ + + + + + + + + + + + 5.1.1. Record Funds In (recordFundsIn) + + + + Central HUB + + + + Central Service + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Central Service + + + Admin API + + + + + Central Service + + + Admin API + + + + + + + Admin-Transfer-Topic + + + + + Admin-Transfer-Topic + + + Admin Event Handler + + + + + Admin Event Handler + + + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Record Funds In + + + + + { + + + "transferId": <uuid>, + + + "externalReference": "string", + + + "action": "recordFundsIn", + + + "amount": { + + + "amount": <decimal>, + + + "currency": "string" + + + }, + + + "reason": "string", + + + "extensionList": { + + + "extension": [ + + + { + + + "key": "string", + + + "value": "string" + + + } + + + ] + + + } + + + } + + + + + 1 + + + POST - /participants/{name}/accounts/{id} + + + + + Message: + + + { + + + id: <payload.transferId> + + + from: "dfspName", + + + to: "Hub", + + + type: "application/json" + + + content: { + + + headers: <payloadHeaders>, + + + payload: <payloadMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: "", + + + type: "transfer", + + + action: "recordFundsIn", + + + createdAt: <timestamp>, + + + state: "" + + + } + + + }, + + + pp: "" + + + } + + + + + 2 + + + Route & Publish Prepare event + + + Error code: + + + 2003 + + + + + 3 + + + Ensure event is replicated + + + as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 4 + + + Respond replication acks + + + have been received + + + + + 5 + + + Respond HTTP - 202 (Accepted) + + + + + 6 + + + Consume message + + + + + 7 + + + Prepare transfer + + + + + DB TRANSACTION + + + + + Reconciliation Transfer Prepare + + + + + ref + + + reconciliationTransferPrepare + + + (payload, trx) + + + + + Reconciliation Transfer Reserve + + + + + ref + + + transferStateAndPositionUpdate + + + ({ + + + transferId: {payload.transferId}, + + + transferStateId: "RESERVED", + + + reason: {payload.reason}, + + + createdDate: {transactionTimestamp}, + + + drUpdated: true, + + + crUpdated: false + + + }, trx) + + + + + Reconciliation Transfer Commit + + + + + 8 + + + Insert transferFulfilment record + + + + INSERT INTO + + + transferFulfilment + + + (transferFulfilmentId, transferId, ilpFulfilment, + + + completedDate, isValid, settlementWindowId, createdDate) + + + VALUES ({Uuid()}, {payload.transferId}, 0, {transactionTimestamp}, + + + 1, NULL, {transactionTimestamp}) + + + + + ref + + + transferStateAndPositionUpdate + + + ({ + + + transferId: {payload.transferId}, + + + transferStateId: "COMMITTED", + + + reason: {payload.reason}, + + + createdDate: {transactionTimestamp}, + + + drUpdated: false, + + + crUpdated: true + + + }, trx) + + + + + 9 + + + Finished await + + diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.1-out-prepare-reserve.plantuml b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.1-out-prepare-reserve.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.1-out-prepare-reserve.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.1-out-prepare-reserve.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.1-out-prepare-reserve.svg b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.1-out-prepare-reserve.svg new file mode 100644 index 000000000..a22743415 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.1-out-prepare-reserve.svg @@ -0,0 +1,443 @@ + + + + + + + + + + + 5.2.1. Record Funds Out - Prepare & Reserve (recordFundsOutPrepareReserve) + + + + Central HUB + + + + Central Service + + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Central Service + + + Admin API + + + + + Central Service + + + Admin API + + + + + + + Admin-Transfer-Topic + + + + + Admin-Transfer-Topic + + + Admin Event Handler + + + + + Admin Event Handler + + + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Record Funds Out - Prepare & Reserve + + + + + { + + + "transferId": <uuid>, + + + "externalReference": "string", + + + "action": "recordFundsOutPrepareReserve", + + + "amount": { + + + "amount": <decimal>, + + + "currency": "string" + + + }, + + + "reason": "string", + + + "extensionList": { + + + "extension": [ + + + { + + + "key": "string", + + + "value": "string" + + + } + + + ] + + + } + + + } + + + + + 1 + + + POST - /participants/{name}/accounts/{id} + + + + + Message: + + + { + + + id: <payload.transferId> + + + from: "Hub", + + + to: "dfspName", + + + type: "application/json" + + + content: { + + + headers: <payloadHeaders>, + + + payload: <payloadMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: "", + + + type: "transfer", + + + action: "recordFundsOutPrepareReserve", + + + createdAt: <timestamp>, + + + state: "" + + + } + + + }, + + + pp: "" + + + } + + + + + 2 + + + Route & Publish Prepare event + + + Error code: + + + 2003 + + + + + 3 + + + Ensure event is replicated + + + as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 4 + + + Respond replication acks + + + have been received + + + + + 5 + + + Respond HTTP - 202 (Accepted) + + + + + 6 + + + Consume message + + + + + 7 + + + Prepare transfer + + + and reserve + + + + + DB TRANSACTION + + + + + Reconciliation Transfer Prepare + + + + + ref + + + reconciliationTransferPrepare + + + (payload, trx) + + + + + Reconciliation Transfer Reserve + + + + + ref + + + transferStateAndPositionUpdate + + + ({ + + + transferId: {payload.transferId}, + + + transferStateId: "RESERVED", + + + reason: {payload.reason}, + + + createdDate: {transactionTimestamp}, + + + drUpdated: true, + + + crUpdated: false + + + }, trx) + + + + + opt + + + [transferStateAndPositionUpdate.crPositionValue > 0] + + + + + payload.reason = 'Aborted due to insufficient funds' + + + + + Reconciliation Transfer Abort + + + + + 8 + + + Insert transferFulfilment record + + + + INSERT INTO + + + transferFulfilment + + + (transferFulfilmentId, transferId, ilpFulfilment, + + + completedDate, isValid, settlementWindowId, createdDate) + + + VALUES ({Uuid()}, {payload.transferId}, 0, {transactionTimestamp}, + + + 1, NULL, {transactionTimestamp}) + + + + + ref + + + transferStateAndPositionUpdate + + + ({ + + + transferId: {payload.transferId}, + + + transferStateId: "ABORTED", + + + reason: {payload.reason}, + + + createdDate: {transactionTimestamp}, + + + drUpdated: true, + + + crUpdated: false + + + }, trx) + + + + + 9 + + + Finished await + + diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.2-out-commit.plantuml b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.2-out-commit.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.2-out-commit.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.2-out-commit.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.2-out-commit.svg b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.2-out-commit.svg new file mode 100644 index 000000000..fd276ff59 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.2-out-commit.svg @@ -0,0 +1,334 @@ + + + + + + + + + + + 5.2.2. Record Funds Out Commit (recordFundsOutCommit) + + + + Central HUB + + + + Central Service + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Central Service + + + Admin API + + + + + Central Service + + + Admin API + + + + + + + Admin-Transfer-Topic + + + + + Admin-Transfer-Topic + + + Admin Event Handler + + + + + Admin Event Handler + + + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Record Funds Out Commit + + + + + { + + + "action": "recordFundsOutCommit", + + + "reason": "string" + + + } + + + + + 1 + + + PUT - /participants/{name}/accounts/ + + + {id}/transfers/{transferId} + + + + + Message: + + + { + + + id: <payload.transferId> + + + from: "Hub", + + + to: "dfspName", + + + type: "application/json" + + + content: { + + + headers: <payloadHeaders>, + + + payload: <payloadMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: "", + + + type: "transfer", + + + action: "recordFundsOutCommit", + + + createdAt: <timestamp>, + + + state: "" + + + } + + + }, + + + pp: "" + + + } + + + + + 2 + + + Route & Publish Prepare event + + + Error code: + + + 2003 + + + + + 3 + + + Ensure event is replicated + + + as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 4 + + + Respond replication acks + + + have been received + + + + + 5 + + + Respond HTTP - 202 (Accepted) + + + + + 6 + + + Consume message + + + + + 7 + + + Commit transfer + + + + + DB TRANSACTION + + + + + Reconciliation Transfer Commit + + + + + 8 + + + Insert transferFulfilment record + + + + INSERT INTO + + + transferFulfilment + + + (transferFulfilmentId, transferId, ilpFulfilment, + + + completedDate, isValid, settlementWindowId, createdDate) + + + VALUES ({transferFulfilmentId}, {payload.transferId}, 0, {transactionTimestamp}, + + + 1, NULL, {transactionTimestamp}) + + + + + ref + + + transferStateAndPositionUpdate + + + ({ + + + transferId: {payload.transferId}, + + + transferStateId: "COMMITTED", + + + reason: {payload.reason}, + + + createdDate: {transactionTimestamp}, + + + drUpdated: false, + + + crUpdated: true + + + }, trx) + + + + + 9 + + + Finished await + + diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.3-out-abort.plantuml b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.3-out-abort.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.3-out-abort.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.3-out-abort.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.3-out-abort.svg b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.3-out-abort.svg new file mode 100644 index 000000000..8db2df0c4 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.3-out-abort.svg @@ -0,0 +1,334 @@ + + + + + + + + + + + 5.2.3. Record Funds Out Abort (recordFundsOutAbort) + + + + Central HUB + + + + Central Service + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Central Service + + + Admin API + + + + + Central Service + + + Admin API + + + + + + + Admin-Transfer-Topic + + + + + Admin-Transfer-Topic + + + Admin Event Handler + + + + + Admin Event Handler + + + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Record Funds Out Abort + + + + + { + + + "action": "recordFundsOutAbort", + + + "reason": "string" + + + } + + + + + 1 + + + PUT - /participants/{name}/accounts/ + + + {id}/transfers/{transferId} + + + + + Message: + + + { + + + id: <payload.transferId> + + + from: "Hub", + + + to: "dfspName", + + + type: "application/json" + + + content: { + + + headers: <payloadHeaders>, + + + payload: <payloadMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: "", + + + type: "transfer", + + + action: "recordFundsOutAbort", + + + createdAt: <timestamp>, + + + state: "" + + + } + + + }, + + + pp: "" + + + } + + + + + 2 + + + Route & Publish Prepare event + + + Error code: + + + 2003 + + + + + 3 + + + Ensure event is replicated + + + as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 4 + + + Respond replication acks + + + have been received + + + + + 5 + + + Respond HTTP - 202 (Accepted) + + + + + 6 + + + Consume message + + + + + 7 + + + Abort transfer + + + + + DB TRANSACTION + + + + + Reconciliation Transfer Abort + + + + + 8 + + + Insert transferFulfilment record + + + + INSERT INTO + + + transferFulfilment + + + (transferFulfilmentId, transferId, ilpFulfilment, + + + completedDate, isValid, settlementWindowId, createdDate) + + + VALUES ({transferFulfilmentId}, {payload.transferId}, 0, {transactionTimestamp}, + + + 1, NULL, {transactionTimestamp}) + + + + + ref + + + transferStateAndPositionUpdate + + + ({ + + + transferId: {payload.transferId}, + + + transferStateId: "ABORTED", + + + reason: {payload.reason}, + + + createdDate: {transactionTimestamp}, + + + drUpdated: true, + + + crUpdated: false + + + }, trx) + + + + + 9 + + + Finished await + + diff --git a/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-in-prepare-reserve-commit.md b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-in-prepare-reserve-commit.md new file mode 100644 index 000000000..4e4ff79a3 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-in-prepare-reserve-commit.md @@ -0,0 +1,7 @@ +# Funds In - Prepare, Reserve, Commit + +Funds In operation performs all the stages of the transfer (prepare, reserve and commit) at once. + +## Sequence Diagram + +![seq-recfunds-5.1.1-in.svg](./assets/diagrams/sequence/seq-recfunds-5.1.1-in.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-abort.md b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-abort.md new file mode 100644 index 000000000..9e59dd187 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-abort.md @@ -0,0 +1,7 @@ +# Funds Out - Abort + +Funds out abort of a prepared reconciliation transfer. + +## Sequence Diagram + +![seq-recfunds-5.2.3-out-abort.svg](./assets/diagrams/sequence/seq-recfunds-5.2.3-out-abort.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-commit.md b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-commit.md new file mode 100644 index 000000000..113b0c44b --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-commit.md @@ -0,0 +1,7 @@ +# Funds Out - Commit + +Funds out commit of a prepared reconciliation transfer. + +## Sequence Diagram + +![seq-recfunds-5.2.2-out-commit.svg](./assets/diagrams/sequence/seq-recfunds-5.2.2-out-commit.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-prepare-reserve.md b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-prepare-reserve.md new file mode 100644 index 000000000..0b55913fd --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-prepare-reserve.md @@ -0,0 +1,8 @@ +# Funds Out - Prepare & Reserve + +Funds Out operation performs the prepare and reserve stages of the transfer at once. But the commit of the transfer or the abort operation are separate processes. + +## Sequence Diagram + + +![seq-recfunds-5.2.1-out-prepare-reserve.svg](./assets/diagrams/sequence/seq-recfunds-5.2.1-out-prepare-reserve.svg) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/reconciliation-transfer-prepare.md b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/reconciliation-transfer-prepare.md new file mode 100644 index 000000000..e257ead28 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/reconciliation-transfer-prepare.md @@ -0,0 +1,7 @@ +# Reconciliation Transfer Prepare + +Design for Reconciliation Transfer Prepare sub-process. + +## Sequence Diagram + +![seq-recfunds-5.1.0.a-reconciliationTransferPrepare.svg](./assets/diagrams/sequence/seq-recfunds-5.1.0.a-reconciliationTransferPrepare.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/transfer-state-and-position-change.md b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/transfer-state-and-position-change.md new file mode 100644 index 000000000..a711df784 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/funds-in-out/transfer-state-and-position-change.md @@ -0,0 +1,7 @@ +# Transfer State and Position Change + +Design for Transfer State and Position Change sub-process. + +## Sequence Diagram + +![seq-recfunds-5.1.0.b-transferStateAndPositionChange.svg](./assets/diagrams/sequence/seq-recfunds-5.1.0.b-transferStateAndPositionChange.svg) diff --git a/mojaloop-technical-overview/central-settlements/oss-settlement-fsd.md b/legacy/mojaloop-technical-overview/central-settlements/oss-settlement-fsd.md similarity index 93% rename from mojaloop-technical-overview/central-settlements/oss-settlement-fsd.md rename to legacy/mojaloop-technical-overview/central-settlements/oss-settlement-fsd.md index 707daeb0a..938a506fa 100644 --- a/mojaloop-technical-overview/central-settlements/oss-settlement-fsd.md +++ b/legacy/mojaloop-technical-overview/central-settlements/oss-settlement-fsd.md @@ -1,1703 +1,1723 @@ ---- -title: "OSS Settlement \n \nBusiness Requirements Document" ---- - -Introduction -============ - -This document describes the requirements for changes to the functionality of the -OSS Mojaloop switch to support: - -1. The immediate requirement for Mowali of being able to settle according to - different timetables for different currencies. - -2. The requirement for TIPS to be able to settle gross via a pooled account. - -3. The requirement for TIPS to use the settlement process for interchange fees. - -4. The requirement for Mojaloop to support the evolving Settlement API - -References -========== - -The following external references are used in this document: - -| Reference | Document | -| :--- | :--- | -| 1 | [Open API for FSP Interoperability Specification](http://mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html) | -| 2 | [Settlement API Interface Definition](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json)| -| 3 | [Current administration API definition](https://mojaloop.io/documentation/api/central-ledger-api-specification.html)| -| | | - -Versions -======== - -| Version | Description | Author | Date | Changes tracked | -|:---------|:------------------|:------------------|:------------|:-----------------| -| 1.0 | Baseline version | Michael Richards | 2 Dec 2019 | No | -| | | | | | - -Definition of terms -=================== - -Settlement model ----------------- - -A settlement model defines a kind of settlement within the scheme. Settlement -models can be defined by scheme administrators, and have the following -characteristics: - -1. They can support settlement either gross or net settlements. If gross, then - a settlement is executed after each transfer is completed. If net, a group - of transfers is settled together. - -2. They can support either multilateral or bilateral settlements. If - settlements are multilateral, each participant settles with the scheme for - the net of its transfers which are included in the settlement. If they are - multilateral, each participant settles separately with each of the other - participants and the scheme is not a party to the settlement. - -3. They can support either deferred or immediate settlements. If settlements - are immediate, they are actioned immediately they are completed. If they are - deferred, they are actioned after a period of delay. - -4. They can support continuous or discontinuous settlements. Discontinuous - settlements require a formal approval from a resource outside the system to - confirm that they have been completed. Continuous settlements can be - approved from within the switch, provided that the criteria for approval are - met. - -5. They can require liquidity support or not. - -Ledger account type -------------------- - -A ledger account type defines a type of internal account. Current values are: - -1. POSITION. Accounts of this type are used for provisioning transfers - -2. SETTLEMENT. Accounts of this type are intended to be reflections of - Settlement Accounts held at the Settlement Bank - -3. HUB_RECONCILIATION. Each implementation of the switch has one account of - this type for each currency supported by the switch, owned by the virtual - DFSP which represents the Hub in the implementation. The account is used - during FUNDS IN/OUT operations to represent movements in participants’ - SETTLEMENT accounts. - -4. HUB_MULTILATERAL_SETTLEMENT. Each implementation of the switch has one - account of this type for each currency supported by the switch, owned by the - virtual DFSP which represents the Hub in the implementation. This account - type is used to record counterparty information for net amounts paid to or - from participants as part of settlements. Entries in this account represent - balancing values corresponding with the net value in a participant’s - POSITION account for a given settlement. - -5. HUB_FEE. Accounts of this type represent accounts into which fees are - collected, or from which they are disbursed. (Not implemented) - -Ledger entry type ------------------ - -A ledger entry type categorises the type of funds which are the content of a -transfer and which are due to or from a participant as a consequence of that -transfer. The current values are: - -1. PRINCIPLE_VALUE. This designates the funds moved as the content of a - transfer in the Interoperability API Specification sense of that term (i.e. - the **amount.amount** item in the **Transaction** object described in - [Section 7.4.17](https://mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html#7317-ilpcondition) of the Interoperability API specification[1](https://mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html).) It should be - spelt “principal.” - -2. INTERCHANGE_FEE. This designates fees paid between participants in the - system. (Not implemented) - -3. HUB_FEE. This designates fees paid between participants and the scheme. (Not - implemented) - -4. POSITION_DEPOSIT. This is used to designate funds transfers which are - intended to increase the value of the position in a particular ledger - account. (Not implemented) - -5. POSITION_WITHDRAWAL. This is used to designate funds transfers which are - intended to reduce the value of the position in a particular ledger account. - (Not implemented) - -6. SETTLEMENT_NET_RECIPIENT. This is used to designate funds which a - participant is owed by the counterparty as part of a settlement (in a - multilateral settlement model, the counterparty will be the hub; in a - bilateral settlement model, it will be another party.) - -7. SETTLEMENT_NET_SENDER. This is used to designate funds which a participant - owes to the counterparty as part of a settlement (in a multilateral - settlement model, the counterparty will be the hub; in a bilateral - settlement model, it will be another party.) - -8. SETTLEMENT_NET_ZERO. This is used to generate formal records where a - participant’s net position in a settlement is zero. - -9. RECORD_FUNDS_IN. This is used to record funds deposited by a participant to - the SETTLEMENT account. - -10. RECORD_FUNDS_OUT. This is used to record funds withdrawn by a participant - from the SETTLEMENT account. - -The last seven of these types relate to the internal structure of the switch and -should be neither visible to nor modifiable by a scheme. The first three fall -into a category which is expected to be extensible by the scheme. The table does -not currently have an indicator to mark this distinction, but one is proposed in -Section TODO. - -Participant role types ----------------------- - -A participant role type defines the role that a particular participant is -playing in a given transaction. The current values of this table are: - -1. PAYER_DFSP. The participant is the debtor in a transfer. - -2. PAYEE_DFSP. The participant is a creditor in a transfer. - -3. HUB. The participant is representing the scheme, and may be either the - creditor or the debtor in a transaction. - -4. DFSP_SETTLEMENT. The participant represents the settlement account of a - participant in the scheme. It may be either the creditor or the debtor in a - transaction. It is used during FUNDS IN/OUT operations. This is used for - entries whose counterparty is an entry in the HUB account. - -5. DFSP_POSITION. The participant represents the position of a participant in - the scheme. It may be either the creditor or the debtor in a transaction. It - is used during the settlement process. This is used for entries whose - counterparty is an entry in the HUB account. - -Settlement states ------------------ - -A settlement may be in a number of possible states. The states currently -supported are: - -1. PENDING_SETTLEMENT. A new settlement consisting of one or more settlement - windows has been created. The net amounts due to or from each participant - have been calculated and a report detailing these net amounts has been - produced. - -2. PS_TRANSFERS_RECORDED: all the calculated net amounts for the settlement - have been converted into transfers between the creditor and debtor accounts. - It is applied for each settlement entry and at settlement level, when all - entries are recorded. This state is not applied to settlement windows. - -3. PS_TRANSFERS_RESERVED: all the funds required for settlement have been - reserved (debit amounts only.) It is applied for each settlement entry and - at settlement level, when all entries are reserved. - -4. PS_TRANSFERS_COMMITTED: all the credit amounts required as part of the - settlement have been committed. It is applied for each settlement entry and - at settlement level, when all entries are committed. - -5. SETTLING: It is used only at settlement level if all accounts are not yet - settled. - -6. SETTLED: This state is applied to settlement accounts in - PS_TRANSFERS_COMMITTED state. When applied to even one account, the - settlement will transit to SETTLING state. When all accounts in a window are - SETTLED, the settlement window will change from PENDING_SETTLEMENT to - SETTLED, while the settlement is still in SETTLING state. When all accounts - from all windows are SETTLED, the settlement will be changed to SETTLED. It - is possible for a settlement to change directly from PS_TRANSFERS_COMMITTED - to SETTLED if all accounts are settled with one request. - -7. ABORTED: the settlement could not be completed and should be rolled back. It - is currently only possible to abort a settlement if the state is one of: - PENDING_SETTLEMENT, PS_TRANSFERS_RECORDED or PS_TRANSFERS_RESERVED. After - having even one account in PS_TRANSFERS_COMMITTED state (even if the - settlement as a whole is still in PS_TRANSFERS_RESERVED), a request to abort - the settlement is rejected. It should be noted that this prevents abortion - in cases such as the default of a participant midway through the settlement - process. - -The present data model contains a foreign key to the enumeration table -containing settlement states from the -**settlementParticipantCurrencyStateChange** table, which maps onto a table -which contains a record for each participant/currency/account type combination. - -Assumption: this means that the states appropriate to a settlement are also to -be applied to the individual elements of a settlement. As a consequence, the -descriptions should be taken to refer to individual settlement amounts as well -as to the settlement as a whole. - -Settlement window states ------------------------- - -A settlement is made up of one or more settlement windows. Each settlement -window has a state associated with it. The current values of this table are as -follows: - -1. OPEN: the settlement window can have ledger movements added to it. - -2. CLOSED: the settlement window cannot have any additional ledger movements - added to it. It is available for settlement. - -3. PENDING_SETTLEMENT: the settlement window’s contents have been included in a - settlement request, but this request is a request for deferred settlement - which has not yet been completed. - -4. SETTLED: the scheme has confirmed that the obligations incurred by - participants as a consequence of the settlement to which this settlement - window belongs have been met by those participants and the settlement is - therefore complete. - -5. ABORTED: the settlement to which this settlement window belongs did not - complete. The settlement window is available to be included in another - settlement. - -Transfer states ---------------- - -Each transaction which passes through the system can be assigned one of a fixed -number of states. The current values of this state are: - -1. RECEIVED_PREPARE: the switch has received the transaction request. - -2. RESERVED: the switch has reserved the funds required to cover the - transaction. - -3. RECEIVED_FULFIL: the switch has received the fulfilment request, and the - transaction has been assigned to a settlement window - -4. COMMITTED: the transaction has been committed. - -5. FAILED: the transaction has failed in some unspecified way and has been - aborted. (Not implemented) - -6. RESERVED_TIMEOUT: the transaction has timed out while in the reserved state - and has been aborted. - -7. RECEIVED_REJECT: the transaction has been rejected by the payee DFSP and - should be aborted. - -8. ABORTED_REJECTED: the transaction has been aborted by the switch as a - consequence of its having been rejected by the payee DFSP. - -9. RECEIVED_ERROR: the transaction was not received correctly by the payee DFSP - and should be aborted. - -10. ABORTED_ERROR: the transaction has been aborted by the switch as a - consequence of its not having been received correctly. - -11. EXPIRED_PREPARED: the transaction has expired during the prepare process and - has been aborted. - -12. EXPIRED_RESERVED: the transaction has timed out during the reservation - process and has been aborted. - -13. INVALID: the transaction has failed the switch’s internal validation process - and has been aborted. - -Transfers and transactions --------------------------- - -Transfers define a movement of funds in the system. There is a table in the -switch which has this name. Some entries in this table are the consequence of -external movements which are generated by scheme participants and processed by -the switch; others are internally generated by the switch (e.g. to record net -movements of funds associated with settlements.) - -It may be a source of confusion that, although “transfers” is a term used e.g. -in the Interoperability API specification to designate the movement of funds -between participants, it is used as the name of a table in the switch which -stores other types of funds movement as well. - -This document will therefore adopt the following convention: - -- “Transfers” refers to the content of instructions issued using the - **/transfers** resource of the Interoperability API definition[1](http://mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html). (see [Section 6.7](http://mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html#67-api-resource-transfers) of the Interoperability API definition[1](http://mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html).) - -- “Transactions” refers to all movements of funds which are tracked by the - switch. - -In scope and out of scope -========================== - -In scope --------- - -The following functional items are in scope: - -1. Requesting a settlement by currency - -2. Requesting a settlement by currency and settlement model - -Out of scope ------------- - -Business rules -============== - -How do things happen now? -------------------------- - -This section describes how the current settlement process works. - -### Categorisation - -The process leading to settlement is initially defined by entries in the -*participantCurrency* table. This table holds a record for each combination of: - -1. Participant - -2. Currency - -3. Ledger account type (see Section 2.2 above.) - -### Recording positions - -Each entry in this table has a corresponding entry in the *participantPosition* -table. This table stores the current committed and reserved positions for each -of the combinations described above. Each change to the positions in this table -is documented by an entry in the *participantPositionChange* table, which refers -the change back to the *transfer* table and thence to the authoritative record -of transactions. - -### Assigning transactions to settlement windows - -As each transfer is fulfilled, a record is created for it in the -**transferFulfilment** table. This record contains a link to the currently open -settlement window. - -Records may be created for transactions which are not transfers. Non-transfer -transactions have their ilpFulfilment set to 0. - -The settlement API [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) contains a resource -(**closeSettlementWindow**) to allow an administrator to close a settlement -window and create a new one. The resource takes a settlement window ID as part -of the query string, together with a string describing the status to be assigned -and a string describing the reason for the change of status. In-line -documentation for the resource states: “If the settlementWindow is open, it can -be closed and a new window is created. If it is already closed, return an error -message. Returns the new settlement window.” - -Settlement windows can only be passed a status of CLOSED using this resource. - -### Initiating a settlement - -The initiation of a settlement is initiated by making a call triggered by the -scheme making a **POST** to the **/settlements** resource in the settlement API. -The caller gives a reason for the settlement request. This is a synchronous -call, whose return is described in Section 4.1.5 below. Internally, the -initiation is marked by the creation of a record in the **settlement** table and -the association of a number of settlement window records in the -**settlementWindow** table with the settlement created. This says: I want this -settlement to contain these settlement windows. Each of the settlement windows -selected to form part of this settlement must have the status CLOSED or ABORTED. -When selected to form part of a settlement, the status of each window should be -changed to PENDING_SETTLEMENT. The status of the settlement itself should also -be set to PENDING_SETTLEMENT. - -### Calculating the content of a settlement - -When a settlement has been requested and the windows which it will contain have -been selected, the switch produces an aggregation of the content of the proposed -settlement at the following levels: - -1. Settlement window (from **settlementWindow**) - -2. Participant (from **participantCurrency**) - -3. Currency (from **participantCurrency**) - -4. Account type (from **participantCurrency**) - -5. Participant role type (from **transferParticipant**) - -6. Ledger entry type (from **transferParticipant**) - -This query can be provisioned from the database FK links from **settlement** to -**settlementwindow**, to **transferFulfilment** (all fulfilled transfers), to -**transfer**, to **transferParticipant**. The amount is taken from the -**transferParticipant** table. Correct! - -Only transfers are included in a settlement. This is implied by the first -aggregation criterion above (Settlement window) and the fact that only transfers -are assigned to the current OPEN window when a **transferFulfilment** record is -created. All COMMITTED transactions should have an entry in the -**transferFulfilment** table. - -The results of this query are used to construct a number of records in the -**settlementParticipantCurrency** table, representing the net amount due to or -from each participant and currency in the settlement as a consequence of the -settlement. For a given settlement, these records are segmented by: Correct! - -1. Participant (from **participantCurrency**) - -2. Currency (from **participantCurrency**) - -3. Account type (from **participantCurrency)** - -This report is used as the basis of the information returned from the initial -**POST** to the **/createSettlement** resource of the settlement API (see -Section 4.1.4 above.) - -Bilateral settlements are not currently implemented. - -### Creating position records for the settlement - -A record is inserted in the **transfer** table for each net amount calculated in -the previous step when the settlement account transitions from -PENDING_SETTLEMENT to PS_TRANSFERS_RECORDED. Please note that PS stands for -PENDING_SETTLEMENT. Each of these records will have the account type SETTLEMENT. -The ledger entry type will be SETTLEMENT_NET_SENDER, SETTLEMENT_NET_RECIPIENT or -SETTLEMENT_NET_ZERO depending on whether the participant owes money to the -scheme, is owed money by the scheme or is neutral in the settlement, -respectively. The transfer participant type is HUB for the Hub participant and -DFSP_POSITION for the DFSP participant. The account type is imposed by the -participant currency – for the Hub participant it is the -HUB_MULTILATERAL_SETTLEMENT and for the DFSP participant it is the POSITION -account. This enables the switch to reset the participant’s position when the -window enters the PS_TRANSFERS_COMMITTED state. - -### Progress of the settlement - -As the scheme verifies that participants have settled the amounts due from them, -the scheme administrator can update the switch with this information. - -#### Updating the status of settlement windows - -Three methods of performing this update are supported. Each of these methods is -discussed in more detail below. - -##### **updateSettlementById** - -An administrator may issue a **PUT** to the **/updateSettlementById** resource -on the settlement API, giving the settlement ID of the settlement they wish to -update as part of the query (e.g. **PUT -/updateSettlementById/settlements/123.**) The content of the request is as -follows: - -1. A state to be assigned to the participants required. The state is - constrained to be either ABORTED or INVALID - -2. A reason for the change of state. - -3. An external reference for the change. - -4. An array of participants to which the status is to be applied. The following - information is given for each participant: - - 1. The ID of the participant. This is the internal Mojaloop ID of the - participant. - - 2. An array of *accounts*. The content of each account is as follows: - - 1. An ID. The description characterises this as the participant’s - currency ID QUESTION: Is this correct? It is an integer, where a - VARCHAR(3) would be expected. - - 2. A reason. A string which presumably can contain anything. - - 3. The state of the settlement for the account. This is not constrained - by an enum, but is a simple string. It is not clear how this status - relates to the overall state given in Item 1 above. - - 4. An external reference for the change in state. - -> A call to this API resource may contain *either* items 1-3 above *or* an -> array of accounts as specified in item 4 above, but not both. If it contains -> items 1-3 above, then all the items must be present. If these rules are -> breached, then the switch will reject the request. - -##### **updateSettlementBySettlementParticipant** - -An administrator may issue a **PUT** to the -**/updateSettlementBySettlementParticipant** resource on the settlement API, -giving the settlement ID and the participant ID of the parts of the settlement -they wish to update as part of the query (e.g. **PUT -/updateSettlementByParticipant/settlements/123/participants/56789.**) The -content of the request is as follows: - -1. An array of state changes, whose content is as follows: - - 1. The currency ID whose status is to be changed. This is an integer, where - a VARCHAR(3) would be expected. - - 2. A reason for the state change. - - 3. The state requested. This is a string, where an enumeration would be - expected. - - 4. An external reference for the change in state. - -Note that this is an array with the same structure as that described in item 4 -of Section 5.1.7.1 above, although it is defined separately in the API -definition. - -##### **updateSettlementBySettlementParticipantAccount** - -An administrator may issue a **PUT** to the -**/updateSettlementBySettlementParticipantAccount** resource on the settlement -API, giving the settlement ID, the participant ID and the account ID of the part -of the settlement they wish to update as part of the query (e.g. **PUT -/updateSettlementByParticipant/settlements/123/participants/56789/accounts/1.**) -The content of the request is as follows: - -1. The state requested. This is a string, where an enumeration would be - expected. - -2. A reason. A string which presumably can contain anything. - -3. An external reference for the change in state. - -Note that this is a structure with most of the same members as the structure -defined in Item 1 of Section 5.1.7.2 above, although the items appear in a -different order. - -#### How changes in settlement window state are processed - -The action taken in response to these calls depends on the status assigned to -the account. In any case, a record is created in the -**settlementParticipantCurrencyStateChange** table, giving the state identifier, -the reason and an external reference for the change. - -There is a sequence of steps defined for a settlement. Each step must be -followed in order, and no steps may be omitted. The sequence of steps is -hard-coded into the application and is as follows: - -1. PENDING_SETTLEMENT - -2. PS_TRANSFERS_RECORDED - -3. PS_TRANSFERS_RESERVED - -4. PS_TRANSFERS_COMMITTED - -5. SETTLED - -A settlement can be aborted provided no account in the settlement has reached a -status of PS_TRANSFERS_COMMITTED. - -The following actions are taken on each change of status: - -##### PENDING_SETTLEMENT to PS_TRANSFERS_RECORDED - -A record is generated in the **transfer** table to record the change in state. -The parties to this transfer are the POSITION account type and the -HUB_MULTILATERAL_SETTLEMENT type. If the participant account is a net creditor -for the settlement, then the ledger entry type will be set to -SETTLEMENT_NET_RECIPIENT. If the participant account is a net debtor for the -settlement, then the ledger entry type will be set to SETTLEMENT_NET_SENDER. If -the participant account is neutral for the settlement, then the ledger entry -type will be set to SETTLEMENT_NET_ZERO. - -A record is also created in the **transferstatechange** table with the -RECEIVED_PREPARE state, which means that no positions have been changed. - -When the last participating account is changed to PS_TRANSFERS_RECORDED, then -the settlement’s status is also changed to PS_TRANSFERS_RECORDED. - -If an administrator attempts to change an account’s state to -PS_TRANSFERS_RECORDED and either the settlement’s state or the settlement -account’s state is not PENDING_SETTLEMENT or PS_TRANSFERS_RECORDED, then the -request will be rejected. - -##### PS_TRANSFERS_RECORDED to PS_TRANSFERS_RESERVED - -A new record is created in the **transferstatechange** table for the transfer -that was created in section 5.1.7.2 above. This record will have a status of -RESERVED. If the participant is a net creditor as a result of the settlement, -then a record will also be created in the participantPositionChange table if the -account being reserved is for a net creditor in the settlement, as defined in -Section 5.1.7.2 above. The Net Debit Cap is checked at this point, and if the -current position exceeds the Net Debit Cap, then the Net Debit Cap is -automatically adjusted by the amount of the net credit due to the account as -part of the settlement and the participant is sent a notification of the new Net -Debit Cap value and its currency. - -When the last participating account is changed to PS_TRANSFERS_RESERVED, then -the settlement’s status is also changed to PS_TRANSFERS_RESERVED. - -If an administrator attempts to change an account’s state to -PS_TRANSFERS_RESERVED and either the settlement’s state or the settlement -account’s state is not PS_TRANSFERS_RECORDED or PS_TRANSFERS_RESERVED, then the -request will be rejected. - -##### PS_TRANSFERS_RESERVED to PS_TRANSFERS_COMMITTED - -A new record is created in the **transferstatechange** table for the transfer -that was created in section 5.1.7.2 above. This record will have a status of -COMMITTED. If the participant is a net debtor as a result of the settlement, -then a record will also be created in the participantPositionChange table if the -account being reserved is for a net debtor in the settlement, as defined in -Section 5.1.7.2 above. - -When the last participating account is changed to PS_TRANSFERS_COMMITTED, then -the settlement’s status is also changed to PS_TRANSFERS_COMMITTED. - -If an administrator attempts to change an account’s state to -PS_TRANSFERS_COMMITTED and either the settlement’s state or the settlement -account’s state is not to PS_TRANSFERS_RESERVED or PS_TRANSFERS_COMMITTED, then -the request will be rejected. - -##### PS_TRANSFERS_COMMITTED to SETTLED - -When the first account is changed to a status of SETTLED, the settlement’s state -is changed to SETTLING. - -When the last participating account is changed to SETTLED, then the settlement’s -status is also changed to SETTLED. - -If an administrator attempts to change an account’s state to SETTLED and either -the settlement’s state or the settlement account’s state is not to -PS_TRANSFERS_COMMITTED or SETTLED, then the request will be rejected. - -### Aborting the settlement - -If there is any failure in the scheme’s process for recovering the amounts due -from participants in a settlement, the scheme can update the switch with this -information by issuing a **PUT** to the **/updateSettlementById** resource of -the settlement API and setting the **state** value of the content of the message -to ABORTED. A **PUT** call on the **/updateSettlementById** resource is the only -method which may be used for ABORTING a settlement. If any account information -is given in the call, then neither the **state** nor the **reason** nor the -**externalReference** fields may be set. if the **state** value is set at the -top level of the call, then the **reason** field must also be set, and the -request will be rejected if any account information is given in the call. - -If an attempt is made to abort a settlement, and any of the accounts in the -settlement have the status PS_TRANSFERS_COMMITTED or SETTLED, then the request -will be rejected. - -When a call is received, a new record is created in the -**settlementParticipantCurrencyStateChange** table, and is given the appropriate -status based on the status reported by the caller. Depending on the update that -was received, this may also require the status of the transaction and that of -the participant position to be updated. No, it is done at settlement level for -the entire settlement and all entries in settlementParticipantCurrency are -affected. - -Note: if the settlement is bilateral, then there is no obvious reason to abort -the entire settlement if one interchange fails. We should think about this use -case and how we would want to represent it. This document does not consider this -use case. - -Aborting a settlement comprises the following steps: - -1. The status of the transfers created in Section 5.1.6 above should be changed - to ABORTED. - -2. A new record is added to the **settlementParticipantCurrencyStateChange** - table for each of the participant records in the settlement. This record has - a status of ABORTED, and the **currentStateChangeId** column in the - **settlementParticipantCurrency** table for that participant record is - changed to point to this new record. - -3. A new record is added to the **settlementWindowStateChange** table for each - settlement window in the settlement. This record has a status of ABORTED, - and the **currentStateChangeId** column in the settlementWindow table for - that window is changed to point to this new record. - -4. A new record is added to the **settlementStateChange** table for the - settlement. This record has a status of ABORTED, and the - **currentStateChangeId** column in the **settlement** table is changed to - point to this new record. - -5. If positions have been reserved for net creditors as a result of the - settlement (see Section 5.1.7.3 above,) then a balancing entry will be - created in the **participantPositionChange** table to reverse the - reservation of funds. This action does not at present reverse any change to - the account’s Net Debit Cap that may have been made as a consequence of this - reservation. - -6. Any records created in the **transfers** table (see Section 5.1.7.2 above) - will have their state changed in two steps by adding records to the - **transferStateChange** table. The first step will change the transfer state - to REJECTED. The second step will change the state to ABORTED. - -Question: should there be/is there a time-out after which a settlement will be -aborted if it has not completed? If there is, how is it set? No, there isn’t -timeout on a settlement level. But when transfers are prepared (for -PS_TRANSFERS_RECORED) expiration is set on a transfer level. Its value is -controlled by a Config.TRANSFER_VALIDITY_SECONDS, which currently defaults to -432000 seconds, which equals 5 days. It is big enough to avoid expiration. -Still, if that happens, it would leave the data in an unrecoverable by the API -state. This is very good point and should be certainly addressed with the next -increment! - -Recording the deposit of funds ------------------------------- - -As participants are informed of their liabilities under the settlement, it is -expected that they will deposit funds in their settlement account to cover those -liabilities. These activities are recorded via the central ledger administration -interface resource **recordFundsIn**. - -This action is called through a POST to the administration interface, giving the -name of the participant and the account to be credited in the form POST -/participants/{participantName}/accounts/{accountId} (e.g. **POST -/participants/myDfsp/accounts/1234**) The content of this message is as follows. - -1. transferId: a UUID to be used to identify the transfer in the switch. - -2. externalReference: a reference used to identify the transfer for the - administrator - -3. action: this should be set to “recordFundsIn” for recording funds in. - -4. reason: the reason why the transfer is being made. - -5. amount: the amount of the transfer. - - 1. amount: the actual amount being transferred - - 2. currency: the ISO 4217 code of the currency of the deposit. - -6. extensionList: a series of key/value pairs which are used to carry - additional information - -When an administrator records that a participant has deposited funds to an -account, the amount deposited is recorded in an entry in the **transfer** table. -The parties to the transfer are recorded by entries in the -**transferParticipant** table, with a ledger account type of the type requested -in the POST for the participant and HUB_RECONCILIATION for the balancing entry. -For deposits, the participant account will be the creditor and the -HUB_RECONCILIATION account the debtor. The application will currently reject -requests to this interface which do not have a ledger account type of -SETTLEMENT. - -A deposit goes through the following changes of state: - -1. A record is created for the transfer in the **transferStateChange** table - with a state of RECEIVED_PREPARE. - -2. Next, a record is created in the **transferStateChange** table with the - state RESERVED. This also creates a record in the - **participantPositionChange** table to record the reservation of funds in - the HUB_RECONCILIATION account, and the **participantPosition** table’s - value for that account is updated. - -3. Finally, a record is created in the **transferStateChange** table with the - state COMMITTED. After this act, records are created in the - **participantPositionChange** table for the creditor account to record the - completion of the deposit, and the appropriate record in the - **participantPosition** table has its balance updated. - -These changes of state are simply chained together in sequence. There is no -interval or trigger between the steps. - -This activity has no direct effect on the settlement process or on the Net Debit -Cap. - -Recording the withdrawal of funds ---------------------------------- - -At various times, participants may wish to withdraw funds from their settlement -accounts: for instance, if they are long-term net beneficiaries of transfers and -are building up a surplus of liquidity. These activities are recorded via a -two-phase process. In the first phase, the funds for the proposed withdrawal are -reserved via the central ledger administration interface resource -**recordFundsOutPrepareReserve**. In the second phase, the withdrawal is -committed via the **recprdFundsOutCommit** resource or aborted through the -**recordFundsOutAbort** resource. - -These activities are defined below. - -### **recordFundsOutPrepareReserve** - -This action is called through a POST to the administration interface, giving the -name of the participant and the account to be credited (e.g. **POST -/participants/myDfsp/accounts/1234**) The content of this message is as follows. - -1. transferId: a UUID to be used to identify the transfer in the switch. - -2. externalReference: a reference used to identify the transfer for the - administrator - -3. action: this should be set to “recordFundsOutPrepareReserve” for recording - funds withdrawals. - -4. reason: the reason why the transfer is being made. - -5. amount: the amount of the transfer. - - 1. amount: the actual amount being transferred - - 2. currency: the ISO 4217 code of the currency of the deposit. - -6. extensionList: a series of key/value pairs which are used to carry - additional information - -When an administrator records that a participant has requested the withdrawal of -funds from an account, the amount to be withdrawn is recorded in an entry in the -**transfer** table. The parties to the transfer are recorded by entries in the -**transferParticipant** table, with a ledger account type of the type requested -in the POST for the participant and HUB_RECONCILIATION for the balancing entry. -For withdrawals, the participant account will be the debtor and the -HUB_RECONCILIATION account the creditor. The application will currently reject -requests to this interface which do not have a ledger account type of -SETTLEMENT. - -Reservation of a withdrawal goes through the following changes of state: - -1. A record is created for the transfer in the **transferStateChange** table - with a state of RECEIVED_PREPARE. - -2. Next, a record is created in the **transferStateChange** table with the - state RESERVED. This also creates a record in the - **participantPositionChange** table to record the reservation of funds in - the participant’s settlement account, and the **participantPosition** - table’s value for that account is updated. - -These changes of state are simply chained together in sequence. There is no -interval or trigger between the steps.**recordFundsOutCommit** - -This action is called through a POST to the administration interface, giving the -name of the participant and the account to be credited (e.g. **POST -/participants/myDfsp/accounts/1234**) The content of this message is as follows. - -1. transferId: a UUID to be used to tie the commit to the preceding reservation - in the switch. - -2. externalReference: a reference used to identify the transfer for the - administrator - -3. action: this should be set to “recordFundsOutCommit” for recording funds - commitments. - -4. reason: the reason why the transfer is being made. - -5. amount: the amount of the transfer. - - 1. amount: the actual amount being transferred - - 2. currency: the ISO 4217 code of the currency of the deposit. - -6. extensionList: a series of key/value pairs which are used to carry - additional information - -When an administrator records that a participant wants to commit the withdrawal -of funds from an account, the original entry in the **transfer** table is -identified. The parties to the transfer are recorded by entries in the -**transferParticipant** table, with a ledger account type of the type requested -in the POST for the participant and HUB_RECONCILIATION for the balancing entry. -For withdrawals, the participant account will be the debtor and the -HUB_RECONCILIATION account the creditor. The application will currently reject -requests to this interface which do not have a ledger account type of -SETTLEMENT. - -Commitment of a withdrawal goes through the following changes of state: a record -is created in the **transferStateChange** table with the state COMMITTED. After -this act, records are created in the **participantPositionChange** table for the -creditor account to record the completion of the deposit, and the appropriate -record in the **participantPosition** table has its balance updated. These -changes of state are simply chained together in sequence. There is no interval -or trigger between the steps. - -This activity has no direct effect on the settlement process or on the Net Debit -Cap. - -Proposed enhancements -===================== - -This section describes the enhancements to the existing OSS settlement process -(described in Section 4.1 above) which are proposed. Each enhancement is shown -in a separate section and, where there are dependencies between enhancements, -these are listed in the enhancement’s description. - -Request settlement by currency [EPIC] -------------------------------------- - -The following changes are required to support settling separately for different -currencies. - -### Database changes - -The following changes are required to support multi-currency settlement. - -#### Addition of a settlementWindowContent table [Story \#1] - -A new table will be added to the database. The name of this table will be -**settlementWindowContent**. The table will contain an entry for each item of -content in a given settlement window, broken down by ledger account type and -currency. The full column structure of the table is as follows: - -| **Column name** | **Description** | **Attributes** | -|-----------------------------------------|---------------------------------------------------|---------------------------------------------------------------------------------------| -| **settlementWindowContentId** | Auto-generated key for the record. | BIGINT(20). Unsigned, not null, primary key, autoincrement | -| **settlementWindowId** | The settlement window that the record belongs to. | BIGINT(20). Unsigned, not null. Foreign Key to **settlementWindow** | -| **ledgerAccountTypeId** | The ledger account that the record refers to. | INT(10). Unsigned, not null. Foreign key to **ledgerAccountType** | -| **currencyId** | The currency that the record refers to. | VARCHAR(3). Not null. Foreign key to **currency**. | -| **createdDate** | The date and time when the record was created. | DATETIME. Not null. Defaults to CURRENT_TIMESTAMP. | -| **currentStateChangeId** | The current state of this entry. | BIGINT(20). Unsigned. Foreign key to **settlementWindowContentStateChange** | - -  - -#### Addition of a settlementWindowContentStateChange table [Story \#2] - -A new table will be added to the database. The name of this table will be -**settlementWindowContentStateChange**. The table will track changes to the -status of entries in the **settlementWindowContent** table. The full column -structure of the table is as follows: - -| **Column name** | **Description** | **Attributes** | -|------------------------------------------|---------------------------------------------------------------------|----------------------------------------------------------------------------| -| **settlementWindowContentStateChangeId** | Auto-generated key for the record. | BIGINT(20). Unsigned, not null, primary key, autoincrement | -| **settlementWindowContentId** | The settlement window content record whose status is being tracked. | BIGINT(20). Unsigned, not null. Foreign Key to **settlementWindowContent** | -| **settlementWindowStateId** | The record’s status. | VARCHAR(50). Not null. Foreign key to **settlementWindowState** | -| **reason** | An optional field giving the reason for the state being set. | VARCHAR(512). | -| **createdDate** | The date and time when the record was created | DATETIME. Not null. Defaults to CURRENT_TIMESTAMP | - -  - -#### Changes to the settlementTransferParticipant table [Story \#3] - -The name of the **settlementTransferParticipant** table should be changed to -**settlementContentAggregation**. - -The column structure of the **settlementContentAggregation** table should be -modified as follows: - -1. Remove the following foreign keys from the table: - 1. settlementtransferparticipant_settlementid_foreign - 2. settlementtransferparticipant_settlementwindowid_foreign -2. Remove the following columns from the table: - 1. settlementId - 2. settlementWindowId -3. Add the following column to the table: - 1. Column name: **settlementWindowContentId** - 2. Attributes: BIGINT(20), unsigned, not null -4. Add the following foreign key to the table: - 1. Name: settlementContentAggregation_settlementwindowcontent_foreign - 2. Child column **settlementWindowContentId** - 3. Refers to table: **settlementWindowContent** - 4. Refers to column: **settlementWindowContentId** - -All database scripts which use the **settlementTransferParticipant** table will -be changed to accommodate the new name and structure of the table. [Story \#8] - -Queries to filter the records in the **settlementContentAggregation** table -required for a settlement in a particular currency will need to join across from -that table to the **participantCurrency** table using the -**participantCurrencyId** column to ascertain the currency to which a particular -row refers. The **currencyId** column is held in the **participantCurrency** -table. [Story \#9] - -#### Add structures relating to settlement models [Story \#4] - -In order to support the specification of settlement models, which will include -currencies, the database changes specified in Section 6.2.1.1 below should be -added to the database. - -Settlement models describing the settlement types required for a given -implementation will be developed and tested.**[Story \#4a]** - -#### Change to settlement table [Story \#5] - -The **settlement** table in the central ledger database needs to be modified to -add a *settlementModel* column. This column should have the following -characteristics: - -- The column should be required (NOT NULL) and unsigned. -- The column’s data type should be integer(10) -- The column should be defined as a foreign key reference to the -*settlementModelId* field of the **settlementModel** table. - -When this change is applied to an existing database, a settlement model to -describe the default settlement should be created. The settlementCurrencyId -column in this model should be left blank (= all currencies.) The -settlementModel column in all existing records in the settlement table should be -set to point to this model’s ID. A script to apply this change should be -created, tested and stored in the repository. - -### Changes to processing - -The following changes to the processing code are required to support -multi-currency settlement. - -#### Change to code supporting closeSettlementWindow resource - -The existing API [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) provides a single function -(**closeSettlementWindow**) to manage settlement windows. This function allows -its user to select a settlement window by ID number and to input a new status -for the window and a reason for that status. - -When a settlement window is closed, the code supporting this activity should -perform two functions, as follows. These functions should be performed in the -background and without impacting system performance. - -##### Generate records in the settlementWindowContent table [Story \#1095] - -The code should generate a record in the **settlementWindowContent** table for -each ledger entry type/currency combination found in the transfers in the -settlement window. This information can be obtained from the following query: -``` -SELECT DISTINCT - @mySettlementWindowId, pc.ledgerAccountTypeId, pc.currencyId -FROM transferFulfilment tf -INNER JOIN transferParticipant tp - ON tp.transferId = tf.transferId -INNER JOIN participantCurrency pc - ON pc.participantCurrencyId = tp.participantCurrencyId -WHERE tf.settlementWindowId = @mySettlementWindowId; -``` - -##### Generate records in the settlementContentAggregation table [Story \#1095] - -The code should calculate the aggregate values for all transfers which form part -of that settlement window and store them in the **settlementContentAggregation** -table. Aggregates should be produced for the following segmentation: - -1. Participant -2. Currency -3. Ledger account type -4. Participant role type -5. Ledger entry type - -The following query will perform this function for a given settlement window: - -``` -INSERT INTO settlementContentAggregation - (settlementWindowContentId, participantCurrencyId, - transferParticipantRoleTypeId, ledgerEntryTypeId, amount) -SELECT swc.settlementWindowContentId, pc.participantCurrencyId, - tp.transferParticipantRoleTypeId, tp.ledgerEntryTypeId, SUM(tp.amount) -FROM transferFulfilment tf -INNER JOIN transferParticipant tp - ON tf.transferId = tp.transferId -INNER JOIN participantCurrency pc - ON pc.participantCurrencyId = tp.participantCurrencyId -INNER JOIN settlementWindowContent swc - ON swc.settlementWindowId = tf.settlementWindowId -  AND swc.ledgerAccountTypeId = pc.ledgerAccountTypeId - AND swc.currencyId = pc.currencyId -WHERE tf.settlementWindowId = @mySettlementWindowId -GROUP BY swc.settlementWindowContentId, pc.participantCurrencyId, - tp.transferParticipantRoleTypeId, tp.ledgerEntryTypeId; -``` - -#### createSettlement - -The parameters for the **createSettlement** resource should be extended to -include the settlement model for which the settlement is required. - -When the settlement is created, the settlement model for which the settlement is -required should be added to the new row in the **settlement** table. [Story \#1097] - -When a settlement is requested, the switch should check that the settlement -model for which settlement is being requested requires NET settlement and not -GROSS settlement. If the requested settlement model requires GROSS settlement, -then the request should be rejected with an error. - -The verification procedures associated with the **createSettlement** resource -should be changed to check that some of the settlement windows associated with -the proposed settlement contain entries for the settlement model requested. If -there are no entries for the settlement model requested for any of the -settlement windows requested, then an error should be returned and the -settlement request rejected. [Story \#1096] - -#### Updating the progress of a settlement - -When the status for a settlement participant is changed to SETTLED, this will result in -changes to the status of all the records in the **settlementContentAggregation** -table for the given participant, identified by the compound key: settlementId + participantCurrencyId. - -[Story \#16] - -The code should then check to see if, as a result of the updates to the records -in **settlementContentAggregation**, all records for a given combination of -settlement window, ledger account type and currency have the same status. If -they have, then the appropriate record in the **settlementWindowContent** table -should be updated to have that status. - -The code should then check to see if all records in the -**settlementWindowContent** table for a given settlement window have the same -status. If they have, then the appropriate record in the **settlementWindow** - -Support continuous gross settlement ------------------------------------ - -Continuous Gross Settlement is a settlement model in which each transaction is -settled as soon as it is fulfilled. The following changes are required to -implement this change. - -### Database changes - -The database changes shown in Section 8 below should be implemented. These can -be summarised as follows: - -#### Changes to support the settlement model - -A number of new tables are required to define a settlement model and to store -the enumerations for its definition types. This comprises the following tables -in the ERD: - -- settlementDelay - -- settlementInterchange - -- settlementModel - -In addition, the **settlementmodel** table has foreign keys to two existing -tables, as follows: - -1. A foreign key to the **currency** table to enable the settlement model to - settle only scheme accounts in a particular currency. If this entry is - blank, this should be interpreted as saying that the settlement model - settles all currencies that are not specified as being settled by other - settlement models for the same account type. - -2. A foreign key to the **ledgerAccountType** table. This specifies that the - settlement model settles accounts of this type. - -#### Changes to the **ledgeraccounttype** table - -The current **ledgeraccounttype** table stores a number of entries for account -types which should not be used for settlements – for instance, -HUB_MULTILATERAL_SETTLEMENT. A column should therefore be added to the -**ledgeraccounttype** table to indicate whether the account type can be attached -to a settlement model or not. This column is called **settleable**, and is -specified as a Boolean value, NOT NULL and with a default of FALSE. - -Of the existing ledger account types, PRINCIPAL_VALUE, INTERCHANGE_FEE and -HUB_FEE should be marked as capable of being attached to settlement models (this -value should be TRUE.) For all other ledger account types, the column should be -set to FALSE. If new ledger account types are added to this table via the -eventual settlement API, then they should have a value of TRUE. - -#### Changes to the **ledgerentrytype** table - -Implementation of the TIPS settlement model requires an explicit association -between ledger entry types and the account types in which they should appear. -Since each ledger entry type should only appear in a single account type, though -multiple ledger entry types may appear in a given account type, this is modelled -by including a foreign key reference to the **ledgeraccounttype** table as a -column in the **ledgerentrytype** table. It should be noted that this applies -only to ledger entry types which are associated with a settlement model, as -described in Section 6.2.1.2 above. The assignment of existing entries in the -database would be as follows: - -| Ledger Entry Type | Ledger Account Type | -|-------------------|---------------------------| -| PRINCIPAL_VALUE | POSITION | -| INTERCHANGE_FEE | INTERCHANGE_FEE | -| HUB_FEE | HUB_FEE | -| | | - -#### Changes to the **settlement** table - -The **settlement** table should have a column added to it to allow the -settlement model to be used in settling it to be specified. The column should be -called *settlementModelId*. It should have the same data type as the equivalent -field in the **settlementModel** table, and should be a foreign key into that -table. It should be defined as not null. - -#### Changes to the **settlementWindow** table - -As well as settlements, individual settlement windows will need to be assigned -to settlement models. The **settlementWindow** table should therefore have a -column added to it to allow the settlement model to be used in settling it to be -specified. The column should be called *settlementModelId*. It should have the -same data type as the equivalent field in the **settlementModel** table, and -should be a foreign key into that table. It should be defined as not null. - -This concludes the list of schema changes required to support the TIPS -settlement models - -### API changes - -API Support for the settlement functionality required for TIPS will include the -following functions: - -#### Close a settlement window - -The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a -**closeSettlementWindow** resource. This function allows its user to select a -settlement window by ID number and to input a new status for the window and a -reason for that status. This resource will retain its current signature, but the -code supporting it needs to change as follows. - -When a settlement window is closed, the system should create a new settlement -window with the same settlement model as the newly closed settlement window, and -should make this the active window. - -When a settlement window is closed, the code supporting this activity should -calculate the aggregate values for all transfers which form part of that -settlement window and store them in the **settlementTransferParticipant** table. -Aggregates should be produced for the following segmentation: - -1. Participant - -2. Currency - -3. Ledger account type - -4. Participant role type - -5. Ledger entry type - -The following example code will produce the aggregations required for a given -settlement window (identified as \@MyWindow in the example): - -SELECT - -S.settlementId - -, W.settlementWindowId - -, P.participantCurrencyId - -, P.transferParticipantRoleTypeId - -, P.ledgerEntryTypeId - -, SUM(P.amount) - -, CURRENT_TIMESTAMP AS createdDate - -FROM - -settlementWindow W INNER JOIN settlementModel M ON W.settlementModelId = -M.idsettlementModel - -INNER JOIN settlementSettlementWindow S ON W.settlementWindowId = -S.settlementWindowId - -INNER JOIN ledgerAccountType L ON M.idsettlementModel = L.settlementModelId - -INNER JOIN transferFulfilment F ON W.settlementWindowId = F.settlementWindowId - -INNER JOIN transferParticipant P ON F.transferId = P.TransferId - -INNER JOIN participantCurrency PC ON P.participantCurrencyId = -PC.participantCurrencyId - -AND PC.ledgerAccountTypeId = L.ledgerAccountTypeId - -WHERE - -W.settlementWindowId = \@MyWindow - -AND - -(PC.currencyId = M.settlementcurrencyId OR M.settlementcurrencyId IS NULL) - -GROUP BY - -S.settlementId - -, W.settlementWindowId - -, P.participantCurrencyId - -, P.transferParticipantRoleTypeId - -, P.ledgerEntryTypeId; - -#### Getting information about a settlement window - -The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a -**getSettlementWindowById** resource. This function allows its user to obtain -information about a settlement window by giving the ID that was returned when -the settlement window was created. - -This call returns a **SettlementWindow** object. This object will need to be -extended to include the name of the settlement model to which the settlement -window belongs. - -#### Getting information about settlement windows using parameters - -The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a -**getSettlementWindowsByParams** resource. This function allows its user to -obtain information about all settlement windows which meet the criteria -specified by the user. The following changes will need to be made to this call: - -1. The parameters supported by the call will need to be extended to allow a - user to request settlement windows by settlement model. The user should be - able to enter the name of a settlement model. - -2. This call returns an array of **SettlementWindow** objects. It is assumed - that these objects will have been changed by the changes specified in - Section 6.2.2.2 above, and that no further processing will be required for - this call. - -#### Requesting a settlement - -The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a **createSettlement** -resource. This function allows its user to request a settlement for a given set -of settlement windows, which are passed to the resource as parameters. The -following changes will need to be made to this call: - -The parameters for the **createSettlement** resource are defined in the -**SettlementEventPayload** object. This object will need to have a parameter -added to specify the settlement model which is to be settled. The parameter -should be called *settlementModel*, and it should be a string. It should be -required. - -The following validation should be performed on this parameter when the request -is received via the API: - -1. The content of the parameter is a case-insensitive match for an active entry - in the **settlementmodel** table, ignoring whitespace. - -2. The *settlementtypeid* column in the record in the selected settlement model - should not point to a record in the **settlementdelay** table whose - *settlementDelayName* value is “IMMEDIATE”. If it does, the request should - be rejected and an error message returned to the caller. - -The id of the settlement model requested should be stored in the -settlementModelId column of the row created in the **settlement** table to -describe the settlement. - -#### Returning the status of a settlement - -The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a **getSettlementById** -resource. This function allows its user to obtain information about a settlement -by giving the ID that was returned when the settlement was created. - -Information about settlements is returned in a **Settlement** object. A -parameter should be added to the Settlement object to record the settlement -model which is being settled by the settlement. - -The parameter should be called *settlementModel*, and it should be a string. It -should be required. - -**Note**: when a settlement is requested, a reason is given; but the -**Settlement** object does not contain the reason. It might be worth including -this in the definition of the **Settlement** object. - -#### Getting information about settlements using parameters - -The existing API definition[2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a -**getSettlementsByParams** resource. This function allows its user to obtain -information about all settlements by giving the ID that was returned when the -settlement was created. The following changes will need to be made to this call: - -1. This call returns an array of **Settlement** objects. It is assumed that - these objects will have been changed by the changes specified in Section - 6.2.2.5 above, and that no further processing will be required for this - call. - -#### Getting information about a specific participant in a settlement - -The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a -**getSettlementBySettlementParticipant** resource. This function allows its user -to obtain information about a settlement which meet the criteria specified by -the user. The following changes will need to be made to this call: - -1. This call returns a **Settlement** object. It is assumed that this object - will have been changed by the changes specified in Section 6.2.2.5 above, - and that no further processing will be required for this call. - -#### Updating a specific settlement - -The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports an -**updateSettlementById** resource. This function allows its user to update -information about a settlement by giving the ID that was returned when the -settlement was created. - -This call returns a **Settlement** object. It is assumed that this object will -have been changed by the changes specified in Section 6.2.2.5 above, and that no -further processing will be required for this call. - -#### Updating a settlement for a specific participant - -The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports an -**updateSettlementBySettlementParticipant** resource. This function allows its -user to update information about a settlement by giving the ID that was returned -when the settlement was created, and the participant whose information is to be -updated. - -This call returns a **Settlement** object. It is assumed that this object will -have been changed by the changes specified in Section 6.2.2.5 above, and that no -further processing will be required for this call. - -#### Updating a settlement for a specific participant and account - -The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports an -**updateSettlementBySettlementParticipantAccount** resource. This function -allows its user to update information about a settlement by giving the ID that -was returned when the settlement was created, and the participant and account -whose information is to be updated. - -This call returns a **Settlement** object. It is assumed that this object will -have been changed by the changes specified in Section 6.2.2.5 above, and that no -further processing will be required for this call. - -#### Recording the deposit of funds by a participant - -The existing administration API [3](https://mojaloop.io/documentation/api/central-ledger-api-specification.html) contains functions to enable -an administrator to record a deposit made by a participant to an account. This -process is described in Section 5.2 above. The API should be changed to align it -with the structures used in the existing settlement API [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json). In addition, the signature of the API should be extended to allow the -administrator to specify the account type that will be updated by the deposit. - -#### Recording the withdrawal of funds by a participant - -The existing administration API [3](https://mojaloop.io/documentation/api/central-ledger-api-specification.html) contains functions to enable -an administrator to record a withdrawal made by a participant from an account. -This process is described in Section 5.3 above. The API should be changed to -align it with the structures used in the existing settlement API [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json). In addition, the signature of the API should be extended to allow -the administrator to specify the account type that will be updated by the -withdrawal. - -#### New resource: openSettlementWindow - -In the current architecture, an instance of each settlement window is created -when the instance is set up, and subsequent settlement windows are created by -closing the current settlement window. In the new settlement management -structure, we will need the ability to create new settlement windows where no -predecessors exist: for instance, when an administrator decides to settle a -particular currency using a different settlement model. - -### Processing changes - -The following processing changes are required to implement the changes required -to support continuous gross settlement. - -#### Attributing ledger entries to the correct ledger account type - -When a ledger entry is created, it should be assigned to the ledger account type -specified in the *ledgeraccounttypeid* column of the row in the -**ledgerentrytype** table appropriate to the ledger entry type which is being -created. - -For example: if a normal entry representing a transfer is being created, it will -have a ledger entry type of PRINCIPAL_VALUE. It should be assigned to the -POSITION account type (the default position at present.) This implies that the -match described in Section 6.2.1.3 above has been implemented. - -Question: how does the switch decide whether or when to construct a record in -the **participantPositionChange** table? How would it be possible to select the -ledger account type to which the position refers? - -Processing interchange fees ----------------------------- - -In order to support the scheme model implemented by TIPS, we need to generate -and settle liabilities incurred as a consequence of making transfers between -particular types of customer. The general form of this rule is as follows: - -- If the transaction is a wallet-to-wallet P2P transaction, then the receiver - DFSP pays the sender DFSP 0.6% of the amount of the transaction. - -- No interchange fees are levied for on-us transactions. - -The business decisions around this requirement are: - -1. The definition of whether or not a payee account is a wallet will be - returned by the payee DFSP as part of customer discovery. The mechanism by - which this is implemented is outside the scope of this document. - -2. Interchange fees will be captured by the switch when the transfers which - incur them are completed. - -3. Interchange fees will have the ledger entry type INTERCHANGE_FEE and will be - recorded in accounts whose type is INTERCHANGE_FEE. - -4. Interchange fees will be settled multilaterally, net and deferred. It is - expected that this settlement will take place monthly. - -5. Interchange fees do not require liability cover by participants. - -This functionality will be implemented as a partial instance of a general -process for defining and executing rules, and for taking actions based on the -outcome of evaluation of a rule. For this particular case, we propose the -changes described in the following sections. - -### Part 1: Run script for batch update of interchange fees when settlement window is closed. - -Include stories to manage account type definition - -### Part 2: Add reservation on prepare using script and modify fulfilment to fulfil all ledger types for which an entry has been made - -### Evaluating a rule - -The process of evaluating a rule is based on the following assumptions: - -1. There will be a standard form of rule evaluation with the following - structure: - - 1. A transaction object will be passed as the parameter to the rule - evaluation function. - - 2. The rule evaluation itself will use a complex if statement. - - 3. If the rule evaluates to TRUE, then an action should be executed as - described in Section 6.3.2 below. - -An example of a rule function to evaluate a TIPS interchange fee rule could be: - -function evaluateInterchangeFee (transaction) { - -if( - -(transaction.payee.fspId.toLowerCase() != transaction.payer.fspId.toLowerCase()) - -&& (transaction.extensionList[“payerAccountType”].toLowerCase() == -"Wallet".toLowerCase() - -&& transaction.extensionList[“payeeAccountType”].toLowerCase() == -"Wallet".toLowerCase()) - -&& (transaction.transactionType.scenario.toLowerCase() == -"TRANSFER".toLowerCase() - -&& transaction.transactionType.initiator.toLowerCase() == "PAYER".toLowerCase() - -&& transaction.transactionType.initiatorType.toLowerCase() == -"CONSUMER".toLowerCase()) - -) { - -// Do some good stuff - -}; - -}; - -### Taking action after evaluating a rule - -If a rule evaluates to TRUE as described in Section 6.3.1 above, then -appropriate action should be taken. In the case of the immediate example of -interchange fees, the action taken should be to add two entries to the -participants’ interchange fee accounts, on recording the debit from the payee of -the interchange fee amount and the other recording the credit to the payer of -the interchange fee amount. - -A simple yet general way of supporting actions of this type is to define a class -(which might be called ruleAction) and adding methods to it to represent the -actions to be taken. The rule evaluation function can then instantiate the class -and call the appropriate function. - -In the case of the interchange fees, we would define an action called -addLedgerEntry, with the following parameters: - -1. The transfer ID for which the ledger entry is being created - -2. The ledger entry type to be used - -3. The currency in which the amount is denominated - -4. The amount of the fee - -5. The FSP ID of the credit party - -6. The FSP ID of the debit party - -This might appear in the rule evaluation function as: - -myAction.addLedgerEntry(transaction.transactionId, - -transaction.transactionId, - -"INTERCHANGE_FEE“, - -transaction.currency, - -transaction.amount\*0.006, - -transaction.payer.fspId, - -transaction.payee.fspId); - -### Providing a generic framework for rule evaluation - -Finally, we will need to provide a generic framework to trigger the evaluation -of rules. This should be an array of evaluation functions, which are triggered -when the status of a transfer changes to FULFILLED. - -Process transfers for continuous gross settlement [EPIC] -------------------------------------------------- - -When a settlement model specifies that an account is to be settled immediate gross, then each ledger entry which is of a type belonging to that scheme account should be settled immediately. This immediate settlement should have the following characteristics: - -- It should be performed by a process which is logged. -- It should be performed immediately, so that participants can check their current position against the transfers that comprise it. -- It should be aggregated to settlement window level, so that the checks which are currently performed on the overall status of a settlement window will continue to work. - -The following sections describe the changes that are required to process transfers for accounts which are settled immediate gross. - -### Database changes - -The following changes are required to the database to implement transfer processing for continuous gross settlement - -#### Addition of a new table to store changes in state - -A new table should be added to store changes in state for individual transfers. The name of this table should be **transferParticipantStateChange**. Its column structure should be as follows: - -1. The unique key to the record. Column name: **transferParticipantStateChangeId**; type: unsigned BIGINT; not nullable; primary key -2. The record in **TransferParticipant** whose state change this record marks. Column name: **transferParticipantId**; type: unsigned BIGINT; not nullable; foreign key to the **transferParticipantId** column of the **transferParticipant** table. -3. The current state of the record in **transferParticipant** to which this state record refers. Column name: **settlementWindowStateId**; data type VARCHAR(50); not nullable; foreign key to the **settlementWindowStateId** column of the **settlementWindowState** table. -4. An explanation of the state change. Column name: **reason**; type: VARCHAR(512); nullable. -5. The date and time when the change was recorded. Column name: **createdDate**; type DATETIME; not nullable; default value **CURRENT_TIMESTAMP**. - -#### Changes to the TransferParticipant table - -The **transferParticipant** table should have a new column added to store the current state of the transaction. The name of the column should be **currentStateChangeId** and its data type should be UNSIGNED BIGINT. The column should be nullable, and it should have a foreign key reference to the **transferParticipantStateChangeId** column of the **transferParticipantStateChange** table. - -### Processing changes - -The following changes to processing are required to support immediate settlement of gross ledger entries. - -#### Generating entries in settlementTransferParticipant - -When a new row is inserted in the **transferParticipant** table, the value of the **currentStateChangeId** column for that row should be set to NULL. - - - -#### Generating entries in settlementContentAggregation - -The following changes to the process that creates aggregation records in the **settlementContentAggregation** table are required. - -1. The aggregation process for a settlement window may not be performed if there are any records in the **transferParticipant** table which belong to the settlement window to be aggregated (as defined by joining the **transferParticipant** records to the matching records in the **transferFulfilment** table on the **transferId** column in both tables) and which have their **currentStateChangeId** column set to NULL. -2. When there are no records in **transferParticipant** which meet the blocking criteria described in step 1 above, then all records belonging to the settlement window which has just been closed, and which currently have the status OPEN, should have their status set to CLOSED. This means: a record should be added to the **transferParticipantStateChange** table for the qualifying **transferParticipant** record whose status is CLOSED, and the **currentStateChangeId** column for the qualifying **transferParticipant** record should be set to point to the newly created record. -2. When aggregating records for insertion into the **settlementContentAggregation** table, if all the records in the **transferParticipant** table which are to be aggregated into a single record in the **settlementContentAggregation** table have the same value in their **currentStateChangeId** column, then the value of the **currentStateId** column in the newly created record in the **settlementContentAggregation** table should be set as follows. The value of the **currentStateId** column in the newly created record in the **settlementContentAggregation** table should be set to the shared value in the constituent records from the **transferParticipant** table, except in the following case: if the shared value in the constituent records from the **transferParticipant** table is OPEN, then the value of the **currentStateId** column should be set to the value CLOSED. - -#### Marking transfers as settled - -The following additional processes are required in order to mark ledger entries which are settled immediate gross as having been settled. - -##### Queueing transfers for settlement processing - -When a transfer is completed, a record is generated in the **transferFulfilment** table. As part of the process that generates this record, the transfer should be placed on a Kafka stream for immediate settlement processing. - -##### Processing settlements - -A new service should be developed for processing settlements. The characteristics of the service should be as follows: - -1. Pick a transfer from the Kafka stream holding transfers awaiting settlement processing. There is no requirement for sequence preservation, so this service can pick up multiple transfer entries if this would accelerate processing. -2 For each record in the **transferParticipant** table which belongs to the transfer *and* whose **ledgerEntryType** column specifies a ledger entry type which belongs to a settlement model which is settled both GROSS and IMMEDIATE, the service should generate consecutive records in the **transferParticipantStateChange** table with the values: CLOSED, PENDING_SETTLEMENT, and SETTLED, in that order. The **currentStateChangeId** column for the record in the **transferParticipant** table should be set to point to the record in the **transferParticipantStateChange** table whose value is SETTLED. -3 For all other records in the **transferParticipant** table which belong to the transfer, the service should generate a record in the **transferParticipantStateChange** table with a value of OPEN. The **currentStateChangeId** column for the record in the **transferParticipant** table should be set to point to the record in the **transferParticipantStateChange** table which was created. - -#### Updating status values for net settlements - -When the status is updated for a participant in a settlement which belongs to a settlement model which is not settled both GROSS and IMMEDIATE, then the constituent records for that participant in the settlement in the **transferParticipant** table need to be updated. The rules for this are: - -1. When the settlement is created, all the records in **transferParticipant** which belong to a transfer which belongs to a window which belongs to the settlement being created (i.e. which are contained in the inner join between **transferParticipant**, **transferfulfilment** (on **transferId**) and **settlementSettlementWindow** (on **settlementWindowId**) for the settlement Id which is being created) should have a record created in **settlementContentAggregationStateChange** with the **settlementWindowStateId** column set to PENDING_SETTLEMENT. -2. When a participant's settlement status is updated to SETTLED in **settlementParticipantCurrency**, then all the records in **transferParticipant** for settlement windows which belong to that settlement, and whose participant and currency IDs match the participant and currency of the records in **settlementParticipantCurrency** which have been updated, shoul have their status set to SETTLED. - -Domain class diagram -==================== - -ERD -=== - -The following ERD describes the new data structures required to model settlements. - -![](/mojaloop-technical-overview/central-settlements/assets/diagrams/Settlement_ERD.png) - -Enumerations ------------- - -The following enumerations are required to support the new ERD: -``` -DELETE FROM settlementGranularity; -INSERT INTO settlementGranularity (name) -VALUES ('GROSS'), ('NET'); - -DELETE FROM settlementInterchange; -INSERT INTO settlementInterchange (name) -VALUES ('BILATERAL'), ('MULTILATERAL'); - -DELETE FROM settlementDelay; -INSERT INTO settlementDelay(name) -VALUES ('IMMEDIATE'), ('DEFERRED'); -``` +--- +title: "OSS Settlement \n \nBusiness Requirements Document" +--- + +Introduction +============ + +This document describes the requirements for changes to the functionality of the +OSS Mojaloop switch to support: + +1. The immediate requirement for Mowali of being able to settle according to + different timetables for different currencies. + +2. The requirement for TIPS to be able to settle gross via a pooled account. + +3. The requirement for TIPS to use the settlement process for interchange fees. + +4. The requirement for Mojaloop to support the evolving Settlement API + +References +========== + +The following external references are used in this document: + +| Reference | Document | +| :--- | :--- | +| 1 | [Open API for FSP Interoperability Specification](http://mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html) | +| 2 | [Settlement API Interface Definition](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json)| +| 3 | [Current administration API definition](https://mojaloop.io/documentation/api/central-ledger-api-specification.html)| +| | | + +Versions +======== + +| Version | Description | Author | Date | Changes tracked | +|:---------|:------------------|:------------------|:------------|:-----------------| +| 1.0 | Baseline version | Michael Richards | 2 Dec 2019 | No | +| | | | | | + +Definition of terms +=================== + +Settlement model +---------------- + +A settlement model defines a kind of settlement within the scheme. Settlement +models can be defined by scheme administrators, and have the following +characteristics: + +1. They can support settlement either gross or net settlements. If gross, then + a settlement is executed after each transfer is completed. If net, a group + of transfers is settled together. + +2. They can support either multilateral or bilateral settlements. If + settlements are multilateral, each participant settles with the scheme for + the net of its transfers which are included in the settlement. If they are + multilateral, each participant settles separately with each of the other + participants and the scheme is not a party to the settlement. + +3. They can support either deferred or immediate settlements. If settlements + are immediate, they are actioned immediately they are completed. If they are + deferred, they are actioned after a period of delay. + +4. They can support continuous or discontinuous settlements. Discontinuous + settlements require a formal approval from a resource outside the system to + confirm that they have been completed. Continuous settlements can be + approved from within the switch, provided that the criteria for approval are + met. + +5. They can require liquidity support or not. + +Ledger account type +------------------- + +A ledger account type defines a type of internal account. Current values are: + +1. POSITION. Accounts of this type are used for provisioning transfers + +2. SETTLEMENT. Accounts of this type are intended to be reflections of + Settlement Accounts held at the Settlement Bank + +3. HUB_RECONCILIATION. Each implementation of the switch has one account of + this type for each currency supported by the switch, owned by the virtual + DFSP which represents the Hub in the implementation. The account is used + during FUNDS IN/OUT operations to represent movements in participants’ + SETTLEMENT accounts. + +4. HUB_MULTILATERAL_SETTLEMENT. Each implementation of the switch has one + account of this type for each currency supported by the switch, owned by the + virtual DFSP which represents the Hub in the implementation. This account + type is used to record counterparty information for net amounts paid to or + from participants as part of settlements. Entries in this account represent + balancing values corresponding with the net value in a participant’s + POSITION account for a given settlement. + +5. HUB_FEE. Accounts of this type represent accounts into which fees are + collected, or from which they are disbursed. (Not implemented) + +Ledger entry type +----------------- + +A ledger entry type categorises the type of funds which are the content of a +transfer and which are due to or from a participant as a consequence of that +transfer. The current values are: + +1. PRINCIPLE_VALUE. This designates the funds moved as the content of a + transfer in the Interoperability API Specification sense of that term (i.e. + the **amount.amount** item in the **Transaction** object described in + [Section 7.4.17](https://mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html#7317-ilpcondition) of the Interoperability API specification[1](https://mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html).) It should be + spelt “principal.” + +2. INTERCHANGE_FEE. This designates fees paid between participants in the + system. (Not implemented) + +3. HUB_FEE. This designates fees paid between participants and the scheme. (Not + implemented) + +4. POSITION_DEPOSIT. This is used to designate funds transfers which are + intended to increase the value of the position in a particular ledger + account. (Not implemented) + +5. POSITION_WITHDRAWAL. This is used to designate funds transfers which are + intended to reduce the value of the position in a particular ledger account. + (Not implemented) + +6. SETTLEMENT_NET_RECIPIENT. This is used to designate funds which a + participant is owed by the counterparty as part of a settlement (in a + multilateral settlement model, the counterparty will be the hub; in a + bilateral settlement model, it will be another party.) + +7. SETTLEMENT_NET_SENDER. This is used to designate funds which a participant + owes to the counterparty as part of a settlement (in a multilateral + settlement model, the counterparty will be the hub; in a bilateral + settlement model, it will be another party.) + +8. SETTLEMENT_NET_ZERO. This is used to generate formal records where a + participant’s net position in a settlement is zero. + +9. RECORD_FUNDS_IN. This is used to record funds deposited by a participant to + the SETTLEMENT account. + +10. RECORD_FUNDS_OUT. This is used to record funds withdrawn by a participant + from the SETTLEMENT account. + +The last seven of these types relate to the internal structure of the switch and +should be neither visible to nor modifiable by a scheme. The first three fall +into a category which is expected to be extensible by the scheme. The table does +not currently have an indicator to mark this distinction, but one is proposed in +Section TODO. + +Participant role types +---------------------- + +A participant role type defines the role that a particular participant is +playing in a given transaction. The current values of this table are: + +1. PAYER_DFSP. The participant is the debtor in a transfer. + +2. PAYEE_DFSP. The participant is a creditor in a transfer. + +3. HUB. The participant is representing the scheme, and may be either the + creditor or the debtor in a transaction. + +4. DFSP_SETTLEMENT. The participant represents the settlement account of a + participant in the scheme. It may be either the creditor or the debtor in a + transaction. It is used during FUNDS IN/OUT operations. This is used for + entries whose counterparty is an entry in the HUB account. + +5. DFSP_POSITION. The participant represents the position of a participant in + the scheme. It may be either the creditor or the debtor in a transaction. It + is used during the settlement process. This is used for entries whose + counterparty is an entry in the HUB account. + +Settlement states +----------------- + +A settlement may be in a number of possible states. The states currently +supported are: + +1. PENDING_SETTLEMENT. A new settlement consisting of one or more settlement + windows has been created. The net amounts due to or from each participant + have been calculated and a report detailing these net amounts has been + produced. + +2. PS_TRANSFERS_RECORDED: all the calculated net amounts for the settlement + have been converted into transfers between the creditor and debtor accounts. + It is applied for each settlement entry and at settlement level, when all + entries are recorded. This state is not applied to settlement windows. + +3. PS_TRANSFERS_RESERVED: all the funds required for settlement have been + reserved (debit amounts only.) It is applied for each settlement entry and + at settlement level, when all entries are reserved. + +4. PS_TRANSFERS_COMMITTED: all the credit amounts required as part of the + settlement have been committed. It is applied for each settlement entry and + at settlement level, when all entries are committed. + +5. SETTLING: It is used only at settlement level if all accounts are not yet + settled. + +6. SETTLED: This state is applied to settlement accounts in + PS_TRANSFERS_COMMITTED state. When applied to even one account, the + settlement will transit to SETTLING state. When all accounts in a window are + SETTLED, the settlement window will change from PENDING_SETTLEMENT to + SETTLED, while the settlement is still in SETTLING state. When all accounts + from all windows are SETTLED, the settlement will be changed to SETTLED. It + is possible for a settlement to change directly from PS_TRANSFERS_COMMITTED + to SETTLED if all accounts are settled with one request. + +7. ABORTED: the settlement could not be completed and should be rolled back. It + is currently only possible to abort a settlement if the state is one of: + PENDING_SETTLEMENT, PS_TRANSFERS_RECORDED or PS_TRANSFERS_RESERVED. After + having even one account in PS_TRANSFERS_COMMITTED state (even if the + settlement as a whole is still in PS_TRANSFERS_RESERVED), a request to abort + the settlement is rejected. It should be noted that this prevents abortion + in cases such as the default of a participant midway through the settlement + process. + +The present data model contains a foreign key to the enumeration table +containing settlement states from the +**settlementParticipantCurrencyStateChange** table, which maps onto a table +which contains a record for each participant/currency/account type combination. + +Assumption: this means that the states appropriate to a settlement are also to +be applied to the individual elements of a settlement. As a consequence, the +descriptions should be taken to refer to individual settlement amounts as well +as to the settlement as a whole. + +Settlement window states +------------------------ + +A settlement is made up of one or more settlement windows. Each settlement +window has a state associated with it. The current values of this table are as +follows: + +1. OPEN: the settlement window can have ledger movements added to it. + +2. CLOSED: the settlement window cannot have any additional ledger movements + added to it. It is available for settlement. + +3. PENDING_SETTLEMENT: the settlement window’s contents have been included in a + settlement request, but this request is a request for deferred settlement + which has not yet been completed. + +4. SETTLED: the scheme has confirmed that the obligations incurred by + participants as a consequence of the settlement to which this settlement + window belongs have been met by those participants and the settlement is + therefore complete. + +5. ABORTED: the settlement to which this settlement window belongs did not + complete. The settlement window is available to be included in another + settlement. + +Transfer states +--------------- + +Each transaction which passes through the system can be assigned one of a fixed +number of states. The current values of this state are: + +1. RECEIVED_PREPARE: the switch has received the transaction request. + +2. RESERVED: the switch has reserved the funds required to cover the + transaction. + +3. RECEIVED_FULFIL: the switch has received the fulfilment request, and the + transaction has been assigned to a settlement window + +4. COMMITTED: the transaction has been committed. + +5. FAILED: the transaction has failed in some unspecified way and has been + aborted. (Not implemented) + +6. RESERVED_TIMEOUT: the transaction has timed out while in the reserved state + and has been aborted. + +7. RECEIVED_REJECT: the transaction has been rejected by the payee DFSP and + should be aborted. + +8. ABORTED_REJECTED: the transaction has been aborted by the switch as a + consequence of its having been rejected by the payee DFSP. + +9. RECEIVED_ERROR: the transaction was not received correctly by the payee DFSP + and should be aborted. + +10. ABORTED_ERROR: the transaction has been aborted by the switch as a + consequence of its not having been received correctly. + +11. EXPIRED_PREPARED: the transaction has expired during the prepare process and + has been aborted. + +12. EXPIRED_RESERVED: the transaction has timed out during the reservation + process and has been aborted. + +13. INVALID: the transaction has failed the switch’s internal validation process + and has been aborted. + +Transfers and transactions +-------------------------- + +Transfers define a movement of funds in the system. There is a table in the +switch which has this name. Some entries in this table are the consequence of +external movements which are generated by scheme participants and processed by +the switch; others are internally generated by the switch (e.g. to record net +movements of funds associated with settlements.) + +It may be a source of confusion that, although “transfers” is a term used e.g. +in the Interoperability API specification to designate the movement of funds +between participants, it is used as the name of a table in the switch which +stores other types of funds movement as well. + +This document will therefore adopt the following convention: + +- “Transfers” refers to the content of instructions issued using the + **/transfers** resource of the Interoperability API definition[1](http://mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html). (see [Section 6.7](http://mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html#67-api-resource-transfers) of the Interoperability API definition[1](http://mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html).) + +- “Transactions” refers to all movements of funds which are tracked by the + switch. + +In scope and out of scope +========================== + +In scope +-------- + +The following functional items are in scope: + +1. Requesting a settlement by currency + +2. Requesting a settlement by currency and settlement model + +Out of scope +------------ + +Business rules +============== + +How do things happen now? +------------------------- + +This section describes how the current settlement process works. + +### Categorisation + +The process leading to settlement is initially defined by entries in the +*participantCurrency* table. This table holds a record for each combination of: + +1. Participant + +2. Currency + +3. Ledger account type (see Section 2.2 above.) + +### Recording positions + +Each entry in this table has a corresponding entry in the *participantPosition* +table. This table stores the current committed and reserved positions for each +of the combinations described above. Each change to the positions in this table +is documented by an entry in the *participantPositionChange* table, which refers +the change back to the *transfer* table and thence to the authoritative record +of transactions. + +### Assigning transactions to settlement windows + +As each transfer is fulfilled, a record is created for it in the +**transferFulfilment** table. This record contains a link to the currently open +settlement window. + +Records may be created for transactions which are not transfers. Non-transfer +transactions have their ilpFulfilment set to 0. + +The settlement API [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) contains a resource +(**closeSettlementWindow**) to allow an administrator to close a settlement +window and create a new one. The resource takes a settlement window ID as part +of the query string, together with a string describing the status to be assigned +and a string describing the reason for the change of status. In-line +documentation for the resource states: “If the settlementWindow is open, it can +be closed and a new window is created. If it is already closed, return an error +message. Returns the new settlement window.” + +Settlement windows can only be passed a status of CLOSED using this resource. + +### Initiating a settlement + +The initiation of a settlement is initiated by making a call triggered by the +scheme making a **POST** to the **/settlements** resource in the settlement API. +The caller gives a reason for the settlement request. This is a synchronous +call, whose return is described in Section 4.1.5 below. Internally, the +initiation is marked by the creation of a record in the **settlement** table and +the association of a number of settlement window records in the +**settlementWindow** table with the settlement created. This says: I want this +settlement to contain these settlement windows. Each of the settlement windows +selected to form part of this settlement must have the status CLOSED or ABORTED. +When selected to form part of a settlement, the status of each window should be +changed to PENDING_SETTLEMENT. The status of the settlement itself should also +be set to PENDING_SETTLEMENT. + +### Calculating the content of a settlement + +When a settlement has been requested and the windows which it will contain have +been selected, the switch produces an aggregation of the content of the proposed +settlement at the following levels: + +1. Settlement window (from **settlementWindow**) + +2. Participant (from **participantCurrency**) + +3. Currency (from **participantCurrency**) + +4. Account type (from **participantCurrency**) + +5. Participant role type (from **transferParticipant**) + +6. Ledger entry type (from **transferParticipant**) + +This query can be provisioned from the database FK links from **settlement** to +**settlementwindow**, to **transferFulfilment** (all fulfilled transfers), to +**transfer**, to **transferParticipant**. The amount is taken from the +**transferParticipant** table. Correct! + +Only transfers are included in a settlement. This is implied by the first +aggregation criterion above (Settlement window) and the fact that only transfers +are assigned to the current OPEN window when a **transferFulfilment** record is +created. All COMMITTED transactions should have an entry in the +**transferFulfilment** table. + +The results of this query are used to construct a number of records in the +**settlementParticipantCurrency** table, representing the net amount due to or +from each participant and currency in the settlement as a consequence of the +settlement. For a given settlement, these records are segmented by: Correct! + +1. Participant (from **participantCurrency**) + +2. Currency (from **participantCurrency**) + +3. Account type (from **participantCurrency)** + +This report is used as the basis of the information returned from the initial +**POST** to the **/createSettlement** resource of the settlement API (see +Section 4.1.4 above.) + +Bilateral settlements are not currently implemented. + +### Creating position records for the settlement + +A record is inserted in the **transfer** table for each net amount calculated in +the previous step when the settlement account transitions from +PENDING_SETTLEMENT to PS_TRANSFERS_RECORDED. Please note that PS stands for +PENDING_SETTLEMENT. Each of these records will have the account type SETTLEMENT. +The ledger entry type will be SETTLEMENT_NET_SENDER, SETTLEMENT_NET_RECIPIENT or +SETTLEMENT_NET_ZERO depending on whether the participant owes money to the +scheme, is owed money by the scheme or is neutral in the settlement, +respectively. The transfer participant type is HUB for the Hub participant and +DFSP_POSITION for the DFSP participant. The account type is imposed by the +participant currency – for the Hub participant it is the +HUB_MULTILATERAL_SETTLEMENT and for the DFSP participant it is the POSITION +account. This enables the switch to reset the participant’s position when the +window enters the PS_TRANSFERS_COMMITTED state. + +### Progress of the settlement + +As the scheme verifies that participants have settled the amounts due from them, +the scheme administrator can update the switch with this information. + +#### Updating the status of settlement windows + +Three methods of performing this update are supported. Each of these methods is +discussed in more detail below. + +##### **updateSettlementById** + +An administrator may issue a **PUT** to the **/updateSettlementById** resource +on the settlement API, giving the settlement ID of the settlement they wish to +update as part of the query (e.g. **PUT +/updateSettlementById/settlements/123.**) The content of the request is as +follows: + +1. A state to be assigned to the participants required. The state is + constrained to be either ABORTED or INVALID + +2. A reason for the change of state. + +3. An external reference for the change. + +4. An array of participants to which the status is to be applied. The following + information is given for each participant: + + 1. The ID of the participant. This is the internal Mojaloop ID of the + participant. + + 2. An array of *accounts*. The content of each account is as follows: + + 1. An ID. The description characterises this as the participant’s + currency ID QUESTION: Is this correct? It is an integer, where a + VARCHAR(3) would be expected. + + 2. A reason. A string which presumably can contain anything. + + 3. The state of the settlement for the account. This is not constrained + by an enum, but is a simple string. It is not clear how this status + relates to the overall state given in Item 1 above. + + 4. An external reference for the change in state. + +> A call to this API resource may contain *either* items 1-3 above *or* an +> array of accounts as specified in item 4 above, but not both. If it contains +> items 1-3 above, then all the items must be present. If these rules are +> breached, then the switch will reject the request. + +##### **updateSettlementBySettlementParticipant** + +An administrator may issue a **PUT** to the +**/updateSettlementBySettlementParticipant** resource on the settlement API, +giving the settlement ID and the participant ID of the parts of the settlement +they wish to update as part of the query (e.g. **PUT +/updateSettlementByParticipant/settlements/123/participants/56789.**) The +content of the request is as follows: + +1. An array of state changes, whose content is as follows: + + 1. The currency ID whose status is to be changed. This is an integer, where + a VARCHAR(3) would be expected. + + 2. A reason for the state change. + + 3. The state requested. This is a string, where an enumeration would be + expected. + + 4. An external reference for the change in state. + +Note that this is an array with the same structure as that described in item 4 +of Section 5.1.7.1 above, although it is defined separately in the API +definition. + +##### **updateSettlementBySettlementParticipantAccount** + +An administrator may issue a **PUT** to the +**/updateSettlementBySettlementParticipantAccount** resource on the settlement +API, giving the settlement ID, the participant ID and the account ID of the part +of the settlement they wish to update as part of the query (e.g. **PUT +/updateSettlementByParticipant/settlements/123/participants/56789/accounts/1.**) +The content of the request is as follows: + +1. The state requested. This is a string, where an enumeration would be + expected. + +2. A reason. A string which presumably can contain anything. + +3. An external reference for the change in state. + +Note that this is a structure with most of the same members as the structure +defined in Item 1 of Section 5.1.7.2 above, although the items appear in a +different order. + +#### How changes in settlement window state are processed + +The action taken in response to these calls depends on the status assigned to +the account. In any case, a record is created in the +**settlementParticipantCurrencyStateChange** table, giving the state identifier, +the reason and an external reference for the change. + +There is a sequence of steps defined for a settlement. Each step must be +followed in order, and no steps may be omitted. The sequence of steps is +hard-coded into the application and is as follows: + +1. PENDING_SETTLEMENT + +2. PS_TRANSFERS_RECORDED + +3. PS_TRANSFERS_RESERVED + +4. PS_TRANSFERS_COMMITTED + +5. SETTLED + +A settlement can be aborted provided no account in the settlement has reached a +status of PS_TRANSFERS_COMMITTED. + +The following actions are taken on each change of status: + +##### PENDING_SETTLEMENT to PS_TRANSFERS_RECORDED + +A record is generated in the **transfer** table to record the change in state. +The parties to this transfer are the POSITION account type and the +HUB_MULTILATERAL_SETTLEMENT type. If the participant account is a net creditor +for the settlement, then the ledger entry type will be set to +SETTLEMENT_NET_RECIPIENT. If the participant account is a net debtor for the +settlement, then the ledger entry type will be set to SETTLEMENT_NET_SENDER. If +the participant account is neutral for the settlement, then the ledger entry +type will be set to SETTLEMENT_NET_ZERO. + +A record is also created in the **transferstatechange** table with the +RECEIVED_PREPARE state, which means that no positions have been changed. + +When the last participating account is changed to PS_TRANSFERS_RECORDED, then +the settlement’s status is also changed to PS_TRANSFERS_RECORDED. + +If an administrator attempts to change an account’s state to +PS_TRANSFERS_RECORDED and either the settlement’s state or the settlement +account’s state is not PENDING_SETTLEMENT or PS_TRANSFERS_RECORDED, then the +request will be rejected. + +##### PS_TRANSFERS_RECORDED to PS_TRANSFERS_RESERVED + +A new record is created in the **transferstatechange** table for the transfer +that was created in section 5.1.7.2 above. This record will have a status of +RESERVED. If the participant is a net creditor as a result of the settlement, +then a record will also be created in the participantPositionChange table if the +account being reserved is for a net creditor in the settlement, as defined in +Section 5.1.7.2 above. The Net Debit Cap is checked at this point, and if the +current position exceeds the Net Debit Cap, then the Net Debit Cap is +automatically adjusted by the amount of the net credit due to the account as +part of the settlement and the participant is sent a notification of the new Net +Debit Cap value and its currency. + +When the last participating account is changed to PS_TRANSFERS_RESERVED, then +the settlement’s status is also changed to PS_TRANSFERS_RESERVED. + +If an administrator attempts to change an account’s state to +PS_TRANSFERS_RESERVED and either the settlement’s state or the settlement +account’s state is not PS_TRANSFERS_RECORDED or PS_TRANSFERS_RESERVED, then the +request will be rejected. + +##### PS_TRANSFERS_RESERVED to PS_TRANSFERS_COMMITTED + +A new record is created in the **transferstatechange** table for the transfer +that was created in section 5.1.7.2 above. This record will have a status of +COMMITTED. If the participant is a net debtor as a result of the settlement, +then a record will also be created in the participantPositionChange table if the +account being reserved is for a net debtor in the settlement, as defined in +Section 5.1.7.2 above. + +When the last participating account is changed to PS_TRANSFERS_COMMITTED, then +the settlement’s status is also changed to PS_TRANSFERS_COMMITTED. + +If an administrator attempts to change an account’s state to +PS_TRANSFERS_COMMITTED and either the settlement’s state or the settlement +account’s state is not to PS_TRANSFERS_RESERVED or PS_TRANSFERS_COMMITTED, then +the request will be rejected. + +##### PS_TRANSFERS_COMMITTED to SETTLED + +When the first account is changed to a status of SETTLED, the settlement’s state +is changed to SETTLING. + +When the last participating account is changed to SETTLED, then the settlement’s +status is also changed to SETTLED. + +If an administrator attempts to change an account’s state to SETTLED and either +the settlement’s state or the settlement account’s state is not to +PS_TRANSFERS_COMMITTED or SETTLED, then the request will be rejected. + +### Aborting the settlement + +If there is any failure in the scheme’s process for recovering the amounts due +from participants in a settlement, the scheme can update the switch with this +information by issuing a **PUT** to the **/updateSettlementById** resource of +the settlement API and setting the **state** value of the content of the message +to ABORTED. A **PUT** call on the **/updateSettlementById** resource is the only +method which may be used for ABORTING a settlement. If any account information +is given in the call, then neither the **state** nor the **reason** nor the +**externalReference** fields may be set. if the **state** value is set at the +top level of the call, then the **reason** field must also be set, and the +request will be rejected if any account information is given in the call. + +If an attempt is made to abort a settlement, and any of the accounts in the +settlement have the status PS_TRANSFERS_COMMITTED or SETTLED, then the request +will be rejected. + +When a call is received, a new record is created in the +**settlementParticipantCurrencyStateChange** table, and is given the appropriate +status based on the status reported by the caller. Depending on the update that +was received, this may also require the status of the transaction and that of +the participant position to be updated. No, it is done at settlement level for +the entire settlement and all entries in settlementParticipantCurrency are +affected. + +Note: if the settlement is bilateral, then there is no obvious reason to abort +the entire settlement if one interchange fails. We should think about this use +case and how we would want to represent it. This document does not consider this +use case. + +Aborting a settlement comprises the following steps: + +1. The status of the transfers created in Section 5.1.6 above should be changed + to ABORTED. + +2. A new record is added to the **settlementParticipantCurrencyStateChange** + table for each of the participant records in the settlement. This record has + a status of ABORTED, and the **currentStateChangeId** column in the + **settlementParticipantCurrency** table for that participant record is + changed to point to this new record. + +3. A new record is added to the **settlementWindowStateChange** table for each + settlement window in the settlement. This record has a status of ABORTED, + and the **currentStateChangeId** column in the settlementWindow table for + that window is changed to point to this new record. + +4. A new record is added to the **settlementStateChange** table for the + settlement. This record has a status of ABORTED, and the + **currentStateChangeId** column in the **settlement** table is changed to + point to this new record. + +5. If positions have been reserved for net creditors as a result of the + settlement (see Section 5.1.7.3 above,) then a balancing entry will be + created in the **participantPositionChange** table to reverse the + reservation of funds. This action does not at present reverse any change to + the account’s Net Debit Cap that may have been made as a consequence of this + reservation. + +6. Any records created in the **transfers** table (see Section 5.1.7.2 above) + will have their state changed in two steps by adding records to the + **transferStateChange** table. The first step will change the transfer state + to REJECTED. The second step will change the state to ABORTED. + +Question: should there be/is there a time-out after which a settlement will be +aborted if it has not completed? If there is, how is it set? No, there isn’t +timeout on a settlement level. But when transfers are prepared (for +PS_TRANSFERS_RECORED) expiration is set on a transfer level. Its value is +controlled by a Config.TRANSFER_VALIDITY_SECONDS, which currently defaults to +432000 seconds, which equals 5 days. It is big enough to avoid expiration. +Still, if that happens, it would leave the data in an unrecoverable by the API +state. This is very good point and should be certainly addressed with the next +increment! + +Recording the deposit of funds +------------------------------ + +As participants are informed of their liabilities under the settlement, it is +expected that they will deposit funds in their settlement account to cover those +liabilities. These activities are recorded via the central ledger administration +interface resource **recordFundsIn**. + +This action is called through a POST to the administration interface, giving the +name of the participant and the account to be credited in the form POST +/participants/{participantName}/accounts/{accountId} (e.g. **POST +/participants/myDfsp/accounts/1234**) The content of this message is as follows. + +1. transferId: a UUID to be used to identify the transfer in the switch. + +2. externalReference: a reference used to identify the transfer for the + administrator + +3. action: this should be set to “recordFundsIn” for recording funds in. + +4. reason: the reason why the transfer is being made. + +5. amount: the amount of the transfer. + + 1. amount: the actual amount being transferred + + 2. currency: the ISO 4217 code of the currency of the deposit. + +6. extensionList: a series of key/value pairs which are used to carry + additional information + +When an administrator records that a participant has deposited funds to an +account, the amount deposited is recorded in an entry in the **transfer** table. +The parties to the transfer are recorded by entries in the +**transferParticipant** table, with a ledger account type of the type requested +in the POST for the participant and HUB_RECONCILIATION for the balancing entry. +For deposits, the participant account will be the creditor and the +HUB_RECONCILIATION account the debtor. The application will currently reject +requests to this interface which do not have a ledger account type of +SETTLEMENT. + +A deposit goes through the following changes of state: + +1. A record is created for the transfer in the **transferStateChange** table + with a state of RECEIVED_PREPARE. + +2. Next, a record is created in the **transferStateChange** table with the + state RESERVED. This also creates a record in the + **participantPositionChange** table to record the reservation of funds in + the HUB_RECONCILIATION account, and the **participantPosition** table’s + value for that account is updated. + +3. Finally, a record is created in the **transferStateChange** table with the + state COMMITTED. After this act, records are created in the + **participantPositionChange** table for the creditor account to record the + completion of the deposit, and the appropriate record in the + **participantPosition** table has its balance updated. + +These changes of state are simply chained together in sequence. There is no +interval or trigger between the steps. + +This activity has no direct effect on the settlement process or on the Net Debit +Cap. + +Recording the withdrawal of funds +--------------------------------- + +At various times, participants may wish to withdraw funds from their settlement +accounts: for instance, if they are long-term net beneficiaries of transfers and +are building up a surplus of liquidity. These activities are recorded via a +two-phase process. In the first phase, the funds for the proposed withdrawal are +reserved via the central ledger administration interface resource +**recordFundsOutPrepareReserve**. In the second phase, the withdrawal is +committed via the **recprdFundsOutCommit** resource or aborted through the +**recordFundsOutAbort** resource. + +These activities are defined below. + +### **recordFundsOutPrepareReserve** + +This action is called through a POST to the administration interface, giving the +name of the participant and the account to be credited (e.g. **POST +/participants/myDfsp/accounts/1234**) The content of this message is as follows. + +1. transferId: a UUID to be used to identify the transfer in the switch. + +2. externalReference: a reference used to identify the transfer for the + administrator + +3. action: this should be set to “recordFundsOutPrepareReserve” for recording + funds withdrawals. + +4. reason: the reason why the transfer is being made. + +5. amount: the amount of the transfer. + + 1. amount: the actual amount being transferred + + 2. currency: the ISO 4217 code of the currency of the deposit. + +6. extensionList: a series of key/value pairs which are used to carry + additional information + +When an administrator records that a participant has requested the withdrawal of +funds from an account, the amount to be withdrawn is recorded in an entry in the +**transfer** table. The parties to the transfer are recorded by entries in the +**transferParticipant** table, with a ledger account type of the type requested +in the POST for the participant and HUB_RECONCILIATION for the balancing entry. +For withdrawals, the participant account will be the debtor and the +HUB_RECONCILIATION account the creditor. The application will currently reject +requests to this interface which do not have a ledger account type of +SETTLEMENT. + +Reservation of a withdrawal goes through the following changes of state: + +1. A record is created for the transfer in the **transferStateChange** table + with a state of RECEIVED_PREPARE. + +2. Next, a record is created in the **transferStateChange** table with the + state RESERVED. This also creates a record in the + **participantPositionChange** table to record the reservation of funds in + the participant’s settlement account, and the **participantPosition** + table’s value for that account is updated. + +These changes of state are simply chained together in sequence. There is no +interval or trigger between the steps.**recordFundsOutCommit** + +This action is called through a POST to the administration interface, giving the +name of the participant and the account to be credited (e.g. **POST +/participants/myDfsp/accounts/1234**) The content of this message is as follows. + +1. transferId: a UUID to be used to tie the commit to the preceding reservation + in the switch. + +2. externalReference: a reference used to identify the transfer for the + administrator + +3. action: this should be set to “recordFundsOutCommit” for recording funds + commitments. + +4. reason: the reason why the transfer is being made. + +5. amount: the amount of the transfer. + + 1. amount: the actual amount being transferred + + 2. currency: the ISO 4217 code of the currency of the deposit. + +6. extensionList: a series of key/value pairs which are used to carry + additional information + +When an administrator records that a participant wants to commit the withdrawal +of funds from an account, the original entry in the **transfer** table is +identified. The parties to the transfer are recorded by entries in the +**transferParticipant** table, with a ledger account type of the type requested +in the POST for the participant and HUB_RECONCILIATION for the balancing entry. +For withdrawals, the participant account will be the debtor and the +HUB_RECONCILIATION account the creditor. The application will currently reject +requests to this interface which do not have a ledger account type of +SETTLEMENT. + +Commitment of a withdrawal goes through the following changes of state: a record +is created in the **transferStateChange** table with the state COMMITTED. After +this act, records are created in the **participantPositionChange** table for the +creditor account to record the completion of the deposit, and the appropriate +record in the **participantPosition** table has its balance updated. These +changes of state are simply chained together in sequence. There is no interval +or trigger between the steps. + +This activity has no direct effect on the settlement process or on the Net Debit +Cap. + +Proposed enhancements +===================== + +This section describes the enhancements to the existing OSS settlement process +(described in Section 4.1 above) which are proposed. Each enhancement is shown +in a separate section and, where there are dependencies between enhancements, +these are listed in the enhancement’s description. + +Request settlement by currency [EPIC] +------------------------------------- + +The following changes are required to support settling separately for different +currencies. + +### Database changes + +The following changes are required to support multi-currency settlement. + +#### Addition of a settlementWindowContent table [Story \#1] + +A new table will be added to the database. The name of this table will be +**settlementWindowContent**. The table will contain an entry for each item of +content in a given settlement window, broken down by ledger account type and +currency. The full column structure of the table is as follows: + +| **Column name** | **Description** | **Attributes** | +|-----------------------------------------|---------------------------------------------------|---------------------------------------------------------------------------------------| +| **settlementWindowContentId** | Auto-generated key for the record. | BIGINT(20). Unsigned, not null, primary key, autoincrement | +| **settlementWindowId** | The settlement window that the record belongs to. | BIGINT(20). Unsigned, not null. Foreign Key to **settlementWindow** | +| **ledgerAccountTypeId** | The ledger account that the record refers to. | INT(10). Unsigned, not null. Foreign key to **ledgerAccountType** | +| **currencyId** | The currency that the record refers to. | VARCHAR(3). Not null. Foreign key to **currency**. | +| **createdDate** | The date and time when the record was created. | DATETIME. Not null. Defaults to CURRENT_TIMESTAMP. | +| **currentStateChangeId** | The current state of this entry. | BIGINT(20). Unsigned. Foreign key to **settlementWindowContentStateChange** | + +  + +#### Addition of a settlementWindowContentStateChange table [Story \#2] + +A new table will be added to the database. The name of this table will be +**settlementWindowContentStateChange**. The table will track changes to the +status of entries in the **settlementWindowContent** table. The full column +structure of the table is as follows: + +| **Column name** | **Description** | **Attributes** | +|------------------------------------------|---------------------------------------------------------------------|----------------------------------------------------------------------------| +| **settlementWindowContentStateChangeId** | Auto-generated key for the record. | BIGINT(20). Unsigned, not null, primary key, autoincrement | +| **settlementWindowContentId** | The settlement window content record whose status is being tracked. | BIGINT(20). Unsigned, not null. Foreign Key to **settlementWindowContent** | +| **settlementWindowStateId** | The record’s status. | VARCHAR(50). Not null. Foreign key to **settlementWindowState** | +| **reason** | An optional field giving the reason for the state being set. | VARCHAR(512). | +| **createdDate** | The date and time when the record was created | DATETIME. Not null. Defaults to CURRENT_TIMESTAMP | + +  + +#### Changes to the settlementTransferParticipant table [Story \#3] + +The name of the **settlementTransferParticipant** table should be changed to +**settlementContentAggregation**. + +The column structure of the **settlementContentAggregation** table should be +modified as follows: + +1. Remove the following foreign keys from the table: + 1. settlementtransferparticipant_settlementid_foreign + 2. settlementtransferparticipant_settlementwindowid_foreign +2. Remove the following columns from the table: + 1. settlementId + 2. settlementWindowId +3. Add the following column to the table: + 1. Column name: **settlementWindowContentId** + 2. Attributes: BIGINT(20), unsigned, not null +4. Add the following foreign key to the table: + 1. Name: settlementContentAggregation_settlementwindowcontent_foreign + 2. Child column **settlementWindowContentId** + 3. Refers to table: **settlementWindowContent** + 4. Refers to column: **settlementWindowContentId** + +All database scripts which use the **settlementTransferParticipant** table will +be changed to accommodate the new name and structure of the table. [Story \#8] + +Queries to filter the records in the **settlementContentAggregation** table +required for a settlement in a particular currency will need to join across from +that table to the **participantCurrency** table using the +**participantCurrencyId** column to ascertain the currency to which a particular +row refers. The **currencyId** column is held in the **participantCurrency** +table. [Story \#9] + +#### Add structures relating to settlement models [Story \#4] + +In order to support the specification of settlement models, which will include +currencies, the database changes specified in Section 6.2.1.1 below should be +added to the database. + +Settlement models describing the settlement types required for a given +implementation will be developed and tested.**[Story \#4a]** + +#### Change to settlement table [Story \#5] + +The **settlement** table in the central ledger database needs to be modified to +add a *settlementModel* column. This column should have the following +characteristics: + +- The column should be required (NOT NULL) and unsigned. +- The column’s data type should be integer(10) +- The column should be defined as a foreign key reference to the +*settlementModelId* field of the **settlementModel** table. + +When this change is applied to an existing database, a settlement model to +describe the default settlement should be created. The settlementCurrencyId +column in this model should be left blank (= all currencies.) The +settlementModel column in all existing records in the settlement table should be +set to point to this model’s ID. A script to apply this change should be +created, tested and stored in the repository. + +### Changes to processing + +The following changes to the processing code are required to support +multi-currency settlement. + +#### Change to code supporting closeSettlementWindow resource + +The existing API [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) provides a single function +(**closeSettlementWindow**) to manage settlement windows. This function allows +its user to select a settlement window by ID number and to input a new status +for the window and a reason for that status. + +When a settlement window is closed, the code supporting this activity should +perform two functions, as follows. These functions should be performed in the +background and without impacting system performance. + +##### Generate records in the settlementWindowContent table [Story \#1095] + +The code should generate a record in the **settlementWindowContent** table for +each ledger entry type/currency combination found in the transfers in the +settlement window. This information can be obtained from the following query: +``` +SELECT DISTINCT + @mySettlementWindowId, pc.ledgerAccountTypeId, pc.currencyId +FROM transferFulfilment tf +INNER JOIN transferParticipant tp + ON tp.transferId = tf.transferId +INNER JOIN participantCurrency pc + ON pc.participantCurrencyId = tp.participantCurrencyId +WHERE tf.settlementWindowId = @mySettlementWindowId; +``` + +##### Generate records in the settlementContentAggregation table [Story \#1095] + +The code should calculate the aggregate values for all transfers which form part +of that settlement window and store them in the **settlementContentAggregation** +table. Aggregates should be produced for the following segmentation: + +1. Participant +2. Currency +3. Ledger account type +4. Participant role type +5. Ledger entry type + +The following query will perform this function for a given settlement window: + +``` +INSERT INTO settlementContentAggregation + (settlementWindowContentId, participantCurrencyId, + transferParticipantRoleTypeId, ledgerEntryTypeId, amount) +SELECT swc.settlementWindowContentId, pc.participantCurrencyId, + tp.transferParticipantRoleTypeId, tp.ledgerEntryTypeId, SUM(tp.amount) +FROM transferFulfilment tf +INNER JOIN transferParticipant tp + ON tf.transferId = tp.transferId +INNER JOIN participantCurrency pc + ON pc.participantCurrencyId = tp.participantCurrencyId +INNER JOIN settlementWindowContent swc + ON swc.settlementWindowId = tf.settlementWindowId +  AND swc.ledgerAccountTypeId = pc.ledgerAccountTypeId + AND swc.currencyId = pc.currencyId +WHERE tf.settlementWindowId = @mySettlementWindowId +GROUP BY swc.settlementWindowContentId, pc.participantCurrencyId, + tp.transferParticipantRoleTypeId, tp.ledgerEntryTypeId; +``` + +#### createSettlement + +The parameters for the **createSettlement** resource should be extended to +include the settlement model for which the settlement is required. + +When the settlement is created, the settlement model for which the settlement is +required should be added to the new row in the **settlement** table. [Story \#1097] + +When a settlement is requested, the switch should check that the settlement +model for which settlement is being requested requires NET settlement and not +GROSS settlement. If the requested settlement model requires GROSS settlement, +then the request should be rejected with an error. + +The verification procedures associated with the **createSettlement** resource +should be changed to check that some of the settlement windows associated with +the proposed settlement contain entries for the settlement model requested. If +there are no entries for the settlement model requested for any of the +settlement windows requested, then an error should be returned and the +settlement request rejected. [Story \#1096] + +#### Updating the progress of a settlement + +When the status for a settlement participant is changed to SETTLED, this will result in +changes to the status of all the records in the **settlementContentAggregation** +table for the given participant, identified by the compound key: settlementId + participantCurrencyId. + +[Story \#16] + +The code should then check to see if, as a result of the updates to the records +in **settlementContentAggregation**, all records for a given combination of +settlement window, ledger account type and currency have the same status. If +they have, then the appropriate record in the **settlementWindowContent** table +should be updated to have that status. + +The code should then check to see if all records in the +**settlementWindowContent** table for a given settlement window have the same +status. If they have, then the appropriate record in the **settlementWindow** + +Support continuous gross settlement +----------------------------------- + +Continuous Gross Settlement is a settlement model in which each transaction is +settled as soon as it is fulfilled. The following changes are required to +implement this change. + +### Database changes + +The database changes shown in Section 8 below should be implemented. These can +be summarised as follows: + +#### Changes to support the settlement model + +A number of new tables are required to define a settlement model and to store +the enumerations for its definition types. This comprises the following tables +in the ERD: + +- settlementDelay + +- settlementInterchange + +- settlementModel + +In addition, the **settlementmodel** table has foreign keys to two existing +tables, as follows: + +1. A foreign key to the **currency** table to enable the settlement model to + settle only scheme accounts in a particular currency. If this entry is + blank, this should be interpreted as saying that the settlement model + settles all currencies that are not specified as being settled by other + settlement models for the same account type. + +2. A foreign key to the **ledgerAccountType** table. This specifies that the + settlement model settles accounts of this type. + +#### Changes to the **ledgeraccounttype** table + +The current **ledgeraccounttype** table stores a number of entries for account +types which should not be used for settlements – for instance, +HUB_MULTILATERAL_SETTLEMENT. A column should therefore be added to the +**ledgeraccounttype** table to indicate whether the account type can be attached +to a settlement model or not. This column is called **settleable**, and is +specified as a Boolean value, NOT NULL and with a default of FALSE. + +Of the existing ledger account types, PRINCIPAL_VALUE, INTERCHANGE_FEE and +HUB_FEE should be marked as capable of being attached to settlement models (this +value should be TRUE.) For all other ledger account types, the column should be +set to FALSE. If new ledger account types are added to this table via the +eventual settlement API, then they should have a value of TRUE. + +#### Changes to the **ledgerentrytype** table + +Implementation of the TIPS settlement model requires an explicit association +between ledger entry types and the account types in which they should appear. +Since each ledger entry type should only appear in a single account type, though +multiple ledger entry types may appear in a given account type, this is modelled +by including a foreign key reference to the **ledgeraccounttype** table as a +column in the **ledgerentrytype** table. It should be noted that this applies +only to ledger entry types which are associated with a settlement model, as +described in Section 6.2.1.2 above. The assignment of existing entries in the +database would be as follows: + +| Ledger Entry Type | Ledger Account Type | +|-------------------|---------------------------| +| PRINCIPAL_VALUE | POSITION | +| INTERCHANGE_FEE | INTERCHANGE_FEE | +| HUB_FEE | HUB_FEE | +| | | + +#### Changes to the **settlement** table + +The **settlement** table should have a column added to it to allow the +settlement model to be used in settling it to be specified. The column should be +called *settlementModelId*. It should have the same data type as the equivalent +field in the **settlementModel** table, and should be a foreign key into that +table. It should be defined as not null. + +#### Changes to the **settlementWindow** table + +As well as settlements, individual settlement windows will need to be assigned +to settlement models. The **settlementWindow** table should therefore have a +column added to it to allow the settlement model to be used in settling it to be +specified. The column should be called *settlementModelId*. It should have the +same data type as the equivalent field in the **settlementModel** table, and +should be a foreign key into that table. It should be defined as not null. + +This concludes the list of schema changes required to support the TIPS +settlement models + +### API changes + +API Support for the settlement functionality required for TIPS will include the +following functions: + +#### Close a settlement window + +The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a +**closeSettlementWindow** resource. This function allows its user to select a +settlement window by ID number and to input a new status for the window and a +reason for that status. This resource will retain its current signature, but the +code supporting it needs to change as follows. + +When a settlement window is closed, the system should create a new settlement +window with the same settlement model as the newly closed settlement window, and +should make this the active window. + +When a settlement window is closed, the code supporting this activity should +calculate the aggregate values for all transfers which form part of that +settlement window and store them in the **settlementTransferParticipant** table. +Aggregates should be produced for the following segmentation: + +1. Participant + +2. Currency + +3. Ledger account type + +4. Participant role type + +5. Ledger entry type + +The following example code will produce the aggregations required for a given +settlement window (identified as \@MyWindow in the example): + +SELECT + +S.settlementId + +, W.settlementWindowId + +, P.participantCurrencyId + +, P.transferParticipantRoleTypeId + +, P.ledgerEntryTypeId + +, SUM(P.amount) + +, CURRENT_TIMESTAMP AS createdDate + +FROM + +settlementWindow W INNER JOIN settlementModel M ON W.settlementModelId = +M.idsettlementModel + +INNER JOIN settlementSettlementWindow S ON W.settlementWindowId = +S.settlementWindowId + +INNER JOIN ledgerAccountType L ON M.idsettlementModel = L.settlementModelId + +INNER JOIN transferFulfilment F ON W.settlementWindowId = F.settlementWindowId + +INNER JOIN transferParticipant P ON F.transferId = P.TransferId + +INNER JOIN participantCurrency PC ON P.participantCurrencyId = +PC.participantCurrencyId + +AND PC.ledgerAccountTypeId = L.ledgerAccountTypeId + +WHERE + +W.settlementWindowId = \@MyWindow + +AND + +(PC.currencyId = M.settlementcurrencyId OR M.settlementcurrencyId IS NULL) + +GROUP BY + +S.settlementId + +, W.settlementWindowId + +, P.participantCurrencyId + +, P.transferParticipantRoleTypeId + +, P.ledgerEntryTypeId; + +#### Getting information about a settlement window + +The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a +**getSettlementWindowById** resource. This function allows its user to obtain +information about a settlement window by giving the ID that was returned when +the settlement window was created. + +This call returns a **SettlementWindow** object. This object will need to be +extended to include the name of the settlement model to which the settlement +window belongs. + +#### Getting information about settlement windows using parameters + +The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a +**getSettlementWindowsByParams** resource. This function allows its user to +obtain information about all settlement windows which meet the criteria +specified by the user. The following changes will need to be made to this call: + +1. The parameters supported by the call will need to be extended to allow a + user to request settlement windows by settlement model. The user should be + able to enter the name of a settlement model. + +2. This call returns an array of **SettlementWindow** objects. It is assumed + that these objects will have been changed by the changes specified in + Section 6.2.2.2 above, and that no further processing will be required for + this call. + +#### Requesting a settlement + +The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a **createSettlement** +resource. This function allows its user to request a settlement for a given set +of settlement windows, which are passed to the resource as parameters. The +following changes will need to be made to this call: + +The parameters for the **createSettlement** resource are defined in the +**SettlementEventPayload** object. This object will need to have a parameter +added to specify the settlement model which is to be settled. The parameter +should be called *settlementModel*, and it should be a string. It should be +required. + +The following validation should be performed on this parameter when the request +is received via the API: + +1. The content of the parameter is a case-insensitive match for an active entry + in the **settlementmodel** table, ignoring whitespace. + +2. The *settlementtypeid* column in the record in the selected settlement model + should not point to a record in the **settlementdelay** table whose + *settlementDelayName* value is “IMMEDIATE”. If it does, the request should + be rejected and an error message returned to the caller. + +The id of the settlement model requested should be stored in the +settlementModelId column of the row created in the **settlement** table to +describe the settlement. + +#### Returning the status of a settlement + +The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a **getSettlementById** +resource. This function allows its user to obtain information about a settlement +by giving the ID that was returned when the settlement was created. + +Information about settlements is returned in a **Settlement** object. A +parameter should be added to the Settlement object to record the settlement +model which is being settled by the settlement. + +The parameter should be called *settlementModel*, and it should be a string. It +should be required. + +**Note**: when a settlement is requested, a reason is given; but the +**Settlement** object does not contain the reason. It might be worth including +this in the definition of the **Settlement** object. + +#### Getting information about settlements using parameters + +The existing API definition[2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a +**getSettlementsByParams** resource. This function allows its user to obtain +information about all settlements by giving the ID that was returned when the +settlement was created. The following changes will need to be made to this call: + +1. This call returns an array of **Settlement** objects. It is assumed that + these objects will have been changed by the changes specified in Section + 6.2.2.5 above, and that no further processing will be required for this + call. + +#### Getting information about a specific participant in a settlement + +The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports a +**getSettlementBySettlementParticipant** resource. This function allows its user +to obtain information about a settlement which meet the criteria specified by +the user. The following changes will need to be made to this call: + +1. This call returns a **Settlement** object. It is assumed that this object + will have been changed by the changes specified in Section 6.2.2.5 above, + and that no further processing will be required for this call. + +#### Updating a specific settlement + +The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports an +**updateSettlementById** resource. This function allows its user to update +information about a settlement by giving the ID that was returned when the +settlement was created. + +This call returns a **Settlement** object. It is assumed that this object will +have been changed by the changes specified in Section 6.2.2.5 above, and that no +further processing will be required for this call. + +#### Updating a settlement for a specific participant + +The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports an +**updateSettlementBySettlementParticipant** resource. This function allows its +user to update information about a settlement by giving the ID that was returned +when the settlement was created, and the participant whose information is to be +updated. + +This call returns a **Settlement** object. It is assumed that this object will +have been changed by the changes specified in Section 6.2.2.5 above, and that no +further processing will be required for this call. + +#### Updating a settlement for a specific participant and account + +The existing API definition [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json) supports an +**updateSettlementBySettlementParticipantAccount** resource. This function +allows its user to update information about a settlement by giving the ID that +was returned when the settlement was created, and the participant and account +whose information is to be updated. + +This call returns a **Settlement** object. It is assumed that this object will +have been changed by the changes specified in Section 6.2.2.5 above, and that no +further processing will be required for this call. + +#### Recording the deposit of funds by a participant + +The existing administration API [3](https://mojaloop.io/documentation/api/central-ledger-api-specification.html) contains functions to enable +an administrator to record a deposit made by a participant to an account. This +process is described in Section 5.2 above. The API should be changed to align it +with the structures used in the existing settlement API [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json). In addition, the signature of the API should be extended to allow the +administrator to specify the account type that will be updated by the deposit. + +#### Recording the withdrawal of funds by a participant + +The existing administration API [3](https://mojaloop.io/documentation/api/central-ledger-api-specification.html) contains functions to enable +an administrator to record a withdrawal made by a participant from an account. +This process is described in Section 5.3 above. The API should be changed to +align it with the structures used in the existing settlement API [2](https://github.com/mojaloop/central-settlement/blob/master/src/interface/swagger.json). In addition, the signature of the API should be extended to allow +the administrator to specify the account type that will be updated by the +withdrawal. + +#### New resource: openSettlementWindow + +In the current architecture, an instance of each settlement window is created +when the instance is set up, and subsequent settlement windows are created by +closing the current settlement window. In the new settlement management +structure, we will need the ability to create new settlement windows where no +predecessors exist: for instance, when an administrator decides to settle a +particular currency using a different settlement model. + +### Processing changes + +The following processing changes are required to implement the changes required +to support continuous gross settlement. + +#### Attributing ledger entries to the correct ledger account type + +When a ledger entry is created, it should be assigned to the ledger account type +specified in the *ledgeraccounttypeid* column of the row in the +**ledgerentrytype** table appropriate to the ledger entry type which is being +created. + +For example: if a normal entry representing a transfer is being created, it will +have a ledger entry type of PRINCIPAL_VALUE. It should be assigned to the +POSITION account type (the default position at present.) This implies that the +match described in Section 6.2.1.3 above has been implemented. + +Question: how does the switch decide whether or when to construct a record in +the **participantPositionChange** table? How would it be possible to select the +ledger account type to which the position refers? + +Processing interchange fees +---------------------------- + +In order to support the scheme model implemented by TIPS, we need to generate +and settle liabilities incurred as a consequence of making transfers between +particular types of customer. The general form of this rule is as follows: + +- If the transaction is a wallet-to-wallet P2P transaction, then the receiver + DFSP pays the sender DFSP 0.6% of the amount of the transaction. + +- No interchange fees are levied for on-us transactions. + +The business decisions around this requirement are: + +1. The definition of whether or not a payee account is a wallet will be + returned by the payee DFSP as part of customer discovery. The mechanism by + which this is implemented is outside the scope of this document. + +2. Interchange fees will be captured by the switch when the transfers which + incur them are completed. + +3. Interchange fees will have the ledger entry type INTERCHANGE_FEE and will be + recorded in accounts whose type is INTERCHANGE_FEE. + +4. Interchange fees will be settled multilaterally, net and deferred. It is + expected that this settlement will take place monthly. + +5. Interchange fees do not require liability cover by participants. + +This functionality will be implemented as a partial instance of a general +process for defining and executing rules, and for taking actions based on the +outcome of evaluation of a rule. For this particular case, we propose the +changes described in the following sections. + +### Part 1: Run script for batch update of interchange fees when settlement window is closed. + +Include stories to manage account type definition + +### Part 2: Add reservation on prepare using script and modify fulfilment to fulfil all ledger types for which an entry has been made + +### Evaluating a rule + +The process of evaluating a rule is based on the following assumptions: + +1. There will be a standard form of rule evaluation with the following + structure: + + 1. A transaction object will be passed as the parameter to the rule + evaluation function. + + 2. The rule evaluation itself will use a complex if statement. + + 3. If the rule evaluates to TRUE, then an action should be executed as + described in Section 6.3.2 below. + +An example of a rule function to evaluate a TIPS interchange fee rule could be: + +function evaluateInterchangeFee (transaction) { + +if( + +(transaction.payee.fspId.toLowerCase() != transaction.payer.fspId.toLowerCase()) + +&& (transaction.extensionList[“payerAccountType”].toLowerCase() == +"Wallet".toLowerCase() + +&& transaction.extensionList[“payeeAccountType”].toLowerCase() == +"Wallet".toLowerCase()) + +&& (transaction.transactionType.scenario.toLowerCase() == +"TRANSFER".toLowerCase() + +&& transaction.transactionType.initiator.toLowerCase() == "PAYER".toLowerCase() + +&& transaction.transactionType.initiatorType.toLowerCase() == +"CONSUMER".toLowerCase()) + +) { + +// Do some good stuff + +}; + +}; + +### Taking action after evaluating a rule + +If a rule evaluates to TRUE as described in Section 6.3.1 above, then +appropriate action should be taken. In the case of the immediate example of +interchange fees, the action taken should be to add two entries to the +participants’ interchange fee accounts, on recording the debit from the payee of +the interchange fee amount and the other recording the credit to the payer of +the interchange fee amount. + +A simple yet general way of supporting actions of this type is to define a class +(which might be called ruleAction) and adding methods to it to represent the +actions to be taken. The rule evaluation function can then instantiate the class +and call the appropriate function. + +In the case of the interchange fees, we would define an action called +addLedgerEntry, with the following parameters: + +1. The transfer ID for which the ledger entry is being created + +2. The ledger entry type to be used + +3. The currency in which the amount is denominated + +4. The amount of the fee + +5. The FSP ID of the credit party + +6. The FSP ID of the debit party + +This might appear in the rule evaluation function as: + +myAction.addLedgerEntry(transaction.transactionId, + +transaction.transactionId, + +"INTERCHANGE_FEE“, + +transaction.currency, + +transaction.amount\*0.006, + +transaction.payer.fspId, + +transaction.payee.fspId); + +### Providing a generic framework for rule evaluation + +Finally, we will need to provide a generic framework to trigger the evaluation +of rules. This should be an array of evaluation functions, which are triggered +when the status of a transfer changes to FULFILLED. + +Process transfers for continuous gross settlement [EPIC] +------------------------------------------------- + +When a settlement model specifies that an account is to be settled immediate gross, then each ledger entry which is of a type belonging to that scheme account should be settled immediately. This immediate settlement should have the following characteristics: + +- It should be performed by a process which is forensically logged. +- It should be performed immediately, so that participants can check their current position against the transfers that comprise it. +- It should be aggregated to settlement window level, so that the checks which are currently performed on the overall status of a settlement window will continue to work. + +The following sections describe the changes that are required to process transfers for accounts which are settled immediate gross. + +### Database changes + +The following changes are required to the database to implement transfer processing for continuous gross settlement + +#### Addition of a new table to store changes in state + +A new table should be added to store changes in state for ledger entries for individual transfers. The name of this table should be **transferParticipantStateChange**. Its column structure should be as follows: + +1. The unique key to the record. Column name: **transferParticipantStateChangeId**; type: unsigned BIGINT; not nullable; primary key +2. The record in **TransferParticipant** whose state change this record marks. Column name: **transferParticipantId**; type: unsigned BIGINT; not nullable; foreign key to the **transferParticipantId** column of the **transferParticipant** table. +3. The current state of the record in **transferParticipant** to which this state record refers. Column name: **settlementWindowStateId**; data type VARCHAR(50); not nullable; foreign key to the **settlementWindowStateId** column of the **settlementWindowState** table. +4. An explanation of the state change. Column name: **reason**; type: VARCHAR(512); nullable. +5. The date and time when the change was recorded. Column name: **createdDate**; type DATETIME; not nullable; default value **CURRENT_TIMESTAMP**. + +#### Changes to the TransferParticipant table + +No changes to the **transferParticipant** table are required. The relationship between records in the **transferParticipant** table and records in the **transferParticipantStateChange** table is managed via the **transferParticipantId** column in the **transferParticipantStateChange** table. + +#### Changes to the settlementModel table + +Existing implementations have functionality which automatically adjusts participants' positions when settlements are completed. In order to support backwards compatibility for these implementations, the settlement model will be expanded to allow automated position adjustment to be switched off and on. + +This functionality will be managed through a new column in the **settlementModel** table. The name of the column will be **adjustPosition**. Its type will be TINYINT(1), and it should not be nullable. It should have a default value of zero (FALSE). + +### Processing changes + +The following changes to processing are required to support immediate settlement of gross ledger entries. + + +#### Generating entries in settlementContentAggregation + +The following changes to the process that creates aggregation records in the **settlementContentAggregation** table are required. + +1. The aggregation process for a settlement window may not be performed if there are any records in the **transferParticipant** table which belong to the settlement window to be aggregated (as defined by joining the **transferParticipant** records to the matching records in the **transferFulfilment** table on the **transferId** column in both tables) and which do not have any corresponding entries in the **transferParticipantStateChange** table. This test is performed via a LEFT OUTER JOIN relationship between the **transferParticipantStateChange** table and the **transferParticipant** table, using the foregin key relation between the **transferParticipantId** columns in the **transferParticipant** table and the **transferParticipantStateChange** table. +2. In the discussion which follows, the current status of a record in **transferParticipant** is defined as: the status of the record in the **transferParticipantStateChange** table which is keyed to the record in **transferParticipant** and which has the latest value in the **createdDate** column of the **transferParticipantStateChange** table. +3. When there are no records in **transferParticipant** which meet the blocking criteria described in step 1 above, then all records belonging to the settlement window which has just been closed, and which currently have the status OPEN, should have their status set to CLOSED. This means: a record should be added to the **transferParticipantStateChange** table for the qualifying **transferParticipant** record whose status is CLOSED, and the **currentStateChangeId** column for the qualifying **transferParticipant** record should be set to point to the newly created record. +4. When aggregating records for insertion into the **settlementContentAggregation** table, if all the records in the **transferParticipant** table which are to be aggregated into a single record in the **settlementContentAggregation** table have the same value in their **currentStateChangeId** column, then the value of the **currentStateId** column in the newly created record in the **settlementContentAggregation** table should be set as follows. The value of the **currentStateId** column in the newly created record in the **settlementContentAggregation** table should be set to the shared value in the constituent records from the **transferParticipant** table, except in the following case: if the shared value in the constituent records from the **transferParticipant** table is OPEN, then the value of the **currentStateId** column should be set to the value CLOSED. + +#### Marking transfers as settled + +The following additional processes are required in order to mark ledger entries which are settled immediate gross as having been settled. + +##### Queueing transfers for settlement processing + +When a transfer is completed, a record is generated in the **transferFulfilment** table. As part of the process that generates this record, the transfer should be placed on a Kafka stream for immediate settlement processing. + +##### Processing settlements + +A new service should be developed for processing gross (i.e. per-transfer) settlements. The requirements for this service are as follows: +1. It should enable an auditor to verify that a given transfer has been settled using the agreed process +2. It should allow transfer settlement to be recorded either internally, using an automatic process, or externally, exporting the information for each transfer to be settled to a configurable endpoint. +3. It should not delay processing of the transfer itself + +The characteristics of the service should be as follows: + +1. Pick a transfer from the Kafka stream holding transfers awaiting settlement processing. There is no requirement for sequence preservation, so this service can pick up multiple transfer entries if this would accelerate processing. +2. For each record in the **transferParticipant** table which belongs to the transfer *and* whose **ledgerEntryType** column specifies a ledger entry type which belongs to a settlement model which is settled both GROSS and IMMEDIATE, the service should generate consecutive records in the **transferParticipantStateChange** table with the values: CLOSED, PENDING_SETTLEMENT, and SETTLED, in that order. The **currentStateChangeId** column for the record in the **transferParticipant** table should be set to point to the record in the **transferParticipantStateChange** table whose value is SETTLED. +3. For each record in the **transferParticipant** table which belongs to the transfer *and* whose **ledgerEntryType** column specifies a ledger entry type which belongs to a settlement model which is settled both GROSS and IMMEDIATE *and* where the settlement model has an export endpoint configured, the process should export the information relating to the entry that is being settled to the endpoint specified in an agreed format. The format to be used, the means of specifying the endpoint to be addressed, and the process by which exports are generated and acknowledged, are not specified at this time. +4. For all other records in the **transferParticipant** table which belong to the transfer, the service should generate a record in the **transferParticipantStateChange** table with a value of OPEN. The **currentStateChangeId** column for the record in the **transferParticipant** table should be set to point to the record in the **transferParticipantStateChange** table which was created. + +#### Updating status values for net settlements + +When the status is updated for a participant in a settlement which belongs to a settlement model which is not settled both GROSS and IMMEDIATE, then the constituent records for that participant in the settlement in the **transferParticipant** table need to be updated. The rules for this are: + +1. When the settlement is created, all the records in **transferParticipant** which belong to a transfer which belongs to a window which belongs to the settlement being created (i.e. which are contained in the inner join between **transferParticipant**, **transferfulfilment** (on **transferId**) and **settlementSettlementWindow** (on **settlementWindowId**) for the settlement Id which is being created) should have a record created in **settlementContentAggregationStateChange** with the **settlementWindowStateId** column set to PENDING_SETTLEMENT. +2. When a participant's settlement status is updated to SETTLED in **settlementParticipantCurrency**, then all the records in **transferParticipant** for settlement windows which belong to that settlement, and whose participant and currency IDs match the participant and currency of the records in **settlementParticipantCurrency** which have been updated, should have their status set to SETTLED. + +#### Gross settlement and position management + +If gross settlement is enabled for a settlement model and that settlement model also has its **adjustPosition** flag set to TRUE, then an adjustment to both participants' positions should be made. This should be done in the following way: + +1. For each record in the **transferParticipant** table which is being settled, create a record in the **participantPositionChange** table with the following characteristics: + a. The **participantPositionId** column should be set to the value of the **participantPositionId** column in the **participantPosition** table for the record whose **participantCurrencyId** field is the same as that of the record in the **transferParticipant** table which has been settled. + b. The **transferStateChangeId** column should be set to the value of the **transferStateChangeId** column for the record in the **transferStateChange** table whose **transferId** column is the same as the value of the **transferId** column in the **transferParticipant** table for the record which is being settled, and which has the latet value in its **createdDate** column. + c. The **value** column should be set to the **amount** column in the **transferParticipant** table for the record which is being settled. + d. The **reservedValue** column should be set to zero. + e. The **createdDate** column should be set to the current date and time. +2. The record in the **participantPosition** table whose **participantCurrencyId** field matches that of the record in the **transferParticipant** table which has been settled should have the **amount** column of the corresponding record in the **transferParticipant** table added to its **value** column. + +Domain class diagram +==================== + +ERD +=== + +The following ERD describes the new data structures required to model settlements. + +![](/mojaloop-technical-overview/central-settlements/assets/diagrams/Settlement_ERD.png) + +Enumerations +------------ + +The following enumerations are required to support the new ERD: +``` +DELETE FROM settlementGranularity; +INSERT INTO settlementGranularity (name) +VALUES ('GROSS'), ('NET'); + +DELETE FROM settlementInterchange; +INSERT INTO settlementInterchange (name) +VALUES ('BILATERAL'), ('MULTILATERAL'); + +DELETE FROM settlementDelay; +INSERT INTO settlementDelay(name) +VALUES ('IMMEDIATE'), ('DEFERRED'); +``` diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/README.md b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/README.md new file mode 100644 index 000000000..1cf8e627b --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/README.md @@ -0,0 +1,111 @@ +# Settlement Process + +## 1. Database Design + +### Notes: + +- `settlementWindow` - a table where all settlement windows are stored; +- `settlementWindowStateChange` - stores information regarding settlement windows state; +- `settlement` - keeps data regarding all settlements; +- `settlementContentAggregation` - contains aggregated values for a settlement, participant currency, role type and ledger entry type grouping in a settlement; +- `settlementModel` - contains the configured settlement models for the switch; +- `settlementWindowContent` - contains an entry for each item of content in a given settlement window, broken down by ledger account type and currency; +- `settlementWindowContentStateChange` - tracks settlement window content state changes; +- `settlementSettlementWindow` - association table for settlements and settlement windows, providing connection many-to-many; +- `settlementStateChange` - tracks the settlement state change; +- `settlementTransferParticipant` - this table is used for staging data for all transfers which are to be included in a settlement; +- `settlementParticipantCurrency` - stores grouped information by participant and currency. For calculation of netAmount, the summarized data from `settlementTransferParticipant` is used; +- `settlementParticipantCurrencyStateChange` - used to track the state change of each individual settlement participant account. + +The remaining tables in the below ERD are either transfer-specific (gray) or lookup (blue) and are included as direct dependencies to depict the relation between the settlement tables and transfer specific entities. + +![Central Settlements. Service ERD](./assets/entities/central-settlements-db-schema.png) + +* [Central Settlements Service DBeaver ERD](./assets/entities/central-settlements-db-schema-dbeaver.erd) + +## 2. Sequence diagrams + +### 2.1. Settlement Windows By Params + +Used for acquiring information regarding Settlement Windows. E.g.: +1. Find the ID of the current OPEN window by querying by state and later use the information for closing that window; +2. Find all CLOSED and/or ABORTED windows to be used for creating a settlement; +3. Other reporting needs. +- [Sequence Diagram for Get Settlement Windows by Parameters](get-settlement-windows-by-params.md) + +### 2.2. Settlement Windows By Params + +Used for acquiring settlement window information when ID is present. +- [Sequence Diagram for Request Settlement Window by Id](get-settlement-window-by-id.md) + +### 2.3. Close Settlement Window + +There is always one open settlement window which groups all ongoing transfers. This functionality is used to close the currently opened window and create the next one. The operations starts on the API and then the Deferred handler consumes a message after the validations are passed and prepares the Settlement Window Content and Settlement Content Aggregation records for the settlement process. +- [Sequence Diagram for Close Settlement Window](post-close-settlement-window.md) + +### 2.4. Create Settlement + +The creation of settlement is possible when at least one OPEN or ABORTED window is provided. The data from all transfers in all provided windows is summarized and as a result the settlement amount is calculated per participant and currency. Depending on its sign we distinct 3 types of participants in regards to the newly created settlement: SETTLEMENT_NET_RECIPIENT, SETTLEMENT_NET_SENDER and SETTLEMENT_NET_ZERO. Newly generated id of type bigint is returned as a response together it all other information. +- [Sequence Diagram for Trigger Settlement Event](post-create-settlement.md) + +### 2.5. Request Settlement + +This endpoint is used for acquiring information regarding a settlement and all included windows and accounts/positions. The ID from the previous request is being utilized for that purpose. +- [Sequence Diagram for Get Settlement by Id](get-settlement-by-id.md) + +### 2.6. Settlement Transfer Acknowledgment + +It is used to advance the settlement through all the states initiated with the creation and finilized by settle or abort. The actual state flow is: +- PENDING_SETTLEMENT: The net settlement report for this window has been taken, with the parameter set to indicate that settlement is to be processed; +- PS_TRANSFERS_RECORDED: Record transfer entries against the Position Account and the Multi-lateral Net Settlement Account, these are the "multi-lateral net  settlement transfers" (MLNS transfers). An identifier might be provided to be past to the reference bank; +- PS_TRANSFERS_RESERVED: All the debit entries for the MLNS transfers are reserved; +- PS_TRANSFERS_COMMITTED: All the credit entries for the MLNS transfers are committed. An identifier might be received and recorded from the Settlement bank to allow reconciliation; +- SETTLING: If all accounts are not yet SETTLED, the Status of the settlement is moved to SETTLING. Note: applies only on settlement level; +- SETTLED: Final state when all outstanding accounts are SETTLED, the entire Settlement is moved to SETTLED. + +[Sequence Diagram for Acknowledgement of Settlement Transfer](put-settlement-transfer-ack.md) + +### 2.7. Settlement Abort + +- ABORTED: Final state when the settlement is not possible. Please, note the settlement might be aborted up to when no account/position has been marked as PS_TRANSFERS_COMMITTED. Also there is no possibility to mark an individual account as ABORTED, but rahter the entire settlement is ABORTED. After performing such operation there is possibility to create a new settlement by including only non-problematic ABORTED accounts + +[Sequence Diagram for Settlement Abort](put-settlement-abort.md) + +### 2.8. Request Settlement By SPA + +Used to request drill-down information regarding a settlement, participant and account. Even though participant and account are optional, the order settlement/{id}/participant/{id}/account/{id} is mandatory. + +- [Sequence Diagram for Get Settlement by Settlement/Participant/Account](get-settlement-by-spa.md) + +### 2.9. Request Settlements By Params + +This endpoint enables advanced reporting capabilities. + +- [Sequence Diagram for Query Settlements by Parameters](get-settlements-by-params.md) + +### 2.10 Gross Settlement Handler + +This handler executes after each transfer is committed and performs the following operations on success: + Handle the updating of the POSITION and SETTLEMENT accounts for participants involved in a transfer where there is a settlement model defined as immediate and gross on the POSITION account to facilitate RTCGS (Real-Time Continuous Gross Settlement) per transfer. + +This is done by consuming events of the notification topic. + +- [Sequence Diagram for Gross Settlement Handler](gross-settlement-handler-consume.md) + +### 2.11 Rules Handler + +This handler executes after each transfer is committed and performs the following operations on success: + Execute the rules defined by the scripts in the SCRIPTS_FOLDER. The rules are validated for valid headers before loading. + +This is done by consuming events of the notification topic. + +- [Sequence Diagram for Rules Handler](rules-handler-consume.md) + +### 2.12 Deferred Handler + +This handler executes after close settlement window operation has been received and validated: + + Handle the updating of the participant accounts involved in the transfers for the settlement window that is closed. The process then continues with settlement event trigger. + +This is done by consuming events of the notification topic, that are emitted by the service after close settlement window command has been sent and validated. +- [Sequence Diagram for Close Settlement Window](post-close-settlement-window.md) \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-gross-settlement-handler.plantuml b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-gross-settlement-handler.plantuml new file mode 100644 index 000000000..fc837adab --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-gross-settlement-handler.plantuml @@ -0,0 +1,204 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Neal Donnan + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declare title +title Gross Settlement Handler Consume (Success) +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors + +collections "topic-notification" as TOPIC_NOTIFICATION +control "Gross Settlement Handler" as SETTLEMENT_HANDLER +control "Gross Settlement Service" as SETTLEMENT_SERVICE +database "central_ledger" as DB +entity "Settlement DAO" as SETTLEMENT_DAO + +box "Settlement Service" #LightGreen + participant TOPIC_NOTIFICATION + participant SETTLEMENT_HANDLER + participant SETTLEMENT_SERVICE + participant SETTLEMENT_DAO +end box + +box "Central Services" #lightyellow + participant DB +end box + +' start flow +activate SETTLEMENT_HANDLER +group Gross Settlement Handler Consume (Success) + alt Consume Single Message + TOPIC_NOTIFICATION <- SETTLEMENT_HANDLER: Consume notification event message + activate TOPIC_NOTIFICATION + deactivate TOPIC_NOTIFICATION + group Validate Message + SETTLEMENT_HANDLER <-> SETTLEMENT_HANDLER: Validate event - Rule: message has payload\nError codes: 2001 + end + opt action == 'COMMIT' + + group Retry (default 3 retries) + group DB TRANSACTION: settle transfer + SETTLEMENT_HANDLER -> SETTLEMENT_SERVICE: Process fulfil message + SETTLEMENT_SERVICE -> SETTLEMENT_DAO: Get Gross settlement model + SETTLEMENT_DAO -> DB: Get settlement model records + activate DB + deactivate DB + hnote over DB #lightyellow + SELECT settlementModel.* + FROM **settlementModel** + INNER JOIN `participantCurrency` AS `pc` ON `pc`.`currencyId` = `settlementModel`.`currencyId` + AND `pc`.`ledgerAccountTypeId` `settlementModel`.`ledgerAccountTypeId` + INNER JOIN `transferParticipant` AS `tp` ON `tp`.`participantCurrencyId` = `pc`.`participantCurrencyId` + INNER JOIN settlementGranularity AS `g` ON `g`.`settlementGranularityId` = `settlementModel`.`settlementGranularityId` + WHERE `tp`.`transferId`, {transferId} + AND `g`.`name`, {settlementGranularityName} + AND `settlementModel`.`isActive`, {1}; + end hnote + SETTLEMENT_DAO <-- DB: Gross settlement model result + SETTLEMENT_SERVICE <-- SETTLEMENT_DAO: Gross settlement model result + group Validate settlement model + SETTLEMENT_SERVICE <-> SETTLEMENT_SERVICE: Valid Gross settlement model with given currency does not exist + SETTLEMENT_SERVICE <-> DB: Get all settlement models + alt Check if NET settlement model with the transfer currency exists + SETTLEMENT_SERVICE <-> SETTLEMENT_SERVICE: Return true + else + SETTLEMENT_SERVICE <-> SETTLEMENT_SERVICE: filter all settlement models by currencyId === null and granularityType === GROSS + SETTLEMENT_SERVICE <-> SETTLEMENT_SERVICE: Return default GROSS settlement model + end + end + SETTLEMENT_SERVICE -> SETTLEMENT_DAO: Settle transfer if CGS + SETTLEMENT_DAO -> DB: Insert transferParticipant entries + activate DB + deactivate DB + hnote over DB #lightyellow + insert into **`transferParticipant`** (transferID, participantCurrencyId, transferParticipantRoleTypeId, ledgerEntryTypeId, + amount) + select `TP`.`transferId`, + `TP`.`participantCurrencyId`, + `TP`.`transferParticipantRoleTypeId`, + `TP`.`ledgerEntryTypeId`, + `TP`.`amount` * -1 + from `transferParticipant` as `TP` + inner join `participantCurrency` as `PC` on `TP`.`participantCurrencyId` = `PC`.`participantCurrencyId` + inner join `settlementModel` as `M` on `PC`.`ledgerAccountTypeId` = `M`.`ledgerAccountTypeId` + inner join `settlementGranularity` as `G` on `M`.`settlementGranularityId` = `G`.`settlementGranularityId` + where (`TP`.`transferId` = {transferId} and (`G`.`name` = 'GROSS')) + union + select `TP`.`transferId`, + `PC1`.`participantCurrencyId`, + `TP`.`transferParticipantRoleTypeId`, + `TP`.`ledgerEntryTypeId`, + `TP`.`amount` + from `transferParticipant` as `TP` + inner join `participantCurrency` as `PC` on `TP`.`participantCurrencyId` = `PC`.`participantCurrencyId` + inner join `settlementModel` as `M` on `PC`.`ledgerAccountTypeId` = `M`.`ledgerAccountTypeId` + inner join `settlementGranularity` as `G` on `M`.`settlementGranularityId` = `G`.`settlementGranularityId` + inner join `participantCurrency` as `PC1` + on `PC1`.`currencyId` = `PC`.`currencyId` and `PC1`.`participantId` = `PC`.`participantId` and + `PC1`.`ledgerAccountTypeId` = `M`.`settlementAccountTypeId` + where (`TP`.`transferId` = {transferId} and (`G`.`name` = 'GROSS')); + end hnote + SETTLEMENT_DAO -> DB: Update participantPosition records + activate DB + deactivate DB + hnote over DB #lightyellow + update **`participantPosition`** as `PP` + inner join (select `PC`.`participantCurrencyId`, `TP`.`Amount` + from `transferParticipant` as `TP` + inner join `participantCurrency` as `PC` + on `TP`.`participantCurrencyId` = `PC`.`participantCurrencyId` + inner join `settlementModel` as `M` + on `PC`.`ledgerAccountTypeId` = `M`.`ledgerAccountTypeId` + inner join `settlementGranularity` as `G` + on `M`.`settlementGranularityId` = `G`.`settlementGranularityId` + where (`TP`.`transferId` = {transferId} and (`G`.`name` = 'GROSS')) + union + select `PC1`.`participantCurrencyId`, `TP`.`amount` + from `transferParticipant` as `TP` + inner join `participantCurrency` as `PC` + on `TP`.`participantCurrencyId` = `PC`.`participantCurrencyId` + inner join `settlementModel` as `M` + on `M`.`ledgerAccountTypeId` = `PC`.`ledgerAccountTypeId` + inner join `settlementGranularity` as `G` + on `M`.`settlementGranularityId` = `G`.`settlementGranularityId` + inner join `participantCurrency` as `PC1` + on `PC1`.`currencyId` = `PC`.`currencyId` and + `PC1`.`participantId` = `PC`.`participantId` and + `PC1`.`ledgerAccountTypeId` = `M`.`settlementAccountTypeId` + where (`TP`.`transferId` = {transferId} and (`G`.`name` = 'GROSS'))) + AS TR ON PP.participantCurrencyId = TR.ParticipantCurrencyId + set `value` = `PP`.`value` - `TR`.`amount`; + end hnote + SETTLEMENT_DAO -> DB: Insert participantPositionChange records + activate DB + deactivate DB + hnote over DB #lightyellow + insert into **`participantPositionChange`** (participantPositionId, transferStateChangeId, value, reservedValue) + select `PP`.`participantPositionId`, `TSC`.`transferStateChangeId`, `PP`.`value`, `PP`.`reservedValue` + from `participantPosition` as `PP` + inner join (select `PC`.`participantCurrencyId` + from `transferParticipant` as `TP` + inner join `participantCurrency` as `PC` + on `TP`.`participantCurrencyId` = `PC`.`participantCurrencyId` + inner join `settlementModel` as `M` + on `PC`.`ledgerAccountTypeId` = `M`.`ledgerAccountTypeId` + inner join `settlementGranularity` as `G` + on `M`.`settlementGranularityId` = `G`.`settlementGranularityId` + where (`TP`.`transferId` = {transferId} and (`G`.`name` = 'GROSS')) + union + select `PC1`.`participantCurrencyId` + from `transferParticipant` as `TP` + inner join `participantCurrency` as `PC` + on `TP`.`participantCurrencyId` = `PC`.`participantCurrencyId` + inner join `settlementModel` as `M` + on `PC`.`ledgerAccountTypeId` = `PC`.`ledgerAccountTypeId` + inner join `settlementGranularity` as `G` + on `M`.`settlementGranularityId` = `G`.`settlementGranularityId` + inner join `participantCurrency` as `PC1` on `PC1`.`currencyId` = `PC`.`currencyId` and + `PC1`.`participantId` = `PC`.`participantId` and + `PC1`.`ledgerAccountTypeId` = `M`.`settlementAccountTypeId` + where (`TP`.`transferId` = {transferId} and (`G`.`name` = 'GROSS'))) AS TR + ON PP.participantCurrencyId = TR.ParticipantCurrencyId + inner join `transferStateChange` as `TSC` + on `TSC`.`transferID` = {transferId} and `TSC`.`transferStateId` = 'SETTLED'; + end hnote + end + end + end + else Consume Batch Messages + note left of SETTLEMENT_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate SETTLEMENT_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-gross-settlement-handler.svg b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-gross-settlement-handler.svg new file mode 100644 index 000000000..5d560d536 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-gross-settlement-handler.svg @@ -0,0 +1,567 @@ + + + + + + + + + + + Gross Settlement Handler Consume (Success) + + + + Settlement Service + + + + Central Services + + + + + + + + + + + + + + + topic-notification + + + + + topic-notification + + + Gross Settlement Handler + + + + + Gross Settlement Handler + + + + + Gross Settlement Service + + + + + Gross Settlement Service + + + + + Settlement DAO + + + + + Settlement DAO + + + + + central_ledger + + + + + central_ledger + + + + + + + + Gross Settlement Handler Consume (Success) + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume notification event message + + + + + Validate Message + + + + + 2 + + + Validate event - Rule: message has payload + + + Error codes: + + + 2001 + + + + + opt + + + [action == 'COMMIT'] + + + + + Retry (default 3 retries) + + + + + DB TRANSACTION: settle transfer + + + + + 3 + + + Process fulfil message + + + + + 4 + + + Get Gross settlement model + + + + + 5 + + + Get settlement model records + + + + SELECT settlementModel.* + + + FROM + + + settlementModel + + + INNER JOIN `participantCurrency` AS `pc` ON `pc`.`currencyId` = `settlementModel`.`currencyId` + + + AND `pc`.`ledgerAccountTypeId` `settlementModel`.`ledgerAccountTypeId` + + + INNER JOIN `transferParticipant` AS `tp` ON `tp`.`participantCurrencyId` = `pc`.`participantCurrencyId` + + + INNER JOIN settlementGranularity AS `g` ON `g`.`settlementGranularityId` = `settlementModel`.`settlementGranularityId` + + + WHERE `tp`.`transferId`, {transferId} + + + AND `g`.`name`, {settlementGranularityName} + + + AND `settlementModel`.`isActive`, {1}; + + + + + 6 + + + Gross settlement model result + + + + + 7 + + + Gross settlement model result + + + + + Validate settlement model + + + + + 8 + + + Valid Gross settlement model with given currency does not exist + + + + + 9 + + + Get all settlement models + + + + + alt + + + [Check if NET settlement model with the transfer currency exists] + + + + + 10 + + + Return true + + + + + + 11 + + + filter all settlement models by currencyId === null and granularityType === GROSS + + + + + 12 + + + Return default GROSS settlement model + + + + + 13 + + + Settle transfer if CGS + + + + + 14 + + + Insert transferParticipant entries + + + + insert into + + + `transferParticipant` + + + (transferID, participantCurrencyId, transferParticipantRoleTypeId, ledgerEntryTypeId, + + + amount) + + + select `TP`.`transferId`, + + + `TP`.`participantCurrencyId`, + + + `TP`.`transferParticipantRoleTypeId`, + + + `TP`.`ledgerEntryTypeId`, + + + `TP`.`amount` * -1 + + + from `transferParticipant` as `TP` + + + inner join `participantCurrency` as `PC` on `TP`.`participantCurrencyId` = `PC`.`participantCurrencyId` + + + inner join `settlementModel` as `M` on `PC`.`ledgerAccountTypeId` = `M`.`ledgerAccountTypeId` + + + inner join `settlementGranularity` as `G` on `M`.`settlementGranularityId` = `G`.`settlementGranularityId` + + + where (`TP`.`transferId` = {transferId} and (`G`.`name` = 'GROSS')) + + + union + + + select `TP`.`transferId`, + + + `PC1`.`participantCurrencyId`, + + + `TP`.`transferParticipantRoleTypeId`, + + + `TP`.`ledgerEntryTypeId`, + + + `TP`.`amount` + + + from `transferParticipant` as `TP` + + + inner join `participantCurrency` as `PC` on `TP`.`participantCurrencyId` = `PC`.`participantCurrencyId` + + + inner join `settlementModel` as `M` on `PC`.`ledgerAccountTypeId` = `M`.`ledgerAccountTypeId` + + + inner join `settlementGranularity` as `G` on `M`.`settlementGranularityId` = `G`.`settlementGranularityId` + + + inner join `participantCurrency` as `PC1` + + + on `PC1`.`currencyId` = `PC`.`currencyId` and `PC1`.`participantId` = `PC`.`participantId` and + + + `PC1`.`ledgerAccountTypeId` = `M`.`settlementAccountTypeId` + + + where (`TP`.`transferId` = {transferId} and (`G`.`name` = 'GROSS')); + + + + + 15 + + + Update participantPosition records + + + + update + + + `participantPosition` + + + as `PP` + + + inner join (select `PC`.`participantCurrencyId`, `TP`.`Amount` + + + from `transferParticipant` as `TP` + + + inner join `participantCurrency` as `PC` + + + on `TP`.`participantCurrencyId` = `PC`.`participantCurrencyId` + + + inner join `settlementModel` as `M` + + + on `PC`.`ledgerAccountTypeId` = `M`.`ledgerAccountTypeId` + + + inner join `settlementGranularity` as `G` + + + on `M`.`settlementGranularityId` = `G`.`settlementGranularityId` + + + where (`TP`.`transferId` = {transferId} and (`G`.`name` = 'GROSS')) + + + union + + + select `PC1`.`participantCurrencyId`, `TP`.`amount` + + + from `transferParticipant` as `TP` + + + inner join `participantCurrency` as `PC` + + + on `TP`.`participantCurrencyId` = `PC`.`participantCurrencyId` + + + inner join `settlementModel` as `M` + + + on `M`.`ledgerAccountTypeId` = `PC`.`ledgerAccountTypeId` + + + inner join `settlementGranularity` as `G` + + + on `M`.`settlementGranularityId` = `G`.`settlementGranularityId` + + + inner join `participantCurrency` as `PC1` + + + on `PC1`.`currencyId` = `PC`.`currencyId` and + + + `PC1`.`participantId` = `PC`.`participantId` and + + + `PC1`.`ledgerAccountTypeId` = `M`.`settlementAccountTypeId` + + + where (`TP`.`transferId` = {transferId} and (`G`.`name` = 'GROSS'))) + + + AS TR ON PP.participantCurrencyId = TR.ParticipantCurrencyId + + + set `value` = `PP`.`value` - `TR`.`amount`; + + + + + 16 + + + Insert participantPositionChange records + + + + insert into + + + `participantPositionChange` + + + (participantPositionId, transferStateChangeId, value, reservedValue) + + + select `PP`.`participantPositionId`, `TSC`.`transferStateChangeId`, `PP`.`value`, `PP`.`reservedValue` + + + from `participantPosition` as `PP` + + + inner join (select `PC`.`participantCurrencyId` + + + from `transferParticipant` as `TP` + + + inner join `participantCurrency` as `PC` + + + on `TP`.`participantCurrencyId` = `PC`.`participantCurrencyId` + + + inner join `settlementModel` as `M` + + + on `PC`.`ledgerAccountTypeId` = `M`.`ledgerAccountTypeId` + + + inner join `settlementGranularity` as `G` + + + on `M`.`settlementGranularityId` = `G`.`settlementGranularityId` + + + where (`TP`.`transferId` = {transferId} and (`G`.`name` = 'GROSS')) + + + union + + + select `PC1`.`participantCurrencyId` + + + from `transferParticipant` as `TP` + + + inner join `participantCurrency` as `PC` + + + on `TP`.`participantCurrencyId` = `PC`.`participantCurrencyId` + + + inner join `settlementModel` as `M` + + + on `PC`.`ledgerAccountTypeId` = `PC`.`ledgerAccountTypeId` + + + inner join `settlementGranularity` as `G` + + + on `M`.`settlementGranularityId` = `G`.`settlementGranularityId` + + + inner join `participantCurrency` as `PC1` on `PC1`.`currencyId` = `PC`.`currencyId` and + + + `PC1`.`participantId` = `PC`.`participantId` and + + + `PC1`.`ledgerAccountTypeId` = `M`.`settlementAccountTypeId` + + + where (`TP`.`transferId` = {transferId} and (`G`.`name` = 'GROSS'))) AS TR + + + ON PP.participantCurrencyId = TR.ParticipantCurrencyId + + + inner join `transferStateChange` as `TSC` + + + on `TSC`.`transferID` = {transferId} and `TSC`.`transferStateId` = 'SETTLED'; + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-rules-handler.plantuml b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-rules-handler.plantuml new file mode 100644 index 000000000..88ff1491c --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-rules-handler.plantuml @@ -0,0 +1,219 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Neal Donnan + * Valentin Genev + -------------- + ******'/ + +@startuml +' declare title +title Rules Handler Consume (Success) +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors + +collections "topic-notification" as TOPIC_NOTIFICATION +control "Rules Handler" as RULES_HANDLER +database "central_ledger" as DB +entity "Scripts Loader" as SCRIPTS_LOADER +entity "Script Engine" as SCRIPT_ENGINE +entity "Transaction DAO" as TRANSACTION_DAO +entity "Settlement DAO" as SETTLEMENT_DAO +entity "Central Ledger DAO" as CENTRAL_LEDGER_DAO + +box "Settlement Service" #LightGreen + participant TOPIC_NOTIFICATION + participant RULES_HANDLER + participant SCRIPTS_LOADER + participant SCRIPT_ENGINE + participant TRANSACTION_DAO + participant SETTLEMENT_DAO + participant CENTRAL_LEDGER_DAO +end box + +box "Central Services" #lightyellow + participant DB +end box + +' start flow +activate RULES_HANDLER +group Rules Handler Consume (Success) + group Load Scripts + RULES_HANDLER -> SCRIPTS_LOADER: load scripts (yaml file) (scriptDirectory) + activate SCRIPTS_LOADER + loop script + SCRIPTS_LOADER -> SCRIPTS_LOADER: validate script type, action and status against enums; validate script is valid JS; validate start and end timestamps; Create a map ScriptMap[type][action][result] + end + SCRIPTS_LOADER --> RULES_HANDLER: create script map + note right of RULES_HANDLER #yellow + example: + { + scriptType: { + scriptAction: { + scriptStatus: {[ + { + name: "interchangeFeeCalculation", + startTime: "2020-06-01T00:00:00.000Z", + endTime: "2100-12-31T23:59:59.999Z", + script: [vm.Script] + } + ]} + } + } + } + end note + deactivate SCRIPTS_LOADER + end + group Process Single Message + TOPIC_NOTIFICATION <- RULES_HANDLER: Consume notification event message + activate TOPIC_NOTIFICATION + deactivate TOPIC_NOTIFICATION + group Validate Message + RULES_HANDLER <-> RULES_HANDLER: Validate event - Rule: message has payload\nError codes: 2001 + end + alt Rule found + RULES_HANDLER <-> RULES_HANDLER: check if ScriptMap[type][action][result] has valid script assigned + group Execute Scripts + RULES_HANDLER -> SCRIPTS_LOADER: execute scripts + activate SCRIPTS_LOADER + loop script + SCRIPTS_LOADER -> SCRIPT_ENGINE: execute(script, message payload) + activate SCRIPT_ENGINE + SCRIPT_ENGINE -> TRANSACTION_DAO: Get transaction by transfer Id + activate TRANSACTION_DAO + TRANSACTION_DAO -> DB: retrieve ILP packet from ilpPacket + activate DB + DB --> TRANSACTION_DAO: ilpPacket row + deactivate DB + TRANSACTION_DAO --> SCRIPT_ENGINE: ilpPacket row + SCRIPT_ENGINE -> TRANSACTION_DAO: Get transaction object + TRANSACTION_DAO -> TRANSACTION_DAO: decode ILP packet + TRANSACTION_DAO --> SCRIPT_ENGINE: Transaction object + SCRIPT_ENGINE -> SCRIPT_ENGINE: execute script in sandbox + deactivate + SCRIPT_ENGINE --> SCRIPTS_LOADER: Ledger entries + deactivate SCRIPT_ENGINE + SCRIPTS_LOADER -> SCRIPTS_LOADER: Merge results + end + SCRIPTS_LOADER --> RULES_HANDLER: script results + deactivate SCRIPTS_LOADER + end + + alt Has ledger entries + group DB TRANSACTION: Validate and Insert ledger entries + RULES_HANDLER -> SETTLEMENT_DAO: Insert valid ledger entries + SETTLEMENT_DAO -> DB: Get the records to insert + activate DB + hnote over DB #lightyellow + select {transferId} AS transferId, + `PC`.`participantCurrencyId`, + IFNULL(`T1`.`transferparticipantroletypeId`, + `T2`.`transferparticipantroletypeId`) as `transferParticipantRoleTypeId`, + `E`.`ledgerEntryTypeId`, + CASE `P`.`name` + WHEN {ledgerEntry.payerFspId} THEN {ledgerEntry.amount} + WHEN {ledgerEntry.payeeFspId} THEN {ledgerEntry.amount * -1} + ELSE 0 + END AS `amount` + from `participantCurrency` as `PC` + inner join `participant` as `P` on `P`.`participantId` = `PC`.`participantId` + inner join `ledgerEntryType` as `E` on `E`.`LedgerAccountTypeId` = `PC`.`LedgerAccountTypeId` + left outer join `transferParticipantRoleType` as `T1` on `P`.`name` = {ledgerEntry.payerFspId} and `T1`.`name` = 'PAYER_DFSP' + left outer join `transferParticipantRoleType` as `T2` on `P`.`name` = {ledgerEntry.payerFspId} and `T2`.`name` = 'PAYEE_DFSP' + where `E`.`name` = {ledgerEntry.ledgerEntryTypeId} + and `P`.`name` in ({ledgerEntry.payerFspId}, {ledgerEntry.payeeFspId}) + and `PC`.`currencyId` = {ledgerEntry.currency}; + end hnote + SETTLEMENT_DAO <-- DB: recordsToInsert + deactivate DB + + alt Has records to insert + SETTLEMENT_DAO -> DB: Insert transferParticipant records + activate DB + deactivate DB + hnote over DB #lightyellow + insert into **transferParticipant** + + end hnote + SETTLEMENT_DAO -> DB: Update positions + activate DB + deactivate DB + loop transferParticipant records + hnote over DB #lightyellow + update **`participantPosition`** + set `value` = `value` + {record.amount} + where `participantCurrencyId` = {record.participantCurrencyId}; + end hnote + end + SETTLEMENT_DAO -> DB: Get transferStateChange record + activate DB + hnote over DB #lightyellow + select `transferStateChangeId` + from **`transferStateChange`** + where `transferId` = {transferId} + and `transferStateId` = 'COMMITTED'; + end hnote + SETTLEMENT_DAO <-- DB: transferStateChange record + deactivate DB + SETTLEMENT_DAO -> DB: Get participantPosition record + activate DB + hnote over DB #lightyellow + select `participantPositionId`, `value`, `reservedValue` + from **`participantPosition`** + where `participantCurrencyId` = {recordsToInsert[0].participantCurrencyId} + OR `participantCurrencyId` = {recordsToInsert[1].participantCurrencyId}; + end hnote + SETTLEMENT_DAO <-- DB: participantPosition record + deactivate DB + SETTLEMENT_DAO -> DB: Insert participantPositionChange records + activate DB + deactivate DB + hnote over DB #lightyellow + insert into **`participantPositionChange`** + select `participantPositionId`, {transferStateChangeId}, `value`, `reservedValue` + from `participantPosition` + where `participantCurrencyId` = {transferParticipantRecord1.participantCurrencyId} + or `participantCurrencyId` = {transferParticipantRecord2.participantCurrencyId}; + end hnote + else No records found + SETTLEMENT_DAO <-> SETTLEMENT_DAO: Error + end + else + SETTLEMENT_DAO <-> SETTLEMENT_DAO: Rollback on Error + end + else + RULES_HANDLER <-> RULES_HANDLER: exit + end + + + else + RULES_HANDLER <-> RULES_HANDLER: exit + end + end +end +deactivate RULES_HANDLER +@enduml diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-rules-handler.svg b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-rules-handler.svg new file mode 100644 index 000000000..1a26ed085 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-rules-handler.svg @@ -0,0 +1,642 @@ + + + + + + + + + + + Rules Handler Consume (Success) + + + + Settlement Service + + + + Central Services + + + + + + + + + + + + + + + + + topic-notification + + + + + topic-notification + + + Rules Handler + + + + + Rules Handler + + + + + Scripts Loader + + + + + Scripts Loader + + + + + Script Engine + + + + + Script Engine + + + + + Transaction DAO + + + + + Transaction DAO + + + + + Settlement DAO + + + + + Settlement DAO + + + + + Central Ledger DAO + + + + + Central Ledger DAO + + + + + central_ledger + + + + + central_ledger + + + + + + + + Rules Handler Consume (Success) + + + + + Load Scripts + + + + + 1 + + + load scripts (yaml file) (scriptDirectory) + + + + + loop + + + [script] + + + + + 2 + + + validate script type, action and status against enums; validate script is valid JS; validate start and end timestamps; Create a map ScriptMap[type][action][result] + + + + + 3 + + + create script map + + + + + example: + + + { + + + scriptType: { + + + scriptAction: { + + + scriptStatus: {[ + + + { + + + name: "interchangeFeeCalculation", + + + startTime: "2020-06-01T00:00:00.000Z", + + + endTime: "2100-12-31T23:59:59.999Z", + + + script: [vm.Script] + + + } + + + ]} + + + } + + + } + + + } + + + + + Process Single Message + + + + + 4 + + + Consume notification event message + + + + + Validate Message + + + + + 5 + + + Validate event - Rule: message has payload + + + Error codes: + + + 2001 + + + + + alt + + + [Rule found] + + + + + 6 + + + check if ScriptMap[type][action][result] has valid script assigned + + + + + Execute Scripts + + + + + 7 + + + execute scripts + + + + + loop + + + [script] + + + + + 8 + + + execute(script, message payload) + + + + + 9 + + + Get transaction by transfer Id + + + + + 10 + + + retrieve ILP packet from ilpPacket + + + + + 11 + + + ilpPacket row + + + + + 12 + + + ilpPacket row + + + + + 13 + + + Get transaction object + + + + + 14 + + + decode ILP packet + + + + + 15 + + + Transaction object + + + + + 16 + + + execute script in sandbox + + + + + 17 + + + Ledger entries + + + + + 18 + + + Merge results + + + + + 19 + + + script results + + + + + alt + + + [Has ledger entries] + + + + + DB TRANSACTION: Validate and Insert ledger entries + + + + + 20 + + + Insert valid ledger entries + + + + + 21 + + + Get the records to insert + + + + select {transferId} AS transferId, + + + `PC`.`participantCurrencyId`, + + + IFNULL(`T1`.`transferparticipantroletypeId`, + + + `T2`.`transferparticipantroletypeId`) as `transferParticipantRoleTypeId`, + + + `E`.`ledgerEntryTypeId`, + + + CASE `P`.`name` + + + WHEN {ledgerEntry.payerFspId} THEN {ledgerEntry.amount} + + + WHEN {ledgerEntry.payeeFspId} THEN {ledgerEntry.amount * -1} + + + ELSE 0 + + + END AS `amount` + + + from `participantCurrency` as `PC` + + + inner join `participant` as `P` on `P`.`participantId` = `PC`.`participantId` + + + inner join `ledgerEntryType` as `E` on `E`.`LedgerAccountTypeId` = `PC`.`LedgerAccountTypeId` + + + left outer join `transferParticipantRoleType` as `T1` on `P`.`name` = {ledgerEntry.payerFspId} and `T1`.`name` = 'PAYER_DFSP' + + + left outer join `transferParticipantRoleType` as `T2` on `P`.`name` = {ledgerEntry.payerFspId} and `T2`.`name` = 'PAYEE_DFSP' + + + where `E`.`name` = {ledgerEntry.ledgerEntryTypeId} + + + and `P`.`name` in ({ledgerEntry.payerFspId}, {ledgerEntry.payeeFspId}) + + + and `PC`.`currencyId` = {ledgerEntry.currency}; + + + + + 22 + + + recordsToInsert + + + + + alt + + + [Has records to insert] + + + + + 23 + + + Insert transferParticipant records + + + + insert into + + + transferParticipant + + + + + 24 + + + Update positions + + + + + loop + + + [transferParticipant records] + + + + update + + + `participantPosition` + + + set `value` = `value` + {record.amount} + + + where `participantCurrencyId` = {record.participantCurrencyId}; + + + + + 25 + + + Get transferStateChange record + + + + select `transferStateChangeId` + + + from + + + `transferStateChange` + + + where `transferId` = {transferId} + + + and `transferStateId` = 'COMMITTED'; + + + + + 26 + + + transferStateChange record + + + + + 27 + + + Get participantPosition record + + + + select `participantPositionId`, `value`, `reservedValue` + + + from + + + `participantPosition` + + + where `participantCurrencyId` = {recordsToInsert[0].participantCurrencyId} + + + OR `participantCurrencyId` = {recordsToInsert[1].participantCurrencyId}; + + + + + 28 + + + participantPosition record + + + + + 29 + + + Insert participantPositionChange records + + + + insert into + + + `participantPositionChange` + + + select `participantPositionId`, {transferStateChangeId}, `value`, `reservedValue` + + + from `participantPosition` + + + where `participantCurrencyId` = {transferParticipantRecord1.participantCurrencyId} + + + or `participantCurrencyId` = {transferParticipantRecord2.participantCurrencyId}; + + + + [No records found] + + + + + 30 + + + Error + + + + + + 31 + + + Rollback on Error + + + + + + 32 + + + exit + + + + + + 33 + + + exit + + diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.1.plantuml b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.1.plantuml similarity index 98% rename from mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.1.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.1.plantuml index 59d493b43..54cafaa6c 100644 --- a/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.1.plantuml +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.1.plantuml @@ -167,6 +167,10 @@ activate OPERATOR SETTLE_DAO -> DB: Associate settlement windows with the settlement activate DB + SETTLE_DAO -> DB: Retrieve SettlementWindowContent id List + opt Settlement Model is Default + SETTLE_DAO -> SETTLE_DAO: filter out the SettlementWindowContent id List\n to exclude content that is not settled by default settlement model + end hnote over DB #lightyellow INSERT INTO **settlementSettlementWindow** (settlementId, settlementWindowId, createdDate) VALUES ({settlementId}, {payload.settlementWindows.idList}, {transactionTimestamp}) diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.1.svg b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.1.svg new file mode 100644 index 000000000..7a99625e7 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.1.svg @@ -0,0 +1,1060 @@ + + + + + + + + + + + 6.2.1. Trigger Settlement Event (createSettlement) + + + + Central HUB + + + + Settlement Service + + + + Central Services + + + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Settlement Service API + + + + + Settlement Service API + + + + + Settlement DAO + + + + + Settlement DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Trigger Settlement Event + + + + + { + + + "settlementModel": "string", + + + "reason": "string", + + + "settlementWindows": [ + + + { + + + "id": 1, + + + }, + + + { + + + "id": 2, + + + } + + + ] + + + } + + + + + 1 + + + POST - /settlements + + + + + 2 + + + Request settlementModel + + + Error code: + + + 2001 + + + + + 3 + + + Retrieve settlementModel + + + + SELECT sg.name settlementGranularity, si.name settlementInterchange, + + + sd.name settlementDelay, sm.ledgerAccountTypeId, + + + sm.currencyId, sm.requireLiquidityCheck + + + FROM + + + settlementModel + + + sm + + + JOIN + + + settlementGranularity + + + sg + + + ON sg.settlementGranularityId = sm.settlementGranularityId + + + JOIN + + + settlementInterchange + + + si + + + ON si.settlementInterchangeId = sm.settlementInterchangeId + + + JOIN + + + settlementDelay + + + sd + + + ON sd.settlementDelayId = sm.settlementDelayId + + + WHERE name = {settlementModelName} + + + AND isActive = 1 + + + + + 4 + + + Return data + + + + + 5 + + + Return + + + settlementModelData (smd) + + + + + break + + + [smd.settlementGranularity != 'NET' || + + + smd.settlementInterchange != 'MULTILATERAL' || + + + smd.settlementDelay != 'DEFERRED'] + + + + + Log ERROR event + + + + + { + + + errorInformation: { + + + "errorCode": <integer>, + + + "errorDescription": "Invalid settlement model" + + + } + + + } + + + + + 6 + + + Respond HTTP - 4xx (Client error) + + + + + 7 + + + Request settlementWindow(s) + + + Error code: + + + 2001 + + + + + 8 + + + Retrieve settlementWindow(s) + + + + SELECT DISTINCT sw.settlementWindowId, sw.currentStateChangeId, sw.createdDate + + + FROM + + + settlementWindow + + + sw + + + JOIN + + + settlementWindowStateChange + + + swsc + + + ON swsc.settlementWindowStateChangeId = sw.currentStateChangeId + + + JOIN + + + settlementWindowContent + + + swc + + + ON swc.settlementWindowId = sw.settlementWindowId + + + JOIN + + + settlementWindowContentStateChange + + + swcsc + + + ON swcsc.settlementWindowContentStateChangeId = sw.currentStateChangeId + + + WHERE sw.settlementWindowId IN {payload.settlementWindows.idList} + + + AND swc.ledgerAccountType = smd.ledgerAccountType + + + AND swc.currencyId = ISNULL(smd.currencyId, swc.currencyId) + + + AND swsc.settlementWindowStateId IN ('CLOSED', 'ABORTED', 'PENDING_SETTLEMENT') + + + AND swcsc.settlementWindowStateId IN ('CLOSED', 'ABORTED') + + + + + 9 + + + Return data + + + + + 10 + + + Return + + + windowsData + + + + + break + + + [payload.settlementWindows.length != windowsData.length] + + + + + Log ERROR event + + + + + { + + + errorInformation: { + + + "errorCode": <integer>, + + + "errorDescription": "Inapplicable windows found: ${windowId1}, ${windowId2}, ..." + + + } + + + } + + + + + 11 + + + Respond HTTP - 4xx (Client error) + + + + + All preliminary validations succeeded + + + + + Main processing + + + + + 12 + + + Create settlement + + + Error code: + + + 2001 + + + + + DB TRANSACTION + + + + + let + + + transactionTimestamp + + + = now() + + + + + 13 + + + Insert new settlement + + + + INSERT INTO + + + settlement + + + (reason, createdDate) + + + VALUES ({payload.reason}, {transactionTimestamp}) + + + + + 14 + + + Return + + + settlementId + + + + + 15 + + + Associate settlement windows with the settlement + + + + + 16 + + + Retrieve SettlementWindowContent id List + + + + + opt + + + [Settlement Model is Default] + + + + + 17 + + + filter out the SettlementWindowContent id List + + + to exclude content that is not settled by default settlement model + + + + INSERT INTO + + + settlementSettlementWindow + + + (settlementId, settlementWindowId, createdDate) + + + VALUES ({settlementId}, {payload.settlementWindows.idList}, {transactionTimestamp}) + + + + + 18 + + + Bind to settlement + + + + settlementWindowContent + + + .settlementId + + + settlementContentAggregation + + + .settlementId + + + .currentStateId + + + + + 19 + + + Change state to 'PENDING_SETTLEMENT' + + + + transferParticipantStateChange + + + transferParticipant + + + settlementWindowContentStateChange + + + settlementWindowContent + + + + + 20 + + + Aggregate settlement net amounts + + + + INSERT INTO + + + settlementParticipantCurrency + + + (settlementId, participantCurrencyId, netAmount, createdDate) + + + SELECT settlementId, participantCurrencyId, SUM(amount), {transactionTimestamp} + + + JOIN + + + settlementContentAggregation + + + WHERE settlementId = {settlementId} + + + GROUP BY settlementId, participantCurrencyId + + + + + 21 + + + Return inserted + + + settlementParticipantCurrencyIdList + + + + + 22 + + + Insert initial settlement accounts state 'PENDING_SETTLEMENT' + + + + INSERT INTO + + + settlementParticipantCurrencyStateChange + + + (settlementParticipantCurrencyId, settlementStateId, reason, createdDate) + + + VALUES ({settlementParticipantCurrencyIdList}, 'PENDING_SETTLEMENT', + + + {payload.reason}, {transactionTimestamp}) + + + + + 23 + + + Return inserted + + + settlementParticipantCurrencyStateChangeIdList + + + + + 24 + + + Merge settlementParticipantCurrencyStateChangeIdList + + + to settlementParticipantCurrencyIdList in order to + + + issue the following update in one knex command + + + + + 25 + + + Update pointers to current state change ids + + + + UPDATE + + + settlementParticipantCurrency + + + SET currentStateChangeId = {settlementParticipantCurrencyStateChangeIdList} + + + WHERE settlementParticipantCurrencyId = {settlementParticipantCurrencyIdList} + + + + + loop + + + [foreach w in windowsData] + + + + + opt + + + [if w.currentStateChangeId IN ('CLOSED', 'ABORTED')] + + + + + 26 + + + Insert new state for settlementWindow 'PENDING_SETTLEMENT' + + + + INSERT INTO + + + settlementWindowStateChange + + + (settlementWindowId, settlementWindowStateId, reason, createdDate) + + + VALUES ({w.settlementWindowId}, 'PENDING_SETTLEMENT', + + + {payload.reason}, {transactionTimestamp}) + + + + + 27 + + + Return inserted + + + settlementWindowStateChangeId + + + + + 28 + + + Update pointers to current state change ids + + + + UPDATE + + + settlementWindow + + + SET currentStateChangeId = {settlementWindowStateChangeId} + + + WHERE settlementWindowId = {w.settlementWindowId} + + + + + 29 + + + Insert initial state for settlement 'PENDING_SETTLEMENT' + + + + INSERT INTO + + + settlementStateChange + + + (settlementId, settlementStateId, reason, createdDate) + + + VALUES ({settlementId}, ‘PENDING_SETTLEMENT’, + + + {payload.reason}, {transactionTimestamp}) + + + + + 30 + + + Return + + + settlementStateChangeId + + + + + 31 + + + Update pointer to current state change id + + + + UPDATE + + + settlement + + + SET currentStateChangeId = {settlementStateChangeId} + + + WHERE settlementId = {settlementId} + + + + + 32 + + + Retrieve all content + + + + settlementWindowContent + + + settlementWindowContentStateChange + + + ledgerAccountType + + + currency + + + settlementWindow + + + settlementWindowStateChange + + + + + 33 + + + Return + + + settlementWindowContentReport + + + + + 34 + + + Use previous result to produce settlementWindowsData ( + + + swd + + + ) array + + + + + 35 + + + Select account data for response + + + + SELECT pc.participantId, spc.participantCurrencyId, spc.netAmount, pc.currencyId + + + FROM + + + settlementParticipantCurrency + + + spc + + + JOIN + + + participantCurrency + + + pc + + + ON pc.participantCurrencyId = spc.participantCurrencyId + + + WHERE spc.settlementId = {settlementId} + + + + + 36 + + + Return + + + accountData + + + + + 37 + + + Construct and return result + + + + + { + + + "id": settlementId, + + + "state": "PENDING_SETTLEMENT", + + + "settlementWindows": [ + + + { + + + "id": swd[m].id, + + + "state": swd[m].state, + + + "reason": swd[m].reason, + + + "createdDate": swd[m].createdDate, + + + "changedDate": swd[m].changedDate, + + + "content": [ + + + { + + + "id": swd[m].content[n].settlementWindowContentId, + + + "state": swd[m].content[n].settlementWindowStateId, + + + "ledgerAccountType": swd[m].content[n].ledgerAccountType, + + + "currencyId": swd[m].content[n].currencyId, + + + "createdDate": swd[m].content[n].createdDate, + + + "changedDate": swd[m].content[n].changedDate + + + } + + + ] + + + } + + + ], + + + "participants": [ + + + { + + + "id": accountData.participantId, + + + "accounts": [ + + + { + + + "id": accountData.participantCurrencyId, + + + "state": "PENDING_SETTLEMENT", + + + "reason": payload.reason, + + + "netSettlementAmount": { + + + "amount": accountData.netAmount, + + + "currency": accountData.currencyId + + + } + + + } + + + ] + + + } + + + ] + + + } + + + + + 38 + + + Respond HTTP - 201 (Created) + + diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.2.plantuml b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.2.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.2.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.2.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.2.svg b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.2.svg new file mode 100644 index 000000000..f47d21e98 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.2.svg @@ -0,0 +1,609 @@ + + + + + + + + + + + 6.2.2. Query Settlements by Parameters (getSettlementsByParams) + + + + Central HUB + + + + Settlement Service + + + + Central Services + + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Settlement Service API + + + + + Settlement Service API + + + + + Settlement DAO + + + + + Settlement DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Query Settlements by Parameters + + + + + Params: + + + ?[state={settlementStateId}] + + + [&fromDateTime={fromDateTime}] + + + [&toDateTime={toDateTime}] + + + [&currency={currencyId}] + + + [&settlementWindowId={settlementWindowId}] + + + [&fromSettlementWindowDateTime={fromSettlementWindowDateTime}] + + + [&toSettlementWindowDateTime={toSettlementWindowDateTime}] + + + [&participantId={participantId}] + + + [&accountId={participantCurrencyId}] + + + + + 1 + + + GET - /settlements + + + + + 2 + + + Retrieve settlements + + + Error code: + + + 2001 + + + + + 3 + + + Retrieve requested data + + + + SELECT + + + DISTINCT + + + s.settlementId, ssc.settlementStateId, + + + ssw.settlementWindowId, swsc.settlementWindowStateId, swsc.reason + + + settlementWindowReason, sw.createdDate, swsc.createdDate changedDate, + + + pc.participantId, spc.participantCurrencyId, spcsc.reason + + + accountReason, spcsc.settlementStateId accountState, spc.netAmount + + + accountAmount, pc.currencyId accountCurrency + + + FROM + + + settlement + + + s + + + JOIN + + + settlementStateChange + + + ssc + + + ON ssc.settlementStateChangeId = s.currentStateChangeId + + + JOIN + + + settlementSettlementWindow + + + ssw + + + ON ssw.settlementId = s.settlementId + + + JOIN + + + settlementWindow + + + sw + + + ON sw.settlementWindowId = ssw.settlementWindowId + + + JOIN + + + settlementWindowStateChange + + + swsc + + + ON swsc.settlementWindowStateChangeId = sw.currentStateChangeId + + + JOIN + + + settlementWindowContent + + + swc + + + ON swc.settlementWindowId = sw.settlementWindowId + + + JOIN + + + settlementWindowContentAggregation + + + swca + + + ON swca.settlementWindowContentId = swc.settlementWindowContentId + + + JOIN + + + settlementParticipantCurrency + + + spc + + + ON spc.settlementId = s.settlementId + + + AND spc.participantCurrencyId = swca.participantCurrencyId + + + JOIN + + + settlementParticipantCurrencyStateChange + + + spcsc + + + ON spcsc.settlementParticipantCurrencyStateChangeId = spc.currentStateChangeId + + + JOIN + + + participantCurrency + + + pc + + + ON pc.participantCurrencyId = spc.participantCurrencyId + + + WHERE [ssc.settlementStateId = {settlementStateId}] + + + [AND s.createdDate >= {fromDateTime}] + + + [AND s.createdDate <= {toDateTime}] + + + [AND pc.currencyId = {currencyId}] + + + [AND sw.settlementWindowId = + + + {settlementWindowId} + + + ] + + + [AND sw.createdDate >= {fromSettlementWindowDateTime}] + + + [AND sw.createdDate <= {toSettlementWindowDateTime}] + + + [AND pc.participantId = {participantId}] + + + [AND spc.participantCurrencyId = {participantCurrencyId}] + + + + + 4 + + + Return data + + + + + 5 + + + Return + + + settlementsData + + + + + alt + + + [Settlement(s) found] + + + + + let settlements = {} + + + let settlement + + + let participant + + + + + loop + + + [settlementsData] + + + + + if (!settlements[settlementsData.settlementId]) { + + + settlements[settlementsData.settlementId] = { + + + "id: settlementsData.settlementId, + + + "state": settlementsData.settlementStateId + + + } + + + } + + + settlement = settlements[settlementsData.settlementId] + + + if (!settlement.settlementWindows[settlementsData.settlementWindowId]) { + + + settlement.settlementWindows[settlementsData.settlementWindowId] = { + + + "id": settlementsData.settlementWindowId, + + + "state": settlementsData.settlementWindowStateId, + + + "reason": settlementsData.settlementWindowReason, + + + "createdDate": settlementsData.createdDate, + + + "changedDate": settlementsData.changedDate + + + } + + + } + + + if (!settlement.participants[settlementsData.participantId]) { + + + settlement.participants[settlementsData.participantId] = { + + + "id": settlementsData.participantId + + + } + + + } + + + participant = settlement.participants[settlementsData.participantId] + + + participant.accounts[settlementsData.accountId] = { + + + "id": settlementsData.participantCurrencyId, + + + "state": settlementsData.accountState, + + + "reason": settlementsData.accountReason, + + + "netSettlementAmount": { + + + "amount": settlementsData.accountAmount, + + + "currency": settlementsData.accountCurrency + + + } + + + } + + + + + 6 + + + Transform + + + settlements + + + map to array + + + + + [ + + + { + + + "id": settlementId, + + + "state": settlementStateId, + + + "settlementWindows": [ + + + { + + + "id": settlementWindowId, + + + "state": settlementWindowStateId, + + + "reason": settlementWindowReason, + + + "createdDate": createdDate, + + + "changedDate": changedDate + + + } + + + ], + + + "participants": [ + + + { + + + "id": participantId, + + + "accounts": [ + + + { + + + "id": participantCurrencyId, + + + "state": accountState, + + + "reason": accountReason, + + + "netSettlementAmount": { + + + "amount": accountAmount, + + + "currency": accountCurrency + + + } + + + } + + + ] + + + } + + + ] + + + } + + + ] + + + + + 7 + + + Respond HTTP - 200 (OK) + + + + + + Log ERROR event + + + + + { + + + errorInformation: { + + + "errorCode": <integer>, + + + "errorDescription": "Client error description" + + + } + + + } + + + + + 8 + + + Respond HTTP - 4xx (Client error) + + diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.3.plantuml b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.3.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.3.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.3.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.3.svg b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.3.svg new file mode 100644 index 000000000..47915f13b --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.3.svg @@ -0,0 +1,916 @@ + + + + + + + + + + + 6.2.3. Get Settlement By Settlement, Participant and Account (getSettlementBySPA) + + + + Central HUB + + + + Settlement Service + + + + Central Services + + + + + + + + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Settlement Service API + + + + + Settlement Service API + + + + + Settlement DAO + + + + + Settlement DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Get Settlement By Settlement, Participant and Account + + + + + alt + + + + + 1 + + + GET - /settlements/{settlementId}/ + + + participants/{participantId} + + + + + + 2 + + + GET - /settlements/{settlementId}/ + + + participants/{participantId}/ + + + accounts/{accountId} + + + + + let settlementFound = false + + + let participantFoundInSettlement = false + + + let accountProvided = accountId > 0 + + + let participantAndAccountMatched = !accountProvided + + + let accountFoundInSettlement = !accountProvided + + + + + 3 + + + Request settlement state + + + Error code: + + + 2001 + + + + + 4 + + + Retrieve settlement + + + + SELECT s.settlementId, ssc.settlementStateId, s.reason, s.createdDate + + + FROM + + + settlement + + + s + + + JOIN + + + settlementStateChange + + + ssc + + + ON ssc.settlementStateChangeId = s.currentStateChangeId + + + WHERE s.settlementId = {id} + + + + + 5 + + + Return + + + settlement + + + + + if (settlement.settlementId) { + + + settlementFound + + + = true + + + } + + + + + opt + + + [settlementFound] + + + + + 6 + + + Check participant + + + Error code: + + + 2001 + + + + + 7 + + + Check exists + + + + SELECT settlementParticipantCurrencyId + + + FROM + + + settlementParticipantCurrency + + + spc + + + JOIN + + + participantCurrency + + + pc + + + ON pc.participantCurrencyId = spc.participantCurrencyId + + + WHERE spc.settlementId = {id} + + + AND pc.participantId = {participantId} + + + + + 8 + + + Return + + + settlementParticipantCurrencyIdList + + + + + if (settlementParticipantCurrencyIdList.length > 0) { + + + participantFoundInSettlement + + + = true + + + } + + + + + opt + + + [participantFoundInSettlement && accountProvided] + + + + + 9 + + + Check participant + + + Error code: + + + 2001 + + + + + 10 + + + Check exists + + + + SELECT participantCurrencyId + + + JOIN + + + participantCurrency + + + WHERE participantCurrencyId = {accountId} + + + AND participantId = {participantId} + + + + + 11 + + + Return + + + account + + + + + if (account) { + + + participantAndAccountMatched + + + = true + + + } + + + + + opt + + + [participantAndAccountMatched] + + + + + 12 + + + Check account in settlement + + + Error code: + + + 2001 + + + + + 13 + + + Check exists + + + + SELECT settlementParticipantCurrencyId + + + FROM + + + settlementParticipantCurrency + + + WHERE spc.settlementId = {id} + + + AND pc.participantCurrencyId = {accountId} + + + + + 14 + + + Return + + + settlementParticipantCurrencyId + + + + + if (settlementParticipantCurrencyId) { + + + accountFoundInSettlement + + + = true + + + } + + + + + alt + + + [settlementFound && participantFoundInSettlement && participantAndAccountMatched && accountFoundInSettlement] + + + + + 15 + + + Request settlement windows + + + Error code: + + + 2001 + + + + + 16 + + + Retrieve windows + + + + + alt + + + [accountProvided] + + + + SELECT + + + DISTINCT + + + sw.settlementWindowId, swsc.settlementWindowStateId, + + + swsc.reason, sw.createdDate, swsc.createdDate changedDate + + + FROM + + + settlementSettlementWindow + + + ssw + + + JOIN + + + settlementWindow + + + sw + + + ON sw.settlementWindowId = ssw.settlementWindowId + + + JOIN + + + settlementWindowStateChange + + + swsc + + + ON swsc.settlementWindowStateChangeId = sw.currentStateChangeId + + + JOIN + + + settlementWindowContent + + + swc + + + ON swc.settlementWindowId = sw.settlementWindowId + + + JOIN + + + settlementWindowContentAggregation + + + swca + + + ON swca.settlementWindowContentId = swc.settlementWindowContentId + + + AND swca.participantCurrencyId = + + + {accountId} + + + WHERE ssw.settlementId = {id} + + + + + SELECT DISTINCT sw.settlementWindowId, swsc.settlementWindowStateId, + + + swsc.reason, sw.createdDate, swsc.createdDate changedDate + + + FROM + + + settlementSettlementWindow + + + ssw + + + JOIN + + + settlementWindow + + + sw + + + ON sw.settlementWindowId = ssw.settlementWindowId + + + JOIN + + + settlementWindowStateChange + + + swsc + + + ON swsc.settlementWindowStateChangeId = sw.currentStateChangeId + + + JOIN + + + settlementWindowContent + + + swc + + + ON swc.settlementWindowId = sw.settlementWindowId + + + JOIN + + + settlementWindowContentAggregation + + + swca + + + ON swca.settlementWindowContentId = swc.settlementWindowContentId + + + AND swca.participantCurrencyId IN( + + + SELECT participantCurrencyId + + + FROM participantCurrency + + + WHERE participantId = + + + {participantId} + + + ) + + + WHERE ssw.settlementId = {id} + + + + + 17 + + + Return + + + windows + + + + + 18 + + + Request settlement accounts + + + Error code: + + + 2001 + + + + + 19 + + + Retrieve accounts + + + + + alt + + + [accountProvided] + + + + SELECT pc.participantId, spc.participantCurrencyId, spcsc.settlementStateId, + + + spcsc.reason, spc.netAmount, pc.currencyId + + + FROM + + + settlementParticipantCurrency + + + spc + + + JOIN + + + settlementParticipantCurrencyStateChange + + + spcsc + + + ON spcsc.settlementParticipantCurrencyStateChangeId = spc.currentStateChangeId + + + JOIN + + + participantCurrency + + + pc + + + ON pc.participantCurrencyId = spc.participantCurrencyId + + + WHERE spc.settlementParticipantCurrencyId = {settlementParticipantCurrencyId} + + + + + SELECT pc.participantId, spc.participantCurrencyId, spcsc.settlementStateId, + + + spcsc.reason, spc.netAmount, pc.currencyId + + + FROM + + + settlementParticipantCurrency + + + spc + + + JOIN + + + settlementParticipantCurrencyStateChange + + + spcsc + + + ON spcsc.settlementParticipantCurrencyStateChangeId = spc.currentStateChangeId + + + JOIN + + + participantCurrency + + + pc + + + ON pc.participantCurrencyId = spc.participantCurrencyId + + + WHERE spc.settlementParticipantCurrencyId IN {settlementParticipantCurrencyIdList} + + + + + 20 + + + Return + + + accounts + + + + + { + + + "id": settlement.settlementId, + + + "state": settlement.settlementStateId, + + + "settlementWindows": [ + + + [ + + + { + + + "id": window.settlementWindowId, + + + "reason": window.reason, + + + "state": window.settlementWindowStateId, + + + "createdDate": window.createdDate, + + + "changedDate": window.changedDate + + + } + + + ] + + + ], + + + "participants": [ + + + { + + + "id": account.participantId, + + + "accounts": [ + + + { + + + "id": account.participantCurrencyId, + + + "reason": account.reason, + + + "state": account.settlementStateId, + + + "netSettlementAmount": { + + + "amount": account.netAmount, + + + "currency": account.currencyId + + + } + + + } + + + ] + + + } + + + ] + + + } + + + + + 21 + + + Respond HTTP - 200 (OK) + + + + [!settlementFound || !participantFoundInSettlement || !participantAndAccountMatched || !accountFoundInSettlement] + + + + + Log ERROR event (based on the failure) + + + + + { + + + errorInformation: { + + + "errorCode": <integer>, + + + "errorDescription": "Client error description" + + + } + + + } + + + + + 22 + + + Respond HTTP - 4xx (Client error) + + diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.4.plantuml b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.4.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.4.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.4.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.4.svg b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.4.svg new file mode 100644 index 000000000..460c5a1ac --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.4.svg @@ -0,0 +1,442 @@ + + + + + + + + + + + 6.2.4. Get Settlement By Id (getSettlementById) + + + + Central HUB + + + + Settlement Service + + + + Central Services + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Settlement Service API + + + + + Settlement Service API + + + + + Settlement DAO + + + + + Settlement DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Get Settlement By Id + + + + + 1 + + + GET - /settlements/{id} + + + + + 2 + + + Request settlement state + + + Error code: + + + 2001 + + + + + 3 + + + Retrieve settlement + + + + SELECT s.settlementId, ssc.settlementStateId, s.reason, s.createdDate + + + FROM + + + settlement + + + s + + + JOIN + + + settlementStateChange + + + ssc + + + ON ssc.settlementStateChangeId = s.currentStateChangeId + + + WHERE s.settlementId = {id} + + + + + 4 + + + Return + + + settlement + + + + + alt + + + [settlement found] + + + + + 5 + + + Request settlement windows + + + Error code: + + + 2001 + + + + + 6 + + + Retrieve windows + + + + SELECT sw.settlementWindowId, swsc.settlementWindowStateId, + + + swsc.reason, sw.createdDate, swsc.createdDate changedDate + + + FROM + + + settlementSettlementWindow + + + ssw + + + JOIN + + + settlementWindow + + + sw + + + ON sw.settlementWindowId = ssw.settlementWindowId + + + JOIN + + + settlementWindowStateChange + + + swsc + + + ON swsc.settlementWindowStateChangeId = sw.currentStateChangeId + + + WHERE ssw.settlementId = {id} + + + + + 7 + + + Return + + + windows + + + + + 8 + + + Request settlement accounts + + + Error code: + + + 2001 + + + + + 9 + + + Retrieve accounts + + + + SELECT pc.participantId, spc.participantCurrencyId, spcsc.settlementStateId, + + + spcsc.reason, spc.netAmount, pc.currencyId + + + FROM + + + settlementParticipantCurrency + + + spc + + + JOIN + + + settlementParticipantCurrencyStateChange + + + spcsc + + + ON spcsc.settlementParticipantCurrencyStateChangeId = spc.currentStateChangeId + + + JOIN + + + participantCurrency + + + pc + + + ON pc.participantCurrencyId = spc.participantCurrencyId + + + WHERE spc.settlementId = {id} + + + + + 10 + + + Return + + + accounts + + + + + { + + + "id": settlement.settlementId, + + + "state": settlement.settlementStateId, + + + "settlementWindows": [ + + + [ + + + { + + + "id": window.settlementWindowId, + + + "reason": window.reason, + + + "state": window.settlementWindowStateId, + + + "createdDate": window.createdDate, + + + "changedDate": window.changedDate + + + } + + + ] + + + ], + + + "participants": [ + + + { + + + "id": account.participantId, + + + "accounts": [ + + + { + + + "id": account.participantCurrencyId, + + + "reason": account.reason, + + + "state": account.settlementStateId, + + + "netSettlementAmount": { + + + "amount": account.netAmount, + + + "currency": account.currencyId + + + } + + + } + + + ] + + + } + + + ] + + + } + + + + + 11 + + + Respond HTTP - 200 (OK) + + + + + + Log ERROR event + + + + + { + + + errorInformation: { + + + "errorCode": <integer>, + + + "errorDescription": "Client error description" + + + } + + + } + + + + + 12 + + + Respond HTTP - 4xx (Client error) + + diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.5.plantuml b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.5.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.5.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.5.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.5.svg b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.5.svg new file mode 100644 index 000000000..73611b591 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.5.svg @@ -0,0 +1,1754 @@ + + + + + + + + + + + 6.2.5. Acknowledgement of Settlement Transfer (updateSettlementById) + + + + Central HUB + + + + Settlement Service + + + + Central Services + + + + + + + + + + + + + + + + + + + + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Settlement Service API + + + + + Settlement Service API + + + + + Settlement DAO + + + + + Settlement DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Acknowledgement of Settlement Transfer + + + + + { + + + "participants": [ + + + { + + + "id": 1 + + + "accounts" : [ + + + { "id": 1, "state": "PENDING_SETTLEMENT", "reason": <string> }, + + + { "id": 2, "state": "PS_TRANSFERS_RECORDED", "reason": <string>, "externalReference": <string> }, + + + { "id": 3, "state": "PS_TRANSFERS_RESERVED", "reason": <string> }, + + + { "id": 4, "state": "PS_TRANSFERS_COMMITTED", "reason": <string>, "externalReference": <string> }, + + + { "id": 5, "state": "SETTLED", "reason": <string> } + + + ] + + + }, + + + { + + + "id": 2 + + + "accounts" : [ + + + { "id": 6, "state": "SETTLED", "reason": <string> } + + + ] + + + } + + + ] + + + } + + + + + 1 + + + PUT - /settlement/{id} + + + + + 2 + + + updateSettlementById routine + + + Error code: + + + 2001 + + + + + DB TRANSACTION + + + + + 3 + + + Retrieve settlement information + + + + SELECT s.settlementId, ssc.settlementStateId, + + + ssc.reason, ssc.createdDate, sm.autoPositionReset + + + FROM + + + settlement + + + s + + + JOIN + + + settlementStateChange + + + ssc + + + ON ssc.settlementStateChangeId = s.currentStateChangeId + + + JOIN + + + settlementModel + + + sm + + + ON sm.settlementModelId = s.settlementModelId + + + WHERE s.settlementId = {id} + + + FOR UPDATE + + + + + 4 + + + Return + + + settlementData + + + + + 5 + + + Retrive settlement accounts information + + + + SELECT pc.participantId, spc.participantCurrencyId, + + + spcsc.settlementStateId, spcsc.reason, + + + spcsc.createdDate, spc.netAmount, pc.currencyId, + + + spc.settlementParticipantCurrencyId AS + + + key + + + FROM + + + settlementParticipantCurrency + + + spc + + + JOIN + + + settlementParticipantCurrencyStateChange + + + spcsc + + + ON spcsc.settlementParticipantCurrencyStateChangeId = + + + spc.currentStateChangeId + + + JOIN + + + participantCurrency + + + pc + + + ON pc.participantCurrencyId = spc.participantCurrencyId + + + WHERE spc.settlementId = {id} + + + FOR UPDATE + + + + + 6 + + + Return + + + settlementAccountsList + + + + + All objects below are for the purpose of the syncronous request. + + + If at some point, Node process memory limit is reached, we may decide to: + + + A. Limit the amount of transfers per window and windows per settlement or + + + B. Move to asyncronous processing where we don't need these objects + + + + + Available raw datasets from DB: + + + settlementData + + + contains information about settlement and its current state/reason + + + settlementAccountsList + + + holds information about all accounts and their current state/reason + + + Local variables and objects: + + + settlementAccounts + + + : { // (derived from + + + settlementAccountsList + + + ) + + + pendingSettlementCount: <integer>, // count of accounts in PENDING_SETTLEMENT state + + + psTransfersRecordedCount: <integer>, // count of accounts in PS_TRANSFERS_RECORDED state + + + psTransfersReservedCount: <integer>, // count of accounts in PS_TRANSFERS_RESERVED state + + + psTransfersCommittedCount: <integer>, // count of accounts in PS_TRANSFERS_COMMITTED state + + + settledCount: <integer>, // count of accounts in SETTLED state + + + abortedCount: <integer> // count of accounts in ABORTED state + + + unknownCount: <integer>, + + + settledIdList: <array>, + + + changedIdList: <array> + + + } + + + settlementAccountsInit + + + copy of previous object to be preserved for comparission at the end + + + allAccounts + + + : { // same as previous but accessed by account id (derived from + + + settlementAccountsList + + + ) + + + participantCurrencyId_key: { // number used to access the object in map-like style + + + id: participantCurrencyId, + + + state: settlementStateId, + + + reason: reason, + + + createdDate: createdDate, + + + netSettlementAmount: { + + + amount: netAmount, + + + currency: currencyId + + + }, + + + participantId: participantId, // could be used to reconstruct allParticipants + + + key: + + + key + + + // will be used to insert new state for settlementParticipantCurrency + + + } + + + } + + + let + + + transactionTimestamp + + + = now() + + + + + 7 + + + Declare and initialize variables + + + + + let settlementAccounts = { + + + pendingSettlementCount: 0, + + + psTransfersRecordedCount: 0, + + + psTransfersReservedCount: 0, + + + psTransfersCommittedCount: 0, + + + settledCount: 0, + + + abortedCount: 0, + + + unknownCount: 0 + + + } + + + let allAccounts = {} // declare map + + + let pid // participantId + + + let aid // accountId (participantCurrencyId) + + + let state + + + + + loop + + + [settlementAccountsList as account] + + + + + 8 + + + Populate + + + allAccounts + + + + + pid = account.participantId + + + aid = account.participantCurrencyId + + + state = account.settlementStateId + + + allAccounts[aid] = { + + + id: aid, + + + state, + + + reason: account.reason, + + + createDate: account.createdDate, + + + netSettlementAmount: { + + + amount: account.netAmount, + + + currency: account.currencyId + + + }, + + + participantId: pid, + + + key: account.key + + + } + + + + + 9 + + + Populate + + + settlementAccounts + + + + + alt + + + [state == 'PENDING_SETTLEMENT'] + + + + + settlementAccounts.pendingSettlementCount++ + + + + [state == 'PS_TRANSFERS_RECORDED'] + + + + + settlementAccounts.psTransfersRecordedCount++ + + + + [state == 'PS_TRANSFERS_RESERVED'] + + + + + settlementAccounts.psTransfersReservedCount++ + + + + [state == 'PS_TRANSFERS_COMMITTED'] + + + + + settlementAccounts.psTransfersCommittedCount++ + + + + [state == 'SETTLED'] + + + + + settlementAccounts.settledCount++ + + + + [state == 'ABORTED'] + + + + + settlementAccounts.abortedCount++ + + + + [default] + + + + + settlementAccounts.unknownCount++ + + + + + 10 + + + Make a copy of settlementAccounts into + + + settlementAccountsInit + + + + + settlementAccountsInit = Object.assign({}, settlementAccounts) + + + + + Available objects after the setup: + + + settlementAccounts + + + is used for tracing settlement state and state transition allowance + + + allAccounts + + + is helper object, same as previous, providing direct access to account by id + + + Now we are ready to process the + + + payload + + + : + + + participants + + + = [] // part of the response object that lists the affected participants and respective accounts + + + settlementParticipantCurrencyStateChange + + + = [] // array to collect inserts to the table + + + settlementParticipantCurrencySettledList + + + = [] // array to collect settled accounts + + + processedAccounts + + + = [] // array to log processed accounts and restrict subsequent processing + + + + + loop + + + [let participant IN payload.participants] + + + + + 11 + + + Loop payload for each + + + participantPayload + + + + + let participantPayload = payload.participants[participant] + + + participants.push({id: participantPayload.id, accounts: []}) + + + let pi = participants.length - 1 + + + participant = participants[pi] + + + + + loop + + + [let account IN participantPayload.accounts] + + + + + 12 + + + Loop payload for each + + + accountPayload + + + + + let accountPayload = participantPayload.accounts[account] + + + + + alt + + + [allAccounts[accountPayload.id] == undefined] + + + + + 13 + + + If the account doesn't match the settlement + + + + + participant.accounts.push({ + + + id: accountPayload.id, + + + errorInformation: { + + + errorCode: 3000, + + + errorDescription: 'Account not found' + + + } + + + }) + + + + [participantPayload.id != allAccounts[accountPayload.id].participantId] + + + + + 14 + + + If the account doesn't match the participant + + + + + participant.accounts.push({ + + + id: accountPayload.id, + + + errorInformation: { + + + errorCode: 3000, + + + errorDescription: 'Participant and account mismatch' + + + } + + + }) + + + + [processedAccounts.indexOf(accountPayload.id) > -1] + + + + + 15 + + + If the account has been previosly processed (duplicated in the payload) + + + + + participant.accounts.push({ + + + id: accountPayload.id, + + + state: allAccounts[accountPayload.id].state, + + + reason: allAccounts[accountPayload.id].reason, + + + createdDate: allAccounts[accountPayload.id].createdDate, + + + netSettlementAmount: allAccounts[accountPayload.id].netSettlementAmount + + + errorInformation: { + + + errorCode: 3000, + + + errorDescription: 'Account already processed once' + + + } + + + }) + + + + [allAccounts[account.id].state == accountPayload.state // allowed] + + + + + 16 + + + Same-state reason amendment is always allowed + + + + + processedAccounts.push(accountPayload.id) + + + participant.accounts.push({ + + + id: accountPayload.id, + + + state: accountPayload.state, + + + reason: accountPayload.reason, + + + externalReference: accountPayload.externalReference, + + + createdDate: transactionTimestamp, + + + netSettlementAmount: allAccounts[accountPayload.id].netSettlementAmount + + + }) + + + settlementParticipantCurrencyStateChange.push({ + + + settlementParticipantCurrencyId: allAccounts[accountPayload.id].key, + + + settlementStateId: accountPayload.state, + + + reason: accountPayload.reason, + + + externalReference: accountPayload.externalReference + + + }) + + + allAccounts[accountPayload.id].reason = accountPayload.reason + + + allAccounts[accountPayload.id].createdDate = currentTimestamp + + + + [settlementData.state == 'PENDING_SETTLEMENT' && accountPayload.state == 'PS_TRANSFERS_RECORDED'] + + + + [settlementData.state == 'PS_TRANSFERS_RECORDED' && accountPayload.state == 'PS_TRANSFERS_RESERVED'] + + + + [settlementData.state == 'PS_TRANSFERS_RESERVED' && accountPayload.state == 'PS_TRANSFERS_COMMITTED'] + + + + [settlementData.state == 'PS_TRANSFERS_COMMITTED' || settlementData.state == 'SETTLING' && accountPayload.state == 'SETTLED'] + + + + + Note + + + : Since we previously checked same-state, here we don't need to match + + + allAccounts[account.id].state == settlementData.state. + + + + + 17 + + + Settlement acknowledgement + + + + + processedAccounts.push(accountPayload.id) + + + participant.accounts.push({ + + + id: accountPayload.id, + + + state: accountPayload.state, + + + reason: accountPayload.reason, + + + externalReference: accountPayload.externalReference, + + + createdDate: transactionTimestamp, + + + netSettlementAmount: allAccounts[accountPayload.id].netSettlementAmount + + + }) + + + settlementParticipantCurrencyStateChange.push({ + + + settlementParticipantCurrencyId: allAccounts[accountPayload.id].key, + + + settlementStateId: accountPayload.state, + + + reason: accountPayload.reason, + + + externalReference: accountPayload.externalReference, + + + settlementTransferId: Uuid() -- only for PS_TRANSFERS_RECORDED + + + }) + + + if (accountPayload.state == 'PS_TRANSFERS_RECORDED') { + + + settlementAccounts.pendingSettlementCount-- + + + settlementAccounts.psTransfersRecordedCount++ + + + } else if (accountPayload.state == 'PS_TRANSFERS_RESERVED') { + + + settlementAccounts.psTransfersRecordedCount-- + + + settlementAccounts.psTransfersReservedCount++ + + + } else if (accountPayload.state == 'PS_TRANSFERS_COMMITTED') { + + + settlementAccounts.psTransfersReservedCount-- + + + settlementAccounts.psTransfersCommittedCount++ + + + } else if (accountPayload.state == 'SETTLED') { + + + settlementParticipantCurrencySettledIdList.push(allAccounts[accountPayload.id].key) + + + settlementAccounts.psTransfersCommittedCount-- + + + settlementAccounts.settledCount++ + + + settlementAccounts.settledIdList.push(accountPayload.id) + + + } + + + settlementAccounts.changedIdList.push(accountPayload.id) + + + allAccounts[accountPayload.id].state = accountPayload.state + + + allAccounts[accountPayload.id].reason = accountPayload.reason + + + allAccounts[accountPayload.id].externalReference = accountPayload.externalReference + + + allAccounts[accountPayload.id].createdDate = currentTimestamp + + + + + + 18 + + + All other state transitions are not permitted + + + + + participant.accounts.push({ + + + id: accountPayload.id, + + + state: allAccounts[accountPayload.id].state, + + + reason: allAccounts[accountPayload.id].reason, + + + createdDate: allAccounts[accountPayload.id].createdDate, + + + netSettlementAmount: allAccounts[accountPayload.id].netSettlementAmount + + + errorInformation: { + + + errorCode: <integer>, + + + errorDescription: 'State change not allowed' + + + } + + + }) + + + + + Bulk insert settlementParticipantCurrencyStateChange + + + + + 19 + + + Insert settlementParticipantCurrencyStateChange + + + + settlementParticipantCurrencyStateChange + + + + + 20 + + + Return + + + settlementParticipantCurrencyStateChangeIdList + + + + + 21 + + + Merge settlementParticipantCurrencyStateChangeIdList + + + to + + + settlementParticipantCurrencyIdList + + + in order to + + + issue the following update in one knex command + + + + + 22 + + + Update pointers to current state change ids + + + + UPDATE + + + settlementParticipantCurrency + + + SET currentStateChangeId = + + + {settlementParticipantCurrencyStateChangeIdList}, + + + settlementTransferId = + + + settlementParticipantCurrencyStateChange.settlementTransferId + + + -- only for PENDING_SETTLEMENT to PS_TRANSFERS_RECORDED + + + WHERE settlementParticipantCurrencyId = + + + {settlementParticipantCurrencyStateChange + + + .settlementParticipantCurrencyIdList} + + + + + opt + + + [autoPositionReset == true] + + + + + alt + + + [settlementData.state == 'PENDING_SETTLEMENT'] + + + + + ref + + + Settlement Transfer Prepare + + + Inputs + + + : settlementId, transactionTimestamp, enums, trx + + + + [settlementData.state == 'PS_TRANSFERS_RECORDED'] + + + + + ref + + + Settlement Transfer Reserve + + + Inputs + + + : settlementId, transactionTimestamp, enums, trx + + + + [settlementData.state == 'PS_TRANSFERS_RESERVED'] + + + + + ref + + + Settlement Transfer Commit + + + Inputs + + + : settlementId, transactionTimestamp, enums, trx + + + + + Update aggregations, contents & windows + + + + + opt + + + [settlementParticipantCurrencySettledIdList.length > 0] + + + + + 23 + + + Change settlementWindowState where applicable + + + + settlementContentAggregation + + + transferParticipantStateChange + + + transferParticipant + + + settlementWindowContentStateChange + + + settlementWindowContent + + + settlementWindowStateChange + + + settlementWindow + + + + + 24 + + + Retrieve all affected content (incl. when settled) + + + + settlementContentAggregation + + + settlementWindowContent + + + settlementWindowContentStateChange + + + ledgerAccountType + + + settlementWindow + + + settlementWindowStateChange + + + + + 25 + + + Return + + + affectedWindowsReport + + + + + 26 + + + Use previous result to produce settlementWindowsData ( + + + swd + + + ) array + + + + + Prepare and insert settlementStateChange + + + + + let settlementStateChanged = true + + + + + alt + + + [settlementData.state == 'PENDING_SETTLEMENT' + + + && settlementAccounts.pendingSettlementCount == 0] + + + + + settlementData.state = 'PS_TRANSFERS_RECORDED' + + + settlementData.reason = 'All settlement accounts are PS_TRANSFERS_RECORDED' + + + + [settlementData.state == 'PS_TRANSFERS_RECORDED' + + + && settlementAccounts.psTransfersRecordedCount == 0] + + + + + settlementData.state = 'PS_TRANSFERS_RESERVED' + + + settlementData.reason = 'All settlement accounts are PS_TRANSFERS_RESERVED' + + + + [settlementData.state == 'PS_TRANSFERS_RESERVED' + + + && settlementAccounts.psTransfersReservedCount == 0] + + + + + settlementData.state = 'PS_TRANSFERS_COMMITTED' + + + settlementData.reason = 'All settlement accounts are PS_TRANSFERS_COMMITTED' + + + + [settlementData.state == 'PS_TRANSFERS_COMMITTED' + + + && settlementAccounts.psTransfersCommittedCount > 0 + + + && settlementAccounts.settledCount > 0] + + + + + settlementData.state = 'SETTLING' + + + settlementData.reason = 'Some settlement accounts are SETTLED' + + + + [(settlementData.state == 'PS_TRANSFERS_COMMITTED' || settlementData.state == 'SETTLING') + + + && settlementAccounts.psTransfersCommittedCount == 0] + + + + + settlementData.state = 'SETTLED' + + + settlementData.reason = 'All settlement accounts are SETTLED' + + + + + + settlementStateChanged = false + + + + + opt + + + [settlementStateChanged == true] + + + + + settlementData.createdDate = currentTimestamp + + + settlementStateChange.push(settlementData) + + + + + 27 + + + Insert settlementStateChange + + + + settlementStateChange + + + + + 28 + + + Return + + + settlementStateChangeId + + + + + 29 + + + Update pointer to current state change id + + + + UPDATE + + + settlement + + + .currentStateChangeId + + + + + 30 + + + Return transaction result + + + + + { + + + "id": {id}, + + + "state": settlementData.state, + + + "createdDate": settlementData.createdDate, + + + "settlementWindows": [ + + + { + + + "id": swd[m].id, + + + "state": swd[m].state, + + + "reason": swd[m].reason, + + + "createdDate": swd[m].createdDate, + + + "changedDate": swd[m].changedDate, + + + "content": [ + + + { + + + "id": swd[m].content[n].settlementWindowContentId, + + + "state": swd[m].content[n].settlementWindowStateId, + + + "ledgerAccountType": swd[m].content[n].ledgerAccountType, + + + "currencyId": swd[m].content[n].currencyId, + + + "createdDate": swd[m].content[n].createdDate, + + + "changedDate": swd[m].content[n].changedDate + + + } + + + ] + + + } + + + ], + + + "participants": [ + + + { + + + "id": <integer>, + + + "accounts": [ + + + { + + + "id": <integer>, + + + "state": "<string>, + + + "reason": <string>, + + + "externalReference": <string>, + + + "createdDate": <date>, + + + "netSettlementAmount": { + + + "amount": <decimal>, + + + "currency": <enum> + + + } + + + }, + + + { + + + "id": <integer>, + + + "state": <string>, + + + "reason": <string>, + + + "createdDate": <date>, + + + "netSettlementAmount": { + + + "amount": <decimal>, + + + "currency": <enum> + + + }, + + + "errorInformation": { + + + "errorCode": <integer>, + + + "errorDescription": <string> + + + } + + + } + + + ] + + + } + + + ] + + + } + + + + + 31 + + + Return response + + diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.6.plantuml b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.6.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.6.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.6.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.6.svg b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.6.svg new file mode 100644 index 000000000..38256e7a0 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.6.svg @@ -0,0 +1,801 @@ + + + + + + + + + + + 6.2.6. Settlement Abort (abortSettlementById) + + + + Central HUB + + + + Settlement Service + + + + Central Services + + + + + + + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Settlement Service API + + + + + Settlement Service API + + + + + Settlement DAO + + + + + Settlement DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Settlement Abort + + + + + { + + + "state": "ABORTED", + + + "reason": {abortReasonString} + + + } + + + + + 1 + + + PUT - /settlement/{id} + + + + + 2 + + + abortSettlementById facade method + + + Error code: + + + 2001 + + + + + 3 + + + Retrieve settlement information + + + + SELECT s.settlementId, ssc.settlementStateId, + + + ssc.reason, ssc.createdDate + + + FROM + + + settlement + + + s + + + JOIN + + + settlementStateChange + + + ssc + + + ON ssc.settlementStateChangeId = s.currentStateChangeId + + + WHERE s.settlementId = {id} + + + + + 4 + + + Return + + + settlementData + + + + + alt + + + [settlementData.settlementStateId == 'PS_TRANSFERS_COMMITTED'|| + + + settlementData.settlementStateId == 'SETTLING'|| + + + settlementData.settlementStateId == 'SETTLED'] + + + + + break + + + + + { + + + errorInformation: { + + + "errorCode": <integer>, + + + "errorDescription": "State change is not allowed" + + + } + + + } + + + + [settlementData.settlementStateId == 'ABORTED'] + + + + + break + + + + + 5 + + + Append additional info at settlement level + + + + INSERT INTO + + + settlementStateChange + + + (settlementId, settlementStateId, reason) + + + VALUES ({id}, 'ABORTED', {abortReasonString}) + + + + + { + + + "id": {id}, + + + "state": 'ABORTED', + + + "reason": {abortReasonString} + + + } + + + + [settlementData.settlementStateId == 'PS_TRANSFERS_RESERVED'] + + + + + 6 + + + Find account in PS_TRANSFERS_COMMITTED + + + + SELECT spc.participantCurrencyId + + + FROM + + + settlementParticipantCurrency + + + spc + + + JOIN + + + settlementParticipantCurrencyStateChange + + + spcsc + + + ON spcsc.settlementParticipantCurrencyStateChangeId = spc.currentStateChangeId + + + WHERE spc.settlementId = {id} + + + AND spcsc.settlementStateId = 'PS_TRANSFERS_COMMITTED' + + + LIMIT 1 + + + + + 7 + + + Return + + + transferCommittedAccount + + + + + break + + + [transferCommittedAccount != undefined] + + + + + { + + + errorInformation: { + + + "errorCode": <integer>, + + + "errorDescription": "At least one settlement transfer is committed" + + + } + + + } + + + + + DB TRANSACTION + + + + + 8 + + + Retrive settlement accounts information + + + + SELECT pc.participantId, spc.participantCurrencyId, + + + spcsc.settlementStateId, spcsc.reason, + + + spcsc.createdDate, spc.netAmount, pc.currencyId, + + + spc.settlementParticipantCurrencyId AS + + + key + + + FROM + + + settlementParticipantCurrency + + + spc + + + JOIN + + + settlementParticipantCurrencyStateChange + + + spcsc + + + ON spcsc.settlementParticipantCurrencyStateChangeId = + + + spc.currentStateChangeId + + + JOIN + + + participantCurrency + + + pc + + + ON pc.participantCurrencyId = spc.participantCurrencyId + + + WHERE spc.settlementId = {id} + + + FOR UPDATE + + + + + 9 + + + Return + + + settlementAccountsList + + + + + 10 + + + Retrive settlement windows information + + + + SELECT ssw.settlementWindowId, swsc.settlementWindowStateId, + + + swsc.reason, swsc.createdDate + + + FROM + + + settlementSettlementWindow + + + ssw + + + JOIN + + + settlementWindow + + + sw + + + ON sw.settlementWindow = ssw.settlementWindowId + + + JOIN + + + settlementWindowStateChange + + + swsc + + + ON swsc.settlementWindowStateChangeId = sw.currentStateChangeId + + + WHERE ssw.settlementId = {id} + + + FOR UPDATE + + + + + 11 + + + Return + + + windowsList + + + + + Bulk insert settlementParticipantCurrencyStateChange + + + + + 12 + + + Insert settlementParticipantCurrencyStateChange + + + + settlementParticipantCurrencyStateChange + + + + + 13 + + + Return + + + spcscIdList + + + + + 14 + + + Merge spcscIdList into settlementAccountsList + + + + + 15 + + + Update all pointers to current state change ids + + + + UPDATE + + + settlementParticipantCurrency + + + .currentStateChangeIds + + + + + ref + + + Settlement Transfer Abort + + + Inputs + + + : settlementId, transactionTimestamp, enums, trx + + + + + Bulk insert and reset contents & aggregations + + + + + 16 + + + Bulk insert aborted state + + + + settlementWindowContentStateChange + + + + + 17 + + + Return + + + swcscIdList + + + + + 18 + + + Merge swcscIdList + + + + + 19 + + + Update current state references and reset settlementId + + + + settlementWindowContent + + + .currentStateChangeIds + + + .settlementId + + + settlementContentAggregation + + + .settlementId + + + + + Bulk insert settlementWindowStateChange + + + + + 20 + + + Insert settlementWindowStateChange + + + + settlementWindowStateChange + + + + + 21 + + + Return + + + swscIdList + + + + + 22 + + + Merge swscIdList into windowList + + + + + 23 + + + Update all pointers to current state change ids + + + + UPDATE + + + settlementWindow + + + .currentStateChangeIds + + + + + Insert settlementStateChange + + + + + 24 + + + Insert settlementStateChange + + + + INSERT INTO + + + settlementStateChange + + + (settlementId, settlementStateId, reason) + + + VALUES ({id}, 'ABORTED', {abortReasonString}) + + + + + 25 + + + Return + + + settlementStateChangeId + + + + + 26 + + + Update pointer to current state change id + + + + UPDATE + + + settlement + + + .currentStateChangeId + + + + + 27 + + + Return facade method result + + + + + alt + + + [success] + + + + + { + + + "id": {id}, + + + "state": 'ABORTED', + + + "reason": {abortReasonString} + + + } + + + + + 28 + + + Respond HTTP - 200 (OK) + + + + + + Log ERROR event + + + + + { + + + errorInformation: { + + + "errorCode": <integer>, + + + "errorDescription": "Client/Server error description" + + + } + + + } + + + + + 29 + + + Respond HTTP 4xx or 5xx + + + (Client/Server error) + + diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.1.plantuml b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.1.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.1.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.1.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.1.svg b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.1.svg new file mode 100644 index 000000000..7ce3f9839 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.1.svg @@ -0,0 +1,297 @@ + + + + + + + + + + + 6.1.1. Request Settlement Window By Id (getSettlementWindowById) + + + + Central HUB + + + + Settlement Service + + + + Central Services + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Settlement Service API + + + + + Settlement Service API + + + + + Settlement DAO + + + + + Settlement DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Request Settlement Window + + + + + 1 + + + GET - /settlementWindows/{id} + + + + + 2 + + + Request settlementWindow by id + + + Error code: + + + 2001 + + + + + 3 + + + Select from DB + + + + SELECT sw.settlementWindowId, swsc.settlementWindowStateId, + + + swsc.reason, sw.createdDate, swsc.createdDate changedDate + + + FROM + + + settlementWindow + + + AS sw + + + JOIN + + + settlementWindowStateChange + + + AS swsc + + + ON swsc.settlementWindowStateChangeId = sw.currentStateChangeId + + + WHERE sw.settlementWindowId = {id} + + + + + 4 + + + Return + + + data + + + + + alt + + + [settlementWindow found] + + + + + 5 + + + Request settlementWindowContent(s) + + + Error code: + + + 2001 + + + + + 6 + + + Select from DB + + + + settlementWindowContent + + + settlementWindowContentStateChange + + + ledgerAccountType + + + + + 7 + + + Return + + + contentList + + + + + { + + + "id": data.settlementWindowId, + + + "state": data.settlementWindowStateId, + + + "reason": data.reason, + + + "createdDate": data.createdDate, + + + "changedDate": data.changedDate, + + + "content": [ + + + { + + + "id": contentList.settlementWindowContentId, + + + "state": contentList.settlementWindowStateId, + + + "ledgerAccountType": contentList.ledgerAccountType, + + + "currencyId": contentList.currencyId, + + + "createdDate": contentList.createdDate, + + + "changedDate": contentList.changedDate, + + + "settlementId": contentList.settlementId + + + } + + + ] + + + } + + + + + 8 + + + Respond HTTP - 200 (OK) + + + + + + Log ERROR event + + + + + { + + + "errorInformation": { + + + "errorCode": <integer>, + + + "errorDescription": <string> + + + } + + + } + + + + + 9 + + + Respond HTTP - 4xx (Client error) + + diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.2.plantuml b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.2.plantuml similarity index 94% rename from mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.2.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.2.plantuml index cca5d36cf..79c75a058 100644 --- a/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.2.plantuml +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.2.plantuml @@ -199,7 +199,7 @@ group Close Settlement Window deactivate SSAPI deactivate OPERATOR - group Close settlement window (SettlementWindowHandler) + group Close settlement window (Deferred Handler) TOPIC_SET_WIN <- SET_WIN_HANDLER: Consume Settlement Window\nevent message activate TOPIC_SET_WIN deactivate TOPIC_SET_WIN @@ -252,18 +252,25 @@ group Close Settlement Window SETTLE_DAO -> DB: Determine window content and insert activate DB + SETTLE_DAO -> DB: Get all Settlement Models + SETTLE_DAO -> SETTLE_DAO: create Settlement Models <-> currencyId map + SETTLE_DAO -> SETTLE_DAO: create list of currencies with Settlement Models + SETTLE_DAO -> DB: Get Settlement Window Content list hnote over DB #lightyellow - INSERT INTO **settlementWindowContent** (settlementWindowId, ledgerAccountTypeId, - currencyId, createdDate) SELECT DISTINCT {id} settlementWindowId, pc.ledgerAccountTypeId, - pc.currencyId, transactionTimestamp + pc.currencyId, m.settlementModelId FROM **transferFulfilment** tf JOIN **transferParticipant** tp ON tp.transferId = tf.transferId JOIN **participantCurrency** pc ON pc.participantCurrencyId = tp.participantCurrencyId + JOIN **settlementModel** m + ON m.ledgerAccountTypeId = pc.ledgerAccountTypeId WHERE tf.settlementWindowId = {id} + AND m.settlementGranularityId = 'NET' end hnote + SETTLE_DAO -> SETTLE_DAO: filter swcList to add currency to each record based on model + SETTLE_DAO -> DB: Insert filtered list deactivate DB SETTLE_DAO -> DB: Aggregate window data and insert @@ -282,6 +289,8 @@ group Close Settlement Window ON swc.settlementWindowId = tf.settlementWindowId AND swc.ledgerAccountTypeId = pc.ledgerAccountTypeId AND swc.currencyId = pc.currencyId + JOIN **settlementModel** m + ON m.settlementModelId = swc.settlementModelId WHERE ttf.settlementWindowId = {id} GROUP BY swc.settlementWindowContentId, pc.participantCurrencyId, tp.transferParticipantRoleTypeId, tp.ledgerEntryTypeId diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.2.svg b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.2.svg new file mode 100644 index 000000000..19abe69d4 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.2.svg @@ -0,0 +1,1135 @@ + + + + + + + + + + + 6.1.2. Close Settlement Window (closeSettlementWindow) + + + + Central HUB + + + + Settlement Service + + + + Central Services + + + + + + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Settlement Service API + + + + + Settlement Service API + + + + + + + topic- + + + settlement-window + + + + + topic- + + + settlement-window + + + Settlement Window + + + Handler + + + + + Settlement Window + + + Handler + + + + + + + topic-event + + + + + topic-event + + + Settlement DAO + + + + + Settlement DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Close Settlement Window + + + + + { + + + "state": "CLOSED", + + + "reason": <string> + + + } + + + + + 1 + + + POST - /settlementWindows/{id} + + + + + 2 + + + Validate payload, existing window, + + + state, assigned transfers, etc. + + + + + break + + + + + { + + + "errorInformation": { + + + "errorCode": <integer>, + + + "errorDescription": "FSPIOP Error Description" + + + } + + + } + + + + + 3 + + + Respond HTTP - 400 (Bad Request) + + + + + 4 + + + Get requested settlementWindow and state + + + Error code: + + + 2001 + + + + + 5 + + + Get settlementWindow state + + + + SELECT sw.settlementWindowId, swsc.settlementWindowStateId, + + + swsc.reason, sw.createdDate, swsc.createdDate changedDate + + + FROM + + + settlementWindow + + + AS sw + + + JOIN + + + settlementWindowStateChange + + + AS swsc + + + ON swsc.settlementWindowStateChangeId = sw.currentStateChangeId + + + WHERE sw.settlementWindowId = {id} + + + + + 6 + + + Return result + + + + + alt + + + [settlementWindow found && settlementWindowStateId == 'OPEN'] + + + + + Process settlement window + + + + + 7 + + + Terminate current window and open a new one + + + Error code: + + + 2001 + + + + + DB TRANSACTION: Terminate window usage and initate next + + + + + let + + + transactionTimestamp + + + = now() + + + + + 8 + + + Terminate requested window + + + + INSERT INTO + + + settlementWindowStateChange + + + (settlementWindowId, settlementWindowStateId, reason, createdDate) + + + VALUES ({id}, 'PROCESSING', {payload.reason}, {transactionTimestamp}) + + + + + 9 + + + Return + + + settlementWindowStateChangeId + + + + + 10 + + + Update pointer to current state change id + + + + UPDATE + + + settlementWindow + + + SET currentStateChangeId = {settlementWindowStateChangeId} + + + WHERE settlementWindowId = {id} + + + + + 11 + + + Create new settlementWindow + + + + INSERT INTO + + + settlementWindow + + + (reason, createdDate) + + + VALUES ({payload.reason}, {transactionTimestamp}) + + + + + 12 + + + Return + + + settlementWindowId + + + + + 13 + + + Insert intial state for the created window + + + + INSERT INTO + + + settlementWindowStateChange + + + (settlementWindowId, settlementWindowStateId, reason, createdDate) + + + VALUES ({settlementWindowId}, 'OPEN', {payload.reason}, {transactionTimestamp}) + + + + + 14 + + + Return + + + newSettlementWindowStateChangeId + + + + + 15 + + + Update pointer to current state change id + + + + UPDATE + + + settlementWindow + + + SET currentStateChangeId = {newSettlementWindowStateChangeId} + + + WHERE settlementWindowId = {settlementWindowId} + + + + + 16 + + + Return success + + + + + Message: + + + { + + + id: <uuid> + + + from: switch, + + + to: switch, + + + type: application/json + + + content: { + + + payload: { + + + settlementWindowId: {id} + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: null, + + + type: setwin, + + + action: close, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 17 + + + Produce Settlement Window + + + event message + + + Error codes: + + + 2003 + + + + + { + + + "id": settlementWindowId, + + + "state": 'OPEN', + + + "reason": payload.reason, + + + "createdDate": transactionTimestamp, + + + "changedDate": transactionTimestamp + + + } + + + + + 18 + + + Respond HTTP - 201 (Created) + + + + + Close settlement window (Deferred Handler) + + + + + 19 + + + Consume Settlement Window + + + event message + + + + + Persist Event Information + + + + + 20 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + let + + + id + + + = message.content.payload.settlementWindowId + + + let + + + windowContentReady + + + = false + + + let + + + iter + + + = 0 + + + + + loop + + + [iter < Config.WIN_AGGREGATION_RETRY_COUNT && !windowContentReady] + + + + + iter++ + + + + + 21 + + + Check if all transferParticipant records + + + for the requested window have been set + + + (currentStateChangeId is NOT NULL). + + + Error code: + + + 2001 + + + + + 22 + + + Use EXISTS query to find NULL currentStateChangeId records + + + + transferFulfilment + + + transferParticipant + + + + + 23 + + + Return result (success / failure) + + + + + opt + + + [transferParticipant records have been processed by central-ledger SettlementModelHandler] + + + + + 24 + + + Generate window content and aggregations + + + Error code: + + + 2001 + + + + + DB TRANSACTION: Generate window content and aggregations + + + + + let + + + transactionTimestamp + + + = now() + + + + + 25 + + + Change all applicable entries to CLOSED state + + + + transferParticipantStateChange + + + transferParticipant + + + + + 26 + + + Determine window content and insert + + + + + 27 + + + Get all Settlement Models + + + + + 28 + + + create Settlement Models <-> currencyId map + + + + + 29 + + + create list of currencies with Settlement Models + + + + + 30 + + + Get Settlement Window Content list + + + + SELECT DISTINCT {id} settlementWindowId, pc.ledgerAccountTypeId, + + + pc.currencyId, m.settlementModelId + + + FROM + + + transferFulfilment + + + tf + + + JOIN + + + transferParticipant + + + tp + + + ON tp.transferId = tf.transferId + + + JOIN + + + participantCurrency + + + pc + + + ON pc.participantCurrencyId = tp.participantCurrencyId + + + JOIN + + + settlementModel + + + m + + + ON m.ledgerAccountTypeId = pc.ledgerAccountTypeId + + + WHERE tf.settlementWindowId = {id} + + + AND m.settlementGranularityId = 'NET' + + + + + 31 + + + filter swcList to add currency to each record based on model + + + + + 32 + + + Insert filtered list + + + + + 33 + + + Aggregate window data and insert + + + + INSERT INTO + + + settlementContentAggregation + + + (settlementWindowContentId, participantCurrencyId, + + + transferParticipantRoleTypeId, ledgerEntryTypeId, currentStateId, createdDate, amount) + + + SELECT swc.settlementWindowContentId, pc.participantCurrencyId, tp.transferParticipantRoleTypeId, + + + tp.ledgerEntryTypeId, 'CLOSED', transactionTimestamp, SUM(tp.amount) + + + FROM + + + transferFulfilment + + + tf + + + JOIN + + + transferParticipant + + + tp + + + ON tf.transferId = tp.transferId + + + JOIN + + + participantCurrency + + + pc + + + ON pc.participantCurrencyId = tp.participantCurrencyId + + + JOIN + + + settlementWindowContent + + + swc + + + ON swc.settlementWindowId = tf.settlementWindowId + + + AND swc.ledgerAccountTypeId = pc.ledgerAccountTypeId + + + AND swc.currencyId = pc.currencyId + + + JOIN + + + settlementModel + + + m + + + ON m.settlementModelId = swc.settlementModelId + + + WHERE ttf.settlementWindowId = {id} + + + GROUP BY swc.settlementWindowContentId, pc.participantCurrencyId, + + + tp.transferParticipantRoleTypeId, tp.ledgerEntryTypeId + + + + + 34 + + + Insert initial window content state change + + + + INSERT INTO + + + settlementWindowContentStateChange + + + (settlementWindowContentId, settlementWindowStateId) + + + SELECT swc.settlementWindowContentId, 'CLOSED' + + + FROM + + + settlementWindowContent + + + swc + + + WHERE swc.settlementWindowId = {id} + + + + + 35 + + + Update pointers to current state change ids + + + + settlementWindowContent + + + + + 36 + + + Return result (success / failure) + + + + + alt + + + [success] + + + + + windowContentReady = true + + + + + 37 + + + Close requested window + + + Error code: + + + 2001 + + + + + 38 + + + Change window state to 'CLOSED' + + + + settlementWindowStateChange + + + settlementWindow.currentStateChangeId + + + + [failure && iter < Config.WIN_AGGREGATION_RETRY_COUNT] + + + + + sleep + + + Config.WIN_AGGREGATION_RETRY_INTERVAL seconds + + + + [failure] + + + + + 39 + + + Fail requested window + + + Error code: + + + 2001 + + + + + 40 + + + Change window state to 'FAILED' + + + + settlementWindowStateChange + + + settlementWindow.currentStateChangeId + + + + 41 + + + Log ERROR event + + + + + 42 + + + Log ERROR event + + + + + { + + + "errorInformation": { + + + "errorCode": <integer>, + + + "errorDescription": "Client error description" + + + } + + + } + + + + + 43 + + + Respond HTTP - 4xx (Client error) + + diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.3.plantuml b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.3.plantuml similarity index 100% rename from mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.3.plantuml rename to legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.3.plantuml diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.3.svg b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.3.svg new file mode 100644 index 000000000..090e598ac --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.3.svg @@ -0,0 +1,297 @@ + + + + + + + + + + + 6.1.3. Get Settlement Windows By Parameters (getSettlementWindowsByParams) + + + + Central HUB + + + + Settlement Service + + + + Central Services + + + + + + + + Hub Employee + + + + + Hub Employee + + + + + Settlement Service API + + + + + Settlement Service API + + + + + Settlement DAO + + + + + Settlement DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Get Settlement Windows By Parameters + + + + + Params: + + + ?participantId={participantId} + + + &state={state} + + + &fromDateTime={fromDateTime} + + + &toDateTime={toDateTime} + + + + + 1 + + + GET - /settlementWindows/{params} + + + + + 2 + + + Request settlementWindow + + + Error code: + + + 2001 + + + + + 3 + + + Request settlementWindows + + + + SELECT DISTINCT sw.settlementId, swsc.settlementWindowStateId, + + + swsc.reason, sw.createdDate, swsc.createdDate changedDate + + + FROM + + + settlementWindow + + + sw + + + JOIN + + + settlementWindowStateChange + + + swsc + + + ON swsc.settlementWindowStateChangeId = sw.currentStateChangeId + + + JOIN + + + transferFulfilment + + + tf + + + ON tf.settlementWindowId = sw.settlementWindowId + + + JOIN + + + transferParticipant + + + tp + + + ON tp.transferId = tf.transferId + + + JOIN + + + participantCurrency + + + pc + + + ON pc.participantCurrencyId = tp.participantCurrencyId + + + [WHERE pc.participantId = {participantId}] + + + [AND swsc.settlementWindowStateId = {state}] + + + [AND sw.createdDate >= {fromDateTime}] + + + [AND sw.createdDate <= {toDateTime}] + + + + + 4 + + + Return data + + + + + 5 + + + Return + + + settlementWindows + + + + + alt + + + [One or more records found] + + + + + [ + + + { + + + "id": settlementWindow.settlementId, + + + "state": settlementWindow.settlementWindowStateId, + + + "reason": settlementWindow.reason, + + + "createdDate": settlementWindow.createdDate, + + + "changedDate": settlementWindow.changedDate + + + } + + + ] + + + + + 6 + + + Respond HTTP - 200 (OK) + + + + + + Log ERROR event + + + + + { + + + "errorInformation": { + + + "errorCode": <integer>, + + + "errorDescription": "Client error description" + + + } + + + } + + + + + 7 + + + Respond HTTP - 4xx (Client error) + + diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/entities/central-settlements-db-schema-dbeaver.erd b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/entities/central-settlements-db-schema-dbeaver.erd new file mode 100644 index 000000000..57065a8da --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/entities/central-settlements-db-schema-dbeaver.erd @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COLOR LEGEND: +Green - subject specific entity +Gray - transfer specific entity +Red - settlement specific entity +Blue - lookup entity + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/entities/central-settlements-db-schema.png b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/entities/central-settlements-db-schema.png new file mode 100644 index 000000000..4930831f1 Binary files /dev/null and b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/assets/entities/central-settlements-db-schema.png differ diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-id.md b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-id.md new file mode 100644 index 000000000..c77185bbc --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-id.md @@ -0,0 +1,7 @@ +# Request Settlement + +Design for Get Settlement by Id process. + +## Sequence Diagram + +![seq-settlement-6.2.4.svg](./assets/diagrams/sequence/seq-settlement-6.2.4.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-spa.md b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-spa.md new file mode 100644 index 000000000..8869a6679 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-spa.md @@ -0,0 +1,7 @@ +# Request Settlement By SPA + +Design for Get Settlement by Settlement/Participant/Account process. + +## Sequence Diagram + +![seq-settlement-6.2.3.svg](./assets/diagrams/sequence/seq-settlement-6.2.3.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-window-by-id.md b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-window-by-id.md new file mode 100644 index 000000000..f025f69c8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-window-by-id.md @@ -0,0 +1,7 @@ +# Request Settlement Window + +Design for Request Settlement Window by Id process. + +## Sequence Diagram + +![seq-setwindow-6.1.1.svg](./assets/diagrams/sequence/seq-setwindow-6.1.1.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-windows-by-params.md b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-windows-by-params.md new file mode 100644 index 000000000..9275f765a --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-windows-by-params.md @@ -0,0 +1,7 @@ +# Settlement Windows By Params + +Design for Get Settlement Windows by Parameters process. + +## Sequence Diagram + +![seq-setwindow-6.1.3.svg](./assets/diagrams/sequence/seq-setwindow-6.1.3.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlements-by-params.md b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlements-by-params.md new file mode 100644 index 000000000..6d0a79cb8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/get-settlements-by-params.md @@ -0,0 +1,7 @@ +# Request Settlements By Params + +Design for Query Settlements by Parameters process. + +## Sequence Diagram + +![seq-settlement-6.2.2.svg](./assets/diagrams/sequence/seq-settlement-6.2.2.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/gross-settlement-handler-consume.md b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/gross-settlement-handler-consume.md new file mode 100644 index 000000000..51e54594b --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/gross-settlement-handler-consume.md @@ -0,0 +1,7 @@ +# Gross Settlement Handler + +Sequence design diagram for the gross settlement handler. + +## Sequence Diagram + +![example](assets/diagrams/sequence/seq-gross-settlement-handler.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/post-close-settlement-window.md b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/post-close-settlement-window.md new file mode 100644 index 000000000..ae1ce9dd1 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/post-close-settlement-window.md @@ -0,0 +1,7 @@ +# Close Settlement Window + +Design for Close Settlement Window process. + +## Sequence Diagram + +![seq-setwindow-6.1.2.svg](./assets/diagrams/sequence/seq-setwindow-6.1.2.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/post-create-settlement.md b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/post-create-settlement.md new file mode 100644 index 000000000..da1f6685c --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/post-create-settlement.md @@ -0,0 +1,7 @@ +# Create Settlement + +Design for Trigger Settlement Event process. + +## Sequence Diagram + +![seq-settlement-6.2.1.svg](./assets/diagrams/sequence/seq-settlement-6.2.1.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-abort.md b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-abort.md new file mode 100644 index 000000000..18acb25f5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-abort.md @@ -0,0 +1,7 @@ +# Settlement Abort + +Design for Settlement Abort process. + +## Sequence Diagram + +![seq-settlement-6.2.6.svg](./assets/diagrams/sequence/seq-settlement-6.2.6.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-transfer-ack.md b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-transfer-ack.md new file mode 100644 index 000000000..3cc0cf37b --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-transfer-ack.md @@ -0,0 +1,7 @@ +# Settlement Transfer Acknowledgment + +Design for Acknowledgement of Settlement Transfer process. + +## Sequence Diagram + +![seq-settlement-6.2.5.svg](./assets/diagrams/sequence/seq-settlement-6.2.5.svg) diff --git a/legacy/mojaloop-technical-overview/central-settlements/settlement-process/rules-handler-consume.md b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/rules-handler-consume.md new file mode 100644 index 000000000..70270ae50 --- /dev/null +++ b/legacy/mojaloop-technical-overview/central-settlements/settlement-process/rules-handler-consume.md @@ -0,0 +1,169 @@ +Rules Handler. Interchange fees example. File format. +----------------------------------------------------- + +## Rules Handler +The Rules handler provides the capability to execute custom rule-based actions as a result of transfer processing events. +Here we are giving example with Interchange fee calculation. +## Sequence Diagram +![example](assets/diagrams/sequence/seq-rules-handler.svg) + +### Interchange fee case +In order to support the various options for accumulating interchange or other fees, we need to generate and settle liabilities incurred as a consequence of making transfers between particular types of customer. The general form of an example rule, that we are using to illustrate how it works is as follows: +- If the transaction is a wallet-to-wallet P2P transaction, then the receiver + DFSP pays the sender DFSP 0.6% of the amount of the transaction. +- No interchange fees are levied for on-us transactions. + +The business decisions around this requirement are: +1. The definition of whether or not a payee account is a wallet is + returned by the payee DFSP as part of customer discovery. In the process, the `extension` of the transaction should should be extended with characterization of the account. +2. Interchange fees are captured by the switch when there is a matching trigger condition. +3. Interchange fees have the ledger entry type INTERCHANGE_FEE and are + recorded in accounts whose type is INTERCHANGE_FEE. +4. Interchange fees are settled multilaterally, net and deferred. + _Make sure Settlement type and ledger account type for the INTERCHANGE FEE records are availabe_ + +This functionality is implemented as a general +process for defining and executing rules, and for taking actions based on the +outcome of evaluation of a rule. + +### Evaluating a rule +The process of evaluating a rule is based on the following assumptions: + +1. There is a standard form of rule evaluation with the following + structure: + 1. A transaction object is passed as the parameter to the rule + evaluation function. + 2. The rule evaluation itself uses a combination of simple and/or complex nested if statements + 3. If the rule evaluates to TRUE, then an action should be executeds + +An example of a rule function to evaluate an interchange fee rule could be: +```js +function evaluateInterchangeFee (transaction) { + if( + (transaction.payee.fspId.toLowerCase() != transaction.payer.fspId.toLowerCase()) + && (transaction.extensionList[“payerAccountType”].toLowerCase() == + "Wallet".toLowerCase() + && transaction.extensionList[“payeeAccountType”].toLowerCase() == + "Wallet".toLowerCase()) + && (transaction.transactionType.scenario.toLowerCase() == + "TRANSFER".toLowerCase() + && transaction.transactionType.initiator.toLowerCase() == "PAYER".toLowerCase() + && transaction.transactionType.initiatorType.toLowerCase() == + "CONSUMER".toLowerCase()) + ) + // Do some good stuff + }; +}; +``` + +### Taking action after evaluating a rule +If a rule evaluates to TRUE, then appropriate action is taken. In the case of the immediate example of interchange fees, the action taken should be to add two entries to the participants’ interchange fee accounts, on recording the debit from the payee of the interchange fee amount and the other recording the credit to the payer of the interchange fee amount. + +There is defined class with methods that represent the actions to be taken. The rule evaluation instatiates the class and calls the appropriate functions. + +In the case of the interchange fees, we have defined an action called +addLedgerEntry, with the following parameters: + +1. The transfer ID for which the ledger entry is being created +2. The ledger entry type to be used +3. The currency in which the amount is denominated +4. The amount of the fee +5. The FSP ID of the credit party +6. The FSP ID of the debit party + +This might appear in the rule evaluation function as: + +```js +myAction.addLedgerEntry(transaction.transactionId, + "INTERCHANGE_FEE“, + "INTERCHANGE_FEE“, + transaction.currency, + transaction.amount\*0.006, + transaction.payer.fspId, + transaction.payee.fspId); +``` +### Providing rules +The files should be placed in a scripts directory, configured by the value of the environmental variable `SETTINGS__SCRIPTS_FOLDER` +Each rule file should be valid JS with the specified headers content. The required headers should be in the exact order and format as they are in the example below the table. + +| Header | Description | Required | +| :- | :- | :-: | +| Name | Rule name | no | +| Type | Message event type. Corresponds to Kafka topic | yes | +| Action | Message event action. ex. Commit, Prepare, Log, etc | yes | +| Status | Status of the operation: success or failure | yes | +| Start | Time to start abiding the rule | yes | +| End | Until when the rule is valid | yes | +| Description | Rule description | no | + +Based on the headers the rule is evaluated to be triggered or not. + +In the below example rule script, a message on the `notification` topic with action `commit` and status `success` will trigger the code. + +```js +/* eslint-disable no-undef */ +// ******************************************************** +// Name: Interchange fee calculation +// Type: notification +// Action: commit +// Status: success +// Start: 2020-06-01T00:00:00.000Z +// End: 2100-12-31T23:59:59.999Z +// Description: This script calculates the interchange fees between DFSPs where the account type is "Wallet" +// ******************************************************** + +// ## Globals: +// payload: The contents of the message from the Kafka topic. +// transfer: The transfer object. + +// # Functions: +// ## Data retrieval functions: +// getTransferFromCentralLedger(transferId): Retrieves a mojaloop transfer from the central-ledger API. + +// ## Helper functions: +// getExtensionValue(list, key): Gets a value from an extension list +// log(message): allows the script to log to standard out for debugging purposes + +// Math functions: +// multiply(number1, number2, decimalPlaces): Uses ml-number to handle multiplication of money values + +// Ledger functions: +// addLedgerEntry: Adds a debit and credit ledger entry to the specified account to the specified DFSPs + +log(JSON.stringify(transfer)) +const payerFspId = transfer.payer.partyIdInfo.fspId +const payeeFspId = transfer.payee.partyIdInfo.fspId + +if ((payeeFspId !== payerFspId) && + (transfer.payee.partyIdInfo.extensionList && // WORKAROUND for issue #2149 + transfer.payer.partyIdInfo.extensionList && // WORKAROUND for issue #2149 + transfer.payee.partyIdInfo.extensionList.extension && // WORKAROUND for issue #2149 + transfer.payer.partyIdInfo.extensionList.extension) && // WORKAROUND for issue #2149 + (getExtensionValue(transfer.payee.partyIdInfo.extensionList.extension, 'accountType') === 'Wallet' && + getExtensionValue(transfer.payer.partyIdInfo.extensionList.extension, 'accountType') === 'Wallet') && + (transfer.transactionType.scenario === 'TRANSFER' && + transfer.transactionType.initiator === 'PAYER' && + transfer.transactionType.initiatorType === 'CONSUMER')) { + log(`Adding an interchange fee for Wallet to Wallet from ${payerFspId} to ${payeeFspId}`) + addLedgerEntry(payload.id, 'INTERCHANGE_FEE', // Ledger account type Id + 'INTERCHANGE_FEE', // Ledger entry type Id + multiply(transfer.amount.amount, 0.006, 2), + transfer.amount.currency, + payerFspId, + payeeFspId) +} +``` + +### Rules script API + +#### Globals + +* `payload` - The contents of the message from the Kafka topic that has the rules script triggered +* `transfer` - The transfer object +#### Functions + +* `getTransferFromCentralLedger(transferId: uuid)` - Retrieves a mojaloop transfer from the central-ledger API. +* `getExtensionValue(list: array, key: string)` - Gets a value from an extension list +* `log(message: string)`: allows the script to log to configured logger with level *INFO* for debugging purposes +* `multiply(number1: number, number2: number, decimalPlaces: number)`: Uses ml-number to handle multiplication of money values +* `addLedgerEntry(transferId: uuid, ledgerAccountTypeId: string, ledgerEntryTypeId: string, amount: number, currency: string, payerFspId: string, payeeFspId: string)`: Adds a debit and credit ledger entries with given legdger account type, amount and currency to the accounts of the specified DFSPs diff --git a/legacy/mojaloop-technical-overview/event-framework/README.md b/legacy/mojaloop-technical-overview/event-framework/README.md new file mode 100644 index 000000000..d1a0f5ece --- /dev/null +++ b/legacy/mojaloop-technical-overview/event-framework/README.md @@ -0,0 +1,233 @@ +# Event Framework + +The purpose of the Event Framework is to provide a standard unified architecture to capture all Mojaloop events. + +_Disclaimer: This is experimental and is being implemented as a PoC. As such the design may change based on the evolution of the PoC's implementation, and any lessons learned._ + + +## 1. Requirements + +- Events will be produced by utilising a standard common library that will publish events to a sidecar component utilising a light-weight highly performant protocol (e.g. gRPC). +- Sidecar module will publish events to a singular Kafka topic that will allow for multiple handlers to consume and process the events as required. +- Kafka partitions will be determined by the event-type (e.g. log, audit, trace, errors etc). +- Each Mojaloop component will have its own tightly coupled Sidecar. +- Event messages will be produced to Kafka using the Trace-Id as the message key. This will ensure that all the messages part of the same trace (transaction) are stored in the same partition in order. + + +## 2. Architecture + +### 2.1 Overview + +![Event Framework Architecture](./assets/diagrams/architecture/architecture-event-framework.svg) + +### 2.2 Micro Service Pods + +![Pod Architecture](./assets/diagrams/architecture/architecture-event-sidecar.svg) + +### 2.3 Event Flow + +![Tracing Architecture](./assets/diagrams/architecture/architecture-event-trace.svg) + + +## 3. Event Envelope Model + +## 3.1 JSON Example + +```JSON +{ + "from": "noresponsepayeefsp", + "to": "payerfsp", + "id": "aa398930-f210-4dcd-8af0-7c769cea1660", + "content": { + "headers": { + "content-type": "application/vnd.interoperability.transfers+json;version=1.0", + "date": "2019-05-28T16:34:41.000Z", + "fspiop-source": "noresponsepayeefsp", + "fspiop-destination": "payerfsp" + }, + "payload": "data:application/vnd.interoperability.transfers+json;version=1.0;base64,ewogICJmdWxmaWxtZW50IjogIlVObEo5OGhaVFlfZHN3MGNBcXc0aV9VTjN2NHV0dDdDWkZCNHlmTGJWRkEiLAogICJjb21wbGV0ZWRUaW1lc3RhbXAiOiAiMjAxOS0wNS0yOVQyMzoxODozMi44NTZaIiwKICAidHJhbnNmZXJTdGF0ZSI6ICJDT01NSVRURUQiCn0" + }, + "type": "application/json", + "metadata": { + "event": { + "id": "3920382d-f78c-4023-adf9-0d7a4a2a3a2f", + "type": "trace", + "action": "span", + "createdAt": "2019-05-29T23:18:32.935Z", + "state": { + "status": "success", + "code": 0, + "description": "action successful" + }, + "responseTo": "1a396c07-47ab-4d68-a7a0-7a1ea36f0012" + }, + "trace": { + "service": "central-ledger-prepare-handler", + "traceId": "bbd7b2c7-3978-408e-ae2e-a13012c47739", + "parentSpanId": "4e3ce424-d611-417b-a7b3-44ba9bbc5840", + "spanId": "efeb5c22-689b-4d04-ac5a-2aa9cd0a7e87", + "startTimestamp": "2015-08-29T11:22:09.815479Z", + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + "tags": { + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + "transctionType": "transfer", + "parentEventType": "bulk-prepare", + "parentEventAction": "prepare" + } + } + } +} +``` + +## 3.2 Schema Definition + +### 3.2.1 Object Definition: EventMessage + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| id | string | Y | The id references the related message. | | +| from | string | N | If the value is not present in the destination, it means that the notification was generated by the connected node (server). | | +| to | string | Y | Mandatory for the sender and optional in the destination. The sender can ommit the value of the domain. | | +| pp | string | N | Optional for the sender, when is considered the identity of the session. Is mandatory in the destination if the identity of the originator is different of the identity of the from property. | | +| metadata | object `` | N | The sender should avoid to use this property to transport any kind of content-related information, but merely data relevant to the context of the communication. Consider to define a new content type if there's a need to include more content information into the message. | | +| type | string | Y | `MIME` declaration of the content type of the message. | | +| content | object \ | Y | The representation of the content. | | + +##### 3.2.1.1 Object Definition: MessageMetadata + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| event | object `` | Y | Event information. | | +| trace | object `` | Y | Trace information. | | + +##### 3.2.1.2 Object Definition: EventMetadata + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| id | string | Y | Generated UUIDv4 representing the event. | 3920382d-f78c-4023-adf9-0d7a4a2a3a2f | +| type | enum `` | Y | Type of event. | [`log`, `audit`, `error` `trace`] | +| action | enum `` | Y | Type of action. | [ `start`, `end` ] | +| createdAt | timestamp | Y | ISO Timestamp. | 2019-05-29T23:18:32.935Z | +| responseTo | string | N | UUIDv4 id link to the previous parent event. | 2019-05-29T23:18:32.935Z | +| state | object `` | Y | Object describing the state. | | + +##### 3.2.1.3 Object Definition: EventStateMetadata + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| status | enum `` | Y | The id references the related message. | success | +| code | number | N | The error code as per Mojaloop specification. | 2000 | +| description | string | N | Description for the status. Normally used to include an description for an error. | Generic server error to be used in order not to disclose information that may be considered private. | + +##### 3.2.1.4 Object Definition: EventTraceMetaData + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| service | string | Y | Name of service producing trace | central-ledger-prepare-handler | +| traceId | 32HEXDIGLC | Y | The end-to-end transaction identifier. | 664314d5b207d3ba722c6c0fdcd44c61 | +| spanId | 16HEXDIGLC | Y | Id for a processing leg identifier for a component or function. | 81fa25e8d66d2e88 | +| parentSpanId | 16HEXDIGLC | N | The id references the related message. | e457b5a2e4d86bd1 | +| sampled | number | N | Indicator if event message should be included in the trace `1`. If excluded it will be left the consumer to decide on sampling. | 1 | +| flags | number | N | Indicator if event message should be included in the trace flow. ( Debug `1` - this will override the sampled value ) | 0 | +| startTimestamp | datetime | N | ISO 8601 with the following format `yyyy-MM-dd'T'HH:mm:ss.SSSSSSz`. If not included the current timestamp will be taken. Represents the start timestamp of a span.| 2015-08-29T11:22:09.815479Z | +| finishTimestamp | datetime | N | ISO 8601 with the following format `yyyy-MM-dd'T'HH:mm:ss.SSSSSSz`. If not included the current timestamp will be taken. Represents the finish timestamp of a span | 2015-08-29T11:22:09.815479Z | +| tags | object `` | Y | The id references the related message. | success | + +_Note: HEXDIGLC = DIGIT / "a" / "b" / "c" / "d" / "e" / "f" ; lower case hex character. Ref: [WC3 standard for trace-context](https://www.w3.org/TR/trace-context/#field-value)._ + +##### 3.2.1.5 Object Definition: EventTraceMetaDataTags + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| transactionId | string | N | Transaction Id representing either a transfer, quote, etc | 659ee338-c8f8-4c06-8aff-944e6c5cd694 | +| transactionType | string | N | The transaction type represented by the transactionId. E.g. (transfer, quote, etc) | transfer | +| parentEventType | string | N | The event-type of the parent Span. | bulk-prepare | +| parentEventAction | string | N | The event-action of the parent Span. | prepare | +| tracestate | string | N | This tag is set if EventSDK environmental variable `EVENT_SDK_TRACESTATE_HEADER_ENABLED` is `true` or if parent span context has the `tracestate` header or tag included. The tag holds updated `tracestate` header value as per the W3C trace headers specification. [More here](#411-wc3-http-headers)| `congo=t61rcWkgMzE,rojo=00f067aa0ba902b7` | +| `` | string | N | Arbitary Key-value pair for additional meta-data to be added to the trace information. | n/a | + +##### 3.2.1.6 Enum: EventStatusType + +| Enum | Description | +| --- | --- | +| success | Event was processed successfully | +| fail | Event was processed with a failure or error | + +##### 3.2.1.7 Enum: EventType + +| Enum | Description | +| --- | --- | +| log | Event representing a general log entry. | +| audit | Event to be signed and persisted into the audit store. | +| trace | Event containing trace context information to be persisted into the tracing store. | + +##### 3.2.1.8 Enum: LogEventAction + +| Enum | Description | +| --- | --- | +| info | Event representing an `info` level log entry. | +| debug | Event representing a `debug` level log entry. | +| error | Event representing an `error` level log entry. | +| verbose | Event representing a `verbose` level log entry. | +| warning | Event representing a `warning` level log entry. | +| performance | Event representing a `performance` level log entry. | + +##### 3.2.1.9 Enum: AuditEventAction + +| Enum | Description | +| --- | --- | +| default | Standard audit action. | +| start | Audit action to represent the start of a process. | +| finish | Audit action to represent the end of a process. | +| ingress | Audit action to capture ingress activity. | +| egress | Audit action to capture egress activity. | + +##### 3.2.1.10 Enum: TraceEventAction + +| Enum | Description | +| --- | --- | +| span | Event action representing a span of a trace. | + + +## 4. Tracing Design + +### 4.1 HTTP Transports + +Below find the current proposed standard HTTP Transport headers for tracing. + +Mojaloop has yet to standardise on either standard, or if it will possible support both. + +#### 4.1.1 W3C Http Headers + +Refer to the following publication for more information: https://w3c.github.io/trace-context/ + +| Header | Description | Example | +| --- | --- | --- | +| traceparent | Dash delimited string of tracing information: \-\-\-\ | 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00 | +| tracestate | Comma delimited vendor specific format captured as follows: \=\| congo=t61rcWkgMzE,rojo=00f067aa0ba902b7 | + +Note: Before this specification was written, some tracers propagated X-B3-Sampled as true or false as opposed to 1 or 0. While you shouldn't encode X-B3-Sampled as true or false, a lenient implementation may accept them. + +Note: (Event-SDK)[https://github.com/mojaloop/event-sdk] since version v9.4.1 has methods to add key value tags in the tracestate, and since version v9.5.2 the tracestate is base64 encoded. To be able to use the tracestate consistently, use matching versions across all services in a system. + +#### 4.1.2 B3 HTTP Headers + +Refer to the following publication for more information: https://github.com/apache/incubator-zipkin-b3-propagation + +| Header | Description | Example | +| --- | --- | --- | +| X-B3-TraceId | Encoded as 32 or 16 lower-hex characters. | a 128-bit TraceId header might look like: X-B3-TraceId: 463ac35c9f6413ad48485a3953bb6124. Unless propagating only the Sampling State, the X-B3-TraceId header is required. | +| X-B3-SpanId | Encoded as 16 lower-hex characters. | a SpanId header might look like: X-B3-SpanId: a2fb4a1d1a96d312. Unless propagating only the Sampling State, the X-B3-SpanId header is required. | +| X-B3-ParentSpanId | header may be present on a child span and must be absent on the root span. It is encoded as 16 lower-hex characters. | A ParentSpanId header might look like: X-B3-ParentSpanId: 0020000000000001 | +| X-B3-Sampled | An accept sampling decision is encoded as `1` and a deny as `0`. Absent means defer the decision to the receiver of this header. | A Sampled header might look like: X-B3-Sampled: 1. | +| X-B3-Flags | Debug is encoded as `1`. Debug implies an accept decision, so don't also send the X-B3-Sampled header. | | + +### 4.2 Kafka Transports + +Refer to `Event Envelope Model` section. This defines the message that will be sent through the Kafka transport. + +Alternatively the tracing context could be stored in Kafka headers which are only supports v0.11 or later. Note that this would break support for older versions of Kafka. + +### 4.3 Known limitations + +- Transfer tracing would be limited to each of the transfer legs (i.e. Prepare and Fulfil) as a result of the Mojaloop API specification not catering for tracing information. The trace information will be send as part of the callbacks by the Switch, but the FSPs will not be required to respond appropriately with a reciprocal trace headers. diff --git a/legacy/mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-framework.svg b/legacy/mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-framework.svg new file mode 100644 index 000000000..47c2c4acb --- /dev/null +++ b/legacy/mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-framework.svg @@ -0,0 +1,3 @@ + + +
    Central-Ledger
    (API)
    Central-Ledger<br>(API)<br>
    Central-Ledger
    Handler #
    Central-Ledger<br>Handler #<br>
    Central-Ledger
    Handler #
    Central-Ledger<br>Handler #<br>
    Central-Ledger
    (Handler #)
    Central-Ledger<br>(Handler #)<br>

    <div style="text-align: left ; font-size: 8px"><br></div>
    ML-API-Adapter
    (API)
    ML-API-Adapter<br>(API)<br>
    Central-Settlements
    (API)
    Central-Settlements<br>(API)<br>
    ML-API-Adapter
    (Handler)
    ML-API-Adapter<br>(Handler)<br>
    Quoting-Service
    (API)
    Quoting-Service<br>(API)<br>
    Account-Lookup-Service
    (API)
    Account-Lookup-Service<br>(API)<br>

    <div style="text-align: left"><br></div>
    Message Types:
    - Tracing
    - Audit
    - Logs
    [Not supported by viewer]
    <div style="text-align: center"></div>
    Kafka
    (Event Stream)
    topic-events
    [Not supported by viewer]

    <div style="text-align: left ; font-size: 8px"><br></div>
    Sidecar
    Sidecar

    <div style="text-align: left ; font-size: 8px"><br></div>
    Sidecar
    Sidecar
    Sidecar
    Sidecar
    Sidecar
    Sidecar

    <div style="text-align: left ; font-size: 8px"><br></div>
    Sidecar
    Sidecar

    <div style="text-align: left ; font-size: 8px"><br></div>
    Sidecar
    Sidecar

    <div style="text-align: left ; font-size: 8px"><br></div>
    Sidecar
    Sidecar
    Sidecar
    Sidecar
    Sidecar
    Sidecar
    EFK
    (Elasticsearch, Fluentd, 
    Kibana & APM)
    [Not supported by viewer]
    Forensic-Logging
    (Future - re-factored from Side-Car into Service for Batch Audits)
    [Not supported by viewer]
    Central-KMS
    Central-KMS
    Audits
    Audits
    Keys
    Keys
    Partitioned by Trace-Id
    [Not supported by viewer]
    Event-stream-processor
    (Mediation,  Translation)
    [Not supported by viewer]
    Open-Tracing
    [Not supported by viewer]
    log, trace, audit
    [Not supported by viewer]
    log, trace, audit
    [Not supported by viewer]
    log, trace, audit
    [Not supported by viewer]
    log, trace, audit
    [Not supported by viewer]

    <div style="text-align: left ; font-size: 8px"><br></div>
    log, trace, audit
    [Not supported by viewer]
    log, trace, audit
    [Not supported by viewer]
    log, trace, audit
    [Not supported by viewer]
    Key provisioning
    [Not supported by viewer]
    Key provisioning
    [Not supported by viewer]
    Message Types:
    - Tracing
    - Audit
    - Logs
    [Not supported by viewer]
    Message Types:
    - Audits
    [Not supported by viewer]
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-sidecar.svg b/legacy/mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-sidecar.svg new file mode 100644 index 000000000..b274a9d3a --- /dev/null +++ b/legacy/mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-sidecar.svg @@ -0,0 +1,3 @@ + + +

    <div style="text-align: left"><br></div>
    POD #2
    POD #2
    Service #2
    Service #2<br>
    POD #1
    POD #1
    <div style="text-align: center"></div>
    Kafka
    (Event Stream)
    topic-events
    [Not supported by viewer]
    Kubernetes Cluster
    [Not supported by viewer]
    Event Framework
    SideCar
    Event Framework<br>SideCar<br>
    gRPC Server
    gRPC Server
    gRPC Client
    gRPC Client
    Kafka
    Client
    [Not supported by viewer]
    Partitioned by Trace-Id
    [Not supported by viewer]
    Service #1
    Service #1<br>
    Event Framework
    SideCar
    Event Framework<br>SideCar<br>
    gRPC Server
    gRPC Server
    gRPC Client
    gRPC Client
    Kafka
    Client
    [Not supported by viewer]
    @mojaloop/
    event-sdk
    @mojaloop/<br>event-sdk
    Event Framework Sidecar included as part of each component Helm Chart
    [Not supported by viewer]
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-trace.svg b/legacy/mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-trace.svg new file mode 100644 index 000000000..5fd81ccfb --- /dev/null +++ b/legacy/mojaloop-technical-overview/event-framework/assets/diagrams/architecture/architecture-event-trace.svg @@ -0,0 +1,3 @@ + + +
    Sidecar
    Sidecar
    Sidecar
    Sidecar
    Service
    Consumer 
    Service...
    Parent Span
    Parent Span
    Trace
    Trace
    Start
    Start
    End
    End
    Child Span
    Child Span
    Start
    Start
    End
    End
    Child Span
    Child Span
    Start
    Start
    End
    End
    Trace Context
    - traceId
    - spanId
    - parentId
    - sampled
    - flags
    - tracestate
    Trace Context...
    Service
    Producer 
    Service...
    Tags: [ transactionId: transferId, transactionType: transfer, source: payerFsp, destination: payeeFsp, tracestate: mojaloop=f32c19568004ce8b ]
    Tags: [ transactionId: transferId, transactionType: transfer, source: payerFsp, destination: payeeFsp, tracestate: mojaloop=f32c19568004ce...
    Child Span
    Child Span
    Start
    Start
    End
    End
    Message Transport
    - HTTP
    - Kafka

    Message Transport...
    Error
    Error
    Kafka
    (Event Topic)
    Kafka...
    Event Sidecar
    Event Sidecar
    Event Sidecar
    Event Sidecar
    Record Trace
    Record...
    Service A
    Service A
    Service B
    Service B
    Trace Message
    - traceId
    - spanId
    - parentId
    - sampled
    - flags
    - tags
    - tracestate
    - content / error
    Trace Message...
    Record Trace
    Record...
    Record Trace
    Record...
    Record Trace
    Record...
    Record Error
    Record...
    Audit
    Audit
    Record
    Audit
    Record...
    Log
    Log
    Record Log
    Record...
    Record
    Audit
    Record...
    Record
    Audit
    Record...
    Record
    Audit
    Record...
    Record
    Audit
    Record...
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/event-stream-processor/README.md b/legacy/mojaloop-technical-overview/event-stream-processor/README.md new file mode 100644 index 000000000..b92c42e5c --- /dev/null +++ b/legacy/mojaloop-technical-overview/event-stream-processor/README.md @@ -0,0 +1,20 @@ +# Event Stream Processor Service + +Event Stream Processor consumes event messages from the `topic-events` topic as a result of messages published by the [event-sidecar](https://github.com/mojaloop/event-sidecar) service. Refer to [Event Framework](../event-framework/README.md) for more information on the overall architecture. + +The Service delivers logs, including audits, and traces to EFK stack with enabled APM plugin. Based on the event message type, the messages are delivered to different indexes in the Elasticsearch. + +## 1. Prerequisites + +The service logs all the events to Elasticsearch instance with enabled APM plugin. Sample docker-compose of the Elastic stack is available [here](https://github.com/mojaloop/event-stream-processor/blob/master/test/util/scripts/docker-efk/docker-compose.yml). The logs and audits are created under custom index template, while the trace data is stored to the default `apm-*` index. +Please, ensure that you have created the `mojatemplate` as it is described into the [event-stream-processor](https://github.com/mojaloop/event-stream-processor#111-create-template) service documentation. + +## 2. Architecture overview + +### 2.1. Flow overview + +![Event Stream Processor flow overview](./assets/diagrams/architecture/event-stream-processor-overview.svg) + +### 2.2 Trace processing flow sequence diagram + +![process-flow.svg](./assets/diagrams/sequence/process-flow.svg) diff --git a/legacy/mojaloop-technical-overview/event-stream-processor/assets/diagrams/architecture/event-stream-processor-overview.svg b/legacy/mojaloop-technical-overview/event-stream-processor/assets/diagrams/architecture/event-stream-processor-overview.svg new file mode 100644 index 000000000..9deb189e9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/event-stream-processor/assets/diagrams/architecture/event-stream-processor-overview.svg @@ -0,0 +1,3 @@ + + +
    topic-event
    topic-event
    Event Stream Processor
    Send to Elasticsearch mojaloop custom schema via Elasticsearch API
    [Not supported by viewer]
    Yes
    Yes
    Is it trace?
    Is it trace?
    No
    No
    Should create master span?
    Should create master span?
    exit
    exit
    No
    No
    APM Agent
    APM Agent
    Create cache for the trace
    Create cache for the trace
    Yes
    Yes
    No
    No
    Is last span?
    Is last span?
    Recreate trace
    Recreate trace
    exit
    exit
    EFK Stack (Elasticsearch, Kibana, APM)
    EFK Stack (Elasticsearch, Kibana, APM)
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/event-stream-processor/assets/diagrams/sequence/process-flow.plantuml b/legacy/mojaloop-technical-overview/event-stream-processor/assets/diagrams/sequence/process-flow.plantuml new file mode 100644 index 000000000..9817a79d8 --- /dev/null +++ b/legacy/mojaloop-technical-overview/event-stream-processor/assets/diagrams/sequence/process-flow.plantuml @@ -0,0 +1,280 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title Event Streaming Processor flow + +autonumber + +' Actor Keys: + +' declare actors + +collections "Notification topic" as TOPIC_NOTIFICATIONS +control "Topic Observable" as TOPIC_OBSERVABLE +control "Tracing Observable" as TRACING_OBSERVABLE +control "Caching Observable" as CACHING_OBSERVABLE +control "Check For Last Span Observable" as LASTSPAN_OBSERVABLE +control "Create Trace Observable" as CREATETRACE_OBSERVABLE +control "Cache Handler" as CACHE_HANDLER +control "Send Trace Handler" as TRACE_HANDLER +control "Send Span Handler" as SPAN_SENDER +database "Cache Storage" as CACHE +boundary "APM" as APM +boundary "Elasticsearch API" as ELASTIC + +box "Central Services" #lightGray + participant TOPIC_NOTIFICATIONS +end box + +box "Event Stream Processor" #LightBlue + participant TOPIC_OBSERVABLE + participant TRACING_OBSERVABLE + participant CACHING_OBSERVABLE + participant LASTSPAN_OBSERVABLE + participant CREATETRACE_OBSERVABLE + participant TRACE_HANDLER + participant SPAN_SENDER + participant CACHE_HANDLER +end box + +box "Cache" #LightSteelBlue + participant CACHE +end box + +box "Elasticsearch" #LightYellow + participant APM + participant ELASTIC +end box + +' start flow + +group New Event Message Received + TOPIC_NOTIFICATIONS -> TOPIC_OBSERVABLE: Consume Event Message + activate TOPIC_OBSERVABLE + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + note over TOPIC_OBSERVABLE #yellow + Message: + { + "from": "payeefsp", + "to": "payerfsp", + "id": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + "content": { + "headers": { + "content-type": "applicationvnd.interoperability.transfers+json;version=1.0", + "date": "2019-05-28T16:34:41.000Z", + "fspiop-source": "payeefsp", + "fspiop-destination": "payerfsp" + }, + "payload": + }, + "type": "application/json", + "metadata": { + "event": { + "id": "3920382d-f78c-4023-adf9-0d7a4a2a3a2f", + "type": "trace", + "action": "span", + "createdAt": "2019-05-29T23:18:32.935Z", + "state": { + "status": "success", + "code": 0, + "description": "action successful" + }, + "responseTo": "1a396c07-47ab-4d68-a7a0-7a1ea36f0012" + }, + "trace": { + "service": "central-ledger-prepare-handler", + "traceId": "bbd7b2c7bbd7b2c7", + "parentSpanId": "44ba9bbc5840", + "spanId": "2aa9cd0a7e87", + "startTimestamp": "2015-08-29T11:22:09.815479Z", + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + "tags": { + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + "transctionType": "transfer", + "parentEventType": "bulk-prepare", + "parentEventAction": "prepare" + } + } + } + } + end note + TOPIC_OBSERVABLE -> ELASTIC: Send message for log purposes to custom index + TOPIC_OBSERVABLE -> TOPIC_OBSERVABLE: Verify its tracing event Message + TOPIC_OBSERVABLE -> TRACING_OBSERVABLE: Send Message to Tracing Observable + deactivate TOPIC_OBSERVABLE + activate TRACING_OBSERVABLE + group Cache Span + TRACING_OBSERVABLE -> CACHING_OBSERVABLE: Send Span Context, \nmetadata.State and Content\nfrom Message + note right of TRACING_OBSERVABLE #yellow + { + spanContext: { + service: "central-ledger-prepare-handler", + traceId: "bbd7b2c7bbd7b2c7", + parentSpanId: "44ba9bbc5840", + spanId: "2aa9cd0a7e87", + startTimestamp: "2015-08-29T11:22:09.815479Z", + finishTimestamp: "2015-08-29T11:22:09.815479Z", + tags: { + transctionId: "659ee338-c8f8-4c06-8aff-944e6c5cd694", + transctionType: "transfer", + parentEventType: "bulk-prepare", + parentEventAction: "prepare" + }, + state: metadata.state, + content + } + end note + deactivate TRACING_OBSERVABLE + activate CACHING_OBSERVABLE + CACHING_OBSERVABLE <- CACHE: Get cachedTrace by traceId + alt the span should not be cached + CACHING_OBSERVABLE -> SPAN_SENDER: currentSpan + SPAN_SENDER -> APM: store to APM + CACHING_OBSERVABLE -> CACHING_OBSERVABLE: Complete + else + CACHING_OBSERVABLE <-> CACHING_OBSERVABLE: Validate transactionType, TransactionAction and service to match Config.START_CRITERIA && !parentSpandId + alt !cachedTrace + CACHING_OBSERVABLE -> CACHING_OBSERVABLE: Create new cachedTrace + note right of CACHING_OBSERVABLE #yellow + { + spans: {}, + masterSpan: null, + lastSpan: null + } + end note + end + alt !parentSpan + CACHING_OBSERVABLE <-> CACHING_OBSERVABLE: Generate MasterSpanId + CACHING_OBSERVABLE <-> CACHING_OBSERVABLE: Make received span child of masterSpan \nmerge({ parentSpanId: MasterSpanId }, { ...spanContext }) + CACHING_OBSERVABLE <-> CACHING_OBSERVABLE: Create MasterSpanContext merge({ tags: { ...tags, masterSpan: MasterSpanId } }, \n{ ...spanContext }, \n{ spanId: MasterSpanId, service: `master-${tags.transactionType}` }) + CACHING_OBSERVABLE <-> CACHING_OBSERVABLE: Add masterSpan to cachedTrace + end + CACHING_OBSERVABLE <-> CACHE_HANDLER: Add span to cachedTrace + note right of CACHING_OBSERVABLE #yellow + { + spans: { + 2aa9cd0a7e87: { + state, + content + spanContext: { + "service": "central-ledger-prepare-handler", + "traceId": "bbd7b2c7bbd7b2c7", + "parentSpanId": MasterSpanId, + "spanId": "2aa9cd0a7e87", + "startTimestamp": "2015-08-29T11:22:09.815479Z", + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + "tags": { + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + "transctionType": "transfer", + "parentEventType": "bulk-prepare", + "parentEventAction": "prepare" + } + } + }, + MasterSpanId: { + state, + content, + MasterSpanContext + } + }, + masterSpan: MasterSpanContext, + lastSpan: null + } + end note + CACHING_OBSERVABLE -> CACHE_HANDLER: Update cachedTrace to Cache + alt cachedTrace not staled or expired + CACHE_HANDLER -> CACHE_HANDLER: unsubscribe from Scheduler + CACHE_HANDLER -> CACHE: record cachedTrace + CACHE_HANDLER <-> CACHE_HANDLER: Reschedule scheduler for handling stale traces + end + end + CACHING_OBSERVABLE -> LASTSPAN_OBSERVABLE: Send traceId to check if last span has been received\nand cached + deactivate CACHING_OBSERVABLE + activate LASTSPAN_OBSERVABLE + end + group Check for last span + LASTSPAN_OBSERVABLE <- CACHE: Get cachedTrace by traceId + LASTSPAN_OBSERVABLE -> LASTSPAN_OBSERVABLE: Sort spans by startTimestamp + loop for currentSpan of SortedSpans + alt parentSpan + LASTSPAN_OBSERVABLE -> LASTSPAN_OBSERVABLE: isError = (errorCode in parentSpan \nOR parentSpan status === failed \nOR status === failed) + LASTSPAN_OBSERVABLE -> LASTSPAN_OBSERVABLE: apply masterSpan and error tags from parent to current span in cachedTrace + alt !isLastSpan + LASTSPAN_OBSERVABLE -> CACHE_HANDLER: Update cachedTrace to Cache + alt cachedTrace not staled or expired + CACHE_HANDLER -> CACHE_HANDLER: unsubscribe from Scheduler + CACHE_HANDLER -> CACHE: record cachedTrace + CACHE_HANDLER <-> CACHE_HANDLER: Reschedule scheduler for handling stale traces + end + else + LASTSPAN_OBSERVABLE -> LASTSPAN_OBSERVABLE: Validate transactionType, TransactionAction, service and isError \nto match Config.START_CRITERIA && !parentSpandId + LASTSPAN_OBSERVABLE -> LASTSPAN_OBSERVABLE: cachedTrace.lastSpan = currentSpan.spanContext + LASTSPAN_OBSERVABLE -> CACHE_HANDLER: Update cachedTrace to Cache + alt cachedTrace not staled or expired + CACHE_HANDLER -> CACHE_HANDLER: unsubscribe from Scheduler + CACHE_HANDLER -> CACHE: record cachedTrace + CACHE_HANDLER <-> CACHE_HANDLER: Reschedule scheduler for handling stale traces + end + LASTSPAN_OBSERVABLE -> CREATETRACE_OBSERVABLE: Send traceId + deactivate LASTSPAN_OBSERVABLE + activate CREATETRACE_OBSERVABLE + end + end + end + end + group Recreate Trace from Cached Trace + CREATETRACE_OBSERVABLE <- CACHE: get cachedTrace by TraceId + alt cachedTrace.lastSpan AND cachedTrace.masterSpan + CREATETRACE_OBSERVABLE -> CREATETRACE_OBSERVABLE: currentSpan = lastSpan + CREATETRACE_OBSERVABLE -> CREATETRACE_OBSERVABLE: resultTrace = [lastSpan] + loop for i = 0; i < cachedTrace.spans.length; i++ + CREATETRACE_OBSERVABLE -> CREATETRACE_OBSERVABLE: get parentSpan of currentSpan + alt parentSpan + CREATETRACE_OBSERVABLE -> CREATETRACE_OBSERVABLE: insert parent span in resultTrace in front + else + CREATETRACE_OBSERVABLE -> CREATETRACE_OBSERVABLE: break loop + end + end + alt cachedTrace.masterSpan === currentSpan.spanId + CREATETRACE_OBSERVABLE -> CREATETRACE_OBSERVABLE: masterSpan.finishTimestamp = resultTrace[resultTrace.length - 1].finishTimestamp + CREATETRACE_OBSERVABLE -> TRACE_HANDLER: send resultTrace + deactivate CREATETRACE_OBSERVABLE + activate TRACE_HANDLER + end + end + end + group send Trace + loop trace elements + TRACE_HANDLER -> SPAN_SENDER: send each span + SPAN_SENDER -> APM: send span to APM + end + TRACE_HANDLER -> TRACE_HANDLER: unsubscribe scheduler for traceId + TRACE_HANDLER -> CACHE: drop cachedTrace + + end + end +@enduml \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/event-stream-processor/assets/diagrams/sequence/process-flow.svg b/legacy/mojaloop-technical-overview/event-stream-processor/assets/diagrams/sequence/process-flow.svg new file mode 100644 index 000000000..0919b3c48 --- /dev/null +++ b/legacy/mojaloop-technical-overview/event-stream-processor/assets/diagrams/sequence/process-flow.svg @@ -0,0 +1,1028 @@ + + + + + + + + + + + Event Streaming Processor flow + + + + Central Services + + + + Event Stream Processor + + + + Cache + + + + Elasticsearch + + + + + + + + + + + + + + + + + + + + + + + + Notification topic + + + + + Notification topic + + + Topic Observable + + + + + Topic Observable + + + + + Tracing Observable + + + + + Tracing Observable + + + + + Caching Observable + + + + + Caching Observable + + + + + Check For Last Span Observable + + + + + Check For Last Span Observable + + + + + Create Trace Observable + + + + + Create Trace Observable + + + + + Send Trace Handler + + + + + Send Trace Handler + + + + + Send Span Handler + + + + + Send Span Handler + + + + + Cache Handler + + + + + Cache Handler + + + + + Cache Storage + + + + + Cache Storage + + + + + APM + + + + + APM + + + + + Elasticsearch API + + + + + Elasticsearch API + + + + + + + + New Event Message Received + + + + + 1 + + + Consume Event Message + + + + + Message: + + + { + + + "from": "payeefsp", + + + "to": "payerfsp", + + + "id": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + + + "content": { + + + "headers": { + + + "content-type": "applicationvnd.interoperability.transfers+json;version=1.0", + + + "date": "2019-05-28T16:34:41.000Z", + + + "fspiop-source": "payeefsp", + + + "fspiop-destination": "payerfsp" + + + }, + + + "payload": <payload> + + + }, + + + "type": "application/json", + + + "metadata": { + + + "event": { + + + "id": "3920382d-f78c-4023-adf9-0d7a4a2a3a2f", + + + "type": "trace", + + + "action": "span", + + + "createdAt": "2019-05-29T23:18:32.935Z", + + + "state": { + + + "status": "success", + + + "code": 0, + + + "description": "action successful" + + + }, + + + "responseTo": "1a396c07-47ab-4d68-a7a0-7a1ea36f0012" + + + }, + + + "trace": { + + + "service": "central-ledger-prepare-handler", + + + "traceId": "bbd7b2c7bbd7b2c7", + + + "parentSpanId": "44ba9bbc5840", + + + "spanId": "2aa9cd0a7e87", + + + "startTimestamp": "2015-08-29T11:22:09.815479Z", + + + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + + + "tags": { + + + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + + + "transctionType": "transfer", + + + "parentEventType": "bulk-prepare", + + + "parentEventAction": "prepare" + + + } + + + } + + + } + + + } + + + + + 2 + + + Send message for log purposes to custom index + + + + + 3 + + + Verify its tracing event Message + + + + + 4 + + + Send Message to Tracing Observable + + + + + Cache Span + + + + + 5 + + + Send Span Context, + + + metadata.State and Content + + + from Message + + + + + { + + + spanContext: { + + + service: "central-ledger-prepare-handler", + + + traceId: "bbd7b2c7bbd7b2c7", + + + parentSpanId: "44ba9bbc5840", + + + spanId: "2aa9cd0a7e87", + + + startTimestamp: "2015-08-29T11:22:09.815479Z", + + + finishTimestamp: "2015-08-29T11:22:09.815479Z", + + + tags: { + + + transctionId: "659ee338-c8f8-4c06-8aff-944e6c5cd694", + + + transctionType: "transfer", + + + parentEventType: "bulk-prepare", + + + parentEventAction: "prepare" + + + }, + + + state: metadata.state, + + + content + + + } + + + + + 6 + + + Get cachedTrace by traceId + + + + + alt + + + [the span should not be cached] + + + + + 7 + + + currentSpan + + + + + 8 + + + store to APM + + + + + 9 + + + Complete + + + + + + 10 + + + Validate transactionType, TransactionAction and service to match Config.START_CRITERIA && !parentSpandId + + + + + alt + + + [!cachedTrace] + + + + + 11 + + + Create new cachedTrace + + + + + { + + + spans: {}, + + + masterSpan: null, + + + lastSpan: null + + + } + + + + + alt + + + [!parentSpan] + + + + + 12 + + + Generate MasterSpanId + + + + + 13 + + + Make received span child of masterSpan + + + merge({ parentSpanId: MasterSpanId }, { ...spanContext }) + + + + + 14 + + + Create MasterSpanContext merge({ tags: { ...tags, masterSpan: MasterSpanId } }, + + + { ...spanContext }, + + + { spanId: MasterSpanId, service: `master-${tags.transactionType}` }) + + + + + 15 + + + Add masterSpan to cachedTrace + + + + + 16 + + + Add span to cachedTrace + + + + + { + + + spans: { + + + 2aa9cd0a7e87: { + + + state, + + + content + + + spanContext: { + + + "service": "central-ledger-prepare-handler", + + + "traceId": "bbd7b2c7bbd7b2c7", + + + "parentSpanId": + + + MasterSpanId + + + , + + + "spanId": "2aa9cd0a7e87", + + + "startTimestamp": "2015-08-29T11:22:09.815479Z", + + + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + + + "tags": { + + + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + + + "transctionType": "transfer", + + + "parentEventType": "bulk-prepare", + + + "parentEventAction": "prepare" + + + } + + + } + + + }, + + + MasterSpanId: + + + { + + + state, + + + content, + + + MasterSpanContext + + + } + + + }, + + + masterSpan: + + + MasterSpanContext + + + , + + + lastSpan: null + + + } + + + + + 17 + + + Update cachedTrace to Cache + + + + + alt + + + [cachedTrace not staled or expired] + + + + + 18 + + + unsubscribe from Scheduler + + + + + 19 + + + record cachedTrace + + + + + 20 + + + Reschedule scheduler for handling stale traces + + + + + 21 + + + Send traceId to check if last span has been received + + + and cached + + + + + Check for last span + + + + + 22 + + + Get cachedTrace by traceId + + + + + 23 + + + Sort spans by startTimestamp + + + + + loop + + + [for currentSpan of SortedSpans] + + + + + alt + + + [parentSpan] + + + + + 24 + + + isError = (errorCode in parentSpan + + + OR parentSpan status === failed + + + OR status === failed) + + + + + 25 + + + apply masterSpan and error tags from parent to current span in cachedTrace + + + + + alt + + + [!isLastSpan] + + + + + 26 + + + Update cachedTrace to Cache + + + + + alt + + + [cachedTrace not staled or expired] + + + + + 27 + + + unsubscribe from Scheduler + + + + + 28 + + + record cachedTrace + + + + + 29 + + + Reschedule scheduler for handling stale traces + + + + + + 30 + + + Validate transactionType, TransactionAction, service and isError + + + to match Config.START_CRITERIA && !parentSpandId + + + + + 31 + + + cachedTrace.lastSpan = currentSpan.spanContext + + + + + 32 + + + Update cachedTrace to Cache + + + + + alt + + + [cachedTrace not staled or expired] + + + + + 33 + + + unsubscribe from Scheduler + + + + + 34 + + + record cachedTrace + + + + + 35 + + + Reschedule scheduler for handling stale traces + + + + + 36 + + + Send traceId + + + + + Recreate Trace from Cached Trace + + + + + 37 + + + get cachedTrace by TraceId + + + + + alt + + + [cachedTrace.lastSpan AND cachedTrace.masterSpan] + + + + + 38 + + + currentSpan = lastSpan + + + + + 39 + + + resultTrace = [lastSpan] + + + + + loop + + + [for i = 0; i < cachedTrace.spans.length; i++] + + + + + 40 + + + get parentSpan of currentSpan + + + + + alt + + + [parentSpan] + + + + + 41 + + + insert parent span in resultTrace in front + + + + + + 42 + + + break loop + + + + + alt + + + [cachedTrace.masterSpan === currentSpan.spanId] + + + + + 43 + + + masterSpan.finishTimestamp = resultTrace[resultTrace.length - 1].finishTimestamp + + + + + 44 + + + send resultTrace + + + + + send Trace + + + + + loop + + + [trace elements] + + + + + 45 + + + send each span + + + + + 46 + + + send span to APM + + + + + 47 + + + unsubscribe scheduler for traceId + + + + + 48 + + + drop cachedTrace + + diff --git a/mojaloop-technical-overview/fraud-services/README.md b/legacy/mojaloop-technical-overview/fraud-services/README.md similarity index 100% rename from mojaloop-technical-overview/fraud-services/README.md rename to legacy/mojaloop-technical-overview/fraud-services/README.md diff --git a/legacy/mojaloop-technical-overview/fraud-services/related-documents/documentation.md b/legacy/mojaloop-technical-overview/fraud-services/related-documents/documentation.md new file mode 100644 index 000000000..920da7b7f --- /dev/null +++ b/legacy/mojaloop-technical-overview/fraud-services/related-documents/documentation.md @@ -0,0 +1,7 @@ +# Fraud Services + +Artefacts available for public reference related to the preventative measures in preventing and discouraging fraudulent activities within the ecosystem. + +## List of current artefacts + +#### [Mojaloop Ecosystem Fraud Overview Document](https://github.com/mojaloop/documentation-artifacts/blob/master/presentations/April%202019%20PI-6_OSS_community%20session/Mojaloop-Fraud-20190410.pdf) diff --git a/legacy/mojaloop-technical-overview/ml-testing-toolkit/README.md b/legacy/mojaloop-technical-overview/ml-testing-toolkit/README.md new file mode 100644 index 000000000..0d5af432d --- /dev/null +++ b/legacy/mojaloop-technical-overview/ml-testing-toolkit/README.md @@ -0,0 +1,16 @@ +Mojaloop Testing Toolkit +============================= + +The **Mojaloop Testing Toolkit** was designed to help Mojaloop Schemes scale effectively by easing the DFSP Onboarding process. Schemes can provide a set of rules and tests on the toolkit and DFSPs can use it for self testing (or self-certification in some cases). This ensures that DFSPs are well and truly ready with their implementations to be integrated with the Scheme and allows for a quick and smooth onboarding process for the Mojaloop Hubs, thereby increasing their scalability. + +This was initially aimed at FSPs/Participants that would like to participate in a Mojaloop scheme. However, in its current form, this tool set can potentially be used by both DFSPs and _Mojaloop Hubs_ to verify integration between the 2 entities. Intentionally build as a standard integration testing tool between a _Digital Financial Service Provider (DFSP)_ and the _Mojaloop Switch_ (Hub), to facilitate testing. + +For additional background on the Self Testing Toolkit, please see [Mojaloop Testing Toolkit](https://github.com/mojaloop/ml-testing-toolkit/blob/master/documents/Mojaloop-Testing-Toolkit.md). It would be to the particpant's benefit to familiarise themselves with the understanding of the [Architecture Diagram](https://github.com/mojaloop/ml-testing-toolkit/blob/master/documents/Mojaloop-Testing-Toolkit.md#7-architecture) that explains the various components and related flows. + +## Usage Guides + +For Web interface follow this [Usage Guide](https://github.com/mojaloop/ml-testing-toolkit/blob/master/documents/User-Guide.md) + +For Command line tool follow this [CLI User Guide](https://github.com/mojaloop/ml-testing-toolkit/blob/master/documents/User-Guide-CLI.md) + +**If you have your own DFSP implementation you can point the peer endpoint to Mojaloop Testing Toolkit on port 5000 and try to send requests from your implementation instead of using mojaloop-simulator.** diff --git a/legacy/mojaloop-technical-overview/overview/README.md b/legacy/mojaloop-technical-overview/overview/README.md new file mode 100644 index 000000000..373cbfa93 --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/README.md @@ -0,0 +1,24 @@ +# Mojaloop Hub + +There are several components that make up the Mojaloop ecosystem. The Mojaloop Hub is the primary container and reference we use to describe the core Mojaloop components. + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture: + +![Current Mojaloop Architecture Overview](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ + +These consist of: + +* The **Mojaloop API Adapters** (**ML-API-Adapter**) provide the standard set of interfaces a DFSP can implement to connect to the system for Transfers. A DFSP that wants to connect up can adapt our example code or implement the standard interfaces into their own software. The goal is for it to be as straightforward as possible for a DFSP to connect to the interoperable network. +* The **Central Services** (**CS**) provide the set of components required to move money from one DFSP to another through the Mojaloop API Adapters. This is similar to how money moves through a central bank or clearing house in developed countries. The Central Services contains the core Central Ledger logic to move money but also will be extended to provide fraud management and enforce scheme rules. +* The **Account Lookup Service** (**ALS**) provides a mechanism to resolve FSP routing information through the Participant API or orchestrate a Party request based on an internal Participant look-up. The internal Participant look-up is handled by a number of standard Oracle adapter or services. Example Oracle adapter/service would be to look-up Participant information from Pathfinder or a Merchant Registry. These Oracle adapters or services can easily be added depending on the schema requirements. +* The **Quoting Service** (**QA**) provides Quoting is the process that determines any fees and any commission required to perform a financial transaction between two FSPs. It is always initiated by the Payer FSP to the Payee FSP, which means that the quote flows in the same way as a financial transaction. +* The **Simulator** (**SIM**) mocks several DFSP functions as follows: + * Oracle end-points for Oracle Participant CRUD operations using in-memory cache; + * Participant end-points for Oracles with support for parameterized partyIdTypes; + * Parties end-points for Payer and Payee FSPs with associated callback responses; + * Transfer end-points for Payer and Payee FSPs with associated callback responses; and + * Query APIs to verify transactions (requests, responses, callbacks, etc) to support QA testing and verification. + +On either side of the Mojaloop Hub there is sample open source code to show how a DFSP can send and receive payments and the client that an existing DFSP could host to connect to the network. diff --git a/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI11.svg b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI11.svg new file mode 100644 index 000000000..df9396cae --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI11.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    Operational Monitoring
    Quality Assurance
    Quality Assurance
    Core Components
    Core Components
    API - Security / Policy / Ingress / Egress
    API - Security / Policy / Ingress / Egress
    Continuous Integration & Delivery
    Continuous Integration & Delivery
    Container Management & Orchestration
    Container Management & Orchestration
    Supporting Components
    Supporting Components
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    Helm...
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    Kubernetes...
    Docker
    (Container Engine)
    Docker...
    Infrastructure
    (AWS, Azure, On-Prem)
    Infrastructure...
    EFK - ElasticSearch / Fluentd / Kibana
    (Log Search / Collection / Monitoring / Tracing)
    EFK - ElasticSearch / Fluentd / Kibana...
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    Promfana - Prometheus / Grafana...
    Open Tracing
    (Distributed Tracing)
    Open Tracing...
    Rancher
    (Infrastructure Management)
    Rancher...
    Mojaloop API Adapter
    (API - Transfers)
    Mojaloop API Adapter...
    Central-Services
    (API - Operational Admin)
    Central-Services...
    Central-Services
    (Handler - Prepare)
    Central-Services...
    Central-Services
    (Handler - Position)
    Central-Services...
    Central-Services
    (Handler - Fulfil)
    Central-Services...
    Central-Services
    (Handler - Get Transfers)
    Central-Services...
    Central-Services
    (Handler - Timeout)
    Central-Services...
    Central-KMS
    (Future - Key Management Store)
    Central-KMS...
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    ALS - Account-Lookup-Service...
    ALS-Oracle-Pathfinder
    (MSISDN Lookup)
    ALS-Oracle-Pathfinder...
    Central-Event-Processor
    (CEP)
    Central-Event-Processor...
    Email-Notifier
    (Handler - Email)
    Email-Notifier...
    Central-Services
    (Handler - Admin)
    Central-Services...
    Circle-CI
    (Test, Build, Deploy)
    Circle-CI...
    Docker Hub
    (Container Repository)
    Docker Hub...
    NPM Org
    (NPM Repository)
    NPM Org...
    GitBooks
    (Documetation)
    GitBooks...
    API Gateway
    (Future - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)
    API Gateway...
    Central-Services
    (Handler - Bulk Prepare)
    Central-Services...
    Central-Services
    (Handler - Bulk Fulfil)
    Central-Services...
    Central-Services
    (Handler - Bulk Process)
    Central-Services...
    Mojaloop API Adapter
    (API - Bulk Transfers)
    Mojaloop API Adapter...
    Forensic-Logging
    (Future - Auditing)
    Forensic-Logging...
    Central-Settlements
    (API - Settlement)
    Central-Settlements...
    Event-Stream-Processor
    Logs, Error, Audits, Tracing)
    Event-Stream-Processor...
    Simulators
    (API, SDK, FSP & Oracle)
    Simulators...
    On-boarding
    (Postman - Scripts)
    On-boarding...
    Functional Tests
    (Postman - Scripts)
    Functional Tests...
    Self Testing Toolkit
    (
    POC UI)
    Self Testing Toolkit...
    License, Security & Audit
    (Dependencies)
    License, Security & Audit...
    Persistence
    Persistence
    Redis
    (SDK - Cache)
    Redis...
    MongoDB
    (CEP - Data)
    MongoDB...
    MySQL
    (Percona - Data)
    MySQL...
    Kafka
    (Message - Streaming)
    Kafka...
    Transaction Request Service
    (API - Transaction)
    Transaction Request Service...
    Software Dev Kits
    Software Dev Kits
    Oracle SDK
    (Participant Store)
    Oracle SDK...
    Mojaloop SDK 
    (FSP Payer/Payee)
    Mojaloop SDK...
    Event SDK
    (Audit, Log, Trace - Client/Server)
    Event SDK...
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    Event-Sidecar...
    Mojaloop API Adapter
    (Handler - Notifications)
    Mojaloop API Adapter...
    Quoting-Service
    (API - Quotes)
    Quoting-Service...
    Finance-Portal-UI
    (API - Bulk Transfers)
    Finance-Portal-UI...
    Settlement-Management
    (Closing, Recon report, Cronjob)
    Settlement-Management...
    Schema-Adapter
    (SDK - Parties, Participants, Quotes, Transfers)
    Schema-Adapter...
    IaC (Infra as Code) Tools
    (Future - Automated
    Prov / Depl / Upgrades)
    IaC (Infra as Code) Tools...
    Third Party API Adapter
    (PoC - API - Transfers)
    Third Party API Adapter...
    Third Party API Adapter
    (PoC - Handler - Notifications)
    Third Party API Adapter...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI12.svg b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI12.svg new file mode 100644 index 000000000..763c5697e --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI12.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    Operational Monitoring
    Quality Assurance
    Quality Assurance
    Core Components
    Core Components
    API - Security / Policy / Ingress / Egress
    API - Security / Policy / Ingress / Egress
    Continuous Integration & Delivery
    Continuous Integration & Delivery
    Container Management & Orchestration
    Container Management & Orchestration
    Supporting Components
    Supporting Components
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    Helm...
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    Kubernetes...
    Docker
    (Container Engine)
    Docker...
    Infrastructure
    (AWS, Azure, On-Prem)
    Infrastructure...
    EFK - ElasticSearch / Fluentd / Kibana
    (Log Search / Collection / Monitoring / Tracing)
    EFK - ElasticSearch / Fluentd / Kibana...
    Promfana - Prometheus / Grafana
    (Metrics - Collection / Monitoring)
    Promfana - Prometheus / Grafana...
    Open Tracing
    (Distributed Tracing)
    Open Tracing...
    Rancher
    (Infrastructure Management)
    Rancher...
    Mojaloop API Adapter
    (API - Transfers)
    Mojaloop API Adapter...
    Central-Services
    (API - Operational Admin)
    Central-Services...
    Central-Services
    (Handler - Prepare)
    Central-Services...
    Central-Services
    (Handler - Position)
    Central-Services...
    Central-Services
    (Handler - Fulfil)
    Central-Services...
    Central-Services
    (Handler - Get Transfers)
    Central-Services...
    Central-Services
    (Handler - Timeout)
    Central-Services...
    Central-KMS
    (Future - Key Management Store)
    Central-KMS...
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    ALS - Account-Lookup-Service...
    ALS-Oracle-Pathfinder
    (MSISDN Lookup)
    ALS-Oracle-Pathfinder...
    Central-Event-Processor
    (CEP)
    Central-Event-Processor...
    Email-Notifier
    (Handler - Email)
    Email-Notifier...
    Central-Services
    (Handler - Admin)
    Central-Services...
    Circle-CI
    (Test, Build, Deploy)
    Circle-CI...
    Docker Hub
    (Container Repository)
    Docker Hub...
    NPM Org
    (NPM Repository)
    NPM Org...
    GitBooks
    (Documetation)
    GitBooks...
    API Gateway (IaC)
    (API - Parties, Participants, Quotes, Transfers, Bulk Transfers; OAuth; MTLS)
    API Gateway (IaC)...
    Central-Services
    (Handler - Bulk Prepare)
    Central-Services...
    Central-Services
    (Handler - Bulk Fulfil)
    Central-Services...
    Central-Services
    (Handler - Bulk Process)
    Central-Services...
    Mojaloop API Adapter
    (API - Bulk Transfers)
    Mojaloop API Adapter...
    Forensic-Logging
    (Future - Auditing)
    Forensic-Logging...
    Central-Settlements
    (API - Settlements)
    Central-Settlements...
    Event-Stream-Processor
    (Logs, Error, Audits, Tracing)
    Event-Stream-Processor...
    Simulators
    (API, SDK, FSP & Oracle)
    Simulators...
    On-boarding
    (Postman - Scripts)
    On-boarding...
    Functional Tests
    (Postman - Scripts)
    Functional Tests...
    Testing Toolkit
    (
    UI, CLI & Backend)
    Testing Toolkit...
    License, Security & Audit
    (Dependencies)
    License, Security & Audit...
    Persistence
    Persistence
    Redis
    (SDK - Cache)
    Redis...
    MongoDB
    (CEP - Data)
    MongoDB...
    MySQL
    (Percona - Data)
    MySQL...
    Kafka
    (Message - Streaming)
    Kafka...
    Transaction Request Service
    (API - Transaction)
    Transaction Request Service...
    Software Dev Kits
    Software Dev Kits
    Oracle SDK
    (Participant Store)
    Oracle SDK...
    Mojaloop SDK 
    (FSP Payer/Payee)
    Mojaloop SDK...
    Event SDK
    (Audit, Log, Trace - Client/Server)
    Event SDK...
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    Event-Sidecar...
    Mojaloop API Adapter
    (Handler - Notifications)
    Mojaloop API Adapter...
    Quoting-Service
    (API - Quotes)
    Quoting-Service...
    Finance-Portal-UI
    (API - Bulk Transfers)
    Finance-Portal-UI...
    Settlement-Management
    (Closing, Recon report, Cronjob)
    Settlement-Management...
    Schema-Adapter
    (SDK - Parties, Participants, Quotes, Transfers)
    Schema-Adapter...
    IaC (Infra as Code) Tools
    (Automated Lab/Env Setup & Configuration)
    IaC (Infra as Code) Tools...
    Third Party API Adapter
    (PoC - API - Transfers)
    Third Party API Adapter...
    Third Party API Adapter
    (PoC - Handler - Notifications)
    Third Party API Adapter...
    Central-Settlements
    (Handler - Settlement Windows)
    Central-Settlements...
    Central-Settlements
    (Handler - Transfer Settlements)
    Central-Settlements...
    Viewer does not support full SVG 1.1
    diff --git a/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg new file mode 100644 index 000000000..06680fbae --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    Operational Monitoring
    Quality Assurance
    Quality Assurance
    Core Components
    Core Components
    API - Security / Policy / Ingress / Egress
    API - Security / Policy / Ingress / Egress
    Continuous Integration & Delivery
    Continuous Integration & Delivery
    Container Management & Orchestration
    Container Management & Orchestration
    Supporting Components
    Supporting Components
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    Helm...
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    Kubernetes...
    Docker
    (Container Engine)
    Docker...
    Infrastructure
    (AWS, Azure, On-Prem)
    Infrastructure...
    EFK - ElasticSearch / Fluentd / Kibana
    (Log Search / Collection / Monitoring / Tracing)
    EFK - ElasticSearch / Fluentd / Kibana...
    Promfana - Prometheus / Grafana
    (Metrics - Collection / Monitoring)
    Promfana - Prometheus / Grafana...
    Open Tracing
    (Distributed Tracing)
    Open Tracing...
    Rancher
    (Infrastructure Management)
    Rancher...
    Mojaloop API Adapter
    (API - Transfers)
    Mojaloop API Adapter...
    Central-Services
    (API - Operational Admin)
    Central-Services...
    Central-Services
    (Handler - Prepare)
    Central-Services...
    Central-Services
    (Handler - Position)
    Central-Services...
    Central-Services
    (Handler - Fulfil)
    Central-Services...
    Central-Services
    (Handler - Get Transfers)
    Central-Services...
    Central-Services
    (Handler - Timeout)
    Central-Services...
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    ALS - Account-Lookup-Service...
    ALS-Oracle-Pathfinder
    (MSISDN Lookup)
    ALS-Oracle-Pathfinder...
    Central-Event-Processor
    (CEP)
    Central-Event-Processor...
    Email-Notifier
    (Handler - Email)
    Email-Notifier...
    Central-Services
    (Handler - Admin)
    Central-Services...
    Circle-CI
    (Test, Build, Deploy)
    Circle-CI...
    Docker Hub
    (Container Repository)
    Docker Hub...
    NPM Org
    (NPM Repository)
    NPM Org...
    GitBooks
    (Documetation)
    GitBooks...
    API Gateway (IaC)
    (API - Parties, Participants, Quotes, Transfers, Bulk Transfers; OAuth; MTLS)
    API Gateway (IaC)...
    Central-Services
    (Handler - Bulk Prepare)
    Central-Services...
    Central-Services
    (Handler - Bulk Fulfil)
    Central-Services...
    Central-Services
    (Handler - Bulk Process)
    Central-Services...
    Mojaloop API Adapter
    (API - Bulk Transfers)
    Mojaloop API Adapter...
    Central-Settlements
    (API - Settlements)
    Central-Settlements...
    Event-Stream-Processor
    (Logs, Error, Audits, Tracing)
    Event-Stream-Processor...
    Simulators
    (API, SDK, FSP & Oracle)
    Simulators...
    On-boarding
    (Postman - Scripts)
    On-boarding...
    Functional Tests
    (Postman - Scripts)
    Functional Tests...
    Testing Toolkit
    (
    UI, CLI & Backend)
    Testing Toolkit...
    License, Security & Audit
    (Dependencies)
    License, Security & Audit...
    Persistence
    Persistence
    Redis
    (SDK - Cache)
    Redis...
    MongoDB
    (CEP - Data)
    MongoDB...
    MySQL
    (Percona - Data)
    MySQL...
    Kafka
    (Message - Streaming)
    Kafka...
    Transaction Request Service
    (API - Transaction)
    Transaction Request Service...
    Software Dev Kits
    Software Dev Kits
    Oracle SDK
    (Participant Store)
    Oracle SDK...
    Mojaloop SDK 
    (FSP Payer/Payee)
    Mojaloop SDK...
    Event SDK
    (Audit, Log, Trace - Client/Server)
    Event SDK...
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    Event-Sidecar...
    Mojaloop API Adapter
    (Handler - Notifications)
    Mojaloop API Adapter...
    Quoting-Service
    (API - Quotes)
    Quoting-Service...
    Finance-Portal-UI
    (API - Bulk Transfers)
    Finance-Portal-UI...
    Settlement-Management
    (Closing, Recon report, Cronjob)
    Settlement-Management...
    Schema-Adapter
    (SDK - Parties, Participants, Quotes, Transfers)
    Schema-Adapter...
    IaC (Infra as Code) Tools
    (Automated Lab/Env Setup & Configuration)
    IaC (Infra as Code) Tools...
    Third Party API Adapter
    (PoC - API - Transfers)
    Third Party API Adapter...
    Third Party API Adapter
    (PoC - Handler - Notifications)
    Third Party API Adapter...
    Central-Settlements
    (Handler - Deferred)
    Central-Settlements...
    Central-Settlements
    (Handler - Gross)
    Central-Settlements...
    Central-Settlements
    (Handler - Rules)
    Central-Settlements...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI3.svg b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI3.svg new file mode 100644 index 000000000..4a658b897 --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI3.svg @@ -0,0 +1,3 @@ + + +
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    [Not supported by viewer]
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    [Not supported by viewer]
    Docker
    (Container Engine)
    [Not supported by viewer]
    Infrastructure
    (AWS, Azure, On-Prem)
    [Not supported by viewer]
    EFK - ElasticSearch / Fluentd / Kabana
    (Log Search / Collection / Monitoring)
    [Not supported by viewer]
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    [Not supported by viewer]
    Zipkin
    (Future - Distributed Tracing)
    [Not supported by viewer]
    Rancher
    (Infrastructure Management)
    [Not supported by viewer]
    PostgreSQL
    (Deprecated - Data)
    [Not supported by viewer]
    MongoDB
    (CEP - Data)
    [Not supported by viewer]
    MySQL
    (Percona - Data)
    [Not supported by viewer]
    Kafka
    (Message - Streaming)
    [Not supported by viewer]
    Mojaloop API Adapter
    (API - Transfers)
    [Not supported by viewer]
    Mojaloop API Adapter
    (Handler - Notifications)
    [Not supported by viewer]
    Central-Services
    (API - Operational Admin)
    [Not supported by viewer]
    Central-Services
    (Handler - Prepare)
    [Not supported by viewer]
    Central-Services
    (Handler - Position)
    [Not supported by viewer]
    Central-Services
    (Handler - Fulfil)
    [Not supported by viewer]
    Central-Services
    (Handler - Get Transfers)
    [Not supported by viewer]
    Central-Services
    (Handler - Timeout)
    [Not supported by viewer]
    Simulator
    (API - QA FSP Simulator)
    [Not supported by viewer]
    Forensic-Logging-Sidecar
    (Auditing)
    [Not supported by viewer]
    Central-KMS
    (Key Management Store)
    [Not supported by viewer]
    Central-Directory
    (Participant Lookup)
    [Not supported by viewer]
    Central-End-User-Registry
    (Custom Participant Store)
    [Not supported by viewer]
    Mock-Pathfinder
    (Mocked Pathfinder)
    [Not supported by viewer]
    Central-Event-Processor
    (CEP)
    [Not supported by viewer]
    Email-Notifier
    (Handler - Email)
    [Not supported by viewer]
    Central-Services
    (Handler - Admin)
    [Not supported by viewer]
    Central-Hub
    (Retired - Operational Web Interface)
    [Not supported by viewer]
    Interop-Switch
    (To be Retired - Transfers, Quotes, Parties, Participants)
    [Not supported by viewer]
    Circle-CI
    (Test, Build, Deploy)
    [Not supported by viewer]
    Docker Hub
    (Container Repository)
    [Not supported by viewer]
    NPM Org
    (NPM Repository)
    [Not supported by viewer]
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI5.svg b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI5.svg new file mode 100644 index 000000000..ac0b21621 --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI5.svg @@ -0,0 +1,3 @@ + + +
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    [Not supported by viewer]
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    [Not supported by viewer]
    Docker
    (Container Engine)
    [Not supported by viewer]
    Infrastructure
    (AWS, Azure, On-Prem)
    [Not supported by viewer]
    EFK - ElasticSearch / Fluentd / Kabana
    (Log Search / Collection / Monitoring)
    [Not supported by viewer]
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    [Not supported by viewer]
    Zipkin
    (Future - Distributed Tracing)
    [Not supported by viewer]
    Rancher
    (Infrastructure Management)
    [Not supported by viewer]
    PostgreSQL
    (Deprecated - Data)
    [Not supported by viewer]
    MongoDB
    (CEP - Data)
    [Not supported by viewer]
    MySQL
    (Percona - Data)
    [Not supported by viewer]
    Kafka
    (Message - Streaming)
    [Not supported by viewer]
    Mojaloop API Adapter
    (API - Transfers)
    [Not supported by viewer]
    Mojaloop API Adapter
    (Handler - Notifications)
    [Not supported by viewer]
    Central-Services
    (API - Operational Admin)
    [Not supported by viewer]
    Central-Services
    (Handler - Prepare)
    [Not supported by viewer]
    Central-Services
    (Handler - Position)
    [Not supported by viewer]
    Central-Services
    (Handler - Fulfil)
    [Not supported by viewer]
    Central-Services
    (Handler - Get Transfers)
    [Not supported by viewer]
    Central-Services
    (Handler - Timeout)
    [Not supported by viewer]
    Simulator
    (API - QA FSP Simulator)
    [Not supported by viewer]
    Forensic-Logging-Sidecar
    (Auditing)
    [Not supported by viewer]
    Central-KMS
    (Key Management Store)
    [Not supported by viewer]
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    [Not supported by viewer]
    ALS-Oracle-Msisdn-Service
    (Pathfinder Lookup Adapter)
    [Not supported by viewer]
    Mock-Pathfinder
    (Mocked Pathfinder)
    [Not supported by viewer]
    Central-Event-Processor
    (CEP)
    [Not supported by viewer]
    Email-Notifier
    (Handler - Email)
    [Not supported by viewer]
    Central-Services
    (Handler - Admin)
    [Not supported by viewer]
    Moja-Hub
    (Future - Operational Web Interface)
    [Not supported by viewer]
    Interop-Switch
    (To be Retired - Transfers, Quotes, Parties, Participants)
    [Not supported by viewer]
    Circle-CI
    (Test, Build, Deploy)
    [Not supported by viewer]
    Docker Hub
    (Container Repository)
    [Not supported by viewer]
    NPM Org
    (NPM Repository)
    [Not supported by viewer]
    GitBooks
    (Documetation)
    [Not supported by viewer]
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI6.svg b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI6.svg new file mode 100644 index 000000000..9697dfc5b --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI6.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    <b>Operational Monitoring</b>
    Quality Assurance
    <b>Quality Assurance</b>
    Core
    <b>Core</b>
    API - Security / Policy / Ingress / Egress
    <b>API - Security / Policy / Ingress / Egress</b>
    Continuous Integration & Delivery
    <b>Continuous Integration & Delivery</b>
    Container Management & Orchestration
    <b>Container Management & Orchestration</b>
    Persistence
    <b>Persistence</b>
    Scaffolding
    [Not supported by viewer]
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    [Not supported by viewer]
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    [Not supported by viewer]
    Docker
    (Container Engine)
    [Not supported by viewer]
    Infrastructure
    (AWS, Azure, On-Prem)
    [Not supported by viewer]
    EFK - ElasticSearch / Fluentd / Kabana
    (Log Search / Collection / Monitoring / PoC - Tracing)
    [Not supported by viewer]
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    [Not supported by viewer]
    Open Tracing
    (POC - Distributed Tracing)
    [Not supported by viewer]
    Rancher
    (Infrastructure Management)
    [Not supported by viewer]
    PostgreSQL
    (Deprecated - Data)
    [Not supported by viewer]
    MongoDB
    (CEP - Data)
    [Not supported by viewer]
    MySQL
    (Percona - Data)
    [Not supported by viewer]
    Kafka
    (Message - Streaming)
    [Not supported by viewer]
    Mojaloop API Adapter
    (API - Transfers)
    [Not supported by viewer]
    Mojaloop API Adapter
    (Handler - Notifications)
    [Not supported by viewer]
    Central-Services
    (API - Operational Admin)
    [Not supported by viewer]
    Central-Services
    (Handler - Prepare)
    [Not supported by viewer]
    Central-Services
    (Handler - Position)
    [Not supported by viewer]
    Central-Services
    (Handler - Fulfil)
    [Not supported by viewer]
    Central-Services
    (Handler - Get Transfers)
    [Not supported by viewer]
    Central-Services
    (Handler - Timeout)
    [Not supported by viewer]
    Event-Logging-Sidecar
    (POC - Logs, Error, Audits, Tracing)
    [Not supported by viewer]
    Central-KMS
    (Key Management Store)
    [Not supported by viewer]
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    [Not supported by viewer]
    ALS-Oracle-Pathfinder-Service
    (Future - MSISDN Lookup)
    [Not supported by viewer]
    Quoting-Service
    (API - Quotes)
    [Not supported by viewer]
    Central-Event-Processor
    (CEP, POCLogs, Error, Audits, Tracing)
    [Not supported by viewer]
    Email-Notifier
    (Handler - Email)
    [Not supported by viewer]
    Central-Services
    (Handler - Admin)
    [Not supported by viewer]
    Moja-Hub
    (Future - Operational UI)
    [Not supported by viewer]
    Circle-CI
    (Test, Build, Deploy)
    [Not supported by viewer]
    Docker Hub
    (Container Repository)
    [Not supported by viewer]
    NPM Org
    (NPM Repository)
    [Not supported by viewer]
    GitBooks
    (Documetation)
    [Not supported by viewer]
    API Gateway
    (POC - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)
    <b>API Gateway<br></b>(<b><font color="#ff1b0a">POC</font></b> - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)<br>
    Central-Services
    (Handler - Bulk Prepare)
    [Not supported by viewer]
    Central-Services
    (Handler - Bulk Fulfil)
    [Not supported by viewer]
    Central-Services
    (Handler - Bulk Process)
    [Not supported by viewer]
    Mojaloop API Adapter
    (API - Bulk Transfers)
    [Not supported by viewer]
    Forensic-Logging-Sidecar
    (Deprecated - Auditing)
    [Not supported by viewer]
    Simulator
    (API - FSP Simulator /
    API - Oracle Simulator)

    [Not supported by viewer]
    Central-Settlements
    (API - Settlement)
    [Not supported by viewer]
    On-boarding
    (Postman - Scripts)
    [Not supported by viewer]
    Functional Tests
    (Postman - Scripts)
    [Not supported by viewer]
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI7.svg b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI7.svg new file mode 100644 index 000000000..2fedecbc1 --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI7.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    <b>Operational Monitoring</b>
    Quality Assurance
    <b>Quality Assurance</b>
    Core Components
    <b>Core Components</b>
    API - Security / Policy / Ingress / Egress
    <b>API - Security / Policy / Ingress / Egress</b>
    Continuous Integration & Delivery
    <b>Continuous Integration & Delivery</b>
    Container Management & Orchestration
    <b>Container Management & Orchestration</b>
    Supporting Components
    <b style="line-height: 0%">Supporting Components</b>
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    [Not supported by viewer]
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    [Not supported by viewer]
    Docker
    (Container Engine)
    [Not supported by viewer]
    Infrastructure
    (AWS, Azure, On-Prem)
    [Not supported by viewer]
    EFK - ElasticSearch / Fluentd / Kabana
    (Log Search / Collection / Monitoring / PoC - Tracing)
    [Not supported by viewer]
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    [Not supported by viewer]
    Open Tracing
    (POC - Distributed Tracing)
    [Not supported by viewer]
    Rancher
    (Infrastructure Management)
    [Not supported by viewer]
    Mojaloop API Adapter
    (API - Transfers)
    [Not supported by viewer]
    Central-Services
    (API - Operational Admin)
    [Not supported by viewer]
    Central-Services
    (Handler - Prepare)
    [Not supported by viewer]
    Central-Services
    (Handler - Position)
    [Not supported by viewer]
    Central-Services
    (Handler - Fulfil)
    [Not supported by viewer]
    Central-Services
    (Handler - Get Transfers)
    [Not supported by viewer]
    Central-Services
    (Handler - Timeout)
    [Not supported by viewer]
    Central-KMS
    (Key Management Store)
    [Not supported by viewer]
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    [Not supported by viewer]
    ALS-Oracle-Pathfinder-Service
    (Future - MSISDN Lookup)
    [Not supported by viewer]
    Central-Event-Processor
    (CEP)
    [Not supported by viewer]
    Email-Notifier
    (Handler - Email)
    [Not supported by viewer]
    Central-Services
    (Handler - Admin)
    [Not supported by viewer]
    Circle-CI
    (Test, Build, Deploy)
    [Not supported by viewer]
    Docker Hub
    (Container Repository)
    [Not supported by viewer]
    NPM Org
    (NPM Repository)
    [Not supported by viewer]
    GitBooks
    (Documetation)
    [Not supported by viewer]
    API Gateway
    (POC - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)
    <b>API Gateway<br></b>(<b><font color="#ff1b0a">POC</font></b> - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)<br>
    Central-Services
    (Handler - Bulk Prepare)
    [Not supported by viewer]
    Central-Services
    (Handler - Bulk Fulfil)
    [Not supported by viewer]
    Central-Services
    (Handler - Bulk Process)
    [Not supported by viewer]
    Mojaloop API Adapter
    (API - Bulk Transfers)
    [Not supported by viewer]
    Forensic-Logging
    (Future - Auditing)
    [Not supported by viewer]
    Central-Settlements
    (API - Settlement)
    [Not supported by viewer]
    Event-Stream-Processor
    Logs, Error, Audits, Tracing)
    [Not supported by viewer]
    Simulator
    (API - FSP & Oracle Simulator)
    [Not supported by viewer]
    On-boarding
    (Postman - Scripts)
    [Not supported by viewer]
    Functional Tests
    (Postman - Scripts)
    [Not supported by viewer]
    Mojaloop-Simulator
    (SDK)
    [Not supported by viewer]
    License & Audit
    (Dependencies)
    [Not supported by viewer]
    Persistence
    <b>Persistence</b>
    PostgreSQL
    (Deprecated - Data)
    [Not supported by viewer]
    MongoDB
    (CEP - Data)
    [Not supported by viewer]
    MySQL
    (Percona - Data)
    [Not supported by viewer]
    Kafka
    (Message - Streaming)
    [Not supported by viewer]
    Transaction Request Service
    (API - Transaction)
    <b>Transaction Request Service</b><br>(API - Transaction)
    Software Dev Kits
    <b>Software Dev Kits</b>
    Oracle SDK
    (Participant Store)
    [Not supported by viewer]
    Mojaloop SDK 
    (FSP Payer/Payee)
    [Not supported by viewer]
    Event SDK
    (Audit, Log, Trace - Client/Server)
    [Not supported by viewer]
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    <b>Event-Sidecar</b><br>(Logs, Error, Audits, Tracing)
    Mojaloop API Adapter
    (Handler - Notifications)
    [Not supported by viewer]
    Quoting-Service
    (API - Quotes)
    [Not supported by viewer]
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg new file mode 100644 index 000000000..3e5b75f13 --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    Operational Monitoring
    Quality Assurance
    Quality Assurance
    Core Components
    Core Components
    API - Security / Policy / Ingress / Egress
    API - Security / Policy / Ingress / Egress
    Continuous Integration & Delivery
    Continuous Integration & Delivery
    Container Management & Orchestration
    Container Management & Orchestration
    Supporting Components
    Supporting Components
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    Helm...
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    Kubernetes...
    Docker
    (Container Engine)
    Docker...
    Infrastructure
    (AWS, Azure, On-Prem)
    Infrastructure...
    EFK - ElasticSearch / Fluentd / Kibana
    (Log Search / Collection / Monitoring / Tracing)
    EFK - ElasticSearch / Fluentd / Kibana...
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    Promfana - Prometheus / Grafana...
    Open Tracing
    (Distributed Tracing)
    Open Tracing...
    Rancher
    (Infrastructure Management)
    Rancher...
    Mojaloop API Adapter
    (API - Transfers)
    Mojaloop API Adapter...
    Central-Services
    (API - Operational Admin)
    Central-Services...
    Central-Services
    (Handler - Prepare)
    Central-Services...
    Central-Services
    (Handler - Position)
    Central-Services...
    Central-Services
    (Handler - Fulfil)
    Central-Services...
    Central-Services
    (Handler - Get Transfers)
    Central-Services...
    Central-Services
    (Handler - Timeout)
    Central-Services...
    Central-KMS
    (Future - Key Management Store)
    Central-KMS...
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    ALS - Account-Lookup-Service...
    ALS-Oracle-Pathfinder
    (MSISDN Lookup)
    ALS-Oracle-Pathfinder...
    Central-Event-Processor
    (CEP)
    Central-Event-Processor...
    Email-Notifier
    (Handler - Email)
    Email-Notifier...
    Central-Services
    (Handler - Admin)
    Central-Services...
    Circle-CI
    (Test, Build, Deploy)
    Circle-CI...
    Docker Hub
    (Container Repository)
    Docker Hub...
    NPM Org
    (NPM Repository)
    NPM Org...
    GitBooks
    (Documetation)
    GitBooks...
    API Gateway
    (Future - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)
    API Gateway...
    Central-Services
    (Handler - Bulk Prepare)
    Central-Services...
    Central-Services
    (Handler - Bulk Fulfil)
    Central-Services...
    Central-Services
    (Handler - Bulk Process)
    Central-Services...
    Mojaloop API Adapter
    (API - Bulk Transfers)
    Mojaloop API Adapter...
    Forensic-Logging
    (Future - Auditing)
    Forensic-Logging...
    Central-Settlements
    (API - Settlement)
    Central-Settlements...
    Event-Stream-Processor
    Logs, Error, Audits, Tracing)
    Event-Stream-Processor...
    Simulators
    (API, SDK, FSP & Oracle)
    Simulators...
    On-boarding
    (Postman - Scripts)
    On-boarding...
    Functional Tests
    (Postman - Scripts)
    Functional Tests...
    Self Testing Toolkit
    (
    POC UI)
    Self Testing Toolkit...
    License, Security & Audit
    (Dependencies)
    License, Security & Audit...
    Persistence
    Persistence
    Redis
    (SDK - Cache)
    Redis...
    MongoDB
    (CEP - Data)
    MongoDB...
    MySQL
    (Percona - Data)
    MySQL...
    Kafka
    (Message - Streaming)
    Kafka...
    Transaction Request Service
    (API - Transaction)
    Transaction Request Service...
    Software Dev Kits
    Software Dev Kits
    Oracle SDK
    (Participant Store)
    Oracle SDK...
    Mojaloop SDK 
    (FSP Payer/Payee)
    Mojaloop SDK...
    Event SDK
    (Audit, Log, Trace - Client/Server)
    Event SDK...
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    Event-Sidecar...
    Mojaloop API Adapter
    (Handler - Notifications)
    Mojaloop API Adapter...
    Quoting-Service
    (API - Quotes)
    Quoting-Service...
    Finance-Portal-UI
    (API - Bulk Transfers)
    Finance-Portal-UI...
    Settlement-Management
    (Closing, Recon report, Cronjob)
    Settlement-Management...
    Schema-Adapter
    (SDK - Parties, Participants, Quotes, Transfers)
    Schema-Adapter...
    IaC (Infra as Code) Tools
    (Future - Automated
    Prov / Depl / Upgrades)
    IaC (Infra as Code) Tools...
    \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/overview/components-PI11.md b/legacy/mojaloop-technical-overview/overview/components-PI11.md new file mode 100644 index 000000000..35b839657 --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/components-PI11.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Current Components - PI11 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI11: + +![Mojaloop Architecture Overview PI11](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI11.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/legacy/mojaloop-technical-overview/overview/components-PI12.md b/legacy/mojaloop-technical-overview/overview/components-PI12.md new file mode 100644 index 000000000..d90d82eb9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/components-PI12.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Current Components - PI12 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI12: + +![Mojaloop Architecture Overview PI12](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI12.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/legacy/mojaloop-technical-overview/overview/components-PI14.md b/legacy/mojaloop-technical-overview/overview/components-PI14.md new file mode 100644 index 000000000..d4c4e3887 --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/components-PI14.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Current Components - PI14 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI14: + +![Mojaloop Architecture Overview PI14](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/legacy/mojaloop-technical-overview/overview/components-PI3.md b/legacy/mojaloop-technical-overview/overview/components-PI3.md new file mode 100644 index 000000000..a3cb1b686 --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/components-PI3.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Legacy Components - PI3 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI3: + +![Mojaloop Architecture Overview PI5](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI3.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/legacy/mojaloop-technical-overview/overview/components-PI5.md b/legacy/mojaloop-technical-overview/overview/components-PI5.md new file mode 100644 index 000000000..f54ac4856 --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/components-PI5.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Legacy Components - PI5 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI5: + +![Mojaloop Architecture Overview PI5](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI5.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/legacy/mojaloop-technical-overview/overview/components-PI6.md b/legacy/mojaloop-technical-overview/overview/components-PI6.md new file mode 100644 index 000000000..a935f7cc5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/components-PI6.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Legacy Components - PI6 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI6: + +![Mojaloop Architecture Overview PI6](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI6.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/legacy/mojaloop-technical-overview/overview/components-PI7.md b/legacy/mojaloop-technical-overview/overview/components-PI7.md new file mode 100644 index 000000000..f2f59dd8a --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/components-PI7.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Legacy Components - PI7 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI7: + +![Mojaloop Architecture Overview PI7](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI7.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/legacy/mojaloop-technical-overview/overview/components-PI8.md b/legacy/mojaloop-technical-overview/overview/components-PI8.md new file mode 100644 index 000000000..3d18e7fac --- /dev/null +++ b/legacy/mojaloop-technical-overview/overview/components-PI8.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Legacy Components - PI8 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI8: + +![Mojaloop Architecture Overview PI8](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/legacy/mojaloop-technical-overview/quoting-service/README.md b/legacy/mojaloop-technical-overview/quoting-service/README.md new file mode 100644 index 000000000..094ac1de2 --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/README.md @@ -0,0 +1,8 @@ +# Quoting Service Overview +The **Quoting Service** (**QS**) _(refer to section `5.1`)_ as per the [Mojaloop {{ book.importedVars.mojaloop.spec.version }} Specification]({{ book.importedVars.mojaloop.spec.uri.doc }}) implements the quoting phase of the various use-cases. + +_Note: In addition to individual quotes, the quoting service supports bulk quotes as well._ + +## Sequence Diagram + +![seq-quotes-1.0.0.svg](./assets/diagrams/sequence/seq-quotes-1.0.0.svg) diff --git a/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.plantuml b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.plantuml new file mode 100644 index 000000000..0405a9868 --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.plantuml @@ -0,0 +1,92 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- +******'/ + +@startuml +Title Retrieve Bulk Quote Information +participant "Payer FSP" as PayerFSP +participant "Switch\n[Quoting Service]" as Switch +participant "Payee FSP" as PayeeFSP + +autonumber +note right of PayerFSP: Payer FSP sends request to get bulk quote details \nto Payee FSP via the Switch +PayerFSP -\ Switch: GET /bulkQuotes/{ID} +note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** +end note +Switch -> Switch: Schema validation +PayerFSP \-- Switch: 202 Accepted +Switch -> Switch: Retrieve bulk quotes endpoint for Payee FSP +alt Payee FSP quotes endpoint is found + note right of Switch: Switch forwards request to Payee FSP (pass-through mode) + Switch -\ PayeeFSP: GET /bulkQuotes/{ID} + PayeeFSP --/ Switch: 202 Accepted + PayeeFSP -> PayeeFSP: Payee FSP retireves bulk quote + alt Payee FSP successfully retieves quote + note left of PayeeFSP: Payee FSP responds to quote request + PayeeFSP -\ Switch: PUT /quotes/{ID} + note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** + end note + Switch --/ PayeeFSP: 200 Ok + alt Response is ok + Switch -> Switch: Retrieve bulk quotes endpoint for the Payer FSP + alt Bulk Quotes callback endpoint found + note left of Switch: Switch forwards bulk quote response to Payer FSP + Switch -\ PayerFSP: PUT /bulkQuotes/{ID} + PayerFSP --/ Switch: 200 Ok + else Bulk Quotes callback endpoint not found + note right of Switch: Switch returns error to Payee FSP + Switch -\ PayeeFSP: PUT /bulkQuotes/{ID}/error + PayeeFSP --/ Switch : 200 Ok + end + else Response is invalid + note right of Switch: Switch returns error to Payee FSP + Switch -\ PayeeFSP: PUT /bulkQuotes/{ID}/error + PayeeFSP --/ Switch : 200 Ok + note over Switch, PayeeFSP #ec7063: Note that under this\nscenario the Payer FSP\nmay not receive a response + end + + else bulkQuote not found + note left of PayeeFSP: Payee FSP returns error to Switch\n **Error code: 3205** + PayeeFSP -\ Switch: PUT /bulkQuotes/{ID}/error + Switch --/ PayeeFSP: 200 OK + note left of Switch: Switch returns error to Payer FSP\n **Error code: 3205** + Switch -\ PayerFSP: PUT /bulkQuotes/{ID}/error + PayerFSP --/ Switch: 200 OK + end +else Payee FSP Bulk quotes endpoint is not found + note left of Switch + Switch returns error to Payer FSP + **Error code: 3201** + end note + PayerFSP /- Switch: PUT /bulkQuotes/{ID}error + PayerFSP --/ Switch: 200 OK +end +@enduml diff --git a/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.svg b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.svg new file mode 100644 index 000000000..9cab870cb --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.svg @@ -0,0 +1,369 @@ + + + + + + + + + + + Retrieve Bulk Quote Information + + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + [Quoting Service] + + + + Switch + + + [Quoting Service] + + + + Payee FSP + + + + Payee FSP + + + + + Payer FSP sends request to get bulk quote details + + + to Payee FSP via the Switch + + + + + 1 + + + GET /bulkQuotes/{ID} + + + + + Validate request against + + + Mojaloop interface specification + + + Error code: 300x, 310x + + + HTTP error response code: 4xx + + + + + 2 + + + Schema validation + + + + + 3 + + + 202 Accepted + + + + + 4 + + + Retrieve bulk quotes endpoint for Payee FSP + + + + + alt + + + [Payee FSP quotes endpoint is found] + + + + + Switch forwards request to Payee FSP (pass-through mode) + + + + + 5 + + + GET /bulkQuotes/{ID} + + + + + 6 + + + 202 Accepted + + + + + 7 + + + Payee FSP retireves bulk quote + + + + + alt + + + [Payee FSP successfully retieves quote] + + + + + Payee FSP responds to quote request + + + + + 8 + + + PUT /quotes/{ID} + + + + + Validate request against + + + Mojaloop interface specification + + + Error code: 300x, 310x + + + HTTP error response code: 4xx + + + + + 9 + + + 200 Ok + + + + + alt + + + [Response is ok] + + + + + 10 + + + Retrieve bulk quotes endpoint for the Payer FSP + + + + + alt + + + [Bulk Quotes callback endpoint found] + + + + + Switch forwards bulk quote response to Payer FSP + + + + + 11 + + + PUT /bulkQuotes/{ID} + + + + + 12 + + + 200 Ok + + + + [Bulk Quotes callback endpoint not found] + + + + + Switch returns error to Payee FSP + + + + + 13 + + + PUT /bulkQuotes/{ID}/error + + + + + 14 + + + 200 Ok + + + + [Response is invalid] + + + + + Switch returns error to Payee FSP + + + + + 15 + + + PUT /bulkQuotes/{ID}/error + + + + + 16 + + + 200 Ok + + + + + Note that under this + + + scenario the Payer FSP + + + may not receive a response + + + + [bulkQuote not found] + + + + + Payee FSP returns error to Switch + + + Error code: 3205 + + + + + 17 + + + PUT /bulkQuotes/{ID}/error + + + + + 18 + + + 200 OK + + + + + Switch returns error to Payer FSP + + + Error code: 3205 + + + + + 19 + + + PUT /bulkQuotes/{ID}/error + + + + + 20 + + + 200 OK + + + + [Payee FSP Bulk quotes endpoint is not found] + + + + + Switch returns error to Payer FSP + + + Error code: 3201 + + + + + 21 + + + PUT /bulkQuotes/{ID}error + + + + + 22 + + + 200 OK + + diff --git a/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.plantuml b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.plantuml new file mode 100644 index 000000000..dfcb1918b --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.plantuml @@ -0,0 +1,86 @@ +@startuml +Title Retrieve Quote Information +participant "Payer FSP" as PayerFSP +participant "Switch\n[Quoting\nService]" as Switch +database "Central Store" as DB +participant "Payee FSP" as PayeeFSP +autonumber +note right of PayerFSP: Payer FSP sends request to get quote details \nto Payee FSP via the Switch +PayerFSP -\ Switch: GET /quotes/{ID} +note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** +end note +Switch -> Switch: Schema validation +PayerFSP \-- Switch: 202 Accepted +Switch -> Switch: Retrieve quotes endpoint for Payee FSP +alt Payee FSP quotes endpoint is found + note right of Switch: Switch forwards request to Payee FSP (pass-through mode)\n + Switch -\ PayeeFSP: GET /quotes/{ID} + PayeeFSP --/ Switch: 202 Accepted + PayeeFSP -> PayeeFSP: Payee FSP retireves quote + alt Payee FSP successfully retieves quote + note left of PayeeFSP: Payee FSP responds to quote request + PayeeFSP -\ Switch: PUT /quotes/{ID} + Switch --/ PayeeFSP: 200 Ok + Switch -> Switch: Validate response (schema, headers (**Error code: 3100**)) + alt Response is ok + alt SimpleRoutingMode is FALSE + Switch -> Switch: Validate response (duplicate response check, handle resend scenario (**Error code: 3106**)) + alt Validation passed + Switch -\ DB: Persist quote response + activate DB + hnote over DB + quoteResponse + quoteResponseDuplicateCheck + quoteResponseIlpPacket + quoteExtensions + geoCode + end hnote + Switch \-- DB: Quote response saved + deactivate DB + end + end + alt SimpleRoutingMode is TRUE + Switch -> Switch: Retrieve quotes endpoint for the Payer FSP + else SimpleRoutingMode is FALSE + Switch -> Switch: Retrieve quote party endpoint (PAYER) + end + alt Quotes callback endpoint found + note left of Switch: Switch forwards quote response to Payer FSP\n + Switch -\ PayerFSP: PUT /quotes/{ID} + PayerFSP --/ Switch: 200 Ok + else Quotes callback endpoint not found + note right of Switch: Switch returns error to Payee FSP + Switch -\ PayeeFSP: PUT /quotes/{ID}/error + PayeeFSP --/ Switch : 200 Ok + end + else Response is invalid + note right of Switch: Switch returns error to Payee FSP + Switch -\ PayeeFSP: PUT /quotes/{ID}/error + PayeeFSP --/ Switch : 200 Ok + note over Switch, PayeeFSP #ec7063: Note that under this\nscenario the Payer FSP\nmay not receive a response + end + + else Quote not found + note left of PayeeFSP: Payee FSP returns error to Switch\n **Error code: 3205** + PayeeFSP -\ Switch: PUT quotes/{ID}/error + Switch --/ PayeeFSP: 200 OK + alt SimpleRoutingMode is FALSE + Switch -> Switch: Persist error data + end + note left of Switch: Switch returns error to Payer FSP\n **Error code: 3205** + Switch -\ PayerFSP: PUT quotes/{ID}/error + PayerFSP --/ Switch: 200 OK + end +else Payee FSP quotes endpoint is not found + note left of Switch + Switch returns error to Payer FSP + **Error code: 3201** + end note + PayerFSP /- Switch: PUT quotes/{ID}error + PayerFSP --/ Switch: 200 OK +end +@enduml diff --git a/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.svg b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.svg new file mode 100644 index 000000000..679d20f98 --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.svg @@ -0,0 +1,496 @@ + + + + + + + + + + + Retrieve Quote Information + + + + + + + + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + [Quoting + + + Service] + + + + Switch + + + [Quoting + + + Service] + + + Central Store + + + + + Central Store + + + + + + Payee FSP + + + + Payee FSP + + + + + + Payer FSP sends request to get quote details + + + to Payee FSP via the Switch + + + + + 1 + + + GET /quotes/{ID} + + + + + Validate request against + + + Mojaloop interface specification + + + Error code: 300x, 310x + + + HTTP error response code: 4xx + + + + + 2 + + + Schema validation + + + + + 3 + + + 202 Accepted + + + + + 4 + + + Retrieve quotes endpoint for Payee FSP + + + + + alt + + + [Payee FSP quotes endpoint is found] + + + + + Switch forwards request to Payee FSP (pass-through mode) + + + <Payer based Rules> + + + + + 5 + + + GET /quotes/{ID} + + + + + 6 + + + 202 Accepted + + + + + 7 + + + Payee FSP retireves quote + + + + + alt + + + [Payee FSP successfully retieves quote] + + + + + Payee FSP responds to quote request + + + + + 8 + + + PUT /quotes/{ID} + + + + + 9 + + + 200 Ok + + + + + 10 + + + Validate response (schema, headers ( + + + Error code: 3100 + + + )) + + + + + alt + + + [Response is ok] + + + + + alt + + + [SimpleRoutingMode is FALSE] + + + + + 11 + + + Validate response (duplicate response check, handle resend scenario ( + + + Error code: 3106 + + + )) + + + + + alt + + + [Validation passed] + + + + + 12 + + + Persist quote response + + + + quoteResponse + + + quoteResponseDuplicateCheck + + + quoteResponseIlpPacket + + + quoteExtensions + + + geoCode + + + + + 13 + + + Quote response saved + + + + + alt + + + [SimpleRoutingMode is TRUE] + + + + + 14 + + + Retrieve quotes endpoint for the Payer FSP + + + + [SimpleRoutingMode is FALSE] + + + + + 15 + + + Retrieve quote party endpoint (PAYER) + + + + + alt + + + [Quotes callback endpoint found] + + + + + Switch forwards quote response to Payer FSP + + + <Payee whole request Rule> + + + + + 16 + + + PUT /quotes/{ID} + + + + + 17 + + + 200 Ok + + + + [Quotes callback endpoint not found] + + + + + Switch returns error to Payee FSP + + + + + 18 + + + PUT /quotes/{ID}/error + + + + + 19 + + + 200 Ok + + + + [Response is invalid] + + + + + Switch returns error to Payee FSP + + + + + 20 + + + PUT /quotes/{ID}/error + + + + + 21 + + + 200 Ok + + + + + Note that under this + + + scenario the Payer FSP + + + may not receive a response + + + + [Quote not found] + + + + + Payee FSP returns error to Switch + + + Error code: 3205 + + + + + 22 + + + PUT quotes/{ID}/error + + + + + 23 + + + 200 OK + + + + + alt + + + [SimpleRoutingMode is FALSE] + + + + + 24 + + + Persist error data + + + + + Switch returns error to Payer FSP + + + Error code: 3205 + + + + + 25 + + + PUT quotes/{ID}/error + + + + + 26 + + + 200 OK + + + + [Payee FSP quotes endpoint is not found] + + + + + Switch returns error to Payer FSP + + + Error code: 3201 + + + + + 27 + + + PUT quotes/{ID}error + + + + + 28 + + + 200 OK + + diff --git a/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.plantuml b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.plantuml new file mode 100644 index 000000000..ca4c1d30f --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.plantuml @@ -0,0 +1,99 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- +******'/ + +@startuml +Title Request Bulk Quote Creation +participant "Payer FSP" as PayerFSP +participant "Switch\n[Quoting Service]" as Switch +participant "Payee FSP" as PayeeFSP +autonumber + +note over PayerFSP, Switch: Payer FSP sends bulk quote request\nto Payee FSP via the Switch +PayerFSP -\ Switch: POST /bulkQuotes +note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** +end note +Switch -> Switch: Schema validation +PayerFSP \-- Switch: 202 Accepted +||| +Switch -> Switch: Bulk Quote request validation (rules engine etc.) +||| +Switch -> Switch: Duplicate check +||| +alt Request is a duplicate but not a resend +||| + note left of Switch + Switch returns error back to Payer FSP + **Error code: 3106** + end note + PayerFSP /- Switch: PUT /bulkQuotes/{ID}/error + PayerFSP --/ Switch: 200 OK +||| +else Request is a duplicate and a resend + Switch -> Switch: Switch handles resend scenario +end +||| +Switch -> Switch: Use fspiop-destination header to retrieve\n bulk quotes endpoint for Payee DFSP +alt Payee bulk quotes endpoint found + note right of Switch: Switch forwards bulk quote request to Payee FSP + Switch -\ PayeeFSP: POST /bulkQuotes + Switch \-- PayeeFSP: 202 OK + + PayeeFSP -> PayeeFSP: Payee FSP calculates individual quotes\nand responds with a bulk quote result + alt Payee bulkQuotes processing successful + note over PayeeFSP, Switch: Payee FSP sends bulk quote response back to Payer FSP via the Switch + Switch /- PayeeFSP: PUT /bulkQuotes/{ID} + Switch --/ PayeeFSP: 200 OK + + Switch -> Switch: Validate bulk quote response + Switch -> Switch: Duplicate check + alt Response is duplicate but not a resend + Switch -\ PayeeFSP: PUT /bulkQuotes/{ID}/error + Switch \-- PayeeFSP: 200 OK + end + alt Response is a duplicate and a resend + Switch -> Switch: Switch handles resend scenario + end + + note left of Switch: Switch forwards quote response to Payer FSP + PayerFSP /- Switch: PUT /bulkQuotes/{ID} + PayerFSP --/ Switch: 200 OK + else Payee rejects bulk quote or encounters an error + note left of PayeeFSP: Payee FSP sends error callback to Payer FSP via the Switch + Switch /- PayeeFSP: PUT /bulkQuotes/{ID}/error + Switch --/ PayeeFSP: 200 OK + note left of Switch: Switch forwards error callback to Payer FSP + PayerFSP /- Switch: PUT /bulkQuotes/{ID}/error + PayerFSP --/ Switch: 200 OK + end +else Payee FSP quotes endpoint not found + note left of Switch: Switch sends an error callback to Payer FSP \n **Error code: 3201** + PayerFSP /- Switch: PUT /bulkQuotes/{ID}/error + PayerFSP --\ Switch: 200 OK +end + +@enduml diff --git a/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.svg b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.svg new file mode 100644 index 000000000..4b3363dd6 --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.svg @@ -0,0 +1,387 @@ + + + + + + + + + + + Request Bulk Quote Creation + + + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + [Quoting Service] + + + + Switch + + + [Quoting Service] + + + + Payee FSP + + + + Payee FSP + + + + + Payer FSP sends bulk quote request + + + to Payee FSP via the Switch + + + + + 1 + + + POST /bulkQuotes + + + + + Validate request against + + + Mojaloop interface specification + + + Error code: 300x, 310x + + + HTTP error response code: 4xx + + + + + 2 + + + Schema validation + + + + + 3 + + + 202 Accepted + + + + + 4 + + + Bulk Quote request validation (rules engine etc.) + + + + + 5 + + + Duplicate check + + + + + alt + + + [Request is a duplicate but not a resend] + + + + + Switch returns error back to Payer FSP + + + Error code: 3106 + + + + + 6 + + + PUT /bulkQuotes/{ID}/error + + + + + 7 + + + 200 OK + + + + [Request is a duplicate and a resend] + + + + + 8 + + + Switch handles resend scenario + + + + + 9 + + + Use fspiop-destination header to retrieve + + + bulk quotes endpoint for Payee DFSP + + + + + alt + + + [Payee bulk quotes endpoint found] + + + + + Switch forwards bulk quote request to Payee FSP + + + + + 10 + + + POST /bulkQuotes + + + + + 11 + + + 202 OK + + + + + 12 + + + Payee FSP calculates individual quotes + + + and responds with a bulk quote result + + + + + alt + + + [Payee bulkQuotes processing successful] + + + + + Payee FSP sends bulk quote response back to Payer FSP via the Switch + + + + + 13 + + + PUT /bulkQuotes/{ID} + + + + + 14 + + + 200 OK + + + + + 15 + + + Validate bulk quote response + + + + + 16 + + + Duplicate check + + + + + alt + + + [Response is duplicate but not a resend] + + + + + 17 + + + PUT /bulkQuotes/{ID}/error + + + + + 18 + + + 200 OK + + + + + alt + + + [Response is a duplicate and a resend] + + + + + 19 + + + Switch handles resend scenario + + + + + Switch forwards quote response to Payer FSP + + + + + 20 + + + PUT /bulkQuotes/{ID} + + + + + 21 + + + 200 OK + + + + [Payee rejects bulk quote or encounters an error] + + + + + Payee FSP sends error callback to Payer FSP via the Switch + + + + + 22 + + + PUT /bulkQuotes/{ID}/error + + + + + 23 + + + 200 OK + + + + + Switch forwards error callback to Payer FSP + + + + + 24 + + + PUT /bulkQuotes/{ID}/error + + + + + 25 + + + 200 OK + + + + [Payee FSP quotes endpoint not found] + + + + + Switch sends an error callback to Payer FSP + + + Error code: 3201 + + + + + 26 + + + PUT /bulkQuotes/{ID}/error + + + + + 27 + + + 200 OK + + diff --git a/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.plantuml b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.plantuml new file mode 100644 index 000000000..86fb8f8b6 --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.plantuml @@ -0,0 +1,117 @@ +@startuml +Title Request Quote Creation +participant "Payer FSP" as PayerFSP +participant "Switch\n[Quoting\nService]" as Switch +database "Central Store" as DB +participant "Payee FSP" as PayeeFSP +autonumber + +note over PayerFSP, Switch: Payer FSP sends request for quote \nto Payee FSP via the Switch +PayerFSP -\ Switch: POST /quotes +note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** +end note +Switch -> Switch: Schema validation +PayerFSP \-- Switch: 202 Accepted +||| +Switch -> Switch: Quote request validation (rules engine etc.) +||| +alt SimpleRoutingMode === FALSE + Switch -> Switch: Duplicate check + ||| + alt Request is a duplicate but not a resend + ||| + note left of Switch + Switch returns error back to Payer FSP + **Error code: 3106** + end note + PayerFSP /- Switch: PUT /quotes/{ID}/error + PayerFSP --/ Switch: 200 OK + ||| + else Request is a duplicate and a resend + Switch -> Switch: Switch handles resend scenario + end + ||| + Switch -\ DB: Persist quote request + activate DB + hnote over DB + quoteDuplicateCheck + transactionReference + quote + quoteParty + quoteExtension + geoCode + end hnote + Switch \-- DB: Quote request saved + deactivate DB +end +||| +alt SimpleRoutingMode === TRUE + Switch -> Switch: Use fspiop-destination header to retrieve quotes endpoint for Payee FSP +else SimpleRoutingMode === FALSE + Switch -> Switch: Retireve Payee FSP endpoint using quote party information +end +||| +alt Payee quotes endpoint found + note right of Switch: Switch forwards quote request to Payee FSP + Switch -\ PayeeFSP: POST /quotes + Switch \-- PayeeFSP: 202 OK + + PayeeFSP -> PayeeFSP: Payee FSP presists and calculates quote + alt Payee quotes processing successful + note left of PayeeFSP: Payee FSP sends quote response back to Payer FSP via the Switch + Switch /- PayeeFSP: PUT /quotes/{ID} + Switch --/ PayeeFSP: 200 OK + + Switch -> Switch: Validate quote response + alt SimpleRoutingMode === FALSE + Switch -> Switch: Duplicate check + alt Response is duplicate but not a resend + Switch -\ PayeeFSP: PUT /quotes/{ID}/error + Switch \-- PayeeFSP: 200 OK + end + alt Response is a duplicate and a resend + Switch -> Switch: Switch handles resend scenario + end + Switch -\ DB: Persist quote response + activate DB + hnote over DB + quoteResponse + quoteDuplicateCheck + quoteResponseIlpPacket + geoCode + quoteExtension + end hnote + Switch \-- DB: Quote response saved + deactivate DB + end + note left of Switch: Switch forwards quote response to Payer FSP + PayerFSP /- Switch: PUT /quotes/{ID} + PayerFSP --/ Switch: 200 OK + else Payee rejects quotes or encounters and error + note left of PayeeFSP: Payee FSP sends error callback to Payer FSP via the Switch + Switch /- PayeeFSP: PUT /quotes/{ID}/error + Switch --/ PayeeFSP: 200 OK + alt SimpleRoutingMode === FALSE + Switch -\ DB: Store quote error + activate DB + hnote over DB + quoteError + end hnote + Switch \-- DB: Quote error saved + deactivate DB + end + note left of Switch: Switch forwards error callback to Payer FSP + PayerFSP /- Switch: PUT /quotes/{ID}/error + PayerFSP --/ Switch: 200 OK + end +else Payee FSP quotes endpoint not found + note left of Switch: Switch sends an error callback to Payer FSP \n **Error code: 3201** + PayerFSP /- Switch: PUT /quotes/{ID}/error + PayerFSP --\ Switch: 200 OK +end + +@enduml diff --git a/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.svg b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.svg new file mode 100644 index 000000000..6250d6e02 --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.svg @@ -0,0 +1,536 @@ + + + + + + + + + + + Request Quote Creation + + + + + + + + + + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + [Quoting + + + Service] + + + + Switch + + + [Quoting + + + Service] + + + Central Store + + + + + Central Store + + + + + + Payee FSP + + + + Payee FSP + + + + + + Payer FSP sends request for quote + + + to Payee FSP via the Switch + + + + + 1 + + + POST /quotes + + + + + Validate request against + + + Mojaloop interface specification + + + Error code: 300x, 310x + + + HTTP error response code: 4xx + + + + + 2 + + + Schema validation + + + + + 3 + + + 202 Accepted + + + + + 4 + + + Quote request validation (rules engine etc.) + + + + + alt + + + [SimpleRoutingMode === FALSE] + + + + + 5 + + + Duplicate check + + + + + alt + + + [Request is a duplicate but not a resend] + + + + + Switch returns error back to Payer FSP + + + Error code: 3106 + + + + + 6 + + + PUT /quotes/{ID}/error + + + + + 7 + + + 200 OK + + + + [Request is a duplicate and a resend] + + + + + 8 + + + Switch handles resend scenario + + + + + 9 + + + Persist quote request + + + + quoteDuplicateCheck + + + transactionReference + + + quote + + + quoteParty + + + quoteExtension + + + geoCode + + + + + 10 + + + Quote request saved + + + + + alt + + + [SimpleRoutingMode === TRUE] + + + + + 11 + + + Use fspiop-destination header to retrieve quotes endpoint for Payee FSP + + + + [SimpleRoutingMode === FALSE] + + + + + 12 + + + Retireve Payee FSP endpoint using quote party information + + + + + alt + + + [Payee quotes endpoint found] + + + + + Switch forwards quote request to Payee FSP + + + + + 13 + + + POST /quotes + + + + + 14 + + + 202 OK + + + + + 15 + + + Payee FSP presists and calculates quote + + + + + alt + + + [Payee quotes processing successful] + + + + + Payee FSP sends quote response back to Payer FSP via the Switch + + + + + 16 + + + PUT /quotes/{ID} + + + + + 17 + + + 200 OK + + + + + 18 + + + Validate quote response + + + + + alt + + + [SimpleRoutingMode === FALSE] + + + + + 19 + + + Duplicate check + + + + + alt + + + [Response is duplicate but not a resend] + + + + + 20 + + + PUT /quotes/{ID}/error + + + + + 21 + + + 200 OK + + + + + alt + + + [Response is a duplicate and a resend] + + + + + 22 + + + Switch handles resend scenario + + + + + 23 + + + Persist quote response + + + + quoteResponse + + + quoteDuplicateCheck + + + quoteResponseIlpPacket + + + geoCode + + + quoteExtension + + + + + 24 + + + Quote response saved + + + + + Switch forwards quote response to Payer FSP + + + + + 25 + + + PUT /quotes/{ID} + + + + + 26 + + + 200 OK + + + + [Payee rejects quotes or encounters and error] + + + + + Payee FSP sends error callback to Payer FSP via the Switch + + + + + 27 + + + PUT /quotes/{ID}/error + + + + + 28 + + + 200 OK + + + + + alt + + + [SimpleRoutingMode === FALSE] + + + + + 29 + + + Store quote error + + + + quoteError + + + + + 30 + + + Quote error saved + + + + + Switch forwards error callback to Payer FSP + + + + + 31 + + + PUT /quotes/{ID}/error + + + + + 32 + + + 200 OK + + + + [Payee FSP quotes endpoint not found] + + + + + Switch sends an error callback to Payer FSP + + + Error code: 3201 + + + + + 33 + + + PUT /quotes/{ID}/error + + + + + 34 + + + 200 OK + + diff --git a/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml new file mode 100644 index 000000000..4f3405364 --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml @@ -0,0 +1,68 @@ +@startuml +Title Quoting Service Sequences +participant "Payer DFSP" +participant "Switch\nQuoting\nService" as Switch +participant "Payee DFSP" + +autonumber +note over "Payer DFSP", Switch: Payer DFSP requests quote from Payee DFSP +"Payer DFSP" -\ Switch: POST /quotes +Switch --/ "Payer DFSP": 202 Accepted +Switch -> Switch: Validate Quote Request + +alt quote is valid + + Switch -> Switch: Persist Quote Data + note over Switch, "Payee DFSP": Switch forwards quote request to Payee DFSP\n + Switch -\ "Payee DFSP": POST /quotes + "Payee DFSP" --/ Switch: 202 Accepted + "Payee DFSP" -> "Payee DFSP": Calculate Fees/Charges + + alt Payee DFSP successfully calculates quote + + note over "Payee DFSP", Switch: Payee DFSP responds to quote request + "Payee DFSP" -\ Switch: PUT /quotes/{ID} + Switch --/ "Payee DFSP": 200 Ok + + Switch -> Switch: Validate Quote Response + + alt response is ok + + Switch -> Switch: Persist Response Data + + note over Switch, "Payer DFSP": Switch forwards quote response to Payer DFSP\n + + Switch -\ "Payer DFSP": PUT /quotes/{ID} + "Payer DFSP" --/ Switch: 200 Ok + + note over "Payer DFSP" #3498db: Payer DFSP continues\nwith transfer if quote\nis acceptable... + else response invalid + + note over Switch, "Payee DFSP": Switch returns error to Payee DFSP + + Switch -\ "Payee DFSP": PUT /quotes/{ID}/error + "Payee DFSP" --/ Switch : 200 Ok + + note over Switch, "Payee DFSP" #ec7063: Note that under this\nscenario the Payer DFSP\nmay not receive a response + + end + else Payee DFSP calculation fails or rejects the request + + note over "Payee DFSP", Switch: Payee DFSP returns error to Switch + + "Payee DFSP" -\ Switch: PUT quotes/{ID}/error + Switch --/ "Payee DFSP": 200 OK + Switch -> Switch: Persist error data + + note over "Payer DFSP", Switch: Switch returns error to Payer DFSP + + Switch -\ "Payer DFSP": PUT quotes/{ID}/error + "Payer DFSP" --/ Switch: 200 OK + + end +else quote invalid + note over "Payer DFSP", Switch: Switch returns error to Payer DFSP + Switch -\ "Payer DFSP": PUT quotes/{ID}/error + "Payer DFSP" --/ Switch: 200 OK +end +@enduml diff --git a/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.svg b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.svg new file mode 100644 index 000000000..b79aecb9d --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.svg @@ -0,0 +1,334 @@ + + + + + + + + + + + Quoting Service Sequences + + + + + + + + + Payer DFSP + + + + Payer DFSP + + + + Switch + + + Quoting + + + Service + + + + Switch + + + Quoting + + + Service + + + + Payee DFSP + + + + Payee DFSP + + + + + Payer DFSP requests quote from Payee DFSP + + + + + 1 + + + POST /quotes + + + + + 2 + + + 202 Accepted + + + + + 3 + + + Validate Quote Request + + + + + alt + + + [quote is valid] + + + + + 4 + + + Persist Quote Data + + + + + Switch forwards quote request to Payee DFSP + + + <Payer based Rules> + + + + + 5 + + + POST /quotes + + + + + 6 + + + 202 Accepted + + + + + 7 + + + Calculate Fees/Charges + + + + + alt + + + [Payee DFSP successfully calculates quote] + + + + + Payee DFSP responds to quote request + + + + + 8 + + + PUT /quotes/{ID} + + + + + 9 + + + 200 Ok + + + + + 10 + + + Validate Quote Response + + + + + alt + + + [response is ok] + + + + + 11 + + + Persist Response Data + + + + + Switch forwards quote response to Payer DFSP + + + <Payee whole request Rule> + + + + + 12 + + + PUT /quotes/{ID} + + + + + 13 + + + 200 Ok + + + + + Payer DFSP continues + + + with transfer if quote + + + is acceptable... + + + + [response invalid] + + + + + Switch returns error to Payee DFSP + + + + + 14 + + + PUT /quotes/{ID}/error + + + + + 15 + + + 200 Ok + + + + + Note that under this + + + scenario the Payer DFSP + + + may not receive a response + + + + [Payee DFSP calculation fails or rejects the request] + + + + + Payee DFSP returns error to Switch + + + + + 16 + + + PUT quotes/{ID}/error + + + + + 17 + + + 200 OK + + + + + 18 + + + Persist error data + + + + + Switch returns error to Payer DFSP + + + + + 19 + + + PUT quotes/{ID}/error + + + + + 20 + + + 200 OK + + + + [quote invalid] + + + + + Switch returns error to Payer DFSP + + + + + 21 + + + PUT quotes/{ID}/error + + + + + 22 + + + 200 OK + + diff --git a/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.plantuml b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.plantuml new file mode 100644 index 000000000..3275abff7 --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.plantuml @@ -0,0 +1,67 @@ +@startuml +Title Quoting Service Sequences +participant "Payer FSP" +participant "Switch\nQuoting\nService" as Switch +participant "Payee FSP" + +autonumber +note over "Payer FSP", Switch: Payer FSP requests quote from Payee FSP +"Payer FSP" -\ Switch: POST /quotes +Switch --/ "Payer FSP": 202 Accepted +Switch -> Switch: Validate Quote Request + +alt quote is valid + + Switch -> Switch: Persist Quote Data + note over Switch, "Payee FSP": Switch forwards quote request to Payee FSP\n + Switch -\ "Payee FSP": POST /quotes + "Payee FSP" --/ Switch: 202 Accepted + "Payee FSP" -> "Payee FSP": Calculate Fees/Charges + + alt Payee FSP successfully calculates quote + + note over "Payee FSP", Switch: Payee FSP responds to quote request + "Payee FSP" -\ Switch: PUT /quotes/{ID} + Switch --/ "Payee FSP": 200 Ok + + Switch -> Switch: Validate Quote Response + + alt response is ok + Switch -> Switch: Persist Response Data + + note over Switch, "Payer FSP": Switch forwards quote response to Payer FSP\n + + Switch -\ "Payer FSP": PUT /quotes/{ID} + "Payer FSP" --/ Switch: 200 Ok + + note over "Payer FSP" #3498db: Payer FSP continues\nwith transfer if quote\nis acceptable... + else response invalid + + note over Switch, "Payee FSP": Switch returns error to Payee FSP + + Switch -\ "Payee FSP": PUT /quotes/{ID}/error + "Payee FSP" --/ Switch : 200 Ok + + note over Switch, "Payee FSP" #ec7063: Note that under this\nscenario the Payer FSP\nmay not receive a response + + end + else Payee FSP calculation fails or rejects the request + + note over "Payee FSP", Switch: Payee FSP returns error to Switch + + "Payee FSP" -\ Switch: PUT quotes/{ID}/error + Switch --/ "Payee FSP": 200 OK + Switch -> Switch: Persist error data + + note over "Payer FSP", Switch: Switch returns error to Payer FSP + + Switch -\ "Payer FSP": PUT quotes/{ID}/error + "Payer FSP" --/ Switch: 200 OK + + end +else quote invalid + note over "Payer FSP", Switch: Switch returns error to Payer FSP + Switch -\ "Payer FSP": PUT quotes/{ID}/error + "Payer FSP" --/ Switch: 200 OK +end +@enduml diff --git a/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.svg b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.svg new file mode 100644 index 000000000..69b7fb6d4 --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.svg @@ -0,0 +1,334 @@ + + + + + + + + + + + Quoting Service Sequences + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + Quoting + + + Service + + + + Switch + + + Quoting + + + Service + + + + Payee FSP + + + + Payee FSP + + + + + Payer FSP requests quote from Payee FSP + + + + + 1 + + + POST /quotes + + + + + 2 + + + 202 Accepted + + + + + 3 + + + Validate Quote Request + + + + + alt + + + [quote is valid] + + + + + 4 + + + Persist Quote Data + + + + + Switch forwards quote request to Payee FSP + + + <Payer based Rules> + + + + + 5 + + + POST /quotes + + + + + 6 + + + 202 Accepted + + + + + 7 + + + Calculate Fees/Charges + + + + + alt + + + [Payee FSP successfully calculates quote] + + + + + Payee FSP responds to quote request + + + + + 8 + + + PUT /quotes/{ID} + + + + + 9 + + + 200 Ok + + + + + 10 + + + Validate Quote Response + + + + + alt + + + [response is ok] + + + + + 11 + + + Persist Response Data + + + + + Switch forwards quote response to Payer FSP + + + <Payee whole request Rule> + + + + + 12 + + + PUT /quotes/{ID} + + + + + 13 + + + 200 Ok + + + + + Payer FSP continues + + + with transfer if quote + + + is acceptable... + + + + [response invalid] + + + + + Switch returns error to Payee FSP + + + + + 14 + + + PUT /quotes/{ID}/error + + + + + 15 + + + 200 Ok + + + + + Note that under this + + + scenario the Payer FSP + + + may not receive a response + + + + [Payee FSP calculation fails or rejects the request] + + + + + Payee FSP returns error to Switch + + + + + 16 + + + PUT quotes/{ID}/error + + + + + 17 + + + 200 OK + + + + + 18 + + + Persist error data + + + + + Switch returns error to Payer FSP + + + + + 19 + + + PUT quotes/{ID}/error + + + + + 20 + + + 200 OK + + + + [quote invalid] + + + + + Switch returns error to Payer FSP + + + + + 21 + + + PUT quotes/{ID}/error + + + + + 22 + + + 200 OK + + diff --git a/legacy/mojaloop-technical-overview/quoting-service/qs-get-bulk-quotes.md b/legacy/mojaloop-technical-overview/quoting-service/qs-get-bulk-quotes.md new file mode 100644 index 000000000..b78339ff6 --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/qs-get-bulk-quotes.md @@ -0,0 +1,7 @@ +# GET Quote By ID + +Design for the retrieval of a Bulk Quote by an FSP. + +## Sequence Diagram + +![seq-get-bulk-quotes-2.1.0.svg](./assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.svg) diff --git a/legacy/mojaloop-technical-overview/quoting-service/qs-get-quotes.md b/legacy/mojaloop-technical-overview/quoting-service/qs-get-quotes.md new file mode 100644 index 000000000..765b5b4bf --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/qs-get-quotes.md @@ -0,0 +1,7 @@ +# GET Quote By ID + +Design for the retrieval of a Quote by an FSP. + +## Sequence Diagram + +![seq-get-quotes-1.1.0.svg](./assets/diagrams/sequence/seq-get-quotes-1.1.0.svg) diff --git a/legacy/mojaloop-technical-overview/quoting-service/qs-post-bulk-quotes.md b/legacy/mojaloop-technical-overview/quoting-service/qs-post-bulk-quotes.md new file mode 100644 index 000000000..28e692e68 --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/qs-post-bulk-quotes.md @@ -0,0 +1,7 @@ +# POST Quote + +Design for a Bulk Quote request by an FSP. + +## Sequence Diagram + +![seq-post-bulk-quotes-2.2.0.svg](./assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.svg) diff --git a/legacy/mojaloop-technical-overview/quoting-service/qs-post-quotes.md b/legacy/mojaloop-technical-overview/quoting-service/qs-post-quotes.md new file mode 100644 index 000000000..b8f99fedf --- /dev/null +++ b/legacy/mojaloop-technical-overview/quoting-service/qs-post-quotes.md @@ -0,0 +1,7 @@ +# POST Quote + +Design for a Quote request by an FSP. + +## Sequence Diagram + +![seq-post-quotes-1.2.0.svg](./assets/diagrams/sequence/seq-post-quotes-1.2.0.svg) diff --git a/mojaloop-technical-overview/sdk-scheme-adapter/README.md b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/README.md similarity index 100% rename from mojaloop-technical-overview/sdk-scheme-adapter/README.md rename to legacy/mojaloop-technical-overview/sdk-scheme-adapter/README.md diff --git a/mojaloop-technical-overview/sdk-scheme-adapter/usage/README.md b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/README.md similarity index 100% rename from mojaloop-technical-overview/sdk-scheme-adapter/usage/README.md rename to legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/README.md diff --git a/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/README.md b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/README.md new file mode 100644 index 000000000..5accc7ec1 --- /dev/null +++ b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/README.md @@ -0,0 +1,206 @@ +# SDK Scheme Adapter and Local K8S cluster testing + +A detailed documentation for dfsps who want to test the mojaloop cluster deployment with scheme adapter and a mock backend service. + +![Overview](scheme-adapter-and-local-k8s-overview.png) + +## Prerequisite + +* A working mojaloop k8s cluster (Local / Cloud deployment) +* DFSP mock backend service +* sdk-scheme-adapter > 8.6.0 + +## Configuration & Starting services + +### Mojaloop Local K8S cluster deployment +Please follow the below link to deploy your own cluster on local system. +https://mojaloop.io/documentation/deployment-guide/ + +A Linux based operating system is recommended and at least 16GB RAM and 4 core processor is required. + +After installation please complete the `OSS-New-Deployment-FSP-Setup.postman_collection` collection available at https://github.com/mojaloop/postman + +Then make sure the oracles & endpoints are configured correctly and that the "Golden Path Collection" can be run successfully. + +### DFSP Mock Backend service & SDK Scheme adapter +The SDK scheme adapter version should be greater than 8.6.0 +The next step starts the scheme adapter from docker-compose file automatically. + +Please download the following repository +https://github.com/mojaloop/sdk-mock-dfsp-backend + +Edit the docker-compose.yml file and verify the following lines. + +``` +version: '3' +services: + redis2: + image: "redis:5.0.4-alpine" + container_name: redis2 + backend: + image: "mojaloop/sdk-mock-dfsp-backend" + env_file: ./backend.env + container_name: dfsp_mock_backend2 + ports: + - "23000:3000" + depends_on: + - scheme-adapter2 + + scheme-adapter2: + image: "mojaloop/sdk-scheme-adapter:latest" + env_file: ./scheme-adapter.env + container_name: sa_sim2 + ports: + - "4000:4000" + depends_on: + - redis2 +``` + +Edit the backend.env file and change the OUTBOUND_ENDPOINT value +``` +OUTBOUND_ENDPOINT=http://sa_sim2:4001 +``` + +Edit scheme-adapter.env and change the following lines +Please replace the endpoint values with the appropriate hostnames provided in /etc/hosts file. + +``` +DFSP_ID=safsp +CACHE_HOST=redis2 +ALS_ENDPOINT=account-lookup-service.local +QUOTES_ENDPOINT=quoting-service.local +TRANSFERS_ENDPOINT=ml-api-adapter.local +BACKEND_ENDPOINT=dfsp_mock_backend2:3000 +AUTO_ACCEPT_PARTY=true +AUTO_ACCEPT_QUOTES=true +VALIDATE_INBOUND_JWS=false +VALIDATE_INBOUND_PUT_PARTIES_JWS=false +JWS_SIGN=true +JWS_SIGN_PUT_PARTIES=true +``` + +### Name resolution configuration - Mac ONLY + +Point the following hostnames to your local machine IP by adding the below line in /etc/hosts file +``` +192.168.5.101 ml-api-adapter.local account-lookup-service.local central-ledger.local central-settlement.local account-lookup-service-admin.local quoting-service.local moja-simulator.local central-ledger central-settlement ml-api-adapter account-lookup-service account-lookup-service-admin quoting-service simulator host.docker.internal moja-account-lookup-mysql +``` + +Make sure to change 192.168.5.101 to your real external IP. + +### Name resolution configuration - Linux ONLY + +Add extra_hosts configuration to scheme-adapter2 config in the docker-compose.yml file, so that the scheme-adapter2 container can resolve dns of account-lookup-service.local, quoting-service.local and ml-api-adapter.local. For example the config could be: + +``` + scheme-adapter2: + image: "mojaloop/sdk-scheme-adapter:latest" + env_file: ./scheme-adapter.env + container_name: sa_sim2 + ports: + - "4000:4000" + depends_on: + - redis2 + extra_hosts: + - "account-lookup-service.local:172.17.0.1" + - "quoting-service.local:172.17.0.1" + - "ml-api-adapter.local:172.17.0.1" +``` + +The 172.17.0.1 is a default docker0 network interface on linux, however please make sure it's valid in your configuration and change it if needed. + +### Start + +Start the backend and scheme adapter using the following command. +``` +cd src +docker-compose up -d +``` + +## Testing + +### Configure new FSP +Download the following files: +* [Mojaloop-Local.postman_environment_modified.json](assets/postman_files/Mojaloop-Local.postman_environment_modified.json) - modified environment variables that point to your local setup +* [OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json](assets/postman_files/OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json) - steps that will setup new FSP + +The SCHEME_ADAPTER_ENDPOINT in the environment file should point to your local scheme-adapter deployment. For mac this is configured already to be http://host.docker.internal:4000. If you're running on Linux, please edit the environment file, so that SCHEME_ADAPTER_ENDPOINT points to your docker0 interface (usually 172.17.0.1 - see remarks in previous step). + +In postman, select the environment file and run the custom collection in the postman to provision a new FSP called "safsp". The endpoints for safsp will be set to the URL of the scheme adapter which is configured in environment file. + +### Add the target MSISDN to payee simulator which is running inside the K8S. Run the following commands +``` +curl -X POST \ + http://moja-simulator.local/payeefsp/parties/MSISDN/27713803912 \ + -H 'Accept: */*' \ + -H 'Accept-Encoding: gzip, deflate' \ + -H 'Cache-Control: no-cache' \ + -H 'Connection: keep-alive' \ + -H 'Content-Length: 406' \ + -H 'Content-Type: application/json' \ + -H 'Host: moja-simulator.local' \ + -H 'User-Agent: PostmanRuntime/7.20.1' \ + -H 'cache-control: no-cache' \ + -d '{ + "party": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27713803912", + "fspId": "payeefsp" + }, + "name": "Siabelo Maroka", + "personalInfo": { + "complexName": { + "firstName": "Siabelo", + "lastName": "Maroka" + }, + "dateOfBirth": "1974-01-01" + } + } +}' + +curl -X POST \ + http://account-lookup-service.local/participants/MSISDN/27713803912 \ + -H 'Accept: application/vnd.interoperability.participants+json;version=1' \ + -H 'Connection: keep-alive' \ + -H 'Content-Length: 50' \ + -H 'Content-Type: application/vnd.interoperability.participants+json;version=1.0' \ + -H 'Date: Fri, 21 Dec 2018 12:17:01 GMT' \ + -H 'FSPIOP-Source: payeefsp' \ + -H 'Host: account-lookup-service.local' \ + -H 'User-Agent: PostmanRuntime/7.11.0' \ + -H 'accept-encoding: gzip, deflate' \ + -H 'cache-control: no-cache,no-cache' \ + -d '{ + "fspId": "payeefsp", + "currency": "USD" +}' +``` + +### Try to send money +Try to send funds from "safsp" (Mock DFSP) to a MSISDN which is in "payeedfsp" (Simulator in K8S) through scheme adapter. +Run the following curl command to issue command to Mock DFSP service. +``` +curl -X POST \ + http://localhost:23000/send \ + -H 'Content-Type: application/json' \ + -d '{ + "from": { + "displayName": "John Doe", + "idType": "MSISDN", + "idValue": "123456789" + }, + "to": { + "idType": "MSISDN", + "idValue": "27713803912" + }, + "amountType": "SEND", + "currency": "USD", + "amount": "100", + "transactionType": "TRANSFER", + "note": "testpayment", + "homeTransactionId": "123ABC" +}' +``` + +You should get a response with COMPLETED currentState. diff --git a/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/Mojaloop-Local.postman_environment_modified.json b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/Mojaloop-Local.postman_environment_modified.json new file mode 100644 index 000000000..eddcac266 --- /dev/null +++ b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/Mojaloop-Local.postman_environment_modified.json @@ -0,0 +1,1012 @@ +{ + "id": "a9937c8b-0281-4128-8b53-1f1f913ff2aa", + "name": "Mojaloop-Local", + "values": [ + { + "key": "payeefsp", + "value": "payeefsp", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "payerfsp", + "value": "payerfsp", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "transferExpiration", + "value": "2019-05-27T15:44:53.292Z", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "transactionRequestId", + "value": "25a00155-c777-4629-a6b7-61cf0d16f499", + "enabled": true + }, + { + "key": "transferDate", + "value": "Fri, 21 Dec 2018 12:17:01 GMT", + "enabled": true + }, + { + "key": "currentTimestamp", + "value": "2018-12-06T17:09:56.386Z", + "enabled": true + }, + { + "key": "quoteDate", + "value": "Fri, 21 Dec 2018 12:19:49 GMT", + "enabled": true + }, + { + "key": "quoteExpiration", + "value": "2018-11-08T21:31:00.534+01:00", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_MOJALOOP", + "value": "localhost:4000", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "BASE_MOJALOOP", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_CENTRAL_LEDGER", + "value": "http://central-ledger.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "BASE_CENTRAL_LEDGER_API", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "BASE_CENTRAL_LEDGER_ADMIN", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_ML_API", + "value": "http://ml-api-adapter.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "BASE_ML_API", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_CENTRAL_SETTLEMENT", + "value": "http://central-settlement.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "BASE_CENTRAL_SETTLEMENT", + "value": "/v1", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_TRANSFER_UUID_ON_PREPARE", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_TRANSFER_UUID_ON_QUOTE\n", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_QUOTE_UUID_ON_QUOTE", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_TIMESTAMP", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_PREPARE_DATE", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_QUOTE_DATE", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_TRANSACTION_UUID_ON_QUOTE", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "transferExpiredExpiration", + "value": "2018-08-31T15:26:01.870Z", + "enabled": true + }, + { + "key": "condition", + "value": "HOr22-H3AfTDHrSkPjJtVPRdKouuMkDXTR4ejlQa8Ks", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "fulfilment", + "value": "uU0nuZNNPgilLlLX2n2r-sSE7-N6U4DukIj3rOLvzek", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_SIMULATOR", + "value": "http://moja-simulator.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "SCHEME_ADAPTER_ENDPOINT", + "value": "http://host.docker.internal:4000", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "quoteId", + "value": "ddaa67b3-5bf8-45c1-bfcf-1e8781177c37", + "enabled": true + }, + { + "key": "ilpPacket", + "value": "AQAAAAAAAADIEHByaXZhdGUucGF5ZWVmc3CCAiB7InRyYW5zYWN0aW9uSWQiOiIyZGY3NzRlMi1mMWRiLTRmZjctYTQ5NS0yZGRkMzdhZjdjMmMiLCJxdW90ZUlkIjoiMDNhNjA1NTAtNmYyZi00NTU2LThlMDQtMDcwM2UzOWI4N2ZmIiwicGF5ZWUiOnsicGFydHlJZEluZm8iOnsicGFydHlJZFR5cGUiOiJNU0lTRE4iLCJwYXJ0eUlkZW50aWZpZXIiOiIyNzcxMzgwMzkxMyIsImZzcElkIjoicGF5ZWVmc3AifSwicGVyc29uYWxJbmZvIjp7ImNvbXBsZXhOYW1lIjp7fX19LCJwYXllciI6eyJwYXJ0eUlkSW5mbyI6eyJwYXJ0eUlkVHlwZSI6Ik1TSVNETiIsInBhcnR5SWRlbnRpZmllciI6IjI3NzEzODAzOTExIiwiZnNwSWQiOiJwYXllcmZzcCJ9LCJwZXJzb25hbEluZm8iOnsiY29tcGxleE5hbWUiOnt9fX0sImFtb3VudCI6eyJjdXJyZW5jeSI6IlVTRCIsImFtb3VudCI6IjIwMCJ9LCJ0cmFuc2FjdGlvblR5cGUiOnsic2NlbmFyaW8iOiJERVBPU0lUIiwic3ViU2NlbmFyaW8iOiJERVBPU0lUIiwiaW5pdGlhdG9yIjoiUEFZRVIiLCJpbml0aWF0b3JUeXBlIjoiQ09OU1VNRVIiLCJyZWZ1bmRJbmZvIjp7fX19", + "enabled": true + }, + { + "key": "payerFspId", + "value": "3", + "enabled": true + }, + { + "key": "payerFspAccountId", + "value": "3", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "payeeFspId", + "value": "4", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "payeeFspAccountId", + "value": "5", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "openWindowID", + "value": 1, + "enabled": true + }, + { + "key": "newOpenWindowID", + "value": 2, + "enabled": true + }, + { + "key": "closedWindowID", + "value": 1, + "enabled": true + }, + { + "key": "settlementId", + "value": 1, + "enabled": true + }, + { + "key": "expectedFullName", + "value": "Siabelo Maroka", + "enabled": true + }, + { + "key": "expectedFirstName", + "value": "Siabelo", + "enabled": true + }, + { + "key": "expectedLastName", + "value": "Maroka", + "enabled": true + }, + { + "key": "expectedDOB", + "value": "3/3/1973", + "enabled": true + }, + { + "key": "pathfinderMSISDN", + "value": "27713803912", + "enabled": true + }, + { + "key": "fullName", + "value": "Siabelo Maroka", + "enabled": true + }, + { + "key": "firstName", + "value": "Siabelo", + "enabled": true + }, + { + "key": "lastName", + "value": "Maroka", + "enabled": true + }, + { + "key": "dob", + "value": "3/3/1973", + "enabled": true + }, + { + "key": "HOST_ML_API_ADAPTER", + "value": "http://ml-api-adapter.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "dateHeader", + "value": "Thu, 24 Jan 2019 10:22:12 GMT", + "enabled": true + }, + { + "key": "participant", + "value": "testfsp4", + "enabled": true + }, + { + "key": "payerfspBeforePosition", + "value": -1782, + "enabled": true + }, + { + "key": "HOST_SWITCH_TRANSFERS", + "value": "http://ml-api-adapter.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "BASE_PATH_SWITCH_TRANSFERS", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_SIMULATOR_K8S_CLUSTER", + "value": "http://moja-simulator", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "payerfspPositionBeforeTransfer", + "value": 0, + "enabled": true + }, + { + "key": "payerNDC", + "value": 1000, + "enabled": true + }, + { + "key": "payeefspPositionBeforeTransfer", + "value": 0, + "enabled": true + }, + { + "key": "blockTransferAmount", + "value": 7494, + "enabled": true + }, + { + "key": "payeeNDC", + "value": 1000, + "enabled": true + }, + { + "key": "payerfspPositionAfterTransfer", + "value": 0, + "enabled": true + }, + { + "key": "transferAmount", + "value": "99", + "enabled": true + }, + { + "key": "payeefspPositionAfterTransfer", + "value": 0, + "enabled": true + }, + { + "key": "payerfspPositionAfterTransferBeforeExpiry", + "value": 1596, + "enabled": true + }, + { + "key": "fspName", + "value": "payerfsp", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "settlementAccountId", + "value": "3", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "reportEndDate", + "value": "2018-10-31", + "enabled": true + }, + { + "key": "reportFSPID", + "value": "payerfsp", + "enabled": true + }, + { + "key": "reportStartDate", + "value": "2018-10-01", + "enabled": true + }, + { + "key": "transactionId", + "value": "97f3f215-37a0-4755-a17c-c39313aa2f98", + "enabled": true + }, + { + "key": "payerfspSettlementAccountId", + "value": 8, + "enabled": true + }, + { + "key": "payeefspSettlementAccountId", + "value": 4, + "enabled": true + }, + { + "key": "fundsInPrepareTransferId", + "value": "b79a979e-9605-4db4-a052-85bc948be414", + "enabled": true + }, + { + "key": "HUBOPERATOR_BEARER_TOKEN", + "value": "NOT_APPLICABLE", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "hub_operator", + "value": "NOT_APPLICABLE", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "payeefspNetSettlementAmount", + "value": -198, + "enabled": true + }, + { + "key": "payerfspNetSettlementAmount", + "value": 198, + "enabled": true + }, + { + "key": "fundsInPrepareAmount", + "value": 500, + "enabled": true + }, + { + "key": "payerfspSettlementAccountBalance", + "value": -4800, + "enabled": true + }, + { + "key": "hubReconAccountBalance", + "value": 4800, + "enabled": true + }, + { + "key": "payerfspAccountBalanceBeforeSettlement", + "value": 0, + "enabled": true + }, + { + "key": "payeefspAccountBalanceBeforeSettlement", + "value": 0, + "enabled": true + }, + { + "key": "fundsOutPrepareTransferId", + "value": "f60c555f-72a7-44c7-a3a8-1f4a4df4b100", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "hubReconAccountBalanceBeforeFundsIn", + "value": "", + "enabled": true + }, + { + "key": "payerfspSettlementAccountBalanceBeforeFundsIn", + "value": "", + "enabled": true + }, + { + "key": "fundsOutPrepareAmount", + "value": "", + "enabled": true + }, + { + "key": "payerfspNDCBeforePrepare", + "value": "", + "enabled": true + }, + { + "key": "payeefspNDCBeforePrepare", + "value": "", + "enabled": true + }, + { + "key": "payeefspPositionAccountId", + "value": 3, + "enabled": true + }, + { + "key": "payerfspPositionAccountId", + "value": 7, + "enabled": true + }, + { + "key": "testfsp1", + "value": "testfsp1", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp2", + "value": "testfsp2", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp1PositionAccountId", + "value": 25, + "enabled": true + }, + { + "key": "testfsp1SettlementAccountId", + "value": 26, + "enabled": true + }, + { + "key": "testfsp2PositionAccountId", + "value": 29, + "enabled": true + }, + { + "key": "testfsp2SettlementAccountId", + "value": 30, + "enabled": true + }, + { + "key": "testfsp1Id", + "value": "13", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp2Id", + "value": "14", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "hubReconAccountBalanceBeforeFundsOutPrepare", + "value": "", + "enabled": true + }, + { + "key": "payerfspSettlementAccountBalanceBeforeFundsOutPrepare", + "value": "", + "enabled": true + }, + { + "key": "fundsOutCommitAmount", + "value": "", + "enabled": true + }, + { + "key": "fundsOutCommitTransferId", + "value": "", + "enabled": true + }, + { + "key": "hubReconAccountBalanceBeforeFundsOutCommit", + "value": "", + "enabled": true + }, + { + "key": "payerfspSettlementAccountBalanceBeforeFundsOutCommit", + "value": "", + "enabled": true + }, + { + "key": "transfer_ID", + "value": "e7b43799-e69e-4578-bd26-2a4b9a22e92e", + "enabled": true + }, + { + "key": "get_transfer_ID", + "value": "7e19ae5f-7db6-4612-ab99-7538a56b4c25", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "env_prefix", + "value": "test", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "hubReconAccountBalanceBeforeFundsInReserve", + "value": "", + "enabled": true + }, + { + "key": "payerfspSettlementAccountBalanceBeforeFundsInReserve", + "value": "", + "enabled": true + }, + { + "key": "validCondition", + "value": "GRzLaTP7DJ9t4P-a_BA0WA9wzzlsugf00-Tn6kESAfM", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "validFulfillment", + "value": "UNlJ98hZTY_dsw0cAqw4i_UN3v4utt7CZFB4yfLbVFA", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "currency", + "value": "USD", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp1PositionAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp1SettleAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp2PositionAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp2SettleAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp3PositionAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp3SettleAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp4PositionAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp4SettleAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfspId3", + "value": "15", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfspId4", + "value": "16", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "invalidFulfillment", + "value": "_3cco-YN5OGpRKVWV3n6x6uNpBTH9tYUdOYmHA", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "completedTimestamp", + "value": "", + "enabled": true + }, + { + "key": "payerfspPositionBeforePrepare", + "value": "", + "enabled": true + }, + { + "key": "payeefspPositionBeforePrepare", + "value": "", + "enabled": true + }, + { + "key": "payerfspPositionAfterPrepare", + "value": "", + "enabled": true + }, + { + "key": "fundsOutPrepareReserveAmount", + "value": "", + "enabled": true + }, + { + "key": "fundsOutPrepareReserveTransferId", + "value": "", + "enabled": true + }, + { + "key": "testfsp1PositionAccountBalanceBeforeTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp1SettleAccountBalanceBeforeTransfer", + "value": "", + "enabled": true + }, + { + "key": "fspiop-signature", + "value": "{\"signature\":\"iU4GBXSfY8twZMj1zXX1CTe3LDO8Zvgui53icrriBxCUF_wltQmnjgWLWI4ZUEueVeOeTbDPBZazpBWYvBYpl5WJSUoXi14nVlangcsmu2vYkQUPmHtjOW-yb2ng6_aPfwd7oHLWrWzcsjTF-S4dW7GZRPHEbY_qCOhEwmmMOnE1FWF1OLvP0dM0r4y7FlnrZNhmuVIFhk_pMbEC44rtQmMFv4pm4EVGqmIm3eyXz0GkX8q_O1kGBoyIeV_P6RRcZ0nL6YUVMhPFSLJo6CIhL2zPm54Qdl2nVzDFWn_shVyV0Cl5vpcMJxJ--O_Zcbmpv6lxqDdygTC782Ob3CNMvg\\\",\\\"protectedHeader\\\":\\\"eyJhbGciOiJSUzI1NiIsIkZTUElPUC1VUkkiOiIvdHJhbnNmZXJzIiwiRlNQSU9QLUhUVFAtTWV0aG9kIjoiUE9TVCIsIkZTUElPUC1Tb3VyY2UiOiJPTUwiLCJGU1BJT1AtRGVzdGluYXRpb24iOiJNVE5Nb2JpbGVNb25leSIsIkRhdGUiOiIifQ\"}", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp3SettlementAccountId", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp4SettlementAccountId", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp3SettlementAccountBalanceBeforeFundsIn", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp4SettlementAccountBalanceBeforeFundsIn", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp3", + "value": "testfsp3", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp4", + "value": "testfsp4", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp1PositionAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp1SettleAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp2PositionAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp2SettleAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp3PositionAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp3SettleAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp4PositionAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp4SettleAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "hubReconAccountBalanceBeforeFundsOutAbort", + "value": "", + "enabled": true + }, + { + "key": "payerfspSettlementAccountBalanceBeforeFundsOutAbort", + "value": "", + "enabled": true + }, + { + "key": "payeefsp_fspiop_signature", + "value": "{\"signature\":\"abcJjvNrkyK2KBieDUbGfhaBUn75aDUATNF4joqA8OLs4QgSD7i6EO8BIdy6Crph3LnXnTM20Ai1Z6nt0zliS_qPPLU9_vi6qLb15FOkl64DQs9hnfoGeo2tcjZJ88gm19uLY_s27AJqC1GH1B8E2emLrwQMDMikwQcYvXoyLrL7LL3CjaLMKdzR7KTcQi1tCK4sNg0noIQLpV3eA61kess\",\"protectedHeader\":\"eyJhbGciOiJSUzI1NiIsIkZTUElPUC1Tb3VyY2UiOiJwYXllZWZzcCIsIkZTUElPUC1EZXN0aW5hdGlvbiI6InBheWVyZnNwIiwiRlNQSU9QLVVSSSI6Ii90cmFuc2ZlcnMvZDY3MGI1OTAtZjc5ZC00YWU5LThjNmUtMTVjZjZjNWMzODk5IiwiRlNQSU9QLUhUVFAtTWV0aG9kIjoiUFVUIiwiRGF0ZSI6IiJ9\"}", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_ACCOUNT_LOOKUP_SERVICE", + "value": "http://account-lookup-service.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_ACCOUNT_LOOKUP_ADMIN", + "value": "http://account-lookup-service-admin.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_QUOTING_SERVICE", + "value": "http://quoting-service.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "payeefsp_signature", + "value": "abcJjvNrkyK2KBieDUbGfhaBUn75aDUATNF4joqA8OLs4QgSD7i6EO8BIdy6Crph3LnXnTM20Ai1Z6nt0zliS_qPPLU9_vi6qLb15FOkl64DQs9hnfoGeo2tcjZJ88gm19uLY_s27AJqC1GH1B8E2emLrwQMDMikwQcYvXoyLrL7LL3CjaLMKdzR7KTcQi1tCK4sNg0noIQLpV3eA61kess", + "type": "text", + "description": "", + "enabled": true + } + ], + "_postman_variable_scope": "environment", + "_postman_exported_at": "2019-05-30T00:29:41.827Z", + "_postman_exported_using": "Postman/6.7.4" +} diff --git a/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json new file mode 100644 index 000000000..70e2b3599 --- /dev/null +++ b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json @@ -0,0 +1,1072 @@ +{ + "info": { + "_postman_id": "52f405c0-bec3-4915-8c43-c250208623aa", + "name": "OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup", + "description": "Author: Sridevi Miriyala\nPurpose: Used to add new FSP and relevant Callback Information", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "FSP Onboarding", + "item": [ + { + "name": "safsp (p2p transfers)", + "item": [ + { + "name": "Add payerfsp - TRANSFERS", + "event": [ + { + "listen": "test", + "script": { + "id": "76c222f4-969b-4081-b4d7-133ebe48f50f", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\"name\": \"safsp\",\"currency\": \"{{currency}}\"}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants" + ] + } + }, + "response": [] + }, + { + "name": "Add initial position and limits - payerfsp", + "event": [ + { + "listen": "test", + "script": { + "id": "d767079d-a9dd-401a-8d6a-5f94654c4259", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"currency\": \"{{currency}}\",\n\t\"limit\": {\n\t \"type\": \"NET_DEBIT_CAP\",\n\t \"value\": 1000000\n\t},\n\t\"initialPosition\": 0\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/initialPositionAndLimits", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "initialPositionAndLimits" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTICIPANT PUT", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTICIPANT_PUT\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/participants/{{partyIdType}}/{{partyIdentifier}}\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTICIPANT PUT Error", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/participants/{{partyIdType}}/{{partyIdentifier}}/error\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTICIPANT PUT Batch", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/participants/{{requestId}}\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTICIPANT PUT Batch Error", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/participants/{{requestId}}/error\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTIES GET", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTIES_GET\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/parties/{{partyIdType}}/{{partyIdentifier}}\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTIES PUT", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTIES_PUT\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/parties/{{partyIdType}}/{{partyIdentifier}}\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTIES PUT Error", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/parties/{{partyIdType}}/{{partyIdentifier}}/error\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - QUOTES PUT", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_QUOTES\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - TRANSFER POST", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_TRANSFER_POST\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/transfers\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - TRANSFER PUT", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_TRANSFER_PUT\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/transfers/{{transferId}}\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - TRANSFER ERROR", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_TRANSFER_ERROR\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/transfers/{{transferId}}/error\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "9. Set Endpoint-NET_DEBIT_CAP_ADJUSTMENT_EMAIL Copy", + "event": [ + { + "listen": "test", + "script": { + "id": "83984619-0430-4a4c-87ec-671bf97894de", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BEARER_TOKEN}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Cache-Control", + "value": "no-cache" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"NET_DEBIT_CAP_ADJUSTMENT_EMAIL\",\n \"value\": \"sridevi.miriyala@modusbox.com\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + }, + "description": "Generated from a curl request: \ncurl -i -X POST {{HOST_CENTRAL_LEDGER}}/participants/testfsp2/initialPositionAndLimits -H 'Cache-Control: no-cache' -H 'Content-Type: application/json' -d '{\n \\\"currency\\\": \\\"USD\\\",\n \\\"limit\\\": {\n \\\"type\\\": \\\"NET_DEBIT_CAP\\\",\n \\\"value\\\": 1000\n },\n \\\"initialPosition\\\": 0\n }'" + }, + "response": [ + { + "name": "2. Create Initial Position and Limits", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Cache-Control", + "value": "no-cache" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"currency\": \"USD\",\n \"limit\": {\n \"type\": \"NET_DEBIT_CAP\",\n \"value\": 1000\n },\n \"initialPosition\": 0\n }" + }, + "url": { + "raw": "http://{{HOST_CENTRAL_LEDGER}}/participants/testfsp/initialPositionAndLimits", + "protocol": "http", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "testfsp", + "initialPositionAndLimits" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "Text", + "header": [], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "Set Endpoint-SETTLEMENT_TRANSFER_POSITION_CHANGE_EMAIL Copy", + "event": [ + { + "listen": "test", + "script": { + "id": "16f8d261-3f2d-470b-986b-c8e23602605b", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BEARER_TOKEN}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Cache-Control", + "value": "no-cache" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"SETTLEMENT_TRANSFER_POSITION_CHANGE_EMAIL\",\n \"value\": \"sridevi.miriyala@modusbox.com\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + }, + "description": "Generated from a curl request: \ncurl -i -X POST {{HOST_CENTRAL_LEDGER}}/participants/testfsp2/initialPositionAndLimits -H 'Cache-Control: no-cache' -H 'Content-Type: application/json' -d '{\n \\\"currency\\\": \\\"USD\\\",\n \\\"limit\\\": {\n \\\"type\\\": \\\"NET_DEBIT_CAP\\\",\n \\\"value\\\": 1000\n },\n \\\"initialPosition\\\": 0\n }'" + }, + "response": [ + { + "name": "2. Create Initial Position and Limits", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Cache-Control", + "value": "no-cache" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"currency\": \"USD\",\n \"limit\": {\n \"type\": \"NET_DEBIT_CAP\",\n \"value\": 1000\n },\n \"initialPosition\": 0\n }" + }, + "url": { + "raw": "http://{{HOST_CENTRAL_LEDGER}}/participants/testfsp/initialPositionAndLimits", + "protocol": "http", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "testfsp", + "initialPositionAndLimits" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "Text", + "header": [], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "DFSP Endpoint-NET_DEBIT_CAP_THRESHOLD_BREACH_EMAIL Copy", + "event": [ + { + "listen": "test", + "script": { + "id": "67082524-b658-4f1c-90c4-af6fc24adb3e", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BEARER_TOKEN}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Cache-Control", + "value": "no-cache" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"NET_DEBIT_CAP_THRESHOLD_BREACH_EMAIL\",\n \"value\": \"sridevi.miriyala@modusbox.com\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + }, + "description": "Generated from a curl request: \ncurl -i -X POST {{HOST_CENTRAL_LEDGER}}/participants/testfsp2/initialPositionAndLimits -H 'Cache-Control: no-cache' -H 'Content-Type: application/json' -d '{\n \\\"currency\\\": \\\"USD\\\",\n \\\"limit\\\": {\n \\\"type\\\": \\\"NET_DEBIT_CAP\\\",\n \\\"value\\\": 1000\n },\n \\\"initialPosition\\\": 0\n }'" + }, + "response": [ + { + "name": "2. Create Initial Position and Limits", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Cache-Control", + "value": "no-cache" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"currency\": \"USD\",\n \"limit\": {\n \"type\": \"NET_DEBIT_CAP\",\n \"value\": 1000\n },\n \"initialPosition\": 0\n }" + }, + "url": { + "raw": "http://{{HOST_CENTRAL_LEDGER}}/participants/testfsp/initialPositionAndLimits", + "protocol": "http", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "testfsp", + "initialPositionAndLimits" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "Text", + "header": [], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "Record Funds In - payerfsp ", + "event": [ + { + "listen": "test", + "script": { + "id": "802139ed-ec95-40f8-99a7-d88f0e77e49d", + "exec": [ + "pm.test(\"Status code is 202\", function () {", + " pm.response.to.have.status(202);", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "id": "461d34bc-33f6-4031-bbc4-b26489ff1953", + "exec": [ + "var uuid = require('uuid');", + "var generatedUUID = uuid.v4();", + "pm.environment.set('fundsInPrepareTransferId', generatedUUID);", + "pm.environment.set('fundsInPrepareAmount', 5000);", + "", + "", + "const payerfspGetStatusRequest = {", + " url: pm.environment.get(\"HOST_CENTRAL_LEDGER\")+pm.environment.get(\"BASE_CENTRAL_LEDGER_ADMIN\")+'/participants/'+pm.environment.get(\"payerfsp\")+'/accounts',", + " method: 'GET',", + " header: {", + " \"Authorization\":\"Bearer \"+pm.environment.get(\"HUB_OPERATOR_BEARER_TOKEN\"),", + " \"FSPIOP-Source\": pm.environment.get(\"hub_operator\"),", + " \"Content-Type\": \"application/json\"", + " }", + "};", + "pm.sendRequest(payerfspGetStatusRequest, function (err, response) {", + " console.log(response.json())", + " var jsonData = response.json()", + " for(var i in jsonData) {", + " if((jsonData[i].ledgerAccountType === 'SETTLEMENT') && (jsonData[i].currency === pm.environment.get(\"currency\"))) {", + " pm.environment.set(\"payerfspSettlementAccountId\",jsonData[i].id)", + " pm.environment.set(\"payerfspSettlementAccountBalanceBeforeFundsIn\",jsonData[i].value)", + " }", + " }", + "});", + "", + "const hubGetStatusRequest = {", + " url: pm.environment.get(\"HOST_CENTRAL_LEDGER\")+pm.environment.get(\"BASE_CENTRAL_LEDGER_ADMIN\")+'/participants/hub/accounts',", + " method: 'GET',", + " header: {", + " \"Authorization\":\"Bearer \"+pm.environment.get(\"BEARER_TOKEN\"),", + " \"FSPIOP-Source\": pm.environment.get(\"payerfsp\"),", + " \"Content-Type\": \"application/json\"", + " }", + "};", + "pm.sendRequest(hubGetStatusRequest, function (err, response) {", + " console.log(response.json())", + " var jsonData = response.json()", + " for(var i in jsonData) {", + " if((jsonData[i].ledgerAccountType === 'HUB_RECONCILIATION') && (jsonData[i].currency === pm.environment.get(\"currency\"))) {", + " pm.environment.set(\"hubReconAccountBalanceBeforeFundsIn\",jsonData[i].value)", + " }", + " }", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BEARER_TOKEN}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "FSPIOP-Source", + "value": "{{payerfsp}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"transferId\": \"{{fundsInPrepareTransferId}}\",\n \"externalReference\": \"string\",\n \"action\": \"recordFundsIn\",\n \"reason\": \"string\",\n \"amount\": {\n \"amount\":\"{{fundsInPrepareAmount}}\" ,\n \"currency\": \"{{currency}}\"\n },\n \"extensionList\": {\n \"extension\": [\n {\n \"key\": \"string\",\n \"value\": \"string\"\n }\n ]\n }\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/accounts/{{payerfspSettlementAccountId}}", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "accounts", + "{{payerfspSettlementAccountId}}" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "e5ffaeb6-241f-4b10-af63-b52b064ff44f", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "efb91eb5-c6c5-460c-89b0-a424f39dcf9a", + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": {}, + "_postman_isSubFolder": true + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "a29d64a2-7a89-4cc9-ac33-2a630283471d", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "7bcf1b8c-ce85-4b11-ac83-899cc81ce501", + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": {} + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "402cb439-04ee-4add-9a65-f4b3f9dafa58", + "type": "text/javascript", + "exec": [ + "", + "// Ensure that the following variables are not set in the environment", + "// This is a fix for the following issue: https://github.com/mojaloop/project/issues/903", + "// This will ensure that templates are not replaced in the endpoint configs:", + "pm.environment.unset('partyIdType')", + "pm.environment.unset('partyIdentifier')", + "pm.environment.unset('requestId')", + "pm.environment.unset('transferId')", + "", + "pm.globals.unset('partyIdType')", + "pm.globals.unset('partyIdentifier')", + "pm.globals.unset('requestId')", + "pm.globals.unset('transferId')" + ] + } + }, + { + "listen": "test", + "script": { + "id": "e73fb24a-c94a-4551-ac31-fb7ceb250579", + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": {} +} \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/scheme-adapter-and-local-k8s-overview.png b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/scheme-adapter-and-local-k8s-overview.png new file mode 100644 index 000000000..4d6282c3c Binary files /dev/null and b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/scheme-adapter-and-local-k8s-overview.png differ diff --git a/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/README.md b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/README.md new file mode 100644 index 000000000..f780e85bc --- /dev/null +++ b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/README.md @@ -0,0 +1,221 @@ +# SDK Scheme Adapter and WSO2 API Gateway + +This documentaion is for testing scheme adapter against a public hosted WSO2 API gateway with SSL encryption and bearer token authentication. + + +![Overview](scheme-adapter-and-wso2-api-gateway-overview.png) + +## Prerequisite + +* Accesss to WSO2 API production api with a generated token. +* sdk-scheme-adapter +* mojaloop-simulator + +## Generate access token and URL from WSO2 API + +* Login to your WSO2 store and go to applications in the menu. Create a new application and access keys if you don't have those already. +* Then go to APIs menu, you should find the following applications. Subscribe to these two APIs by selecting your application and tier from the each API main page. + * Central Ledger Admin API - We will use this endpoint for creating a new fsp and configure endpoints for that fsp. (Please contact your infra team for the proper https endpoints, they need to provision them on the hub) + * FSPIOP API - This is the main API for account lookup, quotes & transfers +* You can try some api requests in "API Console" tab by selecting the generated access token. +* Please make a note of the API URLs for both APIs and access token. + + +## Infrastructure Stuff +The following are the things your infrastructure team should take care off. +Please contact your infra team for further details. +* For getting back the responses, we need a machine with static public IP. And a domain name should be pointed to that IP. +* Generate client and server SSL certificates using MCM portal and keychain tool. This step is to establish secure communication using mutual SSL. +* Provision the endpoints pointing to your https address in WSO2 / HA Proxy. +* Establish JWS authentication +* **AWS Deployment** + * Launch an EC2 instance in AWS console + * Create an EC2 instance in AWS console and select **t2.micro** instance type. + * Select **Ubuntu 18.04** as your operating system. + * After your instance is ready, you can connect to it using ssh and the downloaded key file from AWS EC2 dashboard. + * Install docker and docker-compose in that EC2 instance + + * Open 4000 TCP port in security groups and assign elastic IP + * Add the inbound rule in security group of this EC2 instance that will expose the TCP 4000 port to public + * Use Elastic IP service to assign a static IP for this instance + + * Setup domain name for this instance + * You can use route53 in aws or any other DNS service to point a DNS name to this IP address + * This step is required because the Let's Encrypt certificate authority will not issue certificates for a bare IP address. + + +## Setting up Scheme Adapter with Mojaloop Simulator + +Please download the Mojaloop Simulator repo +``` +git clone https://github.com/mojaloop/mojaloop-simulator.git +``` +* Replace the certificates and keys in src/secrets folder with the generated certificates in the previous step. + +* Edit the file src/docker-compose.yml and change the required parameters. Please refer the following file. + + ``` + version: '3' + services: + redis: + image: "redis:5.0.4-alpine" + container_name: redis + backend: + image: "mojaloop/mojaloop-simulator-backend" + env_file: ./sim-backend.env + container_name: ml_simulator + ports: + - "3000:3000" + - "3001:3001" + - "3003:3003" + depends_on: + - scheme-adapter + + scheme-adapter: + image: "mojaloop/sdk-scheme-adapter:latest" + env_file: ./scheme-adapter.env + container_name: sa_sim2 + volumes: + - ./secrets:/src/secrets + ports: + - "3500:3000" + - "4000:4000" + depends_on: + - redis + ``` + +* Edit the file src/sim-backend.env file and change the container name of the scheme adapter in that. Please refer the following lines. + + ``` + OUTBOUND_ENDPOINT=http://src_scheme-adapter_1:4001 + DFSP_ID=extpayerfsp + ``` + +* Edit the file src/scheme-adapter.env and change the following settings + ``` + MUTUAL_TLS_ENABLED=true + CACHE_HOST=redis + DFSP_ID=extpayerfsp + BACKEND_ENDPOINT=ml_simulator:3000 + PEER_ENDPOINT= + AUTO_ACCEPT_QUOTES=true + ``` + +Then try running the following command to run the services +``` +cd src/ +docker-compose up -d +``` + +We can now access the mojaloop simulator's test api on 3003. + +## Provision a new DFSP "extpayerfsp" with proper endpoints + +We should create a new fsp named "extpayerfp" or with any other name. + +The FSP onboarding section in "OSS-New-Deployment-FSP-Setup" postman collection can be used for this. You can get the postman repo from https://github.com/mojaloop/postman. +* Duplicate the "Mojaloop-Local" environment and change the following valuesin that + * payerfsp - extpayerfsp + * HOST_ML_API_ADAPTER, HOST_ML_API, HOST_SWITCH_TRANSFERS, HOST_ACCOUNT_LOOKUP_SERVICE, HOST_QUOTING_SERVICE - Your WSO2 FSPIOP API endpoint + * HOST_CENTRAL_LEDGER - Your WSO2 Central Services Admin API endpoint + * HOST_CENTRAL_SETTLEMENT - Your WSO2 Central Settlement API endpoint (optional for our testing) + * HOST_SIMULATOR & HOST_SIMULATOR_K8S_CLUSTER - https://:4000 +* Change the URLs in payerfsp onboarding in "FSP Onboarding" section of "OSS-New-Deployment-FSP-Setup" from "payerfsp" to "extpayerfsp" +* Change the authentication as "Bearer Token" and provide the access token we created in WSO2 store for the entire "Payer FSP Onboarding" folder. +* Change the endpoint URLs to the https endpoints provided by your infra team. +* Then run the "Payer FSP Onboarding" folder in that collection with the newly created environment. + +You should get 100% pass then we can confirm that the fsp is created and endpoints are set for the fsp. + +## Provision payeefsp and register a participant against MSISDN simulator + +Generally the simulator running in the switch contains payeefsp and you should register a new participant (phone number) of your choice. + +You can refer the postman request "p2p_happy_path SEND QUOTE / Register Participant {{pathfinderMSISDN}} against MSISDN Simulator for PayeeFSP" in "Golden_Path" collection to achieve this. + +The postman request will send a POST request to /participants/MSISDN/ with the following body and required http headers. +``` +{ + "fspId": "payeefsp", + "currency": "USD" +} +``` + +## Send money + +### In one step +If you want to send the money in one step, the configuration options "AUTO_ACCEPT_QUOTES" & "AUTO_ACCEPT_PARTY" in "scheme_adapter.env" should be enabled. + +``` +curl -X POST \ + "http://localhost:3003/scenarios" \ + -H 'Content-Type: application/json' \ + -d '[ + { + "name": "scenario1", + "operation": "postTransfers", + "body": { + "from": { + "displayName": "From some person name", + "idType": "MSISDN", + "idValue": "44123456789" + }, + "to": { + "idType": "MSISDN", + "idValue": "919848123456" + }, + "amountType": "SEND", + "currency": "USD", + "amount": "100", + "transactionType": "TRANSFER", + "note": "testpayment", + "homeTransactionId": "123ABC" + } + } +]' + +``` + +### In two steps + +The following command is used to send the money in two steps (i.e Requesting the quote first, accept after review the charges and party details) + +``` +curl -X POST \ + "http://localhost:3003/scenarios" \ + -H 'Content-Type: application/json' \ + -d '[ + { + "name": "scenario1", + "operation": "postTransfers", + "body": { + "from": { + "displayName": "From some person name", + "idType": "MSISDN", + "idValue": "44123456789" + }, + "to": { + "idType": "MSISDN", + "idValue": "9848123456" + }, + "amountType": "SEND", + "currency": "USD", + "amount": "100", + "transactionType": "TRANSFER", + "note": "testpayment", + "homeTransactionId": "123ABC" + } + }, + { + "name": "scenario2", + "operation": "putTransfers", + "params": { + "transferId": "{{scenario1.result.transferId}}" + }, + "body": { + "acceptQuote": true + } + } +]' + +``` \ No newline at end of file diff --git a/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/scheme-adapter-and-wso2-api-gateway-overview.png b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/scheme-adapter-and-wso2-api-gateway-overview.png new file mode 100644 index 000000000..206d31d45 Binary files /dev/null and b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/scheme-adapter-and-wso2-api-gateway-overview.png differ diff --git a/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/README.md b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/README.md new file mode 100644 index 000000000..b34595858 --- /dev/null +++ b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/README.md @@ -0,0 +1,180 @@ +# Scheme Adapter to Scheme Adapter testing + +A detailed documentation for dfsps who want to test the transfer of funds from a scheme adapter to another scheme adapter directly using mock backend and mojaloop simulator services. + +![Overview](scheme-adapter-to-scheme-adapter-overview.png) + +## Prerequisite + +* Mojaloop Simulator +* DFSP mock backend service +* Scheme adapter is already included in both the above docker-compose scripts + +## Configuration & Starting services + +The idea is to run two docker-compose scripts in parallel from the above two services. To avoid conflicts we need to edit the docker-compose.yml files and specify the container names. + +### Mojaloop Simulator service + +Please download the Mojaloop Simulator repo +``` +git clone https://github.com/mojaloop/mojaloop-simulator.git +``` +* Edit the file src/docker-compose.yml and add the container names for all the containers. Please refer the following lines + +``` +version: '3' +services: + redis1: + image: "redis:5.0.4-alpine" + container_name: redis1 + sim: + image: "mojaloop-simulator-backend" + build: ../ + env_file: ./sim-backend.env + container_name: ml_sim1 + ports: + - "13000:3000" + - "3001:3001" + - "3003:3003" + depends_on: + - scheme-adapter + scheme-adapter: + image: "mojaloop/sdk-scheme-adapter:latest" + env_file: ./scheme-adapter.env + container_name: sa_sim1 + ports: + - "13500:3000" + - "14000:4000" + depends_on: + - redis1 +``` + +* Edit the file src/sim-backend.env file and change the container name of the scheme adapter in that. Please refer the following lines. + +``` +OUTBOUND_ENDPOINT=http://sa_sim1:4001 +``` + +* Edit the file src/scheme-adapter.env file and change the container names of the another scheme adapter and mojaloop simulator. Please refer the following lines + +``` +DFSP_ID=payeefsp +CACHE_HOST=redis1 +PEER_ENDPOINT=sa_sim2:4000 +BACKEND_ENDPOINT=ml_sim1:3000 +AUTO_ACCEPT_PARTY=true +AUTO_ACCEPT_QUOTES=true +VALIDATE_INBOUND_JWS=false +VALIDATE_INBOUND_PUT_PARTIES_JWS=false +JWS_SIGN=true +JWS_SIGN_PUT_PARTIES=true + +``` + +Then try running the following command to run the services +``` +cd src/ +docker-compose up -d +``` + +We can now access the mojaloop simulator's test api on 3003. + +A new party should be added to the simulator using the following command. Feel free to change the details you want. +``` +curl -X POST "http://localhost:3003/repository/parties" -H "accept: */*" -H "Content-Type: application/json" -d "{\"displayName\":\"Test Payee1\",\"firstName\":\"Test\",\"middleName\":\"\",\"lastName\":\"Payee1\",\"dateOfBirth\":\"1970-01-01\",\"idType\":\"MSISDN\",\"idValue\":\"9876543210\"}" +``` + +Then try to run the following command to check the new party added. +``` +curl -X GET "http://localhost:3003/repository/parties" -H "accept: */*" +``` + +Let's move on to setup another instance of scheme adapter with DFSP mock backend. + +### DFSP Mock Backend service + +The DFSP mock backend is a minimal implementation of an example DFSP. Only basic functions are supported at the moment. + +Please download the following repository +``` +git clone https://github.com/mojaloop/sdk-mock-dfsp-backend.git +``` + +Edit the files src/docker-compose.yml, src/backend.env and src/scheme-adapter.env and add the container names for all the containers. Please refer the following files. +docker-compose.yml +``` +version: '3' +services: + redis2: + image: "redis:5.0.4-alpine" + container_name: redis2 + backend: + image: "mojaloop/sdk-mock-dfsp-backend" + env_file: ./backend.env + container_name: dfsp_mock_backend2 + ports: + - "23000:3000" + depends_on: + - scheme-adapter2 + + scheme-adapter2: + image: "mojaloop/sdk-scheme-adapter:latest" + env_file: ./scheme-adapter.env + container_name: sa_sim2 + depends_on: + - redis2 +``` +scheme-adapter.env +``` +DFSP_ID=payerfsp +CACHE_HOST=redis2 +PEER_ENDPOINT=sa_sim1:4000 +BACKEND_ENDPOINT=dfsp_mock_backend2:3000 +AUTO_ACCEPT_PARTY=true +AUTO_ACCEPT_QUOTES=true +VALIDATE_INBOUND_JWS=false +VALIDATE_INBOUND_PUT_PARTIES_JWS=false +JWS_SIGN=true +JWS_SIGN_PUT_PARTIES=true + +``` + +backend.env +``` +OUTBOUND_ENDPOINT=http://sa_sim2:4001 +``` + +Then try running the following command to run the services +``` +cd src/ +docker-compose up -d +``` + +## Try to send money +Try to send funds from "payerfsp" (Mock DFSP) to a MSISDN which is in "payeefsp" (Mojaloop Simulator) through scheme adapter. +Run the following curl command to issue command to Mock DFSP service. +``` +curl -X POST \ + http://localhost:23000/send \ + -H 'Content-Type: application/json' \ + -d '{ + "from": { + "displayName": "John Doe", + "idType": "MSISDN", + "idValue": "123456789" + }, + "to": { + "idType": "MSISDN", + "idValue": "9876543210" + }, + "amountType": "SEND", + "currency": "USD", + "amount": "100", + "transactionType": "TRANSFER", + "note": "test payment", + "homeTransactionId": "123ABC" +}' +``` + +You should get a response with COMPLETED currentState. diff --git a/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/scheme-adapter-to-scheme-adapter-overview.png b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/scheme-adapter-to-scheme-adapter-overview.png new file mode 100644 index 000000000..35702294c Binary files /dev/null and b/legacy/mojaloop-technical-overview/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/scheme-adapter-to-scheme-adapter-overview.png differ diff --git a/legacy/mojaloop-technical-overview/transaction-requests-service/README.md b/legacy/mojaloop-technical-overview/transaction-requests-service/README.md new file mode 100644 index 000000000..b339478a9 --- /dev/null +++ b/legacy/mojaloop-technical-overview/transaction-requests-service/README.md @@ -0,0 +1,8 @@ +# Transaction Requests Service + +## Sequence Diagram + +![trx-service-overview-spec.svg](./assets/diagrams/sequence/trx-service-overview-spec.svg) + +* The transaction-requests-service is a mojaloop core service that enables Payee initiated use cases such as "Merchant Request to Pay". +* This is a pass through service which also includes Authorizations. diff --git a/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.plantuml b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.plantuml new file mode 100644 index 000000000..0d4005e68 --- /dev/null +++ b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.plantuml @@ -0,0 +1,64 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- + ******'/ + + +@startuml +Title Transaction Requests Service - Authorizations +participant "Payer FSP" +participant "Switch\ntransaction-requests-service" as Switch +participant "Payee FSP" + +autonumber +"Payee FSP" --\ "Payee FSP": Lookup, Transaction request,\nprocessing not shown here +note over "Payee FSP", Switch: Payee FSP generates a transaction-request to the Payer FSP +"Payer FSP" --> "Payer FSP": Do quote, generate OTP\nnotify user (not shown here) +"Payer FSP" -\ Switch: GET /authorizations/{TransactionRequestID} +Switch --/ "Payer FSP": 202 Accepted + +alt authorization request is valid + + Switch -> Switch: Validate GET /authorizations/{TransactionRequestID} (internal validation) + Switch -> Switch: Retrieve corresponding end-points for Payee FSP + note over Switch, "Payee FSP": Switch forwards GET /authorizations request to Payee FSP + Switch -\ "Payee FSP": GET /authorizations/{TransactionRequestID} + "Payee FSP" --/ Switch: 202 Accepted + "Payee FSP" -> "Payee FSP": Process authorization request\n(Payer approves/rejects transaction\nusing OTP) + + note over Switch, "Payee FSP": Payee FSP responds with PUT /authorizations//{TransactionRequestID} + "Payee FSP" -\ Switch: PUT /authorizations//{TransactionRequestID} + Switch --/ "Payee FSP": 200 Ok + + note over "Payer FSP", Switch: Switch forwards PUT /authorizations//{TransactionRequestID} to Payer FSP + Switch -> Switch: Retrieve corresponding end-points for Payer FSP + Switch -\ "Payer FSP": PUT /authorizations//{TransactionRequestID} + "Payer FSP" --/ Switch: 200 Ok + + +else authorization request is invalid + note over "Payer FSP", Switch: Switch returns error callback to Payer FSP + Switch -\ "Payer FSP": PUT /authorizations/{TransactionRequestID}/error + "Payer FSP" --/ Switch: 200 OK + "Payer FSP" --> "Payer FSP": Validate OTP sent by Payee FSP +end +@enduml diff --git a/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.svg b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.svg new file mode 100644 index 000000000..20f251063 --- /dev/null +++ b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.svg @@ -0,0 +1,231 @@ + + + + + + + + + + + Transaction Requests Service - Authorizations + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + transaction-requests-service + + + + Switch + + + transaction-requests-service + + + + Payee FSP + + + + Payee FSP + + + + + 1 + + + Lookup, Transaction request, + + + processing not shown here + + + + + Payee FSP generates a transaction-request to the Payer FSP + + + + + 2 + + + Do quote, generate OTP + + + notify user (not shown here) + + + + + 3 + + + GET /authorizations/{TransactionRequestID} + + + + + 4 + + + 202 Accepted + + + + + alt + + + [authorization request is valid] + + + + + 5 + + + Validate GET /authorizations/{TransactionRequestID} (internal validation) + + + + + 6 + + + Retrieve corresponding end-points for Payee FSP + + + + + Switch forwards GET /authorizations request to Payee FSP + + + + + 7 + + + GET /authorizations/{TransactionRequestID} + + + + + 8 + + + 202 Accepted + + + + + 9 + + + Process authorization request + + + (Payer approves/rejects transaction + + + using OTP) + + + + + Payee FSP responds with PUT /authorizations//{TransactionRequestID} + + + + + 10 + + + PUT /authorizations//{TransactionRequestID} + + + + + 11 + + + 200 Ok + + + + + Switch forwards PUT /authorizations//{TransactionRequestID} to Payer FSP + + + + + 12 + + + Retrieve corresponding end-points for Payer FSP + + + + + 13 + + + PUT /authorizations//{TransactionRequestID} + + + + + 14 + + + 200 Ok + + + + [authorization request is invalid] + + + + + Switch returns error callback to Payer FSP + + + + + 15 + + + PUT /authorizations/{TransactionRequestID}/error + + + + + 16 + + + 200 OK + + + + + 17 + + + Validate OTP sent by Payee FSP + + diff --git a/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.plantuml b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.plantuml new file mode 100644 index 000000000..655cf6e07 --- /dev/null +++ b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.plantuml @@ -0,0 +1,93 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- + ******'/ + + +@startuml +Title Transaction Requests Service - Create +participant "Payer FSP" +participant "Switch\ntransaction-requests-service" as Switch +participant "Payee FSP" + +autonumber +"Payee FSP" -\ "Payee FSP": Lookup process\n(not shown here) +note over "Payee FSP", Switch: Payee FSP generates a transaction-request to the Payer FSP +"Payee FSP" -\ Switch: POST /transactionRequests +Switch -> Switch: Validate POST /transactionRequests schema +Switch --/ "Payee FSP": 202 Accepted + +alt transaction-request is valid + + Switch -> Switch: Validate POST /transactionRequests (internal validation) + Switch -> Switch: Retrieve corresponding end-points for Payer FSP + note over Switch, "Payer FSP": Switch forwards POST /transactionRequests request to Payer FSP + Switch -\ "Payer FSP": POST /transactionRequests + "Payer FSP" --/ Switch: 202 Accepted + "Payer FSP" -> "Payer FSP": Process transaction-request + + alt Payer FSP successfully processes transaction-request + + note over "Payer FSP", Switch: Payer FSP responds to POST /transactionRequests + "Payer FSP" -\ Switch: PUT /transactionRequests/{ID} + Switch --/ "Payer FSP": 200 Ok + + Switch -> Switch: Validate PUT /transactionRequests/{ID} + + alt response is ok + + note over Switch, "Payee FSP": Switch forwards transaction-request response to Payee FSP + Switch -> Switch: Retrieve corresponding end-points for Payee FSP + + Switch -\ "Payee FSP": PUT /transactionRequests/{ID} + "Payee FSP" --/ Switch: 200 Ok + + note over "Payee FSP" #3498db: Wait for a quote, transfer by Payer FSP\nor a rejected transaction-request + else response invalid + + note over Switch, "Payer FSP": Switch returns error to Payer FSP + + Switch -\ "Payer FSP": PUT /transactionRequests/{ID}/error + "Payer FSP" --/ Switch : 200 Ok + + note over Switch, "Payer FSP" #ec7063: Note that under this\nscenario the Payee FSP\nmay not receive a response + + end + else Payer FSP calculation fails or rejects the request + + note over "Payer FSP", Switch: Payer FSP returns error to Switch + + "Payer FSP" -\ Switch: PUT /transactionRequests/{ID}/error + Switch --/ "Payer FSP": 200 OK + + note over "Payee FSP", Switch: Switch returns error to Payee FSP + + Switch -\ "Payee FSP": PUT /transactionRequests/{ID}/error + "Payee FSP" --/ Switch: 200 OK + + end +else transaction-request is invalid + note over "Payee FSP", Switch: Switch returns error to Payee FSP + Switch -\ "Payee FSP": PUT /transactionRequests/{ID}/error + "Payee FSP" --/ Switch: 200 OK +end +@enduml diff --git a/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.svg b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.svg new file mode 100644 index 000000000..b5a1c7313 --- /dev/null +++ b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.svg @@ -0,0 +1,330 @@ + + + + + + + + + + + Transaction Requests Service - Create + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + transaction-requests-service + + + + Switch + + + transaction-requests-service + + + + Payee FSP + + + + Payee FSP + + + + + 1 + + + Lookup process + + + (not shown here) + + + + + Payee FSP generates a transaction-request to the Payer FSP + + + + + 2 + + + POST /transactionRequests + + + + + 3 + + + Validate POST /transactionRequests schema + + + + + 4 + + + 202 Accepted + + + + + alt + + + [transaction-request is valid] + + + + + 5 + + + Validate POST /transactionRequests (internal validation) + + + + + 6 + + + Retrieve corresponding end-points for Payer FSP + + + + + Switch forwards POST /transactionRequests request to Payer FSP + + + + + 7 + + + POST /transactionRequests + + + + + 8 + + + 202 Accepted + + + + + 9 + + + Process transaction-request + + + + + alt + + + [Payer FSP successfully processes transaction-request] + + + + + Payer FSP responds to POST /transactionRequests + + + + + 10 + + + PUT /transactionRequests/{ID} + + + + + 11 + + + 200 Ok + + + + + 12 + + + Validate PUT /transactionRequests/{ID} + + + + + alt + + + [response is ok] + + + + + Switch forwards transaction-request response to Payee FSP + + + + + 13 + + + Retrieve corresponding end-points for Payee FSP + + + + + 14 + + + PUT /transactionRequests/{ID} + + + + + 15 + + + 200 Ok + + + + + Wait for a quote, transfer by Payer FSP + + + or a rejected transaction-request + + + + [response invalid] + + + + + Switch returns error to Payer FSP + + + + + 16 + + + PUT /transactionRequests/{ID}/error + + + + + 17 + + + 200 Ok + + + + + Note that under this + + + scenario the Payee FSP + + + may not receive a response + + + + [Payer FSP calculation fails or rejects the request] + + + + + Payer FSP returns error to Switch + + + + + 18 + + + PUT /transactionRequests/{ID}/error + + + + + 19 + + + 200 OK + + + + + Switch returns error to Payee FSP + + + + + 20 + + + PUT /transactionRequests/{ID}/error + + + + + 21 + + + 200 OK + + + + [transaction-request is invalid] + + + + + Switch returns error to Payee FSP + + + + + 22 + + + PUT /transactionRequests/{ID}/error + + + + + 23 + + + 200 OK + + diff --git a/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.plantuml b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.plantuml new file mode 100644 index 000000000..17262a24a --- /dev/null +++ b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.plantuml @@ -0,0 +1,90 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- + ******'/ + + +@startuml +Title Transaction Requests Service - Query +participant "Payer FSP" +participant "Switch\ntransaction-requests-service" as Switch +participant "Payee FSP" + +autonumber +note over "Payee FSP", Switch: Payee FSP requests the status of a transaction-request at the Payer FSP.\nID here is the ID of prevoiusly created transaction-request +"Payee FSP" -\ Switch: GET /transactionRequests/{ID} +Switch -> Switch: Validate GET /transactionRequests/{ID} +Switch --/ "Payee FSP": 202 Accepted + +alt transaction-request query is valid + + Switch -> Switch: Retrieve corresponding end-points for Payer FSP + note over Switch, "Payer FSP": Switch forwards GET /transactionRequests/{ID} request to Payer FSP + Switch -\ "Payer FSP": GET /transactionRequests/{ID} + "Payer FSP" --/ Switch: 202 Accepted + "Payer FSP" -> "Payer FSP": Retrieve transaction-request + + alt Payer FSP successfully retrieves transaction-request + + note over "Payer FSP", Switch: Payer FSP responds with the\nPUT /transactionRequests/{ID} callback + "Payer FSP" -\ Switch: PUT /transactionRequests/{ID} + Switch --/ "Payer FSP": 200 Ok + + Switch -> Switch: Validate PUT /transactionRequests/{ID} + + alt response is ok + + note over Switch, "Payee FSP": Switch forwards transaction-request response to Payee FSP + Switch -> Switch: Retrieve corresponding end-points for Payee FSP + + Switch -\ "Payee FSP": PUT /transactionRequests/{ID} + "Payee FSP" --/ Switch: 200 Ok + + else response invalid + + note over Switch, "Payer FSP": Switch returns error to Payer FSP + + Switch -\ "Payer FSP": PUT /transactionRequests/{ID}/error + "Payer FSP" --/ Switch : 200 Ok + + note over Switch, "Payer FSP" #ec7063: Note that under this\nscenario the Payee FSP\nmay not receive a response + + end + else Payer FSP is unable to retrieve the transaction-request + + note over "Payer FSP", Switch: Payer FSP returns error to Switch + + "Payer FSP" -\ Switch: PUT /transactionRequests/{ID}/error + Switch --/ "Payer FSP": 200 OK + + note over "Payee FSP", Switch: Switch returns error to Payee FSP + + Switch -\ "Payee FSP": PUT /transactionRequests/{ID}/error + "Payee FSP" --/ Switch: 200 OK + + end +else transaction-request is invalid + note over "Payee FSP", Switch: Switch returns error to Payee FSP + Switch -\ "Payee FSP": PUT /transactionRequests/{ID}/error + "Payee FSP" --/ Switch: 200 OK +end +@enduml diff --git a/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.svg b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.svg new file mode 100644 index 000000000..bbc20538b --- /dev/null +++ b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.svg @@ -0,0 +1,309 @@ + + + + + + + + + + + Transaction Requests Service - Query + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + transaction-requests-service + + + + Switch + + + transaction-requests-service + + + + Payee FSP + + + + Payee FSP + + + + + Payee FSP requests the status of a transaction-request at the Payer FSP. + + + ID here is the ID of prevoiusly created transaction-request + + + + + 1 + + + GET /transactionRequests/{ID} + + + + + 2 + + + Validate GET /transactionRequests/{ID} + + + + + 3 + + + 202 Accepted + + + + + alt + + + [transaction-request query is valid] + + + + + 4 + + + Retrieve corresponding end-points for Payer FSP + + + + + Switch forwards GET /transactionRequests/{ID} request to Payer FSP + + + + + 5 + + + GET /transactionRequests/{ID} + + + + + 6 + + + 202 Accepted + + + + + 7 + + + Retrieve transaction-request + + + + + alt + + + [Payer FSP successfully retrieves transaction-request] + + + + + Payer FSP responds with the + + + PUT /transactionRequests/{ID} callback + + + + + 8 + + + PUT /transactionRequests/{ID} + + + + + 9 + + + 200 Ok + + + + + 10 + + + Validate PUT /transactionRequests/{ID} + + + + + alt + + + [response is ok] + + + + + Switch forwards transaction-request response to Payee FSP + + + + + 11 + + + Retrieve corresponding end-points for Payee FSP + + + + + 12 + + + PUT /transactionRequests/{ID} + + + + + 13 + + + 200 Ok + + + + [response invalid] + + + + + Switch returns error to Payer FSP + + + + + 14 + + + PUT /transactionRequests/{ID}/error + + + + + 15 + + + 200 Ok + + + + + Note that under this + + + scenario the Payee FSP + + + may not receive a response + + + + [Payer FSP is unable to retrieve the transaction-request] + + + + + Payer FSP returns error to Switch + + + + + 16 + + + PUT /transactionRequests/{ID}/error + + + + + 17 + + + 200 OK + + + + + Switch returns error to Payee FSP + + + + + 18 + + + PUT /transactionRequests/{ID}/error + + + + + 19 + + + 200 OK + + + + [transaction-request is invalid] + + + + + Switch returns error to Payee FSP + + + + + 20 + + + PUT /transactionRequests/{ID}/error + + + + + 21 + + + 200 OK + + diff --git a/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.plantuml b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.plantuml new file mode 100644 index 000000000..d88913d33 --- /dev/null +++ b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.plantuml @@ -0,0 +1,138 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation +- Name Surname + +* Henk Kodde +-------------- +******'/ + +@startuml transactionRequests + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title How to use the /transactionRequests service + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee + +' declare actors +participant "Payer\nFSP" as payerfsp +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as payeefsp +actor "<$actor>\nPayee" as Payee + +' start flow +payeefsp <- Payee: I would like to receive\nfunds from +123456789 +activate payeefsp +payeefsp <- payeefsp: Lookup +123456789\n(process not shown here) +Switch <<- payeefsp: **POST /transactionRequest/**\n(Payee information,\ntransaction details) +activate Switch +Switch -->> payeefsp: **HTTP 202** (Accepted) +payerfsp <<- Switch: **POST /transactionRequests/**\n(Payee information,\ntransaction details) +activate payerfsp +payerfsp -->> Switch: **HTTP 202** (Accepted) +payeefsp -> payeefsp: Perform optional validation +payerfsp ->> Switch: **PUT /transactionRequests/**\n(Received status) +payerfsp <<-- Switch: **HTTP 200** (OK) +deactivate payerfsp +Switch ->> payeefsp: **PUT /transactionRequests/**\n(Received status) +Switch <<-- payeefsp: **HTTP 200** (OK) +deactivate Switch +payeefsp -> payeefsp: Wait for either quote and\ntransfer, or rejected\ntransaction request by Payer +payeefsp <[hidden]- payeefsp +deactivate payeefsp +@enduml diff --git a/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.svg b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.svg new file mode 100644 index 000000000..e54569705 --- /dev/null +++ b/legacy/mojaloop-technical-overview/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.svg @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + Payer + + + FSP + + + + Optional + + + Switch + + + + Payee + + + FSP + + + + Payee + + + + + + + I would like to receive + + + funds from +123456789 + + + + Lookup +123456789 + + + (process not shown here) + + + + POST /transactionRequest/ + + + (Payee information, + + + transaction details) + + + + + HTTP 202 + + + (Accepted) + + + + POST /transactionRequests/ + + + (Payee information, + + + transaction details) + + + + + HTTP 202 + + + (Accepted) + + + + Perform optional validation + + + + PUT /transactionRequests/ + + + <ID> + + + (Received status) + + + + + HTTP 200 + + + (OK) + + + + PUT /transactionRequests/ + + + <ID> + + + (Received status) + + + + + HTTP 200 + + + (OK) + + + + Wait for either quote and + + + transfer, or rejected + + + transaction request by Payer + + diff --git a/legacy/mojaloop-technical-overview/transaction-requests-service/authorizations.md b/legacy/mojaloop-technical-overview/transaction-requests-service/authorizations.md new file mode 100644 index 000000000..614b5d0a5 --- /dev/null +++ b/legacy/mojaloop-technical-overview/transaction-requests-service/authorizations.md @@ -0,0 +1,7 @@ +# Transaction Requests + +GET /authorizations/{TransactionRequestID} and PUT /authorizations/{TransactionRequestID} to support authorizations in "Merchant Request to Pay" and other Payee initiated use cases + +## Sequence Diagram + +![seq-trx-req-authorizations-3.0.0.svg](./assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.svg) diff --git a/legacy/mojaloop-technical-overview/transaction-requests-service/transaction-requests-get.md b/legacy/mojaloop-technical-overview/transaction-requests-service/transaction-requests-get.md new file mode 100644 index 000000000..b99202192 --- /dev/null +++ b/legacy/mojaloop-technical-overview/transaction-requests-service/transaction-requests-get.md @@ -0,0 +1,7 @@ +# Transaction Requests - Query + +GET /transactionRequests and PUT /transacionRequests to suppport "Merchant Request to Pay" + +## Sequence Diagram + +![seq-trx-req-service-get-2.0.0.svg](./assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.svg) diff --git a/legacy/mojaloop-technical-overview/transaction-requests-service/transaction-requests-post.md b/legacy/mojaloop-technical-overview/transaction-requests-service/transaction-requests-post.md new file mode 100644 index 000000000..58ea60460 --- /dev/null +++ b/legacy/mojaloop-technical-overview/transaction-requests-service/transaction-requests-post.md @@ -0,0 +1,7 @@ +# Transaction Requests + +POST /transactionRequests and PUT /transacionRequests to suppport "Merchant Request to Pay" + +## Sequence Diagram + +![seq-trx-req-service-1.0.0.svg](./assets/diagrams/sequence/seq-trx-req-service-1.0.0.svg) diff --git a/onboarding.md b/legacy/onboarding.md similarity index 100% rename from onboarding.md rename to legacy/onboarding.md diff --git a/legacy/package-lock.json b/legacy/package-lock.json new file mode 100644 index 000000000..b10908b77 --- /dev/null +++ b/legacy/package-lock.json @@ -0,0 +1,13528 @@ +{ + "name": "documentation", + "version": "11.3.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.12.13" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz", + "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@korzio/djv-draft-04": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@korzio/djv-draft-04/-/djv-draft-04-2.0.1.tgz", + "integrity": "sha512-MeTVcNsfCIYxK6T7jW1sroC7dBAb4IfLmQe6RoCqlxHN5NFkzNpgdnBPR+/0D2wJDUJHM9s9NQv+ouhxKjvUjg==", + "dev": true, + "optional": true + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==" + }, + "@npmcli/ci-detect": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@npmcli/ci-detect/-/ci-detect-1.3.0.tgz", + "integrity": "sha512-oN3y7FAROHhrAt7Rr7PnTSwrHrZVRTS2ZbyxeQwSSYD0ifwM3YNgQqbaRmjcWoPyq77MjchusjJDspbzMmip1Q==", + "dev": true + }, + "@npmcli/git": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.0.3.tgz", + "integrity": "sha512-c/ODsV5ppjB12VDXKc6hzVNgg6ZJX/etILUn3WgF5NLAYBhQLJ3fBq6uB2jQD4OwqOzJdPT1/xA3Xh3aaWGk5w==", + "dev": true, + "requires": { + "@npmcli/promise-spawn": "^1.1.0", + "lru-cache": "^6.0.0", + "mkdirp": "^1.0.3", + "npm-pick-manifest": "^6.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "semver": "^7.3.2", + "unique-filename": "^1.1.1", + "which": "^2.0.2" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "dev": true, + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "@npmcli/move-file": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz", + "integrity": "sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "@npmcli/node-gyp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.2.tgz", + "integrity": "sha512-yrJUe6reVMpktcvagumoqD9r08fH1iRo01gn1u0zoCApa9lnZGEigVKUd2hzsCId4gdtkZZIVscLhNxMECKgRg==", + "dev": true + }, + "@npmcli/promise-spawn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.2.0.tgz", + "integrity": "sha512-nFtqjVETliApiRdjbYwKwhlSHx2ZMagyj5b9YbNt0BWeeOVxJd47ZVE2u16vxDHyTOZvk+YLV7INwfAE9a2uow==", + "dev": true, + "requires": { + "infer-owner": "^1.0.4" + } + }, + "@sindresorhus/is": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.0.tgz", + "integrity": "sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", + "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", + "dev": true, + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@types/cacheable-request": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", + "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", + "dev": true, + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/http-cache-semantics": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", + "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==", + "dev": true + }, + "@types/keyv": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", + "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "14.14.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz", + "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==" + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "@types/q": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", + "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", + "dev": true + }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/yauzl": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", + "optional": true, + "requires": { + "@types/node": "*" + } + }, + "abab": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", + "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=", + "optional": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "accepts": { + "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.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", + "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", + "optional": true + }, + "acorn-globals": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", + "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=", + "optional": true, + "requires": { + "acorn": "^2.1.0" + } + }, + "agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==" + }, + "agentkeepalive": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz", + "integrity": "sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "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 + } + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "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": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dev": true, + "requires": { + "string-width": "^3.0.0" + }, + "dependencies": { + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" + }, + "ansistyles": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ansistyles/-/ansistyles-0.1.3.tgz", + "integrity": "sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk=" + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "apache-crypt": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/apache-crypt/-/apache-crypt-1.2.4.tgz", + "integrity": "sha512-Icze5ny5W5uv3xgMgl8U+iGmRCC0iIDrb2PVPuRBtL3Zy1Y5TMewXP1Vtc4r5X9eNNBEk7KYPu0Qby9m/PmcHg==", + "requires": { + "unix-crypt-td-js": "^1.1.4" + } + }, + "apache-md5": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.5.tgz", + "integrity": "sha512-sbLEIMQrkV7RkIruqTPXxeCMkAAycv4yzTkBzRgOR1BrR5UB7qZtupqxkersTJSf0HZ3sbaNRrNV80TnnM7cUw==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "audit-resolve-core": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/audit-resolve-core/-/audit-resolve-core-1.1.8.tgz", + "integrity": "sha512-F3IWaxu1Xw4OokmtG9hkmsKoJt8DQS7RZvot52zXHsANKvzFRMKVNTP1DAz1ztlRGmJx1XV16PcE+6m35bYoTA==", + "dev": true, + "requires": { + "concat-stream": "^1.6.2", + "debug": "^4.1.1", + "djv": "^2.1.2", + "spawn-shell": "^2.1.0", + "yargs-parser": "^18.1.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "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 + } + } + }, + "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.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bash-color": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/bash-color/-/bash-color-0.0.4.tgz", + "integrity": "sha1-6b6M4zVAytpIgXaMWb1jhlc26RM=" + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "~2.0.0" + } + }, + "bluebird": { + "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.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.x.x" + } + }, + "bootprint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bootprint/-/bootprint-1.0.2.tgz", + "integrity": "sha512-zrbDC1VVvOuOAf85Vc2Ni1AQxyQr0LqV6xJ8CAUCKRGo+EN1gWjTzmGfmRbeVIBsAouGSwYUcPonhHgbQct5+A==", + "requires": { + "commander": "^2.6.0", + "customize-engine-handlebars": "^1.0.0", + "customize-engine-less": "^1.0.1", + "customize-engine-uglify": "^1.0.0", + "customize-watch": "^1.0.0", + "customize-write-files": "^1.0.0", + "debug": "^2.1.2", + "get-promise": "^1.3.1", + "js-yaml": "^3.8.2", + "live-server": "^1.2.0", + "q": "^1.4.1", + "trace-and-clarify-if-possible": "^1.0.3" + } + }, + "bootprint-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bootprint-base/-/bootprint-base-1.1.0.tgz", + "integrity": "sha1-svYgtki/pvxuAnGzhxz8nPeM0DA=", + "requires": { + "bootstrap": "^3.3.2", + "cheerio": "^0.19.0", + "handlebars": "^3.0.0", + "highlight.js": "^8.4.0", + "jquery": "^2", + "json-stable-stringify": "^1.0.0", + "marked": "^0.3.3" + } + }, + "bootprint-json-schema": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bootprint-json-schema/-/bootprint-json-schema-1.1.0.tgz", + "integrity": "sha1-UI6PoRINyW0Lwsa6g0HrzdVFhSg=", + "requires": { + "bootprint-base": "^1.0.0", + "lodash": "^4.17.2" + } + }, + "bootprint-swagger": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bootprint-swagger/-/bootprint-swagger-1.0.1.tgz", + "integrity": "sha1-ykYPsXnZDXVymWwBaFJXroDNHDM=", + "requires": { + "bootprint-json-schema": "^1.0.0", + "highlight.js": "^8.9.1", + "json-stable-stringify": "^1.0.1", + "lodash": "^3.9.3", + "m-io": "^0.3.1" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + }, + "m-io": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/m-io/-/m-io-0.3.1.tgz", + "integrity": "sha1-SgeSJG9oGfdFyLxdlzzeiC8NHvs=", + "requires": { + "mkdirp": "^0.5.1", + "q": "^1.4.1", + "rimraf": "^2.5.3" + } + } + } + }, + "bootstrap": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz", + "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==" + }, + "boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "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==" + }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "cacache": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", + "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", + "dev": true, + "requires": { + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.0", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true + }, + "cacheable-request": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", + "integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^2.0.0" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cheerio": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz", + "integrity": "sha1-dy5wFfLuKZZQltcepBdbdas1SSU=", + "requires": { + "css-select": "~1.0.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "~3.8.1", + "lodash": "^3.2.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cint": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/cint/-/cint-8.2.1.tgz", + "integrity": "sha1-cDhrG0jidz0NYxZqVa/5TvRFahI=", + "dev": true + }, + "clarify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clarify/-/clarify-2.1.0.tgz", + "integrity": "sha512-sWdsTozdtoFQbmncCXqCKeUzQbEZul/WJ8xYGVJgfIf4xMEM5q0La+Gjo2MFNOVL0FfTFteHqw6JX+9M71dAdQ==", + "optional": true, + "requires": { + "stack-chain": "^2.0.0" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, + "cli-table": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.5.tgz", + "integrity": "sha512-7uo2+RMNQUZ13M199udxqwk1qxTOS53EUak4gmu/aioUpdH5RvBz0JkJslcWz6ABKedZNqXXzikMZgHh+qF16A==", + "dev": true, + "requires": { + "colors": "1.0.3" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + } + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + } + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "combined-stream": { + "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" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "dev": true + }, + "component-emitter": { + "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==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "content-disposition": { + "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", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "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", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "requires": { + "boom": "2.x.x" + } + }, + "crypto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", + "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==" + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, + "css-select": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz", + "integrity": "sha1-sRIcpRhI3SZOIkTQWM7iVN7rRLA=", + "requires": { + "boolbase": "~1.0.0", + "css-what": "1.0", + "domutils": "1.4", + "nth-check": "~1.0.0" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-what": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz", + "integrity": "sha1-18wt9FGAZm+Z0rFEYmOUaeAPc2w=" + }, + "csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "requires": { + "css-tree": "^1.1.2" + }, + "dependencies": { + "css-tree": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.2.tgz", + "integrity": "sha512-wCoWush5Aeo48GLhfHPbmvZs59Z+M7k5+B1xDnXbdWNcEF423DoFdqSWE0PM5aNk5nI5cp1q7ms36zGApY/sKQ==", + "dev": true, + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha1-nxJ29bK0Y/IRTT8sdSUK+MGjb0o=", + "optional": true + }, + "cssstyle": { + "version": "0.2.37", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", + "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=", + "optional": true, + "requires": { + "cssom": "0.3.x" + } + }, + "customize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/customize/-/customize-1.1.1.tgz", + "integrity": "sha512-ldop1CRxbtctT+u8oBcihwoEC78m2xCJ4vyEsz/X/k49k8RouTosZeafkht+GzYKPQSnIdx+n8AZzr8o/zBfsg==", + "requires": { + "debug": "^2.2.0", + "deep-aplus": "^1.0.4", + "jsonschema": "^1.0.2", + "jsonschema-extra": "^1.2.0", + "lodash": "^3.9.3", + "m-io": "^0.5.0", + "minimatch": "^3.0.0", + "q": "^1.4.1" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "customize-engine-handlebars": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/customize-engine-handlebars/-/customize-engine-handlebars-1.0.3.tgz", + "integrity": "sha512-o9XSiASy/rsD7Hzy2MYIG1iGdsf7Nqu3hSSw6pH+TVTLdBNusnPxWTYkqxgUCJUnhIKq2Lx6qixZc9hXQGckYg==", + "requires": { + "debug": "^2.2.0", + "handlebars": "^3.0.3", + "lodash": "^3.9.3", + "promised-handlebars": "^1.0.0", + "q": "^1.4.1", + "q-deep": "^1.0.1" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "customize-engine-less": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/customize-engine-less/-/customize-engine-less-1.0.1.tgz", + "integrity": "sha1-rl//DPOSgGx9Dx1NqPfUsuZRCSk=", + "requires": { + "less": "^2.7.1", + "lodash": "^3.10.1", + "q": "^1.4.1" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "customize-engine-uglify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/customize-engine-uglify/-/customize-engine-uglify-1.0.0.tgz", + "integrity": "sha1-Eb3Mqslhn4zHCZHHGtB2K0cB+ug=", + "requires": { + "lodash": "^3.10.1", + "q": "^1.4.1", + "uglify-js": "^2.7.5" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "customize-watch": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/customize-watch/-/customize-watch-1.0.1.tgz", + "integrity": "sha512-2wPI3gLoz0hH9E0kg/srTVYYFyyCZsFmxm2whcXvTQERMBoXhdmGJAxyiI3dXvDbkRk7MoD8lOnonpF3i1Tn9Q==", + "requires": { + "chokidar": "^1.2.0", + "customize": "^1.0.0", + "debug": "^2.2.0", + "deep-aplus": "^1.0.4", + "lodash": "^3.10.1", + "m-io": "^0.5.0", + "q": "^1.4.1" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "customize-write-files": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/customize-write-files/-/customize-write-files-1.1.1.tgz", + "integrity": "sha512-zPcxlElbfDgDkY1lDFK+jiGor6W93iQ7GDcWFLFiIOcZdjQCeW9KeKXt5Yx8Kfpv7cw3w24xaqlJcNQMKqrHMg==", + "requires": { + "debug": "^2.2.0", + "deep-aplus": "^1.0.4", + "m-io": "^0.5.0", + "q": "^1.4.1", + "stream-equal": "^0.1.12" + } + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "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" + } + }, + "debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "requires": { + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true + } + } + }, + "deep-aplus": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/deep-aplus/-/deep-aplus-1.0.4.tgz", + "integrity": "sha1-4exMEKALUEa1ng3dBRnRAa4xXo8=", + "requires": { + "lodash.isplainobject": "^4.0.6" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "optional": true + }, + "default-shell": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/default-shell/-/default-shell-1.0.1.tgz", + "integrity": "sha1-dSMEvdxhdPSespy5iP7qC4gTyLw=", + "dev": true + }, + "defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "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=" + }, + "dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "directory-tree": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/directory-tree/-/directory-tree-2.2.7.tgz", + "integrity": "sha512-fgTad/YdV6Y2njsCRK4fl4ZUlGhmb5xj1qrZUIMjvnrKvghVqh8dkB+OUssjYVvb/Q2L+5+8XG0l5uTGI9/8iQ==", + "dev": true + }, + "djv": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/djv/-/djv-2.1.4.tgz", + "integrity": "sha512-giDn+BVbtLlwtkvtcsZjbjzpALHB77skiv3FIu6Wp8b5j8BunDcVJYH0cGUaexp6s0Sb7IkquXXjsLBJhXwQpA==", + "dev": true, + "requires": { + "@korzio/djv-draft-04": "^2.0.1" + } + }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.4.3.tgz", + "integrity": "sha1-CGVRN5bGswYDGFDhdVFrr4C3Km8=", + "requires": { + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "env-paths": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", + "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", + "dev": true + }, + "err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=" + }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "optional": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.18.0-next.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz", + "integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.1", + "object-inspect": "^1.9.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.3", + "string.prototype.trimstart": "^1.0.3" + } + }, + "es-to-primitive": { + "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", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "optional": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0=", + "optional": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q=", + "optional": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "^2.1.0" + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "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.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "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" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "^1.0.0" + } + }, + "extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "requires": { + "@types/yauzl": "^2.9.1", + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "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==" + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "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-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "fast-json-stable-stringify": { + "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", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "optional": true + }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "finalhandler": { + "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.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "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==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "requires": { + "is-property": "^1.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "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==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-promise": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-promise/-/get-promise-1.4.0.tgz", + "integrity": "sha1-RDBFyGUwvrvtIihh7+0TwNNv9qA=", + "requires": { + "lodash": "^3.8.0", + "q": "^1.2.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "dev": true + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "gitbook-cli": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/gitbook-cli/-/gitbook-cli-2.3.2.tgz", + "integrity": "sha512-eyGtkY7jKHhmgpfuvgAP5fZcUob/FBz4Ld0aLRdEmiTrS1RklimN9epzPp75dd4MWpGhYvSbiwxnpyLiv1wh6A==", + "requires": { + "bash-color": "0.0.4", + "commander": "2.11.0", + "fs-extra": "3.0.1", + "lodash": "4.17.4", + "npm": "5.1.0", + "npmi": "1.0.1", + "optimist": "0.6.1", + "q": "1.5.0", + "semver": "5.3.0", + "tmp": "0.0.31", + "user-home": "2.0.0" + } + }, + "gitbook-plugin-back-to-top-button": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/gitbook-plugin-back-to-top-button/-/gitbook-plugin-back-to-top-button-0.1.4.tgz", + "integrity": "sha1-5iGDOLDvGdWOb2YAmUNQt26ANd8=" + }, + "gitbook-plugin-changelog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gitbook-plugin-changelog/-/gitbook-plugin-changelog-1.0.1.tgz", + "integrity": "sha1-CaEBwqXHm7q1NDyI3/qvZ9GPCVE=", + "requires": { + "lodash": "^4.17.4", + "moment": "^2.18.1" + } + }, + "gitbook-plugin-collapsible-chapters": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/gitbook-plugin-collapsible-chapters/-/gitbook-plugin-collapsible-chapters-0.1.8.tgz", + "integrity": "sha1-dxVcYcrBlRch2L9Es/ImphoeZcU=" + }, + "gitbook-plugin-editlink": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/gitbook-plugin-editlink/-/gitbook-plugin-editlink-1.0.2.tgz", + "integrity": "sha1-ej2Bk/guYfCUF83w52h2MfW2GV4=" + }, + "gitbook-plugin-fontsettings": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gitbook-plugin-fontsettings/-/gitbook-plugin-fontsettings-2.0.0.tgz", + "integrity": "sha1-g1+QCuPdERCG/n7UQl7j3gJIYas=" + }, + "gitbook-plugin-include": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/gitbook-plugin-include/-/gitbook-plugin-include-0.1.0.tgz", + "integrity": "sha1-w1/0dlYKXv/e+tv2OYIknBy8dNw=", + "requires": { + "q": "*" + } + }, + "gitbook-plugin-insert-logo": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/gitbook-plugin-insert-logo/-/gitbook-plugin-insert-logo-0.1.5.tgz", + "integrity": "sha1-2q6N2kGiNtVPE5MeVwsmcpVXiFo=" + }, + "gitbook-plugin-page-toc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/gitbook-plugin-page-toc/-/gitbook-plugin-page-toc-1.1.1.tgz", + "integrity": "sha1-YEZUSvoRNEJ2nwwLO0F8H+TfQRs=" + }, + "gitbook-plugin-plantuml-svg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gitbook-plugin-plantuml-svg/-/gitbook-plugin-plantuml-svg-1.0.1.tgz", + "integrity": "sha1-4QfoSCp/Gu3j0/IXzk1C/BWe6Qk=", + "requires": { + "js-base64": "^2.4.0", + "lodash": "^4.17.4", + "request": "^2.83.0", + "request-promise": "^4.2.2" + } + }, + "gitbook-plugin-search": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/gitbook-plugin-search/-/gitbook-plugin-search-2.2.1.tgz", + "integrity": "sha1-bSW1p3aZD6mP39+jfeMx944PaxM=" + }, + "gitbook-plugin-swagger": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/gitbook-plugin-swagger/-/gitbook-plugin-swagger-0.2.0.tgz", + "integrity": "sha1-g33zIY/9q9/LVu2Xr9SVYinZ0h0=", + "requires": { + "bootprint": "^1.0.0", + "bootprint-swagger": "^1.0.1" + } + }, + "gitbook-plugin-theme-api": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gitbook-plugin-theme-api/-/gitbook-plugin-theme-api-1.1.2.tgz", + "integrity": "sha1-jBRaS61JoSE8AlApC5vZtyrqiPw=", + "requires": { + "cheerio": "0.20.0", + "gitbook-plugin-search": ">=2.0.0", + "lodash": "4.12.0", + "q": "1.4.1", + "q-plus": "0.0.8" + }, + "dependencies": { + "cheerio": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz", + "integrity": "sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU=", + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "~3.8.1", + "jsdom": "^7.0.2", + "lodash": "^4.1.0" + } + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "lodash": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.12.0.tgz", + "integrity": "sha1-K9bcRqBA9Z5obJcu0h2T3FkFMlg=" + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=" + } + } + }, + "gitbook-plugin-uml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gitbook-plugin-uml/-/gitbook-plugin-uml-1.0.1.tgz", + "integrity": "sha512-j9kWSFsfF7Y53LcfegQSkRUSc0cKcA93v0Sxg4wVzca7A9V1ridXiXcSeaKy7OZi386FB2mG+KihViUVZwfcCA==", + "requires": { + "crypto": "^1.0.1", + "fs-extra": "^4.0.1", + "node-plantuml": "^0.6.2", + "q": "^1.5.0" + }, + "dependencies": { + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "node-plantuml": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/node-plantuml/-/node-plantuml-0.6.2.tgz", + "integrity": "sha512-4/nf/gBvKVm4+EbBgFQZf0n8N3jfAA7mRExs3NfgujSsaouktZwYkUzBUqUR8nRzIWDmJ4hA1QiWOjpEArTiZQ==", + "requires": { + "commander": "^2.8.1", + "node-nailgun-client": "^0.1.0", + "node-nailgun-server": "^0.1.3", + "plantuml-encoder": "^1.2.5" + } + } + } + }, + "gitbook-plugin-variables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gitbook-plugin-variables/-/gitbook-plugin-variables-1.1.0.tgz", + "integrity": "sha512-+G97YsciufqZQenG1TziLfKEAIpKwnxiipBOtWM0lZu8OxSR2WG4n/9zGPq3RqYAfzb1BxD6m6i0LmxmOF0vPA==", + "requires": { + "fast-glob": "^2.2.2", + "fs-extra": "^7.0.0", + "js-yaml": "^3.12.0", + "lodash": "^4.17.10", + "native-require": "^1.1.4" + }, + "dependencies": { + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + } + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "^2.0.0" + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" + }, + "global-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", + "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", + "dev": true, + "requires": { + "ini": "1.3.7" + }, + "dependencies": { + "ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "dev": true + } + } + }, + "got": { + "version": "11.8.1", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.1.tgz", + "integrity": "sha512-9aYdZL+6nHmvJwHALLwKSUZ0hMwGaJGYv3hoPLPgnT8BoBXm1SjnZeky+91tfwJaDzun2s4RsBRy48IEYv2q2Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + }, + "handlebars": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-3.0.8.tgz", + "integrity": "sha512-frzSzoxbJZSB719r+lM3UFKrnHIY6VPY/j47+GNOHVnBHxO+r+Y/iDjozAbj1SztmmMpr2CcZY6rLeN5mqX8zA==", + "requires": { + "optimist": "^0.6.1", + "source-map": "^0.1.40", + "uglify-js": "^2.6" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has": { + "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" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } + }, + "highlight.js": { + "version": "8.9.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-8.9.1.tgz", + "integrity": "sha1-uKnFSTISqTkvAiK2SclhFJfr+4g=" + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "requires": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + }, + "dependencies": { + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "http-auth": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/http-auth/-/http-auth-3.1.3.tgz", + "integrity": "sha1-lFz63WZSHq+PfISRPTd9exXyTjE=", + "requires": { + "apache-crypt": "^1.1.2", + "apache-md5": "^1.0.6", + "bcryptjs": "^2.3.0", + "uuid": "^3.0.0" + } + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "http-errors": { + "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.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "http-parser-js": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==" + }, + "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==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "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 + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "http2-wrapper": { + "version": "1.0.0-beta.5.2", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz", + "integrity": "sha512-xYz9goEyBnC8XwXDTuC/MZ6t+MrKVQZOk4s7+PaDkwIsQd8IwqvM+0M6bA/2lvG8GHXcPdf+MejTUeO2LCPCeQ==", + "dev": true, + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, + "https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "requires": { + "agent-base": "5", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "requires": { + "ms": "^2.0.0" + } + }, + "husky": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz", + "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "compare-versions": "^3.6.0", + "cosmiconfig": "^7.0.0", + "find-versions": "^3.2.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "slash": "^3.0.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "find-versions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", + "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "dev": true, + "requires": { + "semver-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "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" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "optional": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "ipaddr.js": { + "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-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "dev": true, + "requires": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + } + }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=", + "dev": true + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==" + }, + "is-my-json-valid": { + "version": "2.20.5", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.5.tgz", + "integrity": "sha512-VTPuvvGQtxvCeghwspQu1rBgjYUT6FGxPlvFKbYuFtgc4ADsX3U5ihZOYN0qyU6u+d4X9xXb0IT5O6QpXKt87A==", + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } + }, + "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-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, + "is-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", + "dev": true + }, + "jquery": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz", + "integrity": "sha1-LInWiJterFIqfuoywUUhVZxsvwI=" + }, + "js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==" + }, + "js-quantities": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/js-quantities/-/js-quantities-1.7.6.tgz", + "integrity": "sha512-h6TH1xK1u/zdjD26M6kKVthZONJSDTIRzrohbqOILfJAyanWHGlJLWuAWkSMtqi8k/IxshStsc97Pkf8SL9yvA==" + }, + "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 + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "jsdom": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz", + "integrity": "sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4=", + "optional": true, + "requires": { + "abab": "^1.0.0", + "acorn": "^2.4.0", + "acorn-globals": "^1.0.4", + "cssom": ">= 0.3.0 < 0.4.0", + "cssstyle": ">= 0.2.29 < 0.3.0", + "escodegen": "^1.6.1", + "nwmatcher": ">= 1.3.7 < 2.0.0", + "parse5": "^1.5.1", + "request": "^2.55.0", + "sax": "^1.1.4", + "symbol-tree": ">= 3.1.0 < 4.0.0", + "tough-cookie": "^2.2.0", + "webidl-conversions": "^2.0.0", + "whatwg-url-compat": "~0.6.5", + "xml-name-validator": ">= 2.0.1 < 3.0.0" + } + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-parse-helpfulerror": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", + "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=", + "dev": true, + "requires": { + "jju": "^1.1.0" + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonlines": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsonlines/-/jsonlines-0.1.1.tgz", + "integrity": "sha1-T80kbcXQ44aRkHxEqwAveC0dlMw=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsonpointer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.1.0.tgz", + "integrity": "sha512-CXcRvMyTlnR53xMcKnuMzfCA5i/nfblTnnr74CZb6C4vG39eu6w51t7nKmU5MfLfbTgGItliNyjO/ciNPDqClg==" + }, + "jsonschema": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz", + "integrity": "sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==" + }, + "jsonschema-extra": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/jsonschema-extra/-/jsonschema-extra-1.2.0.tgz", + "integrity": "sha1-52eGotlQdb4ja5izuAUrD2wVTXs=", + "requires": { + "js-quantities": "^1.5.0", + "lodash.isplainobject": "^2.4.1" + }, + "dependencies": { + "lodash.isplainobject": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-2.4.1.tgz", + "integrity": "sha1-rHOF4uqawDIfMNw7gDKm0iMagBE=", + "requires": { + "lodash._isnative": "~2.4.1", + "lodash._shimisplainobject": "~2.4.1" + } + } + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "keyv": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "less": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", + "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==", + "requires": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "mime": "^1.2.11", + "mkdirp": "^0.5.0", + "promise": "^7.1.1", + "request": "2.81.0", + "source-map": "^0.5.3" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "optional": true, + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "optional": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "optional": true, + "requires": { + "ajv": "^4.9.1", + "har-schema": "^1.0.5" + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "optional": true, + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "optional": true + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "optional": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "optional": true + }, + "qs": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.1.tgz", + "integrity": "sha512-LQy1Q1fcva/UsnP/6Iaa4lVeM49WiOitu2T4hZCyA/elLKu37L99qcBJk4VCCk+rdLvnMzfKyiN3SZTqdAZGSQ==", + "optional": true + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "optional": true, + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~4.2.1", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "performance-now": "^0.2.0", + "qs": "~6.4.0", + "safe-buffer": "^5.0.1", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "optional": true, + "requires": { + "punycode": "^1.4.1" + } + } + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "optional": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "libnpmconfig": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/libnpmconfig/-/libnpmconfig-1.2.1.tgz", + "integrity": "sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "find-up": "^3.0.0", + "ini": "^1.3.5" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "license-checker": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/license-checker/-/license-checker-25.0.1.tgz", + "integrity": "sha512-mET5AIwl7MR2IAKYYoVBBpV0OnkKQ1xGj2IMMeEFIs42QAkEVjRtFZGWmQ28WeU7MP779iAgOaOy93Mn44mn6g==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "nopt": "^4.0.1", + "read-installed": "~4.0.3", + "semver": "^5.5.0", + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0", + "spdx-satisfies": "^4.0.0", + "treeify": "^1.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "live-server": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/live-server/-/live-server-1.2.1.tgz", + "integrity": "sha512-Yn2XCVjErTkqnM3FfTmM7/kWy3zP7+cEtC7x6u+wUzlQ+1UW3zEYbbyJrc0jNDwiMDZI0m4a0i3dxlGHVyXczw==", + "requires": { + "chokidar": "^2.0.4", + "colors": "^1.4.0", + "connect": "^3.6.6", + "cors": "^2.8.5", + "event-stream": "3.3.4", + "faye-websocket": "0.11.x", + "http-auth": "3.1.x", + "morgan": "^1.9.1", + "object-assign": "^4.1.1", + "opn": "^6.0.0", + "proxy-middleware": "^0.15.0", + "send": "^0.17.1", + "serve-index": "^1.9.1" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha1-gEs6e2qZNYw8XGHnHYco8EHP+Rc=", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "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==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "send": { + "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", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + } + } + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash._basebind": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._basebind/-/lodash._basebind-2.4.1.tgz", + "integrity": "sha1-6UC5690nwyfgqNqxtVkWxTQelXU=", + "requires": { + "lodash._basecreate": "~2.4.1", + "lodash._setbinddata": "~2.4.1", + "lodash._slice": "~2.4.1", + "lodash.isobject": "~2.4.1" + } + }, + "lodash._basecreate": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-2.4.1.tgz", + "integrity": "sha1-+Ob1tXip405UEXm1a47uv0oofgg=", + "requires": { + "lodash._isnative": "~2.4.1", + "lodash.isobject": "~2.4.1", + "lodash.noop": "~2.4.1" + } + }, + "lodash._basecreatecallback": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._basecreatecallback/-/lodash._basecreatecallback-2.4.1.tgz", + "integrity": "sha1-fQsmdknLKeehOdAQO3wR+uhOSFE=", + "requires": { + "lodash._setbinddata": "~2.4.1", + "lodash.bind": "~2.4.1", + "lodash.identity": "~2.4.1", + "lodash.support": "~2.4.1" + } + }, + "lodash._basecreatewrapper": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._basecreatewrapper/-/lodash._basecreatewrapper-2.4.1.tgz", + "integrity": "sha1-TTHy595+E0+/KAN2K4FQsyUZZm8=", + "requires": { + "lodash._basecreate": "~2.4.1", + "lodash._setbinddata": "~2.4.1", + "lodash._slice": "~2.4.1", + "lodash.isobject": "~2.4.1" + } + }, + "lodash._createwrapper": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._createwrapper/-/lodash._createwrapper-2.4.1.tgz", + "integrity": "sha1-UdaVeXPaTtVW43KQ2MGhjFPeFgc=", + "requires": { + "lodash._basebind": "~2.4.1", + "lodash._basecreatewrapper": "~2.4.1", + "lodash._slice": "~2.4.1", + "lodash.isfunction": "~2.4.1" + } + }, + "lodash._isnative": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=" + }, + "lodash._objecttypes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=" + }, + "lodash._setbinddata": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._setbinddata/-/lodash._setbinddata-2.4.1.tgz", + "integrity": "sha1-98IAzRuS7yNrOZ7s9zxkjReqlNI=", + "requires": { + "lodash._isnative": "~2.4.1", + "lodash.noop": "~2.4.1" + } + }, + "lodash._shimisplainobject": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._shimisplainobject/-/lodash._shimisplainobject-2.4.1.tgz", + "integrity": "sha1-AeyTsu5j5Z8aqDiZrG+gkFrHWW8=", + "requires": { + "lodash.forin": "~2.4.1", + "lodash.isfunction": "~2.4.1" + } + }, + "lodash._slice": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._slice/-/lodash._slice-2.4.1.tgz", + "integrity": "sha1-dFz0GlNZexj2iImFREBe+isG2Q8=" + }, + "lodash.bind": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-2.4.1.tgz", + "integrity": "sha1-XRn6AFyMTSNvr0dCx7eh/Kvikmc=", + "requires": { + "lodash._createwrapper": "~2.4.1", + "lodash._slice": "~2.4.1" + } + }, + "lodash.forin": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.forin/-/lodash.forin-2.4.1.tgz", + "integrity": "sha1-gInq7X0lsIZyt8Zv0HrFXQYjIOs=", + "requires": { + "lodash._basecreatecallback": "~2.4.1", + "lodash._objecttypes": "~2.4.1" + } + }, + "lodash.identity": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.identity/-/lodash.identity-2.4.1.tgz", + "integrity": "sha1-ZpTP+mX++TH3wxzobHRZfPVg9PE=" + }, + "lodash.isfunction": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.4.1.tgz", + "integrity": "sha1-LP1XXHPkmKtX4xm3f6Aq3vE6lNE=" + }, + "lodash.isobject": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", + "requires": { + "lodash._objecttypes": "~2.4.1" + } + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.noop": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.4.1.tgz", + "integrity": "sha1-T7VPgWZS5a4Q6PcvcXo4jHMmU4o=" + }, + "lodash.support": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.support/-/lodash.support-2.4.1.tgz", + "integrity": "sha1-Mg4LZwMWc8KNeiu12eAzGkUkBRU=", + "requires": { + "lodash._isnative": "~2.4.1" + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "m-io": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/m-io/-/m-io-0.5.0.tgz", + "integrity": "sha1-chuybdjUN13Oy1bY3AFm64vp0AM=", + "requires": { + "fs-extra": "^2.0.0", + "q": "^1.4.1" + }, + "dependencies": { + "fs-extra": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "^4.1.6" + } + } + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "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 + } + } + }, + "make-fetch-happen": { + "version": "8.0.14", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz", + "integrity": "sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ==", + "dev": true, + "requires": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.0.5", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^5.0.0", + "ssri": "^8.0.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "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" + } + }, + "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==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "minipass-fetch": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.3.3.tgz", + "integrity": "sha512-akCrLDWfbdAWkMLBxJEeWTdNsjML+dt5YgOI4gJ53vuO0vrmYQkUPxa6j6V65s9CcePIr2SSWqjT2EcrNseryQ==", + "dev": true, + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "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 + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "marked": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", + "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==" + }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "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=" + }, + "merge-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz", + "integrity": "sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==", + "dev": true, + "requires": { + "is-plain-obj": "^1.1" + } + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" + }, + "mime-types": { + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "requires": { + "mime-db": "1.46.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + }, + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-fetch": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.3.0.tgz", + "integrity": "sha512-Yb23ESZZ/8QxiBvSpJ4atbVMVDx2CXrerzrtQzQ67eLqKg+zFIkYFTagk3xh6fdo+e/FvDtVuCD4QcuYDRR3hw==", + "dev": true, + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "dependencies": { + "minizlib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.0.tgz", + "integrity": "sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + } + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, + "requires": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha1-ESC0PcNZp4Xc5ltVuC4lfM9HlWY=", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "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": "^1.2.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + } + } + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "native-require": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/native-require/-/native-require-1.1.4.tgz", + "integrity": "sha512-fOB7diEP3ErNZnMh+Zqdufw79rIPrcAbHanixB5WoWpfU06ZfoUjynGDDQ22uKBhkpgzcI3WXQglhzpWBPKKGA==" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "nested-error-stacks": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz", + "integrity": "sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==", + "dev": true + }, + "node-fetch-npm": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz", + "integrity": "sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==", + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node-nailgun-client": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/node-nailgun-client/-/node-nailgun-client-0.1.2.tgz", + "integrity": "sha512-OC611lR0fsDUSptwnhBf8d3sj4DZ5fiRKfS2QaGPe0kR3Dt9YoZr1MY7utK0scFPTbXuQdSBBbeoKYVbME1q5g==", + "requires": { + "commander": "^2.8.1" + } + }, + "node-nailgun-server": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/node-nailgun-server/-/node-nailgun-server-0.1.4.tgz", + "integrity": "sha512-e0Hbh6XPb/7GqATJ45BePaUEO5AwR7InRW/pGeMKHH1cqPMBFCeqdBNfvi+bkVLnsbYOOQE+pAek9nmNoD8sYw==", + "requires": { + "commander": "^2.8.1" + } + }, + "node-plantuml": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/node-plantuml/-/node-plantuml-0.5.0.tgz", + "integrity": "sha1-A8LthW5rJyxxShVoRTp0fCZv3B8=", + "dev": true, + "requires": { + "commander": "^2.8.1", + "node-nailgun-client": "^0.1.0", + "node-nailgun-server": "^0.1.3", + "plantuml-encoder": "^1.2.4" + } + }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true + }, + "npm": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-5.1.0.tgz", + "integrity": "sha512-pt5ClxEmY/dLpb60SmGQQBKi3nB6Ljx1FXmpoCUdAULlGqGVn2uCyXxPCWFbcuHGthT7qGiaGa1wOfs/UjGYMw==", + "requires": { + "JSONStream": "~1.3.1", + "abbrev": "~1.1.0", + "ansi-regex": "~3.0.0", + "ansicolors": "~0.3.2", + "ansistyles": "~0.1.3", + "aproba": "~1.1.2", + "archy": "~1.0.0", + "bluebird": "~3.5.0", + "cacache": "~9.2.9", + "call-limit": "~1.1.0", + "chownr": "~1.0.1", + "cmd-shim": "~2.0.2", + "columnify": "~1.5.4", + "config-chain": "~1.1.11", + "debuglog": "*", + "detect-indent": "~5.0.0", + "dezalgo": "~1.0.3", + "editor": "~1.0.0", + "fs-vacuum": "~1.2.10", + "fs-write-stream-atomic": "~1.0.10", + "fstream": "~1.0.11", + "fstream-npm": "~1.2.1", + "glob": "~7.1.2", + "graceful-fs": "~4.1.11", + "has-unicode": "~2.0.1", + "hosted-git-info": "~2.5.0", + "iferr": "~0.1.5", + "imurmurhash": "*", + "inflight": "~1.0.6", + "inherits": "~2.0.3", + "ini": "~1.3.4", + "init-package-json": "~1.10.1", + "lazy-property": "~1.0.0", + "lockfile": "~1.0.3", + "lodash._baseindexof": "*", + "lodash._baseuniq": "~4.6.0", + "lodash._bindcallback": "*", + "lodash._cacheindexof": "*", + "lodash._createcache": "*", + "lodash._getnative": "*", + "lodash.clonedeep": "~4.5.0", + "lodash.restparam": "*", + "lodash.union": "~4.6.0", + "lodash.uniq": "~4.5.0", + "lodash.without": "~4.4.0", + "lru-cache": "~4.1.1", + "mississippi": "~1.3.0", + "mkdirp": "~0.5.1", + "move-concurrently": "~1.0.1", + "node-gyp": "~3.6.2", + "nopt": "~4.0.1", + "normalize-package-data": "~2.4.0", + "npm-cache-filename": "~1.0.2", + "npm-install-checks": "~3.0.0", + "npm-package-arg": "~5.1.2", + "npm-registry-client": "~8.4.0", + "npm-user-validate": "~1.0.0", + "npmlog": "~4.1.2", + "once": "~1.4.0", + "opener": "~1.4.3", + "osenv": "~0.1.4", + "pacote": "~2.7.38", + "path-is-inside": "~1.0.2", + "promise-inflight": "~1.0.1", + "read": "~1.0.7", + "read-cmd-shim": "~1.0.1", + "read-installed": "~4.0.3", + "read-package-json": "~2.0.9", + "read-package-tree": "~5.1.6", + "readable-stream": "~2.3.2", + "readdir-scoped-modules": "*", + "request": "~2.81.0", + "retry": "~0.10.1", + "rimraf": "~2.6.1", + "safe-buffer": "~5.1.1", + "semver": "~5.3.0", + "sha": "~2.0.1", + "slide": "~1.1.6", + "sorted-object": "~2.0.1", + "sorted-union-stream": "~2.1.3", + "ssri": "~4.1.6", + "strip-ansi": "~4.0.0", + "tar": "~2.2.1", + "text-table": "~0.2.0", + "uid-number": "0.0.6", + "umask": "~1.1.0", + "unique-filename": "~1.1.0", + "unpipe": "~1.0.0", + "update-notifier": "~2.2.0", + "uuid": "~3.1.0", + "validate-npm-package-license": "*", + "validate-npm-package-name": "~3.0.0", + "which": "~1.2.14", + "worker-farm": "~1.3.1", + "wrappy": "~1.0.2", + "write-file-atomic": "~2.1.0" + }, + "dependencies": { + "JSONStream": { + "version": "1.3.1", + "resolved": false, + "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "dependencies": { + "jsonparse": { + "version": "1.3.1", + "resolved": false, + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, + "through": { + "version": "2.3.8", + "resolved": false, + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + } + } + }, + "abbrev": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=" + }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "agentkeepalive": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansicolors": { + "version": "0.3.2", + "resolved": false, + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" + }, + "ansistyles": { + "version": "0.1.3", + "resolved": false, + "integrity": "sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk=" + }, + "aproba": { + "version": "1.1.2", + "resolved": false, + "integrity": "sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==" + }, + "archy": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + }, + "bluebird": { + "version": "3.5.0", + "resolved": false, + "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" + }, + "cacache": { + "version": "9.2.9", + "resolved": false, + "integrity": "sha512-ghg1j5OyTJ6qsrqU++dN23QiTDxb5AZCFGsF3oB+v9v/gY+F4X8L/0gdQMEjd+8Ot3D29M2etX5PKozHRn2JQw==", + "requires": { + "bluebird": "^3.5.0", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^1.3.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.1", + "ssri": "^4.1.6", + "unique-filename": "^1.1.0", + "y18n": "^3.2.1" + } + }, + "call-limit": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-b9YbA/PaQqLNDsK2DwK9DnGZH+o=" + }, + "chownr": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "cmd-shim": { + "version": "2.0.2", + "resolved": false, + "integrity": "sha1-b8vamUg6j9FdfTChlspp1oii79s=", + "requires": { + "graceful-fs": "^4.1.2", + "mkdirp": "~0.5.0" + } + }, + "columnify": { + "version": "1.5.4", + "resolved": false, + "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", + "requires": { + "strip-ansi": "^3.0.0", + "wcwidth": "^1.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "requires": { + "defaults": "^1.0.3" + }, + "dependencies": { + "defaults": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + }, + "dependencies": { + "clone": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=" + } + } + } + } + } + } + }, + "config-chain": { + "version": "1.1.11", + "resolved": false, + "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + }, + "dependencies": { + "proto-list": { + "version": "1.2.4", + "resolved": false, + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + } + } + }, + "debug": { + "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" + } + }, + "debuglog": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=" + }, + "detect-indent": { + "version": "5.0.0", + "resolved": false, + "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=" + }, + "dezalgo": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + }, + "dependencies": { + "asap": { + "version": "2.0.5", + "resolved": false, + "integrity": "sha1-UidltQw1EEkOUtfc/ghe+bqWlY8=" + } + } + }, + "editor": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-YMf4e9YrzGqJT6jM1q+3gjok90I=" + }, + "fs-vacuum": { + "version": "1.2.10", + "resolved": false, + "integrity": "sha1-t2Kb7AekAxolSP35n17PHMizHjY=", + "requires": { + "graceful-fs": "^4.1.2", + "path-is-inside": "^1.0.1", + "rimraf": "^2.5.2" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": false, + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fstream-npm": { + "version": "1.2.1", + "resolved": false, + "integrity": "sha512-iBHpm/LmD1qw0TlHMAqVd9rwdU6M+EHRUnPkXpRi5G/Hf0FIFH+oZFryodAU2MFNfGRh/CzhUFlMKV3pdeOTDw==", + "requires": { + "fstream-ignore": "^1.0.0", + "inherits": "2" + }, + "dependencies": { + "fstream-ignore": { + "version": "1.0.5", + "resolved": false, + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "requires": { + "fstream": "^1.0.0", + "inherits": "2", + "minimatch": "^3.0.0" + }, + "dependencies": { + "minimatch": { + "version": "3.0.4", + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.8", + "resolved": false, + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + } + } + } + } + } + } + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": false, + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "fs.realpath": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.8", + "resolved": false, + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + } + } + } + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": false, + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": false, + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==" + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "requires": { + "agent-base": "4", + "debug": "3.1.0" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + }, + "iferr": { + "version": "0.1.5", + "resolved": false, + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": false, + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "inflight": { + "version": "1.0.6", + "resolved": false, + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": false, + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.4", + "resolved": false, + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" + }, + "init-package-json": { + "version": "1.10.1", + "resolved": false, + "integrity": "sha1-zYc6FneWvvuZYSsodioLY5P9j2o=", + "requires": { + "glob": "^7.1.1", + "npm-package-arg": "^4.0.0 || ^5.0.0", + "promzard": "^0.3.0", + "read": "~1.0.1", + "read-package-json": "1 || 2", + "semver": "2.x || 3.x || 4 || 5", + "validate-npm-package-license": "^3.0.1", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "promzard": { + "version": "0.3.0", + "resolved": false, + "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", + "requires": { + "read": "1" + } + } + } + }, + "lazy-property": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-hN3Es3Bnm6i9TNz6TAa0PVcREUc=" + }, + "lockfile": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-Jjj8OaAzHpysGgS3F5mTHJxQ33k=" + }, + "lodash._baseindexof": { + "version": "3.1.0", + "resolved": false, + "integrity": "sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=" + }, + "lodash._baseuniq": { + "version": "4.6.0", + "resolved": false, + "integrity": "sha1-DrtE5FaBSveQXGIS+iybLVG4Qeg=", + "requires": { + "lodash._createset": "~4.0.0", + "lodash._root": "~3.0.0" + }, + "dependencies": { + "lodash._createset": { + "version": "4.0.3", + "resolved": false, + "integrity": "sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=" + }, + "lodash._root": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" + } + } + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=" + }, + "lodash._cacheindexof": { + "version": "3.0.2", + "resolved": false, + "integrity": "sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=" + }, + "lodash._createcache": { + "version": "3.1.2", + "resolved": false, + "integrity": "sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=", + "requires": { + "lodash._getnative": "^3.0.0" + } + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": false, + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": false, + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": false, + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" + }, + "lodash.union": { + "version": "4.6.0", + "resolved": false, + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": false, + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "lodash.without": { + "version": "4.4.0", + "resolved": false, + "integrity": "sha1-PNRXSgC2e643OpS3SHcmQFB7eqw=" + }, + "lru-cache": { + "version": "4.1.1", + "resolved": false, + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + }, + "dependencies": { + "pseudomap": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "yallist": { + "version": "2.1.2", + "resolved": false, + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } + } + }, + "make-fetch-happen": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-2.6.0.tgz", + "integrity": "sha512-FFq0lNI0ax+n9IWzWpH8A4JdgYiAp2DDYIZ3rsaav8JDe8I+72CzK6PQW/oom15YDZpV5bYW/9INd6nIJ2ZfZw==", + "requires": { + "agentkeepalive": "^3.3.0", + "cacache": "^10.0.0", + "http-cache-semantics": "^3.8.0", + "http-proxy-agent": "^2.0.0", + "https-proxy-agent": "^2.1.0", + "lru-cache": "^4.1.1", + "mississippi": "^1.2.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^3.0.1", + "ssri": "^5.0.0" + }, + "dependencies": { + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "cacache": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + }, + "dependencies": { + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + } + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + } + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mississippi": { + "version": "1.3.0", + "resolved": false, + "integrity": "sha1-0gFYPrEjJ+PFwWQqQEqcrPlONPU=", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^1.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.0", + "resolved": false, + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "typedarray": { + "version": "0.0.6", + "resolved": false, + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + } + } + }, + "duplexify": { + "version": "3.5.0", + "resolved": false, + "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", + "requires": { + "end-of-stream": "1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "end-of-stream": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=", + "requires": { + "once": "~1.3.0" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": false, + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "requires": { + "wrappy": "1" + } + } + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + } + } + }, + "end-of-stream": { + "version": "1.4.0", + "resolved": false, + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "requires": { + "once": "^1.4.0" + } + }, + "flush-write-stream": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } + }, + "from2": { + "version": "2.3.0", + "resolved": false, + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + }, + "dependencies": { + "cyclist": { + "version": "0.2.2", + "resolved": false, + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=" + } + } + }, + "pump": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-Oz7mUS+U8OV1U4wXmV+fFpkKXVE=", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.3.5", + "resolved": false, + "integrity": "sha1-G2ccYZlAq8rqwK0OOjwWS+dgmTs=", + "requires": { + "duplexify": "^3.1.2", + "inherits": "^2.0.1", + "pump": "^1.0.0" + } + }, + "stream-each": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha1-HpXUdXP1gNgU3A/4zQ9m8c5TyZE=", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "stream-shift": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + } + } + }, + "through2": { + "version": "2.0.3", + "resolved": false, + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + } + } + }, + "mkdirp": { + "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": "^1.2.5" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + }, + "dependencies": { + "run-queue": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "^1.1.1" + } + } + } + }, + "node-gyp": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.3.tgz", + "integrity": "sha512-7789TDMqJpv5iHxn1cAESCBEC/sBHAFxAvgXAcvzWenEWl0qf6E2Kk/Xwdl5ZclktUJzxJPVa27OMkBvaHKqCQ==", + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": ">=2.9.0 <2.82.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "resolved": false, + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1" + } + } + } + }, + "nopt": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": false, + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "is-builtin-module": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "^1.0.0" + }, + "dependencies": { + "builtin-modules": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + } + } + } + } + }, + "npm-cache-filename": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE=" + }, + "npm-install-checks": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-1K7N/VGlPjcjt7L5Oy7ijjB7wNc=", + "requires": { + "semver": "^2.3.0 || 3.x || 4 || 5" + } + }, + "npm-package-arg": { + "version": "5.1.2", + "resolved": false, + "integrity": "sha512-wJBsrf0qpypPT7A0LART18hCdyhpCMxeTtcb0X4IZO2jsP6Om7EHN1d9KSKiqD+KVH030RVNpWS9thk+pb7wzA==", + "requires": { + "hosted-git-info": "^2.4.2", + "osenv": "^0.1.4", + "semver": "^5.1.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "npm-registry-client": { + "version": "8.4.0", + "resolved": false, + "integrity": "sha512-PVNfqq0lyRdFnE//nDmn3CC9uqTsr8Bya9KPLIevlXMfkP0m4RpCVyFFk0W1Gfx436kKwyhLA6J+lV+rgR81gQ==", + "requires": { + "concat-stream": "^1.5.2", + "graceful-fs": "^4.1.6", + "normalize-package-data": "~1.0.1 || ^2.0.0", + "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0", + "npmlog": "2 || ^3.1.0 || ^4.0.0", + "once": "^1.3.3", + "request": "^2.74.0", + "retry": "^0.10.0", + "semver": "2 >=2.2.1 || 3.x || 4 || 5", + "slide": "^1.1.3", + "ssri": "^4.1.2" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.0", + "resolved": false, + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "typedarray": { + "version": "0.0.6", + "resolved": false, + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + } + } + } + } + }, + "npm-user-validate": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-jOyg9c6gTU6TUZ73LQVXp1Ei6VE=" + }, + "npmlog": { + "version": "4.1.2", + "resolved": false, + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + }, + "dependencies": { + "are-we-there-yet": { + "version": "1.1.4", + "resolved": false, + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + }, + "dependencies": { + "delegates": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "gauge": { + "version": "2.7.4", + "resolved": false, + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": false, + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": false, + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "string-width": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "dependencies": { + "code-point-at": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + }, + "dependencies": { + "number-is-nan": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + } + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + }, + "wide-align": { + "version": "1.1.2", + "resolved": false, + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "requires": { + "string-width": "^1.0.2" + } + } + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + } + } + }, + "once": { + "version": "1.4.0", + "resolved": false, + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.4.3", + "resolved": false, + "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=" + }, + "osenv": { + "version": "0.1.4", + "resolved": false, + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + }, + "dependencies": { + "os-homedir": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + } + } + }, + "pacote": { + "version": "2.7.38", + "resolved": false, + "integrity": "sha512-XxHUyHQB7QCVBxoXeVu0yKxT+2PvJucsc0+1E+6f95lMUxEAYERgSAc71ckYXrYr35Ew3xFU/LrhdIK21GQFFA==", + "requires": { + "bluebird": "^3.5.0", + "cacache": "^9.2.9", + "glob": "^7.1.2", + "lru-cache": "^4.1.1", + "make-fetch-happen": "^2.4.13", + "minimatch": "^3.0.4", + "mississippi": "^1.2.0", + "normalize-package-data": "^2.4.0", + "npm-package-arg": "^5.1.2", + "npm-pick-manifest": "^1.0.4", + "osenv": "^0.1.4", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^4.0.0", + "safe-buffer": "^5.1.1", + "semver": "^5.3.0", + "ssri": "^4.1.6", + "tar-fs": "^1.15.3", + "tar-stream": "^1.5.4", + "unique-filename": "^1.1.0", + "which": "^1.2.12" + }, + "dependencies": { + "minimatch": { + "version": "3.0.4", + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.8", + "resolved": false, + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + } + } + } + } + }, + "npm-pick-manifest": { + "version": "1.0.4", + "resolved": false, + "integrity": "sha512-MKxNdeyOZysPRTTbHtW0M5Fw38Jo/3ARsoGw5qjCfS+XGjvNB/Gb4qtAZUFmKPM2mVum+eX559eHvKywU856BQ==", + "requires": { + "npm-package-arg": "^5.1.2", + "semver": "^5.3.0" + } + }, + "promise-retry": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + }, + "dependencies": { + "err-code": { + "version": "1.1.2", + "resolved": false, + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=" + } + } + }, + "protoduck": { + "version": "4.0.0", + "resolved": false, + "integrity": "sha1-/kh02MeRM2bP2erRJFOiLNNlf44=", + "requires": { + "genfun": "^4.0.1" + }, + "dependencies": { + "genfun": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-7RAEHy5KfxsKOEZtF6XD4n3x38E=" + } + } + }, + "tar-stream": { + "version": "1.5.4", + "resolved": false, + "integrity": "sha1-NlSc8E7RrumyowwBQyUiONr5QBY=", + "requires": { + "bl": "^1.0.0", + "end-of-stream": "^1.0.0", + "readable-stream": "^2.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "bl": { + "version": "1.2.1", + "resolved": false, + "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "requires": { + "readable-stream": "^2.0.5" + } + }, + "end-of-stream": { + "version": "1.4.0", + "resolved": false, + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "requires": { + "once": "^1.4.0" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + } + } + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "qs": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.1.tgz", + "integrity": "sha512-LQy1Q1fcva/UsnP/6Iaa4lVeM49WiOitu2T4hZCyA/elLKu37L99qcBJk4VCCk+rdLvnMzfKyiN3SZTqdAZGSQ==" + }, + "read": { + "version": "1.0.7", + "resolved": false, + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "requires": { + "mute-stream": "~0.0.4" + }, + "dependencies": { + "mute-stream": { + "version": "0.0.7", + "resolved": false, + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + } + } + }, + "read-cmd-shim": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-LV0Vd4ajfAVdIgd8MsU/gynpHHs=", + "requires": { + "graceful-fs": "^4.1.2" + } + }, + "read-installed": { + "version": "4.0.3", + "resolved": false, + "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=", + "requires": { + "debuglog": "^1.0.1", + "graceful-fs": "^4.1.2", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "slide": "~1.1.3", + "util-extend": "^1.0.1" + }, + "dependencies": { + "util-extend": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=" + } + } + }, + "read-package-json": { + "version": "2.0.9", + "resolved": false, + "integrity": "sha512-vuV8p921IgyelL4UOKv3FsRuRZSaRn30HanLAOKargsr8TbBEq+I3MgloSRXYuKhNdYP1wlEGilMWAIayA2RFg==", + "requires": { + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "json-parse-helpfulerror": "^1.0.2", + "normalize-package-data": "^2.0.0" + }, + "dependencies": { + "json-parse-helpfulerror": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=", + "requires": { + "jju": "^1.1.0" + }, + "dependencies": { + "jju": { + "version": "1.3.0", + "resolved": false, + "integrity": "sha1-2t2e8BkkvHKLA/L3l5vb1i96Kqo=" + } + } + } + } + }, + "read-package-tree": { + "version": "5.1.6", + "resolved": false, + "integrity": "sha512-FCX1aT3GWyY658wzDICef4p+n0dB+ENRct8E/Qyvppj6xVpOYerBHfUu7OP5Rt1/393Tdglguf5ju5DEX4wZNg==", + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "once": "^1.3.0", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.2", + "resolved": false, + "integrity": "sha1-WgTfBeT1f+Pw3Gj90R3FyXx+b00=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.0", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "isarray": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": false, + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "string_decoder": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + } + }, + "readdir-scoped-modules": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-n6+jfShr5dksuuve4DDcm19AZ0c=", + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "registry-auth-token": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "request": { + "version": "2.81.0", + "resolved": false, + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~4.2.1", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "performance-now": "^0.2.0", + "qs": "~6.4.0", + "safe-buffer": "^5.0.1", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.0.0" + }, + "dependencies": { + "aws-sign2": { + "version": "0.6.0", + "resolved": false, + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" + }, + "aws4": { + "version": "1.6.0", + "resolved": false, + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "caseless": { + "version": "0.12.0", + "resolved": false, + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": false, + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "~1.0.0" + }, + "dependencies": { + "delayed-stream": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": false, + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.1.4", + "resolved": false, + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" + }, + "dependencies": { + "asynckit": { + "version": "0.4.0", + "resolved": false, + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + } + } + }, + "har-validator": { + "version": "4.2.1", + "resolved": false, + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "requires": { + "ajv": "^4.9.1", + "har-schema": "^1.0.5" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": false, + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + }, + "dependencies": { + "co": { + "version": "4.6.0", + "resolved": false, + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "~0.0.0" + }, + "dependencies": { + "jsonify": { + "version": "0.0.0", + "resolved": false, + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + } + } + } + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": false, + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" + } + } + }, + "hawk": { + "version": "3.1.3", + "resolved": false, + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + }, + "dependencies": { + "boom": { + "version": "2.10.1", + "resolved": false, + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.x.x" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": false, + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "requires": { + "boom": "2.x.x" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": false, + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "sntp": { + "version": "1.0.9", + "resolved": false, + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "requires": { + "hoek": "2.x.x" + } + } + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "dependencies": { + "assert-plus": { + "version": "0.2.0", + "resolved": false, + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" + }, + "jsprim": { + "version": "1.4.0", + "resolved": false, + "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "extsprintf": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": false, + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "verror": { + "version": "1.3.6", + "resolved": false, + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "requires": { + "extsprintf": "1.0.2" + } + } + } + } + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": false, + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": false, + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "mime-types": { + "version": "2.1.15", + "resolved": false, + "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", + "requires": { + "mime-db": "~1.27.0" + }, + "dependencies": { + "mime-db": { + "version": "1.27.0", + "resolved": false, + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=" + } + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": false, + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "performance-now": { + "version": "0.2.0", + "resolved": false, + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" + }, + "stringstream": { + "version": "0.0.5", + "resolved": false, + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "tough-cookie": { + "version": "2.3.2", + "resolved": false, + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "requires": { + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": false, + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": false, + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + } + } + }, + "retry": { + "version": "0.10.1", + "resolved": false, + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" + }, + "rimraf": { + "version": "2.6.1", + "resolved": false, + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": false, + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "semver": { + "version": "5.3.0", + "resolved": false, + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + }, + "sha": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-YDCCL70smCOUn49y7WQR7lzyWq4=", + "requires": { + "graceful-fs": "^4.1.2", + "readable-stream": "^2.0.2" + } + }, + "slide": { + "version": "1.1.6", + "resolved": false, + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, + "smart-buffer": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", + "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=" + }, + "socks": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", + "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", + "requires": { + "ip": "^1.1.4", + "smart-buffer": "^1.0.13" + } + }, + "socks-proxy-agent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz", + "integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==", + "requires": { + "agent-base": "^4.1.0", + "socks": "^1.1.10" + } + }, + "sorted-object": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-fWMfS9OnmKJK8d/8+/6DM3pd9fw=" + }, + "sorted-union-stream": { + "version": "2.1.3", + "resolved": false, + "integrity": "sha1-x3lMfgd4gAUv9xqNSi27Sppjisc=", + "requires": { + "from2": "^1.3.0", + "stream-iterate": "^1.1.0" + }, + "dependencies": { + "from2": { + "version": "1.3.0", + "resolved": false, + "integrity": "sha1-iEE7qqX5pZfP3pIh2GmGzTwGHf0=", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~1.1.10" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": false, + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "isarray": { + "version": "0.0.1", + "resolved": false, + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": false, + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + } + } + }, + "stream-iterate": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha1-K9fHcpbBcCpGSIuK1B95hl7s1OE=", + "requires": { + "readable-stream": "^2.1.5", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "stream-shift": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + } + } + } + } + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "4.1.6", + "resolved": false, + "integrity": "sha512-WUbCdgSAMQjTFZRWvSPpauryvREEA+Krn19rx67UlJEJx/M192ZHxMmJXjZ4tkdFm+Sb0SXGlENeQVlA5wY7kA==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": false, + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + } + } + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "requires": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": false, + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "uid-number": { + "version": "0.0.6", + "resolved": false, + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" + }, + "umask": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=" + }, + "unique-filename": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", + "requires": { + "unique-slug": "^2.0.0" + }, + "dependencies": { + "unique-slug": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", + "requires": { + "imurmurhash": "^0.1.4" + } + } + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "update-notifier": { + "version": "2.2.0", + "resolved": false, + "integrity": "sha1-G1g3z5DAc22IYncytmHBOPht5y8=", + "requires": { + "boxen": "^1.0.0", + "chalk": "^1.0.0", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "boxen": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-sbad1SIwXoB6md7ud329blFnsQI=", + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^1.1.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^0.1.0", + "widest-line": "^1.0.0" + }, + "dependencies": { + "ansi-align": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "requires": { + "string-width": "^2.0.0" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": false, + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" + }, + "string-width": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha1-AwZkVh/BRslCPsfZeP4kV0N/5tA=", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": false, + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "term-size": { + "version": "0.1.1", + "resolved": false, + "integrity": "sha1-hzYLljlsq1dgljcUzaDQy+7K2co=", + "requires": { + "execa": "^0.4.0" + }, + "dependencies": { + "execa": { + "version": "0.4.0", + "resolved": false, + "integrity": "sha1-TrZGejaglfq7KXD/nV4/t7zm68M=", + "requires": { + "cross-spawn-async": "^2.1.1", + "is-stream": "^1.1.0", + "npm-run-path": "^1.0.0", + "object-assign": "^4.0.1", + "path-key": "^1.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn-async": { + "version": "2.2.5", + "resolved": false, + "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=", + "requires": { + "lru-cache": "^4.0.0", + "which": "^1.2.8" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "npm-run-path": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=", + "requires": { + "path-key": "^1.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": false, + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "path-key": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + } + } + } + } + }, + "widest-line": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-DAnIXCqUaD0Nfq+O4JfVZL8OEFw=", + "requires": { + "string-width": "^1.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "dependencies": { + "code-point-at": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + }, + "dependencies": { + "number-is-nan": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + } + } + } + } + } + } + }, + "chalk": { + "version": "1.1.3", + "resolved": false, + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": false, + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": false, + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "has-ansi": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "configstore": { + "version": "3.1.0", + "resolved": false, + "integrity": "sha1-Rd+QcHPibfoc9LLVL1tgVF6qEdE=", + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "4.1.1", + "resolved": false, + "integrity": "sha1-qEk/C3te7sglJbXHWH+n3nyoWcE=", + "requires": { + "is-obj": "^1.0.0" + }, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + } + } + }, + "make-dir": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg=", + "requires": { + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": false, + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "unique-string": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "requires": { + "crypto-random-string": "^1.0.0" + }, + "dependencies": { + "crypto-random-string": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" + } + } + } + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, + "is-npm": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=" + }, + "latest-version": { + "version": "3.1.0", + "resolved": false, + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "requires": { + "package-json": "^4.0.0" + }, + "dependencies": { + "package-json": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + }, + "dependencies": { + "got": { + "version": "6.7.1", + "resolved": false, + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + }, + "dependencies": { + "create-error-class": { + "version": "3.0.2", + "resolved": false, + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "requires": { + "capture-stack-trace": "^1.0.0" + }, + "dependencies": { + "capture-stack-trace": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" + } + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": false, + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "get-stream": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "is-redirect": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + }, + "timed-out": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "unzip-response": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "^1.0.1" + }, + "dependencies": { + "prepend-http": { + "version": "1.0.4", + "resolved": false, + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + } + } + } + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": false, + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "requires": { + "rc": "^1.0.1" + } + } + } + } + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "semver-diff": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "requires": { + "semver": "^5.0.3" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" + } + } + }, + "uuid": { + "version": "3.1.0", + "resolved": false, + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "requires": { + "spdx-correct": "~1.0.0", + "spdx-expression-parse": "~1.0.0" + }, + "dependencies": { + "spdx-correct": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "requires": { + "spdx-license-ids": "^1.0.2" + }, + "dependencies": { + "spdx-license-ids": { + "version": "1.2.2", + "resolved": false, + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" + } + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": false, + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" + } + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "requires": { + "builtins": "^1.0.3" + }, + "dependencies": { + "builtins": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=" + } + } + }, + "which": { + "version": "1.2.14", + "resolved": false, + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "requires": { + "isexe": "^2.0.0" + }, + "dependencies": { + "isexe": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + } + } + }, + "worker-farm": { + "version": "1.3.1", + "resolved": false, + "integrity": "sha1-QzMRK7SbF6oFC4eJXKayys9A5f8=", + "requires": { + "errno": ">=0.1.1 <0.2.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + }, + "dependencies": { + "errno": { + "version": "0.1.4", + "resolved": false, + "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "requires": { + "prr": "~0.0.0" + }, + "dependencies": { + "prr": { + "version": "0.0.0", + "resolved": false, + "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=" + } + } + }, + "xtend": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha512-0TZ20a+xcIl4u0+Mj5xDH2yOWdmQiXlKf9Hm+TgDXjTMsEYb+gDrmb8e8UNAzMCitX8NBqG4Z/FUQIyzv/R1JQ==", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "slide": "^1.1.5" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + } + } + }, + "npm-audit-resolver": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/npm-audit-resolver/-/npm-audit-resolver-2.2.1.tgz", + "integrity": "sha512-9Jo5EdxREaXRrFm7eiuT1qu7fXKDfO+oiu+EgvJ/JCd2PIAgzVGF+xFoNK9AnyUsMFvSTdJM6+YlgUgF/N86GA==", + "dev": true, + "requires": { + "audit-resolve-core": "^1.1.8", + "chalk": "^2.4.2", + "djv": "^2.1.2", + "jsonlines": "^0.1.1", + "read": "^1.0.7", + "spawn-shell": "^2.1.0", + "yargs-parser": "^18.1.3", + "yargs-unparser": "^1.6.3" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-check-updates": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-7.0.2.tgz", + "integrity": "sha512-MyH17fUCFbYShuIyxZj6yqB6YZ47+AjPCgXQiH1oqNe3vElBoJ0toY7nwy88qJbfXnFqjTFigzs9lsoKSK0iUw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "cint": "^8.2.1", + "cli-table": "^0.3.1", + "commander": "^5.1.0", + "find-up": "4.1.0", + "get-stdin": "^8.0.0", + "json-parse-helpfulerror": "^1.0.3", + "libnpmconfig": "^1.2.1", + "lodash": "^4.17.19", + "p-map": "^4.0.0", + "pacote": "^11.1.10", + "progress": "^2.0.3", + "prompts": "^2.3.2", + "rc-config-loader": "^3.0.0", + "requireg": "^0.2.2", + "semver": "^7.3.2", + "semver-utils": "^1.1.4", + "spawn-please": "^0.3.0", + "update-notifier": "^4.1.0" + }, + "dependencies": { + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "npm-install-checks": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", + "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "dev": true, + "requires": { + "semver": "^7.1.1" + }, + "dependencies": { + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, + "npm-package-arg": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz", + "integrity": "sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==", + "dev": true, + "requires": { + "hosted-git-info": "^3.0.6", + "semver": "^7.0.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", + "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "npm-packlist": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-2.1.4.tgz", + "integrity": "sha512-Qzg2pvXC9U4I4fLnUrBmcIT4x0woLtUgxUi9eC+Zrcv1Xx5eamytGAfbDWQ67j7xOcQ2VW1I3su9smVTIdu7Hw==", + "dev": true, + "requires": { + "glob": "^7.1.6", + "ignore-walk": "^3.0.3", + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.0.tgz", + "integrity": "sha512-ygs4k6f54ZxJXrzT0x34NybRlLeZ4+6nECAIbr2i0foTnijtS1TJiyzpqtuUAJOps/hO0tNDr8fRV5g+BtRlTw==", + "dev": true, + "requires": { + "npm-install-checks": "^4.0.0", + "npm-package-arg": "^8.0.0", + "semver": "^7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "npm-registry-fetch": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-9.0.0.tgz", + "integrity": "sha512-PuFYYtnQ8IyVl6ib9d3PepeehcUeHN9IO5N/iCRhyg9tStQcqGQBRVHmfmMWPDERU3KwZoHFvbJ4FPXPspvzbA==", + "dev": true, + "requires": { + "@npmcli/ci-detect": "^1.0.0", + "lru-cache": "^6.0.0", + "make-fetch-happen": "^8.0.9", + "minipass": "^3.1.3", + "minipass-fetch": "^1.3.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.0.0", + "npm-package-arg": "^8.0.0" + }, + "dependencies": { + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npmi": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npmi/-/npmi-1.0.1.tgz", + "integrity": "sha1-FddpJzVHVF5oCdzwzhiu1IsCkOI=", + "requires": { + "npm": "^2.1.12", + "semver": "^4.1.0" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "builtins": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-0.0.7.tgz", + "integrity": "sha1-NVIZzWzxjb58Acx/0tznZc/cVJo=" + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" + } + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "requires": { + "ajv": "^4.9.1", + "har-schema": "^1.0.5" + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "minimist": { + "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.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "node-gyp": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.3.tgz", + "integrity": "sha512-7789TDMqJpv5iHxn1cAESCBEC/sBHAFxAvgXAcvzWenEWl0qf6E2Kk/Xwdl5ZclktUJzxJPVa27OMkBvaHKqCQ==", + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": ">=2.9.0 <2.82.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1" + } + }, + "npm": { + "version": "2.15.12", + "resolved": "https://registry.npmjs.org/npm/-/npm-2.15.12.tgz", + "integrity": "sha1-33w+1aJ3w/nUtdgZsFMR0QogCuY=", + "requires": { + "abbrev": "~1.0.9", + "ansi": "~0.3.1", + "ansi-regex": "*", + "ansicolors": "~0.3.2", + "ansistyles": "~0.1.3", + "archy": "~1.0.0", + "async-some": "~1.0.2", + "block-stream": "0.0.9", + "char-spinner": "~1.0.1", + "chmodr": "~1.0.2", + "chownr": "~1.0.1", + "cmd-shim": "~2.0.2", + "columnify": "~1.5.4", + "config-chain": "~1.1.10", + "dezalgo": "~1.0.3", + "editor": "~1.0.0", + "fs-vacuum": "~1.2.9", + "fs-write-stream-atomic": "~1.0.8", + "fstream": "~1.0.10", + "fstream-npm": "~1.1.1", + "github-url-from-git": "~1.4.0", + "github-url-from-username-repo": "~1.0.2", + "glob": "~7.0.6", + "graceful-fs": "~4.1.6", + "hosted-git-info": "~2.1.5", + "imurmurhash": "*", + "inflight": "~1.0.4", + "inherits": "~2.0.3", + "ini": "~1.3.4", + "init-package-json": "~1.9.4", + "lockfile": "~1.0.1", + "lru-cache": "~4.0.1", + "minimatch": "~3.0.3", + "mkdirp": "~0.5.1", + "node-gyp": "~3.6.0", + "nopt": "~3.0.6", + "normalize-git-url": "~3.0.2", + "normalize-package-data": "~2.3.5", + "npm-cache-filename": "~1.0.2", + "npm-install-checks": "~1.0.7", + "npm-package-arg": "~4.1.0", + "npm-registry-client": "~7.2.1", + "npm-user-validate": "~0.1.5", + "npmlog": "~2.0.4", + "once": "~1.4.0", + "opener": "~1.4.1", + "osenv": "~0.1.3", + "path-is-inside": "~1.0.0", + "read": "~1.0.7", + "read-installed": "~4.0.3", + "read-package-json": "~2.0.4", + "readable-stream": "~2.1.5", + "realize-package-specifier": "~3.0.1", + "request": "~2.74.0", + "retry": "~0.10.0", + "rimraf": "~2.5.4", + "semver": "~5.1.0", + "sha": "~2.0.1", + "slide": "~1.1.6", + "sorted-object": "~2.0.0", + "spdx-license-ids": "~1.2.2", + "strip-ansi": "~3.0.1", + "tar": "~2.2.1", + "text-table": "~0.2.0", + "uid-number": "0.0.6", + "umask": "~1.1.0", + "validate-npm-package-license": "~3.0.1", + "validate-npm-package-name": "~2.2.2", + "which": "~1.2.11", + "wrappy": "~1.0.2", + "write-file-atomic": "~1.1.4" + }, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" + }, + "ansi": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", + "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=" + }, + "ansi-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", + "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=" + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async-some": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-TYqBYg1ZWHkbW5j4AtMgd3bpVQk=", + "requires": { + "dezalgo": "^1.0.2" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "~2.0.0" + } + }, + "char-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/char-spinner/-/char-spinner-1.0.1.tgz", + "integrity": "sha1-5upnvSR+EHESmDt6sEee02KAAIE=" + }, + "chmodr": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chmodr/-/chmodr-1.0.2.tgz", + "integrity": "sha1-BGYrky0PAuxm3qorDqQoEZaOPrk=" + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "cmd-shim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-2.0.2.tgz", + "integrity": "sha1-b8vamUg6j9FdfTChlspp1oii79s=", + "requires": { + "graceful-fs": "^4.1.2", + "mkdirp": "~0.5.0" + } + }, + "columnify": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", + "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", + "requires": { + "strip-ansi": "^3.0.0", + "wcwidth": "^1.0.0" + }, + "dependencies": { + "wcwidth": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.0.tgz", + "integrity": "sha1-AtBZ/3qPx0Hg9rXaHmmytA2uym8=", + "requires": { + "defaults": "^1.0.0" + }, + "dependencies": { + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + }, + "dependencies": { + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=" + } + } + } + } + } + } + }, + "config-chain": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.10.tgz", + "integrity": "sha1-f8OD3g/MhNcRy0Zb0XZXnK1hI0Y=", + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + }, + "dependencies": { + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + } + } + }, + "dezalgo": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + }, + "dependencies": { + "asap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.3.tgz", + "integrity": "sha1-H8HRVk7hFiDfym1nAphQkT+fRnk=" + } + } + }, + "editor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/editor/-/editor-1.0.0.tgz", + "integrity": "sha1-YMf4e9YrzGqJT6jM1q+3gjok90I=" + }, + "fs-vacuum": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fs-vacuum/-/fs-vacuum-1.2.9.tgz", + "integrity": "sha1-T5AZOrjqAokJlbzU6ARlml02ay0=", + "requires": { + "graceful-fs": "^4.1.2", + "path-is-inside": "^1.0.1", + "rimraf": "^2.5.2" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.8.tgz", + "integrity": "sha1-5Jqt3yiPh9Rv+eiC8hahOrxAd4s=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + } + } + }, + "fstream-npm": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fstream-npm/-/fstream-npm-1.1.1.tgz", + "integrity": "sha1-a5F122I5qD2CCeIyQmxJTbspaQw=", + "requires": { + "fstream-ignore": "^1.0.0", + "inherits": "2" + }, + "dependencies": { + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "requires": { + "fstream": "^1.0.0", + "inherits": "2", + "minimatch": "^3.0.0" + } + } + } + }, + "github-url-from-git": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/github-url-from-git/-/github-url-from-git-1.4.0.tgz", + "integrity": "sha1-KF5rUggZABveEoZ0cEN55P8D4N4=" + }, + "github-url-from-username-repo": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-fdeTMNKr5pwQws73lxTJchV5Hfo=" + }, + "glob": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "path-is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", + "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=" + } + } + }, + "graceful-fs": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha1-UUw4dysxvuLgi+3CGgrrOr9UwZ4=" + }, + "hosted-git-info": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz", + "integrity": "sha1-C6gdkNouJas0ozLm7HeTbhWYEYs=" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "inflight": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz", + "integrity": "sha1-2zIEzVqd4ubNiQuFxuL2a89PYgo=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" + }, + "init-package-json": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-1.9.4.tgz", + "integrity": "sha1-tAU9C0Dwz4QqQZZpN8s9wPU06FY=", + "requires": { + "glob": "^6.0.0", + "npm-package-arg": "^4.0.0", + "promzard": "^0.3.0", + "read": "~1.0.1", + "read-package-json": "1 || 2", + "semver": "2.x || 3.x || 4 || 5", + "validate-npm-package-license": "^3.0.1", + "validate-npm-package-name": "^2.0.1" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "path-is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", + "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=" + } + } + }, + "promzard": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz", + "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", + "requires": { + "read": "1" + } + } + } + }, + "lockfile": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.1.tgz", + "integrity": "sha1-nTU+z+P1TRULtX+J1RdGk1o5xPU=" + }, + "lru-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz", + "integrity": "sha1-E0OVXtry432bnn7nJB4nxLn7cr4=", + "requires": { + "pseudomap": "^1.0.1", + "yallist": "^2.0.0" + }, + "dependencies": { + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "yallist": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz", + "integrity": "sha1-MGxUODXwnuGkyyO3vOmrNByRzdQ=" + } + } + }, + "minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "requires": { + "brace-expansion": "^1.0.0" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": false, + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1" + } + }, + "normalize-git-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/normalize-git-url/-/normalize-git-url-3.0.2.tgz", + "integrity": "sha1-jl8Uvgva7bc+ByADEKpBbCc1D8Q=" + }, + "normalize-package-data": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz", + "integrity": "sha1-jZJPFClg4Xd+f/4XBUNjHMfLAt8=", + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "^1.0.0" + }, + "dependencies": { + "builtin-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.0.tgz", + "integrity": "sha1-EFOVX9mUpXRuUl5Kxxe4HK8HSRw=" + } + } + } + } + }, + "npm-cache-filename": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz", + "integrity": "sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE=" + }, + "npm-install-checks": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-1.0.7.tgz", + "integrity": "sha1-bZGu2grJaAHx7Xqt7hFqbAoIalc=", + "requires": { + "npmlog": "0.1 || 1 || 2", + "semver": "^2.3.0 || 3.x || 4 || 5" + } + }, + "npm-package-arg": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-4.1.0.tgz", + "integrity": "sha1-LgFfisAHN8uX+ZfJy/BZ9Cp0Un0=", + "requires": { + "hosted-git-info": "^2.1.4", + "semver": "4 || 5" + } + }, + "npm-registry-client": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-7.2.1.tgz", + "integrity": "sha1-x5ImawiMwxP4Ul5+NSSGJscj23U=", + "requires": { + "concat-stream": "^1.5.2", + "graceful-fs": "^4.1.6", + "normalize-package-data": "~1.0.1 || ^2.0.0", + "npm-package-arg": "^3.0.0 || ^4.0.0", + "npmlog": "~2.0.0 || ~3.1.0", + "once": "^1.3.3", + "request": "^2.74.0", + "retry": "^0.10.0", + "semver": "2 >=2.2.1 || 3.x || 4 || 5", + "slide": "^1.1.3" + }, + "dependencies": { + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~2.0.0", + "typedarray": "~0.0.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + } + } + }, + "retry": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.0.tgz", + "integrity": "sha1-ZJ4VykCEItmDGBYZNef31lLUNd0=" + } + } + }, + "npm-user-validate": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/npm-user-validate/-/npm-user-validate-0.1.5.tgz", + "integrity": "sha1-UkZdUMLSApSlcSW5lrrtv1bFAEs=" + }, + "npmlog": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", + "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", + "requires": { + "ansi": "~0.3.1", + "are-we-there-yet": "~1.1.2", + "gauge": "~1.2.5" + }, + "dependencies": { + "are-we-there-yet": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz", + "integrity": "sha1-gORw6VoIR5T+GJkmLFZnxuiN4bM=", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.0 || ^1.1.13" + }, + "dependencies": { + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + } + } + }, + "gauge": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", + "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", + "requires": { + "ansi": "^0.3.0", + "has-unicode": "^2.0.0", + "lodash.pad": "^4.1.0", + "lodash.padend": "^4.1.0", + "lodash.padstart": "^4.1.0" + }, + "dependencies": { + "has-unicode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.0.tgz", + "integrity": "sha1-o82Wwwe6QdVZxaLuQIwSoRxMLsM=" + }, + "lodash._baseslice": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lodash._baseslice/-/lodash._baseslice-4.0.0.tgz", + "integrity": "sha1-9c4d+YKUjsr/Y/IjhTQVt7l2NwQ=" + }, + "lodash._basetostring": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz", + "integrity": "sha1-kyfJ3FFYhmt/pLnUL0Y45XZt2d8=" + }, + "lodash.pad": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.4.0.tgz", + "integrity": "sha1-+qON8mwKaexQhqgiRslY4VDcsas=", + "requires": { + "lodash._baseslice": "~4.0.0", + "lodash._basetostring": "~4.12.0", + "lodash.tostring": "^4.0.0" + } + }, + "lodash.padend": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.5.0.tgz", + "integrity": "sha1-oonpN37i5t6Lp/EfOo6zJgcLdhk=", + "requires": { + "lodash._baseslice": "~4.0.0", + "lodash._basetostring": "~4.12.0", + "lodash.tostring": "^4.0.0" + } + }, + "lodash.padstart": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.5.0.tgz", + "integrity": "sha1-PqGQ9nNIQcM2TSedEeBWcmtgp5o=", + "requires": { + "lodash._baseslice": "~4.0.0", + "lodash._basetostring": "~4.12.0", + "lodash.tostring": "^4.0.0" + } + }, + "lodash.tostring": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.4.tgz", + "integrity": "sha1-Vgwn0fjq3eA8LM4Zj+9cAx2CmPs=" + } + } + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.1.tgz", + "integrity": "sha1-iXWQrNGu0zEbcDtYvMtNQ/VvKJU=" + }, + "osenv": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.3.tgz", + "integrity": "sha1-g88FxtZFj8TVrGNi6jJdkvJ1Qhc=", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + }, + "dependencies": { + "os-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.0.tgz", + "integrity": "sha1-43B4vGG1hpBjBTiXJX457BJhtwI=" + }, + "os-tmpdir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.1.tgz", + "integrity": "sha1-6bQjoe2vR5iCVi6S7XHXdDoHG24=" + } + } + }, + "qs": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.4.tgz", + "integrity": "sha512-E57gmgKXqDda+qWTkUJgIwgJICK7zgMfqZZopTRKZ6mY9gzLlmJN9EpXNnDrTxXFlOM/a+I28kJkF/60rqgnYw==" + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "requires": { + "mute-stream": "~0.0.4" + }, + "dependencies": { + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=" + } + } + }, + "read-installed": { + "version": "4.0.3", + "resolved": false, + "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=", + "requires": { + "debuglog": "^1.0.1", + "graceful-fs": "^4.1.2", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "slide": "~1.1.3", + "util-extend": "^1.0.1" + }, + "dependencies": { + "debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=" + }, + "readdir-scoped-modules": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-n6+jfShr5dksuuve4DDcm19AZ0c=", + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "util-extend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.1.tgz", + "integrity": "sha1-u3A7eUgCk93Nz7PGqf6iD0g0Fbw=" + } + } + }, + "read-package-json": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.0.4.tgz", + "integrity": "sha1-Ye0bIlbqQ42ACIlQkL6EuOeZyFM=", + "requires": { + "glob": "^6.0.0", + "graceful-fs": "^4.1.2", + "json-parse-helpfulerror": "^1.0.2", + "normalize-package-data": "^2.0.0" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "path-is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", + "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=" + } + } + }, + "json-parse-helpfulerror": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", + "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=", + "requires": { + "jju": "^1.1.0" + }, + "dependencies": { + "jju": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.3.0.tgz", + "integrity": "sha1-2t2e8BkkvHKLA/L3l5vb1i96Kqo=" + } + } + } + } + }, + "readable-stream": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", + "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", + "requires": { + "buffer-shims": "^1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + } + }, + "realize-package-specifier": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/realize-package-specifier/-/realize-package-specifier-3.0.1.tgz", + "integrity": "sha1-/eMukmRI44+ZM02Vt7CNUeOpjZ8=", + "requires": { + "dezalgo": "^1.0.1", + "npm-package-arg": "^4.0.0" + } + }, + "request": { + "version": "2.74.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.74.0.tgz", + "integrity": "sha1-dpPKdou7DqXIzgjAhKRe+gW4kqs=", + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "bl": "~1.1.2", + "caseless": "~0.11.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~1.0.0-rc4", + "har-validator": "~2.0.6", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "node-uuid": "~1.4.7", + "oauth-sign": "~0.8.1", + "qs": "~6.2.0", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "~0.4.1" + }, + "dependencies": { + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" + }, + "aws4": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz", + "integrity": "sha1-/efVKSRm0jDl7g9OA42d+qsI/GE=" + }, + "bl": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "requires": { + "readable-stream": "~2.0.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + } + } + } + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "~1.0.0" + }, + "dependencies": { + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + } + } + }, + "extend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", + "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "1.0.0-rc4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz", + "integrity": "sha1-BaxrwiIntD5EYfSIFhVUaZ1Pi14=", + "requires": { + "async": "^1.5.2", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.10" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "requires": { + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "requires": { + "graceful-readlink": ">= 1.0.0" + }, + "dependencies": { + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + } + } + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + }, + "dependencies": { + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + } + } + } + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + }, + "dependencies": { + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.x.x" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "requires": { + "boom": "2.x.x" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "requires": { + "hoek": "2.x.x" + } + } + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "dependencies": { + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" + }, + "jsprim": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.0.tgz", + "integrity": "sha1-zi4b74NSBLTzCZkoxgL4tq5hVlA=", + "requires": { + "extsprintf": "1.0.2", + "json-schema": "0.2.2", + "verror": "1.3.6" + }, + "dependencies": { + "extsprintf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" + }, + "json-schema": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz", + "integrity": "sha1-UDVPGfYDkXxpX3C4Wvp3w7DyNQY=" + }, + "verror": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "requires": { + "extsprintf": "1.0.2" + } + } + } + } + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "mime-types": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", + "integrity": "sha1-wlnEcb2oCKhdbNGTtDCl+uRHOzw=", + "requires": { + "mime-db": "~1.23.0" + }, + "dependencies": { + "mime-db": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz", + "integrity": "sha1-oxtAcK2uon1zLqMzdApk0OyaZlk=" + } + } + }, + "node-uuid": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", + "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "tough-cookie": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.1.tgz", + "integrity": "sha1-mcd9+7fYBCSeiimdTLD9gf7wg/0=" + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=" + } + } + }, + "retry": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.0.tgz", + "integrity": "sha1-ZJ4VykCEItmDGBYZNef31lLUNd0=" + }, + "rimraf": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "requires": { + "glob": "^7.0.5" + } + }, + "semver": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.1.0.tgz", + "integrity": "sha1-hfLPhVBGXE3wAM99hvawVBBqueU=" + }, + "sha": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/sha/-/sha-2.0.1.tgz", + "integrity": "sha1-YDCCL70smCOUn49y7WQR7lzyWq4=", + "requires": { + "graceful-fs": "^4.1.2", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.2.tgz", + "integrity": "sha1-vsgb6ujPRVFovC5bKzH1vPrtmxs=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "process-nextick-args": "~1.0.0", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "integrity": "sha1-awcIWu+aPMrG7lO/nT3wwVIaVTg=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "process-nextick-args": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.3.tgz", + "integrity": "sha1-4nLu2CXV6fTqdNjXOx/jEcO+tjA=" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "util-deprecate": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.1.tgz", + "integrity": "sha1-NVaj0TxMaqeYPX4kJUeBlxmbeIE=" + } + } + } + } + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, + "sorted-object": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sorted-object/-/sorted-object-2.0.0.tgz", + "integrity": "sha1-HP6pgWCQR9gEOAekkKnZmzF/r38=" + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" + }, + "umask": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/umask/-/umask-1.1.0.tgz", + "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=" + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "requires": { + "spdx-correct": "~1.0.0", + "spdx-expression-parse": "~1.0.0" + }, + "dependencies": { + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "requires": { + "spdx-license-ids": "^1.0.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.2.tgz", + "integrity": "sha1-1SsUtelnB3FECvIlvLVjEirEUvY=", + "requires": { + "spdx-exceptions": "^1.0.4", + "spdx-license-ids": "^1.0.0" + }, + "dependencies": { + "spdx-exceptions": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-1.0.4.tgz", + "integrity": "sha1-IguEI5EZrpBFqJLbgag/TOFvgP0=" + } + } + } + } + }, + "validate-npm-package-name": { + "version": "2.2.2", + "resolved": false, + "integrity": "sha1-9laVsi9zJEQgGaPH+jmm5/0pkIU=", + "requires": { + "builtins": "0.0.7" + } + }, + "which": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.11.tgz", + "integrity": "sha1-yLLu6muMFln6fB3U/aq+lTPcXos=", + "requires": { + "isexe": "^1.1.1" + }, + "dependencies": { + "isexe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz", + "integrity": "sha1-NvPiLmB1CSD15yQaR2qMakInWtA=" + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "1.1.4", + "resolved": false, + "integrity": "sha1-sfUtwujcDjywTRh6JfdYo4qQyjs=", + "requires": { + "graceful-fs": "^4.1.2", + "imurmurhash": "^0.1.4", + "slide": "^1.1.5" + } + } + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.1.tgz", + "integrity": "sha512-LQy1Q1fcva/UsnP/6Iaa4lVeM49WiOitu2T4hZCyA/elLKu37L99qcBJk4VCCk+rdLvnMzfKyiN3SZTqdAZGSQ==" + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~4.2.1", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "performance-now": "^0.2.0", + "qs": "~6.4.0", + "safe-buffer": "^5.0.1", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.0.0" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "^1.4.1" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "nwmatcher": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz", + "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==", + "optional": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-inspect": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "dev": true + }, + "object-keys": { + "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-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "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" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", + "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "object.values": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", + "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "has": "^1.0.3" + } + }, + "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" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true + }, + "opn": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-6.0.0.tgz", + "integrity": "sha512-I9PKfIZC+e4RXZ/qr1RhgyCnGgYX0UEIlXgWnCOVACIvFgaC9rz6Won7xbdhoHrd8IIhV7YEpHjreNUNkqCGkQ==", + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "optional": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-cancelable": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", + "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==", + "dev": true + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "pacote": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.2.7.tgz", + "integrity": "sha512-ogxPor11v/rnU9ukwLlI2dPx22q9iob1+yZyqSwerKsOvBMhU9e+SJHtxY4y2N0MRH4/5jGsGiRLsZeJWyM4dQ==", + "dev": true, + "requires": { + "@npmcli/git": "^2.0.1", + "@npmcli/installed-package-contents": "^1.0.6", + "@npmcli/promise-spawn": "^1.2.0", + "@npmcli/run-script": "^1.8.2", + "cacache": "^15.0.5", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.3", + "mkdirp": "^1.0.3", + "npm-package-arg": "^8.0.1", + "npm-packlist": "^2.1.4", + "npm-pick-manifest": "^6.0.0", + "npm-registry-fetch": "^9.0.0", + "promise-retry": "^2.0.1", + "read-package-json-fast": "^2.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.1.0" + }, + "dependencies": { + "@npmcli/installed-package-contents": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", + "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", + "dev": true, + "requires": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "@npmcli/run-script": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.8.5.tgz", + "integrity": "sha512-NQspusBCpTjNwNRFMtz2C5MxoxyzlbuJ4YEhxAKrIonTiirKDtatsZictx9RgamQIx6+QuHMNmPl0wQdoESs9A==", + "dev": true, + "requires": { + "@npmcli/node-gyp": "^1.0.2", + "@npmcli/promise-spawn": "^1.3.2", + "infer-owner": "^1.0.4", + "node-gyp": "^7.1.0", + "read-package-json-fast": "^2.0.1" + }, + "dependencies": { + "@npmcli/promise-spawn": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz", + "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==", + "dev": true, + "requires": { + "infer-owner": "^1.0.4" + } + } + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "node-gyp": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", + "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", + "dev": true, + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.3", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "request": "^2.88.2", + "rimraf": "^3.0.2", + "semver": "^7.3.2", + "tar": "^6.0.2", + "which": "^2.0.2" + } + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse5": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", + "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", + "optional": true + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "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==", + "dev": true + }, + "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=" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "requires": { + "through": "~2.3" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "plantuml-encoder": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/plantuml-encoder/-/plantuml-encoder-1.4.0.tgz", + "integrity": "sha512-sxMwpDw/ySY1WB2CE3+IdMuEcWibJ72DDOsXLkSmEaSzwEUaYBT6DWgOfBiHGCux4q433X6+OEFWjlVqp7gL6g==" + }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "optional": true + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "optional": true, + "requires": { + "asap": "~2.0.3" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "dependencies": { + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + } + } + }, + "promised-handlebars": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/promised-handlebars/-/promised-handlebars-1.0.6.tgz", + "integrity": "sha1-2ZfglDsD9j/oL/I8uQSyes/AUNg=", + "requires": { + "deep-aplus": "^1.0.2", + "q": "^1.4.1" + } + }, + "prompts": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz", + "integrity": "sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "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==" + }, + "proxy-middleware": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz", + "integrity": "sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY=" + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "optional": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "requires": { + "escape-goat": "^2.0.0" + } + }, + "puppeteer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-3.3.0.tgz", + "integrity": "sha512-23zNqRltZ1PPoK28uRefWJ/zKb5Jhnzbbwbpcna2o5+QMn17F0khq5s1bdH3vPlyj+J36pubccR8wiNA/VE0Vw==", + "requires": { + "debug": "^4.1.0", + "extract-zip": "^2.0.0", + "https-proxy-agent": "^4.0.0", + "mime": "^2.0.3", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^3.0.2", + "tar-fs": "^2.0.0", + "unbzip2-stream": "^1.3.3", + "ws": "^7.2.3" + }, + "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==" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "q": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.0.tgz", + "integrity": "sha1-3QG6ydBtMObyGa7LglPunr3DCPE=" + }, + "q-deep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/q-deep/-/q-deep-1.0.3.tgz", + "integrity": "sha1-zQcD2irMuuZXDmAMaKVt5mEHkMs=", + "requires": { + "deep-aplus": "^1.0.1", + "q": "^1.1.2" + } + }, + "q-plus": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/q-plus/-/q-plus-0.0.8.tgz", + "integrity": "sha1-TMZssZvRRbQ+nhtUAjYUI3e2Hqs=", + "requires": { + "q": "^1.1.2" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "range-parser": { + "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.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + } + } + }, + "rc-config-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-3.0.0.tgz", + "integrity": "sha512-bwfUSB37TWkHfP+PPjb/x8BUjChFmmBK44JMfVnU7paisWqZl/o5k7ttCH+EQLnrbn2Aq8Fo1LAsyUiz+WF4CQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "js-yaml": "^3.12.0", + "json5": "^2.1.1", + "require-from-string": "^2.0.2" + }, + "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 + } + } + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true, + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-installed": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz", + "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=", + "dev": true, + "requires": { + "debuglog": "^1.0.1", + "graceful-fs": "^4.1.2", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "slide": "~1.1.3", + "util-extend": "^1.0.1" + } + }, + "read-package-json": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz", + "integrity": "sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==", + "dev": true, + "requires": { + "glob": "^7.1.1", + "json-parse-even-better-errors": "^2.3.0", + "normalize-package-data": "^2.0.0", + "npm-normalize-package-bin": "^1.0.0" + } + }, + "read-package-json-fast": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.2.tgz", + "integrity": "sha512-5fyFUyO9B799foVk4n6ylcoAktG/FbE3jwRKxvwaeSrIunaoMc0u81dzXxjeAFKOce7O5KncdfwpGvvs6r5PsQ==", + "dev": true, + "requires": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "readable-stream": { + "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": { + "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" + } + }, + "readdir-scoped-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", + "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", + "dev": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "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", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" + } + } + }, + "request-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", + "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", + "requires": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", + "requires": { + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "requireg": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/requireg/-/requireg-0.2.2.tgz", + "integrity": "sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg==", + "dev": true, + "requires": { + "nested-error-stacks": "~2.0.1", + "rc": "~1.2.7", + "resolve": "~1.7.1" + }, + "dependencies": { + "resolve": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + } + } + }, + "resolve": { + "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" + } + }, + "resolve-alpn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.0.0.tgz", + "integrity": "sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dev": true, + "requires": { + "lowercase-keys": "^2.0.0" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha1-NXl/E6f9rcVmFCwp1PB8ytSD4+w=", + "requires": { + "glob": "^7.1.3" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "^1.1.1" + } + }, + "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==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "requires": { + "semver": "^6.3.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 + } + } + }, + "semver-utils": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/semver-utils/-/semver-utils-1.1.4.tgz", + "integrity": "sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==", + "dev": true + }, + "send": { + "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", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "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==" + } + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "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" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + } + } + }, + "serve-static": { + "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.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha1-oY1AUw5vB95CKMfe/kInr4ytAFs=", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "requires": { + "hoek": "2.x.x" + } + }, + "socks": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.5.1.tgz", + "integrity": "sha512-oZCsJJxapULAYJaEYBSzMcz8m3jqgGrHaGhkmU/o/PQfFWYWxkAaA0UMGImb6s6tEXfKi959X6VJjMMQ3P6TTQ==", + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz", + "integrity": "sha512-lEpa1zsWCChxiynk+lCycKuC502RxDWLKJZoIhnxrWNjLSDGYRFflHA1/228VkRcnv9TIb8w98derGbpKxJRgA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4", + "socks": "^2.3.3" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "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 + } + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "requires": { + "amdefine": ">=0.0.4" + } + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" + }, + "spawn-please": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/spawn-please/-/spawn-please-0.3.0.tgz", + "integrity": "sha1-2zOOxM/2Orxp8dDgjO6euL69nRE=", + "dev": true + }, + "spawn-shell": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spawn-shell/-/spawn-shell-2.1.0.tgz", + "integrity": "sha512-mjlYAQbZPHd4YsoHEe+i0Xbp9sJefMKN09JPp80TqrjC5NSuo+y1RG3NBireJlzl1dDV2NIkIfgS6coXtyqN/A==", + "dev": true, + "requires": { + "default-shell": "^1.0.1", + "merge-options": "~1.0.1", + "npm-run-path": "^2.0.2" + } + }, + "spdx-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz", + "integrity": "sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==", + "dev": true, + "requires": { + "array-find-index": "^1.0.2", + "spdx-expression-parse": "^3.0.0", + "spdx-ranges": "^2.0.0" + } + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "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==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "spdx-ranges": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz", + "integrity": "sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==", + "dev": true + }, + "spdx-satisfies": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/spdx-satisfies/-/spdx-satisfies-4.0.1.tgz", + "integrity": "sha512-WVzZ/cXAzoNmjCWiEluEA3BjHp5tiUmmhn9MK+X0tBbR9sOqtC6UQwmgCNrAIZvNlMuBUYAaHYfb2oqlF9SwKA==", + "dev": true, + "requires": { + "spdx-compare": "^1.0.0", + "spdx-expression-parse": "^3.0.0", + "spdx-ranges": "^2.0.0" + } + }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "requires": { + "through": "2" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dev": true, + "requires": { + "minipass": "^3.1.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "stack-chain": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-2.0.0.tgz", + "integrity": "sha512-GGrHXePi305aW7XQweYZZwiRwR7Js3MWoK/EHzzB9ROdc75nCnjSJVi21rdAGxFl+yCx2L2qdfl5y7NO4lTyqg==", + "optional": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "requires": { + "duplexer": "~0.1.1" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-equal": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/stream-equal/-/stream-equal-0.1.13.tgz", + "integrity": "sha1-F8LXz43lVw0P+5njpRQqWMdrxK4=", + "requires": { + "@types/node": "*" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "string.prototype.trimend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", + "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", + "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "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" + } + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "svgexport": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/svgexport/-/svgexport-0.4.1.tgz", + "integrity": "sha512-qRQuxZA6gT34xMs+9m/BGVlxFxQ1ftLi1HB1gUiOGYrp/Jm6whhTZEmYchQFy+wHKGdkyLB93w5MXoEcNtbcNg==", + "requires": { + "async": "^3.2.0", + "puppeteer": "^3.0.2" + } + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "dev": true + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha1-QwY30ki6d+B4iDlR+5qg7tfGP6I=", + "optional": true + }, + "tar": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", + "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + } + } + }, + "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" + } + } + } + }, + "term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "tmp": { + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", + "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", + "requires": { + "os-tmpdir": "~1.0.1" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + } + } + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=" + }, + "tough-cookie": { + "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.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "optional": true + }, + "trace": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/trace/-/trace-3.1.1.tgz", + "integrity": "sha512-iVxFnDKps8bCRQ6kXj66rHYFJY3fNkoYPHeFTFZn89YdwmmQ9Hz97IFPf3NdfbCF3zuqUqFpRNTu6N9+eZR2qg==", + "optional": true, + "requires": { + "stack-chain": "^2.0.0" + } + }, + "trace-and-clarify-if-possible": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trace-and-clarify-if-possible/-/trace-and-clarify-if-possible-1.0.5.tgz", + "integrity": "sha512-CmBz2eGrPxQ5miq51B4XnON0iC62q6q7CEzrRaFYZYi8xdX1ivafyk5cYshmVXp6p14cYvK3H4o1drYa3MEJOA==", + "requires": { + "clarify": "^2.1.0", + "trace": "^3.1.1" + } + }, + "treeify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", + "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "optional": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "type-is": { + "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.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha1-C2/nuDWuzaYcbqTU8CwUIh4QmEc=", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=" + }, + "unix-crypt-td-js": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz", + "integrity": "sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha1-j2bbzVWog6za5ECK+LA1pQRMGJQ=" + }, + "update-notifier": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", + "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", + "dev": true, + "requires": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "pupa": "^2.0.1", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } + } + }, + "uri-js": { + "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" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "requires": { + "os-homedir": "^1.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util-extend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", + "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "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", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "webidl-conversions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz", + "integrity": "sha1-O/glj30xjHRDw28uFpQCoaZwNQY=", + "optional": true + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + }, + "whatwg-url-compat": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz", + "integrity": "sha1-AImBEa9om7CXVBzVpFymyHmERb8=", + "optional": true, + "requires": { + "tr46": "~0.0.1" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "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==", + "optional": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "ws": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz", + "integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==" + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true + }, + "xml-name-validator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", + "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=", + "optional": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } + } + }, + "yargs-unparser": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.4.tgz", + "integrity": "sha512-QxEx9+qEr7jwVM4ngnk95+sKZ5QXm5gx0cL97LDby0SiC8HHoUK0LPBg475JwQcRCqIVfMD8SubCWp1dEgKuwQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "decamelize": "^1.2.0", + "flat": "^5.0.2", + "is-plain-obj": "^1.1.0", + "yargs": "^14.2.3" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "yargs": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.1" + } + }, + "yargs-parser": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", + "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} \ No newline at end of file diff --git a/legacy/package.json b/legacy/package.json new file mode 100644 index 000000000..f3417fe6d --- /dev/null +++ b/legacy/package.json @@ -0,0 +1,72 @@ +{ + "name": "documentation", + "version": "11.3.2", + "description": "Mojaloop Documentation GitBook Project", + "dependencies": { + "express": "4.17.1", + "gitbook-cli": "2.3.2", + "gitbook-plugin-back-to-top-button": "0.1.4", + "gitbook-plugin-changelog": "1.0.1", + "gitbook-plugin-collapsible-chapters": "0.1.8", + "gitbook-plugin-editlink": "1.0.2", + "gitbook-plugin-fontsettings": "2.0.0", + "gitbook-plugin-include": "0.1.0", + "gitbook-plugin-insert-logo": "0.1.5", + "gitbook-plugin-page-toc": "1.1.1", + "gitbook-plugin-plantuml-svg": "1.0.1", + "gitbook-plugin-swagger": "0.2.0", + "gitbook-plugin-theme-api": "1.1.2", + "gitbook-plugin-uml": "1.0.1", + "gitbook-plugin-variables": "1.1.0", + "svgexport": "0.4.1" + }, + "devDependencies": { + "directory-tree": "^2.2.5", + "got": "^11.8.0", + "husky": "^4.2.5", + "license-checker": "25.0.1", + "node-plantuml": "^0.5.0", + "npm-audit-resolver": "2.2.1", + "npm-check-updates": "7.0.2", + "plantuml-encoder": "^1.4.0", + "strip-comments": "^2.0.1", + "svgo": "^1.3.2" + }, + "scripts": { + "audit:check": "SHELL=sh check-audit", + "audit:resolve": "SHELL=sh resolve-audit", + "build:plantuml:all": "./scripts/_build_plantuml_all.sh", + "build:plantuml:diff": "./scripts/_build_plantuml_diff.sh", + "dep:check": "npx ncu -e 2", + "dep:update": "npx ncu -u", + "docker:build": "docker build --no-cache -t mojaloop/documentation .", + "docker:push": "docker push mojaloop/documentation", + "docker:run": "docker run --rm -it --name mojadoc -p 8989:8989 mojaloop/documentation", + "express:run": "node index.js", + "gitbook:build": "gitbook build", + "gitbook:export:pdf": "gitbook pdf ./", + "gitbook:install": "gitbook install", + "gitbook:serve": "gitbook serve --port 8989", + "gitbook:serveNoReload": "gitbook serve --no-live --port 8989", + "license:check": "npm run license:list -- --failOn `cat .licensebanned | grep '^[^#;]' | awk 'BEGIN { ORS=\"\" } { print p$0\";\"; } END { print \n }'`", + "license:list": "license-checker . --excludePackages `cat .licenseignore | grep '^[^#;]' | awk 'BEGIN { ORS=\"\" } { print p$0\";\"; } END { print \n }'` --production --csv", + "run": "npm run gitbook:serve", + "start": "npm run gitbook:serveNoReload" + }, + "husky": { + "hooks": { + "pre-commit": "npm run build:plantuml:diff", + "post-commit": "git update-index --again" + } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/mojaloop/documentation.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/mojaloop/documentation/issues" + }, + "homepage": "https://github.com/mojaloop/documentation#readme" +} diff --git a/publish-gh-pages.sh b/legacy/publish-gh-pages.sh similarity index 100% rename from publish-gh-pages.sh rename to legacy/publish-gh-pages.sh diff --git a/legacy/quality-security/assets/cqs_overview.drawio b/legacy/quality-security/assets/cqs_overview.drawio new file mode 100644 index 000000000..85bb9fe29 --- /dev/null +++ b/legacy/quality-security/assets/cqs_overview.drawio @@ -0,0 +1 @@ +1ZZNc9sgEIZ/jY6ZESA57tFV7bSdeKapD8mVSFiiRaBiZMv59V0E+oqaTjNNMq0PGngXdlmeXckBScrmStOq2KqMiQCHWROQDwHGSxTD0wpnJ8SdkGueOQkNwo4/MC+GXq15xg6ThUYpYXg1FVMlJUvNRKNaq9N02V6JadSK5mwm7FIq5uotz0zh04rDQf/IeF50kVHoLSXtFnvhUNBMnUYSWQck0UoZNyqbhAl7d929uH2bJ6z9wTST5k82bL+d764/31xvYp7ebh9oc1ceLyLn5UhF7RMO8EKAv/f3MMjtoBP2CuJAGubs72bxo1ad4eLQklvBAoSqZjB2Xm5qKrg5B/aQIIY7lta6FZx3OLcLMA0K8uggeBIfa1XLjNn0EJhPBTdsV9HUWk9QjKAVphTebL378kIE5lSn3RRmR6YNB+orwXMJmlGV35MooXQbj2zan9W5ECOdLKPV5Qr0g9HqO+ssUknWH9sGYM2T6FBfENBITJXMaHtXTV9VbotvIhQt3Pw0lCR559cUo3LE2AOmvg3y3vdQKTDwxfKMwkGzwvmiVa5pCeKWSmiL0ib3V8gGRLgD6D2Fj4DGcygoJDja/Abi68FaTmEtyQwWwr+AhZbhK8HCM1g7Q2VGdXZoG3JBS3v17gnKlX3pCi7hxfuWAJ8D6hHtaBNFcfIyAHEU/2sAyQzgV7ZnkBBcPA4/lZVo240aruT/ggwneN026AsgI5fk7ZDBdPhqt7bRXx+y/gk= \ No newline at end of file diff --git a/legacy/quality-security/assets/cqs_overview.svg b/legacy/quality-security/assets/cqs_overview.svg new file mode 100644 index 000000000..99bedbfb2 --- /dev/null +++ b/legacy/quality-security/assets/cqs_overview.svg @@ -0,0 +1,3 @@ + + +
    Quality + Security
    Quality + Security
    Program Management
    Program Manageme...
    Standards & Guidelines
    Standards & Guid...
    Reference Implementation
    Reference Implem...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/legacy/quality-security/program-management/readme.md b/legacy/quality-security/program-management/readme.md new file mode 100644 index 000000000..10be50e8e --- /dev/null +++ b/legacy/quality-security/program-management/readme.md @@ -0,0 +1,77 @@ +# Program Management + +This section provides an overview of Mojaloop's Risk and Security Management Initiatives. + +**Who is this for?** +*Risk Management, Compliance, Governance, Regulatory, and Leadership Stakeholders* + +## 1. Mojaloop Data Security and Privacy Program: +### 1.1 Code Quality & Security Program Overview + +**Objective:** Continuously improve the Trust (reliability, transparency, privacy, quality, and security) of the Mojaloop System. + +**Delivery Model:** Supports both functional and non-functional requirements of the project, working alongside with other workstreams & various governance committees on a shared responsibility Model. + +#### Approach: +- Standards and Control Centric – Define and maintain Mojaloop software quality and security standards and guidelines – In certain areas we provide reference implementation. +- Risk and Threat Centric – Perform risk and threat modelling to identify, validate, classify & prioritize security requirements. + +#### Key Milestones: +- PI 1 – 8: Foundation Phase - Built-in confidentiality and Integrity as part of the Core Mojaloop Architecture. + - Developed and Implemented (To some degree) Signatures, MTLS, PKI, encryption standards + - Established a code quality and security framework - DevOps & CI/CD Tools automation, workflows & policies +- PI 9 – Current: Improvement Phase – Consolidate, optimize & improve. + - Introduced a risk and threat driven approach + - Baselining Mojaloop against best practice standards – PCI DSS and GDPR + - Focus on the data – Data Protection Standards and Introduction of a Cryptographic Processing Module (CPM) + +#### Guiding Principles: +- We endeavor to ensure that our policy and governance framework is as lightweight as possible to encourage community volunteers to contribute freely and easily. +- The overarching aim of the Code is to prescribe the use of certain quality/security practices and techniques delivered as guidelines and in some areas, we have reference technology implementations whereas for other areas we require certain policies or standards to be adhered to and verifiable. + +### 1.2 Current PI Objectives (PI 12) + +1. Enhance security in new functionality additions +2. Support major implementations +3. Design a secure cryptographic processing module +4. Improve data protection measures and controls +5. Baselining of Mojaloop against industry standards +6. Maintain and enhance secure DevOps/CI CD practices +7. Improve communication and community engagement +8. Improve access control measures + +#### Epics: +1. Data Protection and Privacy +2. Core Functionality Support +3. Implementation Support +4. Community Engagement +5. Identity and Access Management +6. DevSecOps Integration +7. Cryptography Support +8. Standard Baselining + +### 1.3 PI Reports (8 – 10) + +1. [PI 8](https://raw.githubusercontent.com/mojaloop/documentation-artifacts/master/presentations/September%202019%20PI-8_OSS_community%20session/cqs_pi_08_report.pdf) +2. [PI 9](https://raw.githubusercontent.com/mojaloop/documentation-artifacts/master/presentations/January%202020%20OSS%20Community%20Session/cqs_pi_09_report.pdf) +3. [PI 10](https://github.com/mojaloop/documentation-artifacts/blob/master/presentations/April%202020%20Community%20Event/Presentations/code_quality_and_security-PI%2010%20final.pdf) +4. [PI 11](https://github.com/mojaloop/documentation-artifacts/blob/master/presentations/July%202020%20Community%20Event/Presentations/Code%20Quality%20Security%20PI%2010%20Report%20-%2020%20July%202020%20v1.9%20Final.pdf) +5. PI 12 _(link coming soon)_ + +### 1.4 Vulnerability disclosure procedure + +See [Vulnerability Disclosure Procedure](./vulnerability-disclosure-procedure.md) for more information + + +## 2. Scheme Rules Risk Management, Security, Privacy and Data Confidentiality + +See [Scheme Rules Guidelines](./scheme-rules-guidelines.md) for more information + +## 3. Standard Baselining Reports + +- [GDPR Scoping Analysis Report](https://raw.githubusercontent.com/mojaloop/documentation-artifacts/master/reference/gdpr_scope_analysis_report.pdf) +- [PCI DSS Baseline report and recommendations – Responsibility matrix (Hub/Switch)](https://github.com/mojaloop/documentation-artifacts/raw/mojaloop/reference/Mojaloop%20PCI%20DSS%20Compliace%20Baseline%20Requirement%20Overall%20Report%20v1.0%2005012021.xlsx) + +## 4. Code Security Overview + +Refer to [this presentation](https://raw.githubusercontent.com/mojaloop/documentation-artifacts/master/reference/code_security_overview.pdf) for an overview of the Code Security Practices in the Mojaloop Community. \ No newline at end of file diff --git a/legacy/quality-security/program-management/scheme-rules-guidelines.md b/legacy/quality-security/program-management/scheme-rules-guidelines.md new file mode 100644 index 000000000..b2536916e --- /dev/null +++ b/legacy/quality-security/program-management/scheme-rules-guidelines.md @@ -0,0 +1,51 @@ +# Security, Risk Management, and Data Confidentiality + +> Note: this document is a reference from the [Scheme Business Rules](https://docs.mojaloop.io/mojaloop-business-docs/documents/scheme-business-rules.html) +> Please refer to [Mojaloop Business Docs](https://docs.mojaloop.io/mojaloop-business-docs/) for more information and context + +## 1.1 Confidentiality and Protection of Personal Information +- Confidential Information of the Scheme that is disclosed to Participants will be held in confidence by Participants and will be used only for the purposes permitted by the Rules. Scheme Confidential Information may include proprietary technology and other matters designated by the Scheme. +- Transaction data will not be owned by the Scheme and will be owned by a Participant as it relates to its Customer's Transactions. +- The confidentiality of Transaction data and any Personal Information processed in the Platform will be protected by the Scheme and Participants according to Applicable Law. +- Statistics or data which identify a Participant or from which the Participant may be identified will not be disclosed to other Participants. The Scheme may prepare for internal use and disclose to third parties for promotional purposes statistics based on aggregate, anonymized data as permitted by Applicable Law. +- The Scheme will make disclosures of Confidential Information to comply with Applicable Law or the directive of a Regulatory Authority. +- The Scheme will protect Personal Information in its possession or under its control from misuse and otherwise treat such information in accordance with Applicable Law protecting privacy of individuals. +- The Scheme will maintain industry leading security measures to protect information from unauthorized access and use. +- Participants will notify the Scheme and acknowledge that the Scheme may notify other Participants, of any Security Incident in the systems or premises of the Participant, its affiliated entities or any third-party vendor engaged by the Participant to provide services in support of the Participant's participation in the Scheme. +- The Scheme may conduct investigations into Security Incidents. Participants will cooperate fully and promptly with the investigation. Such investigations will be at the expense of the affected Participant. +- The Scheme may require a Participant to conduct investigations of Security Incidents and may require that such investigations be conducted by qualified independent security auditors acceptable to the Scheme. +- The Scheme may impose conditions of continued participation on the affected Participant regarding remedy of the causes of the Security Incident and ongoing security measures. +- The investigation and report, as well as remedies that may be required will be held confidential to the extent permitted by Applicable Law. + +## 1.2 Risk Management Policies + +This section assumes that the development of risk management policies by the Scheme and its participants will be evolving. This section contemplates that some of these policies will (eventually) be in the Rules; others will not + +- Risk management policies and procedures may be stated in the Rules, in Associated Documents, or in other written policy documents created by the Scheme and distributed to Participants +- Risk management policies and procedures will include fiscal soundness, system integrity, compliance with Applicable Law, particularly as to Anti-Money Laundering/Combatting Terrorism Financing measures, privacy of personal information and data security +- Risk management functions include procedures applicable to Participants for monitoring of risks, including reporting requirements and audits + + +## 1.3 Business Continuity +- Provisions to ensure business continuity on the part of the Scheme, its vendors, and Participants. + + +## Appendix: Risk Management, Security, Privacy, and Service Standards +> Schemes may or may not want to specify standards or require that Participants comply with other established standards. Schemes may furthermore specify different standards for different categories of Participants. The list below is given purely as an example. + +Participants must adhere to the following practices of service quality security, data privacy and customer service as they apply to a Participant in connection with the Scheme. +- Participants will establish a risk management framework for identifying, assessing and controlling risks relative to their use of the Scheme. +- Participants will ensure that the systems, applications and network that support the use of the Scheme are designed and developed securely. +- Participants will implement processes to securely manage all systems and operations that support the use of the Scheme. +- Participants will implement processes to ensure that systems used for the Scheme are secure from unauthorized intrusion or misuse. +- Participants will implement processes to ensure the authentication of their customers in creating and approving transactions that use the Scheme. +- Participants will develop effective business continuity and contingency plans. +- Participants will manage technical and business operations to allow timely responses to API calls received from the Scheme Platform or from other Participants via the Scheme Platform. +- Participants will establish written agreements governing their relationship with agents, processors, and other entities providing outsourced services that pertain to the Scheme. +- Participants will develop policies and processes for ongoing management and oversight of staff, agents, processors, and other entities providing outsourced services that pertain to the Scheme. +- Participants will ensure that customers are provided with clear, prominent, and timely information regarding fees and terms and conditions with respect to services using the Scheme. +- Participants will develop and publish customer service policies and procedures with respect to services using the Scheme. +- Participants will provide an appropriate mechanism for customers to address questions and problems. Participants will specify how disputes can be resolved if internal resolution fails. +- Participants will comply with good practices and Applicable Laws governing customer data privacy. +- Participants will ensure that Customers are provided with clear, prominent, and timely information regarding their data privacy practices. + diff --git a/legacy/quality-security/program-management/vulnerability-disclosure-procedure.md b/legacy/quality-security/program-management/vulnerability-disclosure-procedure.md new file mode 100644 index 000000000..a8770999d --- /dev/null +++ b/legacy/quality-security/program-management/vulnerability-disclosure-procedure.md @@ -0,0 +1,35 @@ +# Mojaloop Vulnerability Reporting Procedure + +## Overview + +This procedure is for guiding the public on how security vulnerabilities should be reported safely and responsibly to the dedicated security team within Mojaloop. As representatives of the Mojaloop Community, we strongly encourage everyone to alert us of the potential security vulnerabilities privately first, before disclosing them in a public forum – a right everyone is entitled to without any permission whatever from us as the maintainer of the platform. + +## Contacts + +Contact security@mojaloop.io to report a security vulnerability in the Mojaloop codebase. + +We cannot accept regular bug reports or other security related queries at these addresses. All mail sent to these addresses that does not relate to an undisclosed security problem in an Mojaloop project will be ignored. + +NB. Security vulnerabilities should not be entered in a project's public bug tracker unless the necessary configuration is in place to limit access to the issue to only the reporter and the project security team. + +## Reporting Format +Please send one plain-text email for each vulnerability you are reporting. We may ask you to resubmit your report if you send it as an image, movie, HTML, or PDF attachment when it could just as easily be described with plain text. + +## Vulnerability Types + +We have no restrictions whatsoever for the vulnerability type or method used to uncover the vulnerabilities. The public is welcome to use any methods or tools available to them, including analysis of the source, and apply any methodology of their own in finding vulnerabilities, provided that the vulnerability report is clear and self-descriptive. + +## Advance Security + +We use standard TLS encryption in our mail systems however should the reporter requires additional layer security before sending the info then we are flexible to cater for that on a case by case basis by contacting godfreyk@crosslaketech.com + +## Vulnerability Information + +Further information regarding handling of published vulnerabilities for an Mojaloop project can usually be found on the project’s GitHub Account. If you cannot find the information you are looking for on GitHub, you should ask your question on the project's user mailing list above. + +## Vulnerability Handling +An overview of the vulnerability handling process is: +1. The reporter reports the vulnerability privately to Mojaloop. +2. The appropriate project's security team works privately with the reporter to resolve the vulnerability. +3. A new release of the Mojaloop package concerned is made that includes the fix. +4. The vulnerability is publicly announced to the Mojaloop Community diff --git a/legacy/quality-security/readme.md b/legacy/quality-security/readme.md new file mode 100644 index 000000000..e6789cdbe --- /dev/null +++ b/legacy/quality-security/readme.md @@ -0,0 +1,17 @@ +# Quality & Security + + + +The Quality and Security effort in Mojaloop is focused on delivering high quality, secure, and maintable software. This spans from recommending best practices for deployers to architecting processes to ensure that our code is scanned for vulnerabilities and security patches are applied regularly. + +## Overview + +We break down this effort into the following three categories: + +1. [Program Management](./program-management/readme.md) +1. [Standards + Guidelines](./standards-guidelines/readme.md) +1. [Reference Implementation](./reference-implementation.md) + +## Other Links + +- [Summary of the Snyk investigation](./snyk_investigation.md) diff --git a/legacy/quality-security/reference-implementation.md b/legacy/quality-security/reference-implementation.md new file mode 100644 index 000000000..bf62b0140 --- /dev/null +++ b/legacy/quality-security/reference-implementation.md @@ -0,0 +1,22 @@ +# Reference Implementation + +> Reference implementations are standard, and guidelines as applied on the Mojaloop standard API. The target audience is architects, DevOps teams, security engineering, QA teams and Developers. + + +## 1. Architectural Implementations +- 1. [Signature Standard](https://docs.mojaloop.io/mojaloop-specification/documents/Signature.html) +- 2. [Encryption Standard](https://docs.mojaloop.io/mojaloop-specification/documents/Encryption.html) +- 3. [Interledger Cryptographic interlock](https://docs.mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html#4-interledger-protocol) +- 4. [Secure PISP Account Linking](https://github.com/mojaloop/pisp/tree/master/docs/linking) +- 5. [Certificate Management (MCM)](https://github.com/modusbox/connection-manager-api) + +## 2. Code level security measures +- 1. Open Source Vulnerability Management + - i. [`npm`](https://github.com/modusbox/connection-manager-api) + `npm-audit-resolver` + - ii. [GitHub/Dependabot](https://github.blog/2020-06-01-keep-all-your-packages-up-to-date-with-dependabot/) +- 2. Open Source License Management - NPM Audit, [license-scanner](https://github.com/mojaloop/license-scanner) +- 3. Static Code Analysis – SonarQube _in progress, details coming soon_ +- 4. Container Security + - i. [Anchore-cli](https://github.com/mojaloop/ci-config#container-scanning) + + \ No newline at end of file diff --git a/code_quality_security/snyk_investigation.md b/legacy/quality-security/snyk_investigation.md similarity index 100% rename from code_quality_security/snyk_investigation.md rename to legacy/quality-security/snyk_investigation.md diff --git a/legacy/quality-security/standards-guidelines/audit_logging_standard.md b/legacy/quality-security/standards-guidelines/audit_logging_standard.md new file mode 100644 index 000000000..6f166062f --- /dev/null +++ b/legacy/quality-security/standards-guidelines/audit_logging_standard.md @@ -0,0 +1,71 @@ +# Audit Logging Standard + +| | | +|---|---| +|version| `v1.0`| + + +In order for audit logs to be useful, they must record sufficient information to serve the operational needs, preserve accountability, and detect malicious activity. This standard defines these events and content recommended to be captured in a Mojaloop implementation. Running applications and infrastructure components will produce audit records for at least the following events: +1. System start-up and shutdown +2. User logon and logoff +3. Privilege escalation +4. Account creation +5. Password changes + +Information systems should produce audit records for the following event types, depending on system capabilities: +1. Starting and stopping of processes and services / applications or APIs +2. Addition of modules / libraries to an application +3. Installation of patches and updates +4. Compiling of code within the environment +5. Initialization of a new pod or container within a cluster +6. Installation and removal of software +7. System alerts and error messages +8. System administration activities across applications and infrastructure +9. Access (as well as attempts to access) to and modification of Restricted Data + + +Audit logs create records that help you track access to the Mojaloop environment. Therefore, a complete audit log needs to include, at a minimum all or a combination of: +- Capture CRUD actions in systems and databases and operational use cases. This will ensure all actions that result in Creation, Read, Update and Delete actions are captured with relevant details as below. +- Record / Artifact ID +- Audit log ID and sequence number (tracking sequence of Audit logs ensures we can detect audit log deletion) +- Event type, status, and/or error codes +- Service/command/application name +- User or system account associated with an event +- Device used (e.g. source and destination IPs, terminal session ID, web browser, etc.) +- User IDs +- Date and time records for when Users log on and off the system +- Terminal ID +- Access to systems, applications, and data – whether successful or not +- Files accessed +- Networks access +- System configuration changes +- System utility usage +- Exceptions +- Security-related events such as triggered alarms +- Protection system notifications (i.e. intrusion detection or anti-malware notifications) +- Source and destination IP addresses + + +## Importance of Audit Logs + +Audit logging provides a historical account of all activities done by actors within a Mojaloop ecosystem. It will help Mojaloop implementations in the following ways: + +1. **Threat Detection Analytics** – Through audit logs it is possible for Mojaloop switch operators to track changes and detect possible anomalies and identify malicious actions and trigger appropriate responses. This will go a long way in mitigating against possible fraud at DFSP and switch level. +2. **Customer Forensics** – In cases of queries from DFSPs, audit logs can assist give a forensic breakdown of transaction details as well as actions by authorized switch actors. +3. **Compliance** – Compliance standards such as GDPR have requirements to extract “all” customer data and also “delete” all customer data. For this to be possible, the audit data may also need to be extracted and preserved/deleted as appropriate. Audit logs are a critical requirement in most global best practice standards and regulatory frameworks such as PCI-DSS and GDPR. + + +## Recommended logging standards + +| Item | Description | +| ---- | ----------- | +| **Ensure audit logs are in a format that is
    useful for human interrogation as well as machine analysis.** | In order to get the most out of your logs, you need to make your logs both readable for humans and structured for machines. Use a standard structured format like JSON where applicable. | +| **Have uniform log structure across all
    applications and infrastructure** | A prerequisite for good logging is to have a standard structure of your log file, which would be consistent across all log files.
    Each log line should represent one single event and contain at least the timestamp, the hostname, the service and the logger name. | +| **Develop metrics for your logs** | The common metric types are:

    Meter – measures the rate of events (e.g. rate of visitors to your website)
    Timer – measures the time some procedure takes (e.g. your webserver response time)
    Counter – increment and decrement an integer value (e.g. number of signed-in users)
    Gauge – measure an arbitrary value (e.g. CPU)

    track and log metrics, or alternatively store metrics separately from your logs. | +| **Provide adequate context in log entries** | Each log line should contain enough information to make it easy to understand exactly what was going on, and what the state of the application was during that time. | +| **Use an appropriate logging framework** | Logging frameworks enable you to set up different appenders, each with its output formats and its custom log pattern. Popular logging frameworks are log4j and log4net among others. | +| **Log security audit logs as well as application
    uptime event logs** | Application Event Log – This logging most often has to do with program level events, such as administrative actions and abnormal related events that technical staff use for debugging software problems. This identifies system problems before they are big enough to cause harm, such as system outages or failures, which can hinder productivity.

    Application Audit Log – Audit logs capture events which can show “who” did “what” activity and “how” the system behaved. These logs most often refers to user level transactions, such as a change to a financial record that was made by ‘Allan Smith’ at ‘21:00HRS’ on ‘May 12, 2019.’ | +| **Do not log sensitive information** | Ensure application logs do not contain sensitive information such as passwords, PII data and any information that may aid an attacker to gain further access to a network / application as much as possible.

    Lower exposure by not logging sensitive data or by scrubbing it before it is transmitted. | +| **Use fault tolerant protocols to transmit audit logs** | TCP or RELP (Reliable Event Logging Protocol) can be used to transmit logs instead of UDP, which can lose packets. Automatically retry if sending fails.| +| **Set up audit log access controls** | Set up adequate controls to restrict who can access, query, and administer audit log servers. This can be handled by third party tools that integrate with the logging server.

    NIST recommends that organizations create and maintain a secure log management infrastructure. | + diff --git a/legacy/quality-security/standards-guidelines/log_analysis_report.md b/legacy/quality-security/standards-guidelines/log_analysis_report.md new file mode 100644 index 000000000..03c558e16 --- /dev/null +++ b/legacy/quality-security/standards-guidelines/log_analysis_report.md @@ -0,0 +1,97 @@ +## Log Analysis Report – 03 Oct 2020 + +Below is a summary of the log analysis performed on Mojaloop on the 3rd Oct 2020 + +| Service | Mojaloop State | PII Data | Other Observations | +| ------- | -------------- | -------- | ------------------ | +| account-lookup | fresh-install | NONE | | +| bulk-api-adapter | fresh-install | NONE | | +| central-event-processor | fresh-install | NONE | MySQL Root password in log |s| +| central-ledger | fresh-install | NONE | MySQL root password in logs

    SQL script creating user contains password| +| central-settlement | fresh-install | NONE | | +| cl-handler-bulk-transfer-fulfil/prepare/process | fresh-install | NONE | | +| emailnotifier | fresh-install | NONE | | +| finance-portal | fresh-install | NONE | | +| finance-portal-settlement-management | fresh-install | NONE | Mysql centalledger passwor |d| +| kafka-broker | fresh-install | NONE | | +| kafka-metrics | fresh-install | NONE | | +| kafka-exporter | fresh-install | NONE | | +| ml-api-adapter | fresh-install | NONE | | +| ml-api-adapter-handler-notification| | fresh-install | NONE | | +| mongodb | fresh-install | NONE | | +| quoting-service | fresh-install | NONE | | +| sim-payeefsp-backend | fresh-install | NONE | | +| sim-payeefsp-cache | fresh-install | NONE | | +| sim-payeefsp-scheme-adapter | fresh-install | NONE | | +| sim-testfsp1-backend | fresh-install | NONE | | +| sim-testfsp1-cache | post-seeding | NONE | | +| sim-testfsp1-scheme-adapter | post-seeding | NONE | | +| account-lookup | post-seeding | YES | | +| bulk-api-adapter | post-seeding | NONE | | +| central-event-processor | post-seeding | NONE | | +| central-ledger | post-seeding | NONE | MySQL root password in logs

    SQL script creating user contains password | +| central-settlement | post-seeding | NONE | +| cl-handler-bulk-transfer-fulfil/prepare/process | post-seeding | NONE | +| emailnotifier | post-seeding | NONE | +| finance-portal-cmg-backend | post-seeding | NONE | MySQL Root password in logs
    Testkey and Testsecret
    azureclientID || +| finance-portal-cmg-frontend | post-seeding | NONE | +| finance-portal-settlement-management | post-seeding | NONE | Mysql centalledger password| +| kafka-broker | post-seeding | NONE | | +| kafka-metrics | post-seeding | NONE | | +| kafka-exporter | post-seeding | NONE | | +| ml-api-adapter | post-seeding | NONE | | +| ml-api-adapter-handler-notification | post-seeding | NONE | | +| mongodb | post-seeding | NONE | | +| quoting-service | post-seeding | NONE | | +| sim-payeefsp-backend | post-seeding | NONE | | +| sim-payeefsp-cache | post-seeding | NONE | | +| sim-payeefsp-scheme-adapter | post-seeding | NONE | | +| sim-testfsp1-backend | post-seeding | NONE | | +| sim-testfsp1-cache | post-seeding | NONE | | +| sim-testfsp1-scheme-adapter | post-seeding | NONE | | +| account-lookup-mysql-database | post-golden-path-tests | NONE | MySQL root password in logs

    SQL script creating service users contains password | +| account-lookup-mysql-logs | post-golden-path-tests | NONE | | +| account-lookup-mysql-metrics | post-golden-path-tests | NONE | | +| account-lookup-service | post-golden-path-tests | YES | | +| account-lookup-service-sidecar | post-golden-path-tests | NONE | | +| account-lookup-service-admin | post-golden-path-tests | NONE | | +| account-lookup-service-admin-sidecar | post-golden-path-tests | NONE | | +| bulk-api-adapter-handler-notification | post-golden-path-tests | NONE | | +| bulk-api-adapter | post-golden-path-tests | NONE | | +| bulk-api-adapter-service | post-golden-path-tests | NONE | | +| central-event-processor | post-golden-path-tests | NONE | | +| central-event-handler-admin-transfer | post-golden-path-tests | NONE | | +| central-event-handler-timeout | post-golden-path-tests | NONE | | +| central-event-handler-transfer-util | post-golden-path-tests | NONE | | +| central-event-handler-transfer-fulfil | post-golden-path-tests | NONE | | +| central-event-handler-transfer-get | post-golden-path-tests | NONE | | +| central-event-handler-transfer-position | post-golden-path-tests | NONE | | +| central-event-handler-transfer-prepare | post-golden-path-tests | NONE | | +| central-ledger-mysql-0-database | post-golden-path-tests | NONE | MySQL root password in logs

    SQL script creating user contains password | +| central-ledger-mysql-0-log | post-golden-path-tests | NONE | | +| central-ledger-mysql-0-metrics | post-golden-path-tests | NONE | | +| central-ledger-service | post-golden-path-tests | NONE | | +| central-settlement | post-golden-path-tests | NONE | | +| cl-handler-bulk-transfer-fulfil/prepare/process | post-golden-path-tests | NONE | | +| emailnotifier | post-golden-path-tests | NONE | | +| finance-portal-cmg-backend | post-golden-path-tests | NONE | | +| finance-portal-cmg-frontend | post-golden-path-tests | NONE | | +| finance-portal-settlement-management | post-golden-path-tests | NONE | Mysql centalledger password| +| kafka-broker | post-golden-path-tests | NONE | | +| kafka-metrics | post-golden-path-tests | NONE | | +| kafka-exporter | post-golden-path-tests | NONE | | +| ml-api-adapter | post-golden-path-tests | NONE | | +| ml-api-adapter-handler-notification | post-golden-path-tests | NONE | | +| ml-api-adapter-handler-adapter-service | post-golden-path-tests | NONE | | +| ml-api-adapter-handler-adapter-service-sidecar | post-golden-path-tests | NONE | | +| mongodb | post-golden-path-tests | NONE | | +| quoting-service | post-golden-path-tests | YES | | +| quoting-service-sidecar | post-golden-path-tests | NONE | | +| sim-payeefsp-backend | post-golden-path-tests | NONE | | +| sim-payeefsp-cache | post-golden-path-tests | NONE | | +| sim-payeefsp-scheme-adapter | post-golden-path-tests | NONE | | +| sim-payerfsp-backend | post-golden-path-tests | NONE | | +| sim-payerfsp-cache | post-golden-path-tests | NONE | | +| sim-testfsp1-backend | post-golden-path-tests | NONE | | +| sim-testfsp1-cache | post-golden-path-tests | NONE | | + diff --git a/legacy/quality-security/standards-guidelines/readme.md b/legacy/quality-security/standards-guidelines/readme.md new file mode 100644 index 000000000..2c4b9f357 --- /dev/null +++ b/legacy/quality-security/standards-guidelines/readme.md @@ -0,0 +1,32 @@ +# Standards and Guidelines + +> Standards and guidelines are basically recommended security measures and controls to be considered for implementation by the switch core team and hub operators. The target audience is architects, implementation engineers, security management and IT Ops. + +## 1. Design Principles +- 1. [Coding Standards](../contributors-guide/standards) + +## 2. Scheme Trust Architecture +- 1. [Encryption Standard](https://docs.mojaloop.io/mojaloop-specification/documents/Encryption.html) +- 2. [Signature Standard](https://docs.mojaloop.io/mojaloop-specification/documents/Signature.html) +- 3. [PKI Best Practice Standard](https://docs.mojaloop.io/mojaloop-specification/documents/PKI%20Best%20Practices.html) +- 4. [Interledger Cryptographic interlock](https://docs.mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html#4-interledger-protocol) +- 5. Cryptographic Processing Module (CPM) Designs: + - [CPM High Level Design](https://github.com/mojaloop/documentation-artifacts/blob/master/reference/cpm_high_level_design_v1.0.pdf) + - [CPM Techincal Spec](https://github.com/mojaloop/documentation-artifacts/blob/master/reference/cpm_design_technical_spec_v1.0.pdf) + - [CPM Design Framework](https://github.com/mojaloop/documentation-artifacts/blob/master/reference/cpm_design_framework_v1.0.pdf) + - [CPM Use Cases](https://github.com/mojaloop/documentation-artifacts/blob/master/reference/cpm_design_use_cases_v1.0.pdf) + +## 3. Data Protection Standards +- 1. [Secure Kafka and Zookeeper Standard](https://github.com/mojaloop/documentation-artifacts/blob/master/reference/kafka_zookeeper_security_standard_v1.0.pdf) +- 2. Secure Logging + Auditing Standard + - [Audit + Logging Standard](./audit_logging_standard.md) + - [Log Analyis Report](./log_analysis_report.md) +c) [Database Security Standard](https://github.com/mojaloop/documentation-artifacts/blob/master/reference/database_security_standard_v1.0.pdf) +## 4. Security Architectural Reviews +- 1. [Mojaloop Portals](https://github.com/mojaloop/documentation-artifacts/blob/master/reference/portal_threat_models_v1.0.pdf) +- 2. [PISP Linking and Transfer Flows](https://github.com/mojaloop/documentation-artifacts/blob/master/reference/pisp_thread_analysis_v1.0.pdf) + +## 5. Secure Network Access + +- [Standard and Recommendations](https://github.com/mojaloop/documentation-artifacts/blob/master/reference/secure_network_access_v1.0.pdf) + diff --git a/repositories/README.md b/legacy/repositories/README.md similarity index 100% rename from repositories/README.md rename to legacy/repositories/README.md diff --git a/repositories/assets/diagrams/helm/HelmChartOverview.png b/legacy/repositories/assets/diagrams/helm/HelmChartOverview.png similarity index 100% rename from repositories/assets/diagrams/helm/HelmChartOverview.png rename to legacy/repositories/assets/diagrams/helm/HelmChartOverview.png diff --git a/repositories/assets/diagrams/helm/HelmHierarchyRelationship.png b/legacy/repositories/assets/diagrams/helm/HelmHierarchyRelationship.png similarity index 100% rename from repositories/assets/diagrams/helm/HelmHierarchyRelationship.png rename to legacy/repositories/assets/diagrams/helm/HelmHierarchyRelationship.png diff --git a/repositories/assets/diagrams/helm/HelmHierarchyValues.png b/legacy/repositories/assets/diagrams/helm/HelmHierarchyValues.png similarity index 100% rename from repositories/assets/diagrams/helm/HelmHierarchyValues.png rename to legacy/repositories/assets/diagrams/helm/HelmHierarchyValues.png diff --git a/repositories/helm.md b/legacy/repositories/helm.md similarity index 100% rename from repositories/helm.md rename to legacy/repositories/helm.md diff --git a/repositories/project.md b/legacy/repositories/project.md similarity index 100% rename from repositories/project.md rename to legacy/repositories/project.md diff --git a/legacy/scripts/_build_plantuml_all.sh b/legacy/scripts/_build_plantuml_all.sh new file mode 100755 index 000000000..342d5fd2f --- /dev/null +++ b/legacy/scripts/_build_plantuml_all.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PUML_PORT=9999 +export PUML_BASE_URL=http://localhost:${PUML_PORT} + +## +# searches through repo for plantuml sources +# and exports them using `node-plantuml` +## + +trap ctrl_c INT +function ctrl_c() { + echo "exit early - stopping docker" + docker stop puml-local + exit 1 +} + +# run the docker puml server +docker run -d --rm \ + --name puml-local \ + -p ${PUML_PORT}:8080 \ + plantuml/plantuml-server:jetty-v1.2020.21 + +# note: this `find` is not optimal, but both BSD and GNU compatible +for i in $(find ${DIR}/.. -name '*.p*uml' | grep -v node_modules); do + echo "rendering .puml -> .svg for diagram diagram: $i" + + ${DIR}/_render_svg.mjs $i +done + + +docker stop puml-local \ No newline at end of file diff --git a/legacy/scripts/_build_plantuml_diff.sh b/legacy/scripts/_build_plantuml_diff.sh new file mode 100755 index 000000000..4bed4e8b1 --- /dev/null +++ b/legacy/scripts/_build_plantuml_diff.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PUML_PORT=9999 +export PUML_BASE_URL=http://localhost:${PUML_PORT} + +## +# searches through staged files for .puml/.plantuml sources +# and updates svgs them using `node-plantuml` +## + +trap ctrl_c INT +function ctrl_c() { + echo "exit early - stopping docker" + docker stop puml-local + exit 1 +} + +# run the docker puml server +docker run -d --rm \ + --name puml-local \ + -p ${PUML_PORT}:8080 \ + plantuml/plantuml-server:jetty-v1.2020.21 + +for i in $(git diff --staged --name-only `find ${DIR}/.. -name '*.p*uml'`); do + echo "rendering .puml -> .svg for diagram diagram: $i" + ${DIR}/_render_svg.mjs $1 +done + +docker stop puml-local + +git add ./**/*.svg diff --git a/legacy/scripts/_render_svg.js b/legacy/scripts/_render_svg.js new file mode 100755 index 000000000..cc0f3c2f1 --- /dev/null +++ b/legacy/scripts/_render_svg.js @@ -0,0 +1,58 @@ +#!/usr/bin/env node + + +/** + * Uses plantuml server to render a puml to svg + */ + +const fs = require('fs') +const path = require('path') +const util = require('util') +const got = require('got') +const SVGO = require('svgo') +const plantumlEncoder = require('plantuml-encoder') + +const rendererBaseUrl = process.env.PUML_BASE_URL || 'http://www.plantuml.com/plantuml' + +svgo = new SVGO({ + js2svg: { pretty: true, indent: 2 }, + plugins: [ + { removeComments: true }, + ] +}); + +async function main() { + let [_, _script, inputPath, outputPath] = process.argv + + if (!inputPath) { + console.log("usage: ./_render_svg.mjs []") + process.exit(1) + } + + // If not specified, replace .puml or .plantuml with `.svg` + if (!outputPath) { + outputPath = inputPath.replace('.puml', '.svg') + .replace('.plantuml', '.svg') + } + + const rawPumlContents = fs.readFileSync(inputPath) + const encoded = plantumlEncoder.encode(rawPumlContents.toString()) + const url = path.join(rendererBaseUrl, 'svg', encoded) + let result + try { + result = await got.get(url) + } catch (err) { + console.log('http request failed to render puml with error', err.message) + if (err.message.indexOf('Response code 403') > -1) { + console.log('Note: sometimes the public puml renderer fails when the input diagrams are too large. Try running your own renderer server with docker.') + } + process.exit(1) + } + + // Strip comments and prettify svg + // This makes sure that our .svg files are deterministic and diffable + const formatted = await svgo.optimize(result.body) + fs.writeFileSync(outputPath, formatted.data) +} + +main() \ No newline at end of file diff --git a/markdownlint.yaml b/markdownlint.yaml new file mode 100644 index 000000000..2521dcb85 --- /dev/null +++ b/markdownlint.yaml @@ -0,0 +1,14 @@ +# Default state for all rules +default: true + +# https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md013---line-length +MD013: false + +# https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md024---multiple-headings-with-the-same-content +MD024: false + +# https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md033---inline-html +MD033: false + +# https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md034---bare-url-used +MD034: false diff --git a/mojaloop-roadmap.md b/mojaloop-roadmap.md deleted file mode 100644 index 87c32a1e2..000000000 --- a/mojaloop-roadmap.md +++ /dev/null @@ -1,244 +0,0 @@ -# Mojaloop Roadmap - -## Mojaloop Roadmap - -### Functional Epics - -* Event Logging Framework: Support operational reporting and auditing of processing -* Error Handling Framework: Consistent reporting in line with specification and support operational auditing -* API Gateway: Provide role, policy-based access, security, abstraction, throttling & control, identity management -* Endpoints for P2P, Merchant: Provide endpoints to support P2P and Merchant payments -* Settlements: Complete settlements process to handle failures and reconciliation positions -* Central directory/Account lookup service: Provide native implementation for ALS to confirm the API specification to provide user lookup -* Fraud & Risk Management System: Provide support for a fraud and risk management system -* Forensic Logging: Support forensic logging to support auditing and reporting -* Reporting API: Provide an API for reporting - -### Operational Epics - -* Testing Framework: Provide a framework for automated regression, functional and other testing to ensure quality -* Performance Improvements: Provide a framework for automated regression, functional and other testing to ensure quality -* ELK framework & logging: Provide framework or dashboards for Operational support, Debugging and Resolving issues -* DevOps: Provide flexibility, dynamism in deployments, improve monitoring and reliability mechanisms -* Rules Engine: Provide a framework to enforce, implement Business, Scheme rules - -### Non-Functional Epics - -* Deprecate Postgres: Avoid usage of multiple databases to improve supportability and maintenance and move to MySQL -* Security & Threat Modeling: Address security vulnerabilities, issues and provide a report on status of the System's security so that they can be addressed -* Documentation: Update documentation to support adoption by community, for labs, deployment by various partners -* API-Led Design: Refactor central services so that schema validation, paths can be addressed thoroughly \(automatically\) and decrease maintenance, development effort \(for those services don't already follow this\) -* API-led connectivity is a methodical way to connect data to applications through reusable and purposeful APIs. - -### Detailed Roadmap Items - \(Exported from StoriesOnBoard\) - -| Activity | Task | Subtask | Subtask description | Status | Estimation | Release | Personas | -| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | -| High Level Topics - Blue, Epics - Yellow, Releases - Orange. Stories - Green. | Designs/Whitepapers - Pink . Workshops - purple. Not in Scope / needs clarity - Gray | ? A third release with focus on Security, Auditing, Operational readiness | Includes features/functionality missing from PI5 and PI6 | Todo | | | Useful Resources | -| High Level Topics - Blue, Epics - Yellow, Releases - Orange. Stories - Green. | Designs/Whitepapers - Pink . Workshops - purple. Not in Scope / needs clarity - Gray | Release 5.0.0 - First version after the MVP with critical bug fixes and key features | First version after the MVP with critical bug fixes and features focusing on functionality needed with inputs from early adopters | Todo | | PI-5 | Useful Resources | -| High Level Topics - Blue, Epics - Yellow, Releases - Orange. Stories - Green. | Designs/Whitepapers - Pink . Workshops - purple. Not in Scope / needs clarity - Gray | Release 6.0.0 - A second release after the MVP with key features, streamlined deployment, on-boarding and monitoring capabilities | | Todo | | PI-6 | Useful Resources | -| NFR: DFSP Handler Provisioning | The Switch system scales when on-boarding FSPs | Design provisioning & management of FSP onboarding | Description: End state: | Ready | | PI-5 | Hub Tech Ops Hub Operator DFSP System Integrators DFSP | -| NFR: DFSP Handler Provisioning | The Switch system scales when on-boarding FSPs | Identify Approaches & Technologies for Management & Balancing of FSPs PoC | | Ready | | PI-5 | Hub Tech Ops Hub Operator DFSP System Integrators DFSP | -| NFR: DFSP Handler Provisioning | The Switch system scales when on-boarding FSPs | PoC for Management & Balancing of FSPs on Test Handlers to determine the best approach | | Ready | | PI-5 | Hub Tech Ops Hub Operator DFSP System Integrators DFSP | -| NFR: DFSP Handler Provisioning | The Switch system scales when on-boarding FSPs | Assess Performance capabilities, impact of the PoC | | Todo | | PI-5 | Hub Tech Ops Hub Operator DFSP System Integrators DFSP | -| NFR: DFSP Handler Provisioning | The Switch system scales when on-boarding FSPs | Management & Balancing of FSPs for High-Availability and On-boarding for non-FSP Specific Handlers | | Ready | | PI-6 | Hub Tech Ops Hub Operator DFSP System Integrators DFSP | -| NFR: DFSP Handler Provisioning | The Switch system scales when on-boarding FSPs | Management & Balancing of FSPs for High-Availability and On-boarding for FSP Specific Handlers | | Ready | | PI-6 | Hub Tech Ops Hub Operator DFSP System Integrators DFSP | -| NFR: DFSP Handler Provisioning | The Switch system scales when on-boarding FSPs | QA, testing - validation | | Ready | | PI-6 | Hub Tech Ops Hub Operator DFSP System Integrators DFSP | -| NFR: API Gateway | Gateway, Developer Portal | Access control policies | | Todo | | | Switch DFSP DFSP System Integrators Hub Customer Care Hub Operator Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: API Gateway | Gateway, Developer Portal | Apply validation controls at the API Gateway level | | Todo | | | Switch DFSP DFSP System Integrators Hub Customer Care Hub Operator Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: API Gateway | Gateway, Developer Portal | Confirm the technology for API Gateway, Developer Portal | Confirm that WSO2 is the way to go or if there's a better alternative \(better suited for Open Source\) | Todo | | PI-5 | Switch DFSP DFSP System Integrators Hub Customer Care Hub Operator Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: API Gateway | Gateway, Developer Portal | Design solution with WSO2 API Gateway | **Security**: 1. Inbound rules 1. Outbound rules 1. Headers validation 1. Throttling | Todo | | PI-5 | Switch DFSP DFSP System Integrators Hub Customer Care Hub Operator Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: API Gateway | Gateway, Developer Portal | Setup API Gateway using WSO2 - Infrastructure | | Ready | | PI-5 | Switch DFSP DFSP System Integrators Hub Customer Care Hub Operator Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: API Gateway | Gateway, Developer Portal | Integration with Switch services \(ml-api-adapter\) | | Ready | | PI-5 | Switch DFSP DFSP System Integrators Hub Customer Care Hub Operator Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: API Gateway | Gateway, Developer Portal | Provide Authentication | | Todo | | PI-6 | Switch DFSP DFSP System Integrators Hub Customer Care Hub Operator Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: API Gateway | Gateway, Developer Portal | Developer Portal \(FSPs, Hub Operator\) | | Ready | | PI-6 | Switch DFSP DFSP System Integrators Hub Customer Care Hub Operator Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: API Gateway | Gateway, Developer Portal | Developer on-boarding | | Todo | | PI-6 | Switch DFSP DFSP System Integrators Hub Customer Care Hub Operator Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: API Gateway | Gateway, Developer Portal | QA, Testing | | Todo | | PI-6 | Switch DFSP DFSP System Integrators Hub Customer Care Hub Operator Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: DevOps, CI/CD | Deployment automation and Lab work | Making existing helm charts more maintainable & manageable | | Ready | | PI-5 | Switch Hub Tech Ops Hub Customer Care | -| NFR: DevOps, CI/CD | Deployment automation and Lab work | Automate Lab Setup - chooses services \(things like Gateway, etc\) | Possibly using something like Terraform, Vagrant | Todo | | PI-6 | Switch Hub Tech Ops Hub Customer Care | -| NFR: DevOps, CI/CD | Deployment automation and Lab work | Validate Lab envt setup using a test framework | | Todo | | PI-6 | Switch Hub Tech Ops Hub Customer Care | -| NFR: DevOps, CI/CD | API Gateway is incorporated into the CI/CD pipeline & deployments are automated | Incorporating the API Gateway into the deployment process | | Todo | | PI-5 | Switch Hub Tech Ops Hub Customer Care | -| NFR: DevOps, CI/CD | API Gateway is incorporated into the CI/CD pipeline & deployments are automated | Incorporating the API Gateway into the CI/CD pipeline | | Todo | | PI-5 | Switch Hub Tech Ops Hub Customer Care | -| NFR: DevOps, CI/CD | API Gateway is incorporated into the CI/CD pipeline & deployments are automated | Automate deployment of artifacts as part of CI/CD pipeline | Currently the artifacts are published to dockerhub/npm repos based on the outcome of the testing phases but the deployment fails as quite a bit of automation is needed. This involves updating helm charts dynamically, values files and other such resources. This would tremendously reduce the amount of time involved in getting out a deployment after a release. Currently we do the deployment manually \(which is not that bad\) but this can be eliminated. | Ready | | PI-6 | Switch Hub Tech Ops Hub Customer Care | -| NFR: DevOps, CI/CD | API Gateway is incorporated into the CI/CD pipeline & deployments are automated | Integrate Contract, Interface and Functional Tests in CI/CD Pipeline | | Ready | | PI-6 | Switch Hub Tech Ops Hub Customer Care | -| NFR: DevOps, CI/CD | Monitoring, Management of resources | Enable health checks to report holistically | | Ready | | PI-5 | Switch Hub Tech Ops Hub Customer Care | -| NFR: DevOps, CI/CD | Monitoring, Management of resources | Support for Zipkin | | Todo | | PI-5 | Switch Hub Tech Ops Hub Customer Care | -| NFR: DevOps, CI/CD | Monitoring, Management of resources | ELK: Support for Alerts, Notifications | | Ready | | PI-6 | Switch Hub Tech Ops Hub Customer Care | -| NFR: DevOps, CI/CD | Monitoring, Management of resources | Integrating ELK with Event Logging Framework, etc | | Ready | | PI-6 | Switch Hub Tech Ops Hub Customer Care | -| NFR: DevOps, CI/CD | Monitoring, Management of resources | ELK Dashboards for KPIs, etc | | Ready | | PI-6 | Switch Hub Tech Ops Hub Customer Care | -| NFR: Quality Assurance, Testing | Testing, QA | Standardized simulator \(mock FSPs\) to support automated testing | 1. Simulators that dynamically generate conditions, fulfilments etc as part of the end-to-end proccess 1. Include error end-points \(addressed in another item\) 1. Perform validations 1. Rework the simulator to generate the end-points based on the Swagger \(to easily validate\): API first approach | Ready | | PI-5 | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: Quality Assurance, Testing | Testing, QA | Automated Functional Tests - document coverage | | Ready | | PI-5 | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: Quality Assurance, Testing | Testing, QA | Periodic comprehensive functional testing on deployments | | Todo | | PI-5 | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: Quality Assurance, Testing | Testing, QA | Automated Integration Tests | | Ready | | PI-6 | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: Quality Assurance, Testing | Testing, QA | Automated Contract Tests | Contract - meaning the API Specification itself. Automated tests to ensure the Switch adheres to the API/Swagger specification, example, headers, schema, etc This ensures the users of the System that the implementation conforms to the API Specification. | Ready | | PI-6 | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: Quality Assurance, Testing | Testing, QA | Update Automated Contract, Integration, Functional Tests | | Ready | | PI-6 | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: Quality Assurance, Testing | QA, Bug Fixes | QA, Bug Fixes | | Ready | | | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: Quality Assurance, Testing | QA, Bug Fixes | Bug Fixes, QA | | Ready | | PI-5 | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: Quality Assurance, Testing | QA, Bug Fixes | QA, Bug Fixes | | Ready | | PI-6 | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: Quality Assurance, Testing | Performance Testing, Baselining | Performance testing & Improvements | | Ready | | | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: Quality Assurance, Testing | Performance Testing, Baselining | Performance testing baselining after addition of new features, frameworks | Towards the end of the PI/Sprint | Ready | | PI-5 | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: Quality Assurance, Testing | Performance Testing, Baselining | Automated Performance Tests | | Ready | | PI-6 | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| NFR: Quality Assurance, Testing | Performance Testing, Baselining | Regular Performance testing as part of CI/CD | | Ready | | PI-6 | Switch BMGF Hub Tech Ops Hub Security, Risk and Compliance Team | -| FR: Settlement Management | Settlements Management | Enhance Alerts and Notifications | | Ready | | PI-5 | DFSP Switch Hub Operator Hub Finance Team | -| FR: Settlement Management | Settlements Management | Follow-up items to be confirmed after the OSS Settlements API is drafted | | Todo | | PI-5 | DFSP Switch Hub Operator Hub Finance Team | -| FR: Settlement Management | Settlements Management | Handle failed acknowledgements for Settlements | | Ready | 8.00 | PI-6 | DFSP Switch Hub Operator Hub Finance Team | -| FR: Settlement Management | Settlements Management | Settlement Reconciliation Reports | | Ready | | PI-6 | DFSP Switch Hub Operator Hub Finance Team | -| FR: Settlement Management | Reporting API for FSP Consumption | Identification of Framework for reporting | | Todo | | PI-5 | DFSP Switch Hub Operator Hub Finance Team | -| FR: Settlement Management | Reporting API for FSP Consumption | Identify data sets that can be queried - Transactions | | Ready | | PI-5 | DFSP Switch Hub Operator Hub Finance Team | -| FR: Settlement Management | Reporting API for FSP Consumption | Settlements reporting format decisions | | Todo | | PI-5 | DFSP Switch Hub Operator Hub Finance Team | -| FR: Settlement Management | Reporting API for FSP Consumption | Identify data sets that can be queried - Transfers | | Ready | | PI-6 | DFSP Switch Hub Operator Hub Finance Team | -| FR: Settlement Management | Reporting API for FSP Consumption | Standardize query API | | Ready | | PI-6 | DFSP Switch Hub Operator Hub Finance Team | -| FR: Settlement Management | Reporting API for FSP Consumption | Implementation of reporting functionality | | Todo | | PI-6 | DFSP Switch Hub Operator Hub Finance Team | -| FR: Settlement Management | Reporting API for FSP Consumption | QA, testing | | Todo | | PI-6 | DFSP Switch Hub Operator Hub Finance Team | -| NFR: Implementation Topology Guidelines | Deployment Topology Guidelines | Scaling guidelines for deployment | | Todo | | | Switch DFSP System Integrators Hub Tech Ops | -| NFR: Implementation Topology Guidelines | Deployment Topology Guidelines | Guidelines for optimal performance | | Todo | | | Switch DFSP System Integrators Hub Tech Ops | -| NFR: Implementation Topology Guidelines | Deployment Topology Guidelines | HA guidelines for deployment | | Todo | | | Switch DFSP System Integrators Hub Tech Ops | -| NFR: Implementation Topology Guidelines | Deployment Topology Guidelines | Recommended deployment topologies | | Todo | | PI-5 | Switch DFSP System Integrators Hub Tech Ops | -| NFR: Implementation Topology Guidelines | Deployment Topology Guidelines | Security guidelines for implementation, deployment | | Todo | | PI-5 | Switch DFSP System Integrators Hub Tech Ops | -| NFR: Implementation Topology Guidelines | Deployment Topology Guidelines | Documentation - clarity, remove ambiguity. Review | | Todo | | PI-5 | Switch DFSP System Integrators Hub Tech Ops | -| NFR: Implementation Topology Guidelines | Deployment Topology Guidelines | Guidelines for cloud/on-prem providers | | Todo | | PI-6 | Switch DFSP System Integrators Hub Tech Ops | -| NFR: Implementation Topology Guidelines | Workshops | Workshops for Hub Operators | | Todo | | PI-5 | Switch DFSP System Integrators Hub Tech Ops | -| NFR: Implementation Topology Guidelines | Workshops | Workshops for OSS contributors | | Todo | | PI-5 | Switch DFSP System Integrators Hub Tech Ops | -| NFR: Implementation Topology Guidelines | Workshops | Workshops for FSP and System Integrators | | Todo | | PI-6 | Switch DFSP System Integrators Hub Tech Ops | -| NFR: Implementation Topology Guidelines | Workshops | Workshops for OSS contributors - 2 | | Todo | | PI-6 | Switch DFSP System Integrators Hub Tech Ops | -| NFR: Implementation Topology Guidelines | Workshops | Workshops for Hub Operators - 2 | | Todo | | PI-6 | Switch DFSP System Integrators Hub Tech Ops | -| NFR: Event Logging | Event Logging Framework | Central processing of events and raising alerts/alarms/errors | Extend existing functionality **Interesting Events that need to be produced/captured**: 1. Up/down events for services, 1. Threshold on number of occurrences 1. Dashboards - Thresholds - CPU utilization, Disk space, configurable 1. Error events in services 1. Infrastructure events \(Up/Down\). 1. Connectivity events \(Connect/Disconnect\) 1. General service events \(started, halted, etc\) 1. Mojaloop errors based on the specification **Business**: 1. Thresholds 1. Limits \(NDC\) 1. Position events 1. Settlement events \(settling, window closure, etc\) **Things to take care of**: 1. Mode of notifications 1. Separation of Technical and Commercial/Financial/Business related information - access to logs to be restricted From Ops 1. Duration of persistence of logs, etc \(especially commercial/business data\) - comply with guidelines/ standards. 1. HA events and assess reliability - How do we measure the uptime of the system and availability | Todo | | | Switch Hub Tech Ops Hub Customer Care Hub Security, Risk and Compliance Team Hub Operator | -| NFR: Event Logging | Event Logging Framework | Recommended usage of the alerting system | | Todo | | | Switch Hub Tech Ops Hub Customer Care Hub Security, Risk and Compliance Team Hub Operator | -| NFR: Event Logging | Event Logging Framework | Design event logging Framework | Framework for producing & capturing Event logs that can be used for monitoring **Interesting Events that need to be produced/captured**: - Up/down events for services, - Threshold on number of occurrences - Dashboards - Thresholds - CPU utilization, Disk space, configurable - Error events in services - Infrastructure events \(Up/Down\). - Connectivity events \(Connect/Disconnect\) - General service events \(started, halted, etc\) - Mojaloop errors based on the specification **Business**: - Thresholds - Limits \(NDC\) - Position events - Settlement events \(settling, window closure, etc\) **Things to take care of**: - Mode of notifications - Separation of Technical and Commercial/Financial/Business related information - access to logs to be restricted From Ops - Duration of persistence of logs, etc \(especially commercial/business data\) - comply with guidelines/ standards. - HA events and assess reliability - How do we measure the uptime of the system and availability | Todo | | PI-6 | Switch Hub Tech Ops Hub Customer Care Hub Security, Risk and Compliance Team Hub Operator | -| NFR: Event Logging | Event Logging Framework | Implement Common Library for events | | Ready | 15.00 | PI-6 | Switch Hub Tech Ops Hub Customer Care Hub Security, Risk and Compliance Team Hub Operator | -| NFR: Event Logging | Event Logging Framework | Implementation for producing & capturing Event logs that can be used for monitoring | Framework for producing & capturing Event logs that can be used for monitoring **Interesting Events that need to be produced/captured**: 1. Up/down events for services, 1. Threshold on number of occurrences 1. Dashboards - Thresholds - CPU utilization, Disk space, configurable 1. Error events in services 1. Infrastructure events \(Up/Down\). 1. Connectivity events \(Connect/Disconnect\) 1. General service events \(started, halted, etc\) 1. Mojaloop errors based on the specification **Business**: 1. Thresholds 1. Limits \(NDC\) 1. Position events 1. Settlement events \(settling, window closure, etc\) **Things to take care of**: 1. Mode of notifications 1. Separation of Technical and Commercial/Financial/Business related information - access to logs to be restricted From Ops 1. Duration of persistence of logs, etc \(especially commercial/business data\) - comply with guidelines/ standards. 1. HA events and assess reliability - How do we measure the uptime of the system and availability | Ready | 8.00 | PI-6 | Switch Hub Tech Ops Hub Customer Care Hub Security, Risk and Compliance Team Hub Operator | -| NFR: Event Logging | Event Logging Framework | Testing the common library, framework for producing, capturing events | | Todo | | PI-6 | Switch Hub Tech Ops Hub Customer Care Hub Security, Risk and Compliance Team Hub Operator | -| NFR: Event Logging | Dashboards for Monitoring | Logging standards, implement & standardize | | Ready | | PI-5 | Switch Hub Tech Ops Hub Customer Care Hub Security, Risk and Compliance Team Hub Operator | -| NFR: Event Logging | Dashboards for Monitoring | Changes to logging to enhance traceability | | Ready | | PI-5 | Switch Hub Tech Ops Hub Customer Care Hub Security, Risk and Compliance Team Hub Operator | -| NFR: Event Logging | Dashboards for Monitoring | Design and identify dashboards needed for monitoring | | Todo | | PI-5 | Switch Hub Tech Ops Hub Customer Care Hub Security, Risk and Compliance Team Hub Operator | -| NFR: Event Logging | Dashboards for Monitoring | Operational Dashboards for monitoring specific events end-to-end | | Todo | | PI-6 | Switch Hub Tech Ops Hub Customer Care Hub Security, Risk and Compliance Team Hub Operator | -| NFR: Event Logging | Dashboards for Monitoring | Operational Dashboards for monitoring alerts/alarms/errors | | Todo | | PI-6 | Switch Hub Tech Ops Hub Customer Care Hub Security, Risk and Compliance Team Hub Operator | -| NFR: Event Logging | Dashboards for Monitoring | Testing various dashboards | | Todo | | PI-6 | Switch Hub Tech Ops Hub Customer Care Hub Security, Risk and Compliance Team Hub Operator | -| NFR: Error Handling | Implementing error endpoints | Design solution for supporting error endpoints for transfers | | Todo | | PI-5 | Hub Tech Ops Switch DFSP DFSP System Integrators Hub Customer Care | -| NFR: Error Handling | Implementing error endpoints | Implement support for error endpoints for transfers | | Todo | | PI-5 | Hub Tech Ops Switch DFSP DFSP System Integrators Hub Customer Care | -| NFR: Error Handling | Implementing error endpoints | Updating simulators to support error endpoints | | Todo | | PI-5 | Hub Tech Ops Switch DFSP DFSP System Integrators Hub Customer Care | -| NFR: Error Handling | Implementing error endpoints | Support for endpoints for other resources | | Todo | | PI-5 | Hub Tech Ops Switch DFSP DFSP System Integrators Hub Customer Care | -| NFR: Error Handling | Implementing error endpoints | Enhance notification mechanism to handle notification issues, perform retries | Retries according to configuration that can be set | Todo | | PI-6 | Hub Tech Ops Switch DFSP DFSP System Integrators Hub Customer Care | -| NFR: Error Handling | Error Handling Framework | Publish an event to be consumed by the event framework | | Ready | | | Hub Tech Ops Switch DFSP DFSP System Integrators Hub Customer Care | -| NFR: Error Handling | Error Handling Framework | Design an error handling framework for a standardized way of returning results of execution | | Todo | | PI-5 | Hub Tech Ops Switch DFSP DFSP System Integrators Hub Customer Care | -| NFR: Error Handling | Error Handling Framework | Design error mapping for the error handling framework | | Todo | | PI-6 | Hub Tech Ops Switch DFSP DFSP System Integrators Hub Customer Care | -| NFR: Error Handling | Error Handling Framework | Common library for error framework | | Ready | | PI-6 | Hub Tech Ops Switch DFSP DFSP System Integrators Hub Customer Care | -| NFR: Error Handling | Error Handling Framework | Implement the error handling framework | | Ready | | PI-6 | Hub Tech Ops Switch DFSP DFSP System Integrators Hub Customer Care | -| FR: Bulk Payments | Bulk Payments Design | Design for Bulk Payments: version - 1, based on the ML Spec | | Ready | | PI-5 | DFSP Switch DFSP System Integrators Identity Oracles | -| FR: Bulk Payments | Bulk Payments Design | Design for Bulk Payments: version - 2 | | Ready | | PI-5 | DFSP Switch DFSP System Integrators Identity Oracles | -| FR: Bulk Payments | Bulk Payments Design | Finalize design for Bulk Payments | | Todo | | PI-6 | DFSP Switch DFSP System Integrators Identity Oracles | -| FR: Bulk Payments | Bulk Payments Implementation | Implementing resources: bulkTransfers | | Todo | | | DFSP Switch DFSP System Integrators Identity Oracles | -| FR: Bulk Payments | Bulk Payments Implementation | Bulk payments error handling | | Todo | | | DFSP Switch DFSP System Integrators Identity Oracles | -| FR: Bulk Payments | Bulk Payments Implementation | Testing Bulk Payments | | Todo | | | DFSP Switch DFSP System Integrators Identity Oracles | -| FR: Bulk Payments | Bulk Payments Implementation | Implementing resources for bulk look-up, etc | | Todo | | PI-5 | DFSP Switch DFSP System Integrators Identity Oracles | -| FR: Bulk Payments | Bulk Payments Implementation | Implementing resources: bulkQuotes | | Todo | | PI-6 | DFSP Switch DFSP System Integrators Identity Oracles | -| FR: Bulk Payments | Bulk Payments Implementation | Implementing resources: bulkTransfers - PoC | | Ready | | PI-6 | DFSP Switch DFSP System Integrators Identity Oracles | -| FR: Forensic Logging | Forensic Logging | Migrate central-kms from scala to node and associated DB to the selected type | | Ready | | | DFSP Hub Security, Risk and Compliance Team Hub Tech Ops | -| FR: Forensic Logging | Forensic Logging | Revisit/review Forensic Logging Architecture | | Ready | | PI-5 | DFSP Hub Security, Risk and Compliance Team Hub Tech Ops | -| FR: Forensic Logging | Forensic Logging | Migrate from postgres to selected persistent store \(mysql/kafka\) | | Ready | | PI-5 | DFSP Hub Security, Risk and Compliance Team Hub Tech Ops | -| FR: Forensic Logging | Forensic Logging | Sidecars to periodically validate the connected services | | Todo | | PI-6 | DFSP Hub Security, Risk and Compliance Team Hub Tech Ops | -| FR: Forensic Logging | Forensic Logging | Ensure algorithm and encryption functionality work as expected | | Ready | | PI-6 | DFSP Hub Security, Risk and Compliance Team Hub Tech Ops | -| FR: Forensic Logging | Auditing | Define/gather auditing requirements | | Todo | | PI-5 | DFSP Hub Security, Risk and Compliance Team Hub Tech Ops | -| FR: Forensic Logging | Auditing | Implement auditing events or logging capabilities in components | | Todo | | PI-6 | DFSP Hub Security, Risk and Compliance Team Hub Tech Ops | -| FR: Forensic Logging | Auditing | Use for auditing \(test by generating reports\) | | Ready | | PI-6 | DFSP Hub Security, Risk and Compliance Team Hub Tech Ops | -| FR: Forensic Logging | Auditing | Integration with Event Handling / ELK ? | | Ready | | PI-6 | DFSP Hub Security, Risk and Compliance Team Hub Tech Ops | -| FR: Central Directory \(account lookup\) | central directory alignment to ML Spec with existing capabilities | Design solution for integration with current services | | Ready | | PI-5 | DFSP DFSP System Integrators Switch Identity Oracles | -| FR: Central Directory \(account lookup\) | central directory alignment to ML Spec with existing capabilities | Migrate code from Mowali and replace the existing legacy code | | Ready | | PI-5 | DFSP DFSP System Integrators Switch Identity Oracles | -| FR: Central Directory \(account lookup\) | central directory alignment to ML Spec with existing capabilities | QA, testing for lookup, integration with overall use cases | | Todo | | PI-5 | DFSP DFSP System Integrators Switch Identity Oracles | -| FR: Central Directory \(account lookup\) | Extend Central directory capabilities to support Merchant registries, multiple identifiers | Support for multiple identifiers? | | Todo | | | DFSP DFSP System Integrators Switch Identity Oracles | -| FR: Central Directory \(account lookup\) | Extend Central directory capabilities to support Merchant registries, multiple identifiers | Design solution for Merchant registries | - As an FSP, I want to know the FSP that a Merchant belongs to - As an FSP, I want to register a new Merchant and assign a unique TILL number - As a Merchant, I want to be able to request a DFSP to assign me a Merchant number \(design\) - As a Switch, I should maintain a record of mapping between FSPs and Merchant IDs | Todo | | PI-6 | DFSP DFSP System Integrators Switch Identity Oracles | -| FR: Central Directory \(account lookup\) | Extend Central directory capabilities to support Merchant registries, multiple identifiers | Implementing solution for Merchant payments | | Todo | | PI-6 | DFSP DFSP System Integrators Switch Identity Oracles | -| FR: Central Directory \(account lookup\) | Extend Central directory capabilities to support Merchant registries, multiple identifiers | QA, testing for lookup, integration with overall merchant use cases | | Todo | | PI-6 | DFSP DFSP System Integrators Switch Identity Oracles | -| FR: Merchant "Request to Pay" | Supporting 'Merchant request to pay' | Design solution and identify pre-requisites for Merchant payments | | Todo | | PI-5 | DFSP Switch DFSP System Integrators | -| FR: Merchant "Request to Pay" | Supporting 'Merchant request to pay' | Implement Resources: transactionRequests, authorizations | | Ready | | PI-5 | DFSP Switch DFSP System Integrators | -| FR: Merchant "Request to Pay" | Supporting 'Merchant request to pay' | Implement error endpoints and related functionality | | Todo | | PI-5 | DFSP Switch DFSP System Integrators | -| FR: Merchant "Request to Pay" | Supporting 'Merchant request to pay' | 'Merchant request to pay' is supported, released | | Todo | | PI-5 | DFSP Switch DFSP System Integrators | -| FR: Merchant "Request to Pay" | Supporting 'Merchant request to pay' | QA, testing on the feature | | Todo | | PI-6 | DFSP Switch DFSP System Integrators | -| NFR \(new\): Community Support | Supporting community regarding deployment, Mojaloop Specification | Update documentation to support community | | Todo | | PI-5 | BMGF DFSP Useful Resources Hub Operator Hub Customer Care DFSP System Integrators | -| NFR \(new\): Community Support | Supporting community regarding deployment, Mojaloop Specification | Provide support to community requests on deployment | | Todo | | PI-5 | BMGF DFSP Useful Resources Hub Operator Hub Customer Care DFSP System Integrators | -| NFR \(new\): Community Support | Supporting community regarding deployment, Mojaloop Specification | Provide support to community requests regarding the Spec | | Todo | | PI-5 | BMGF DFSP Useful Resources Hub Operator Hub Customer Care DFSP System Integrators | -| NFR \(new\): Community Support | Supporting community regarding deployment, Mojaloop Specification | Provide an FAQ/Wiki section for deployment and Spec questions | | Todo | | PI-6 | BMGF DFSP Useful Resources Hub Operator Hub Customer Care DFSP System Integrators | -| Others \(not covered\) / Hardening \(Cleanup, Refactoring, etc\) | Formalizing the Operations/Admin API | Formalize the Admin/operations API | | Ready | | PI-5 | | -| Others \(not covered\) / Hardening \(Cleanup, Refactoring, etc\) | Formalizing the Operations/Admin API | Provide features to manage FSPs | | Ready | | PI-6 | | -| Others \(not covered\) / Hardening \(Cleanup, Refactoring, etc\) | Formalizing the Operations/Admin API | central hub with UI ? | | Ready | | PI-6 | | -| Others \(not covered\) / Hardening \(Cleanup, Refactoring, etc\) | FRMS | Investigate capabilities & features needed | | Ready | | PI-6 | | -| Others \(not covered\) / Hardening \(Cleanup, Refactoring, etc\) | FRMS | Prioritizing Rules/Policies to implement | | Ready | | PI-6 | | -| Others \(not covered\) / Hardening \(Cleanup, Refactoring, etc\) | Refactoring: API Led Design, Implementation for central services | Designing all central services to support API Led Design | | Ready | | PI-5 | | -| Others \(not covered\) / Hardening \(Cleanup, Refactoring, etc\) | Refactoring: API Led Design, Implementation for central services | Refactoring for ml-api-adapter | | Ready | | PI-6 | | -| Others \(not covered\) / Hardening \(Cleanup, Refactoring, etc\) | Refactoring: API Led Design, Implementation for central services | Refactoring for central services | | Ready | | PI-6 | | -| Security | | | | | | | Hub Security, Risk and Compliance Team DFSP Switch | -| Cross currency | Account Lookup Service | Change in Currency | ALS naming convention for routing - if moving from MSISDN only Identify currency and impact to Standard Transfers | Todo | | PI-5 | DFSP Identity Oracles Hub Finance Team | -| Cross currency | Quotation | Regulatory Data | KYC Data Need to clarify - including understanding Multi Currency What data needs to be passed - via DFSPs and through CCP How is that data passed and validated? Impact on timeouts Rules and Design | Todo | | PI-5 | DFSP Identity Oracles Hub Finance Team | -| Cross currency | Quotation | FX Rate Management | | Todo | | PI-5 | DFSP Identity Oracles Hub Finance Team | -| Cross currency | Quotation | Fees consolidation | How are fees passed along the chain? Not already in the quote Is there a need for transparency? If not how and where are all the fees calculated and brought to common currency? | Todo | | PI-5 | DFSP Identity Oracles Hub Finance Team | -| Cross currency | Transfer | Limit Management | Velocity Rules for sender and receiver Regulatory data required to confirm | Todo | | PI-5 | DFSP Identity Oracles Hub Finance Team | -| Cross currency | Transfer | Sequencing of Position management and fund movement | As now 4 \(+\) positions affected control financial risk | Todo | | PI-5 | DFSP Identity Oracles Hub Finance Team | -| Cross currency | Transfer | Rollback | How does it work - design | Todo | | PI-5 | DFSP Identity Oracles Hub Finance Team | -| Cross currency | Transfer | Timeout | | Todo | | PI-5 | DFSP Identity Oracles Hub Finance Team | -| Cross currency | Settlement | Reporting of Transfer | Managing the trail of the hops for the CCP and regulatory for Send and Receive | Todo | | PI-5 | DFSP Identity Oracles Hub Finance Team | -| Documentation | | | | | | | BMGF DFSP Useful Resources | -| FRMS | | | | | | | Hub Security, Risk and Compliance Team DFSP | -| Lab for FSPs, deployment tools | | | | | | | BMGF | -| Cross-network payments | | | | | | | | -| Payment Hub | | | | | | | | -| | | | | | | | | -| | | | | | | | | -| | | | | | | | | -| | | | | | | | | -| | | | | | | | | -| | | | | | | | | -| | | | | | | | | -| | | | | | | | | -| | | | | | | | | - -## Beyond Phase 3 - -Below is a list of larger initiatives and epics by area that will help to further develop the Mojaloop project. Some of these have been entered as epics or stories, but most are still in the "concept" phase. - -### Functional Epics - -* Native Implementation P2P: Implementation of resources to support Payee initiated and other Use Cases from the Specification, along with supporting P2P Use case completely -* Native Implementation Payee: Implementation of resources to support Payee initiated transactions and ones that involve OTPs -* Bulk Payments: Design & Implementation of resources to support Bulk Payments - -### Central Services - -* Directory Interoperability -* Multi-currency and schemes -* Enforcing Currency configurations -* Fees: UI for configuring fees -* Increase performance -* Fraud Scores and Reasons -* Role management -* DSP Management -* Stopping/Pausing a DFSP -* boarding protocol - -### DFSP/Account Management - -* Agent Network -* NFCC identity merchant -* Persistent merchant ID -* Onboarding protocol -* Change password -* Password requirements -* Hold/Restart account - -### Security - -* Central certificate service -* Implement fee quote transfer service in the center -* Prevent user guessing from rogue DFSPs -* Preferred authorizations - -### Market Deployment - -* Integration with major mobile money vendors in Africa \(PDP initiative\) - -### CI/CD & Testing - -* Implement auto deployment to test environment -* Automatically run acceptance tests in test environment as part of build/deploy -* Automate bulk import tests -* Forensic log test -* Account management test diff --git a/mojaloop-technical-overview/README.md b/mojaloop-technical-overview/README.md deleted file mode 100644 index fb890d414..000000000 --- a/mojaloop-technical-overview/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Mojaloop Technical Overview - -## Mojaloop Services - -The basic idea behind Mojaloop is that we need to connect multiple Digital Financial Services Providers (DFSPs) together into a competitive and interoperable network in order to maximize opportunities for poor people to get access to financial services with low or no fees. We don't want a single monopoly power in control of all payments in a country, or a system that shuts out new players. It also doesn't help if there are too many isolated subnetworks. The following diagrams shows the Mojaloop interconnects between DFSPs and the Mojaloop Hub (schema implementation example) for a Peer-to-Peer (P2P) Transfer: - -Mojaloop addresses these issues in several key ways: -* A set of central services provides a hub through which money can flow from one DFSP to another. This is similar to how money moves through a central bank or clearing house in developed countries. Besides a central ledger, central services can provide identity lookup, fraud management, and enforce scheme rules. -* A standard set of interfaces a DFSP can implement to connect to the system, and example code that shows how to use the system. A DFSP that wants to connect up can adapt our example code or implement the standard interfaces into their own software. The goal is for it to be as straightforward as possible for a DFSP to connect to the interoperable network. -* Complete working open-source implementations of both sides of the interfaces - an example DFSP that can send and receive payments and the client that an existing DFSP could host to connect to the network. - -![Mojaloop End-to-end Architecture Flow PI5](./assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg) - -The Mojaloop Hub is the primary container and reference we use to describe the Mojaloop echo-system which is split in to the following domains: -* Mojaloop Open Source Services - Core Mojaloop Open Source Software (OSS) that has been supported by the Bill & Melinda Gates Foundation in partnership with the Open Source Community. -* Mojaloop Hub - Overall Mojaloop reference (and customizable) implementation for Hub Operators is based on the above OSS solution. diff --git a/mojaloop-technical-overview/account-lookup-service/README.md b/mojaloop-technical-overview/account-lookup-service/README.md deleted file mode 100644 index f69b48dba..000000000 --- a/mojaloop-technical-overview/account-lookup-service/README.md +++ /dev/null @@ -1,96 +0,0 @@ -# Account Lookup Service - -The **Account Lookup Service** (**ALS**) _(refer to section `6.2.1.2`)_ as per the [Mojaloop {{ book.importedVars.mojaloop.spec.version }} Specification]({{ book.importedVars.mojaloop.spec.uri.doc }}) implements the following use-cases: - -* Participant Look-up -* Party Look-up -* Manage Participants Registry information - * Adding Participant Registry information - * Deleting Participant Registry information - -Use-cases that have been implemented over and above for Hub Operational use: -* Admin Operations - * Manage Oracle End-point Routing information - * Manage Switch End-point Routing information - -## 1. Design Considerations - -### 1.1. Account Lookup Service (ALS) -The ALS design provides a generic Central-Service component as part of the core Mojaloop. The purpose of this component is to provide routing and alignment to the Mojaloop API Specification. This component will support multiple Look-up registries (Oracles). This ALS will provide an Admin API to configure routing/config for each of the Oracles similiar to the Central-Service API for the End-point configuration for DFSP routing by the Notification-Handler (ML-API-Adapter Component). The ALS will in all intense purpose be a switch with a persistence store for the storage/management of the routing rules/config. - -#### 1.1.1. Assumptions - -* The ALS design will only cater for a single switch for the time being. -* Support for multiple switches will utilise the same DNS resolution mechanism that is being developed for the Cross Border/Network design. - -#### 1.1.2. Routing - -The routing configuration will be based on the following: -* PartyIdType - See section `7.5.6` of the Mojaloop Specification -* Currency - See section `7.5.5` of the Mojaloop Specification. Currency code defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic string. This will be optional, however `isDefault` indicator must be set to `true` if the `Currency` is not provided. -* isDefault - Indicator that a specific Oracle is the default provider for a specific PartyIdType. Note that there can be many default Oracles, but there can only be a single Oracle default for a specific PartyIdType. The default Oracle for a specific PartyIdType will only be selected if the originating request does not include a Currency filter. - - -### 1.2. ALS Oracle -The ALS Oracle be implemented as either a **Service** or **Adapter** (semantic dependant on use - Mediation = Adapter, Service = Implementation) will provide a look-up registry component with similar functionality of the `/participants` Mojaloop API resources. It has however loosely based on the ML API specification as it's interface implements a sync pattern which reduces the correlation/persistence requirements of the Async Callback pattern implemented directly by the ML API Spec. This will provide all ALS Oracle Services/Adapters with a standard interface which will be mediated by the ALS based on its routing configuration. -This component (or back-end systems) will also be responsible for the persistence & defaulting of the Participant details. - -## 2. Participant Lookup Design - -### 2.1. Architecture overview -![Architecture Flow Account-Lookup for Participants](./assets/diagrams/architecture/arch-flow-account-lookup-participants.svg) - -_Note: The Participant Lookup use-case similarly applies to for a Payee Initiated use-case such as transactionRequests. The difference being that the Payee is the initiation in the above diagram._ - -### 2.2. Sequence diagrams - -#### 2.2.1. GET Participants - -- [Sequence Diagram for GET Participants](als-get-participants.md) - -#### 2.2.2. POST Participants - -- [Sequence Diagram for POST Participants](als-post-participants.md) - -#### 2.2.3. POST Participants (Batch) - -- [Sequence Diagram for POST Participants (Batch)](als-post-participants-batch.md) - -#### 2.2.4. DEL Participants - -- [Sequence Diagram for DEL Participants](als-del-participants.md) - -## 3. Party Lookup Design - -### 3.1. Architecture overview -![Architecture Flow Account-Lookup for Parties](./assets/diagrams/architecture/arch-flow-account-lookup-parties.svg) - -### 3.2. Sequence diagram - -#### 3.2.1. GET Parties - -- [Sequence Diagram for GET Parties](als-get-parties.md) - -## 4. Database Design - -### 4.1. ALS Database Schema - -#### Notes -- `partyIdType` - Values are currently seeded as per section _`7.5.6`_ [Mojaloop {{ book.importedVars.mojaloop.spec.version }} Specification]({{ book.importedVars.mojaloop.spec.uri.doc }}). -- `currency` - See section `7.5.5` of the Mojaloop Specification. Currency code defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic string. This will be optional, and must provide a "default" config if no Currency is either provided or provide a default if the Currency is provided, but only the "default" End-point config exists. -- `endPointType` - Type identifier for the end-point (e.g. `URL`) which provides flexibility for future transport support. -- `migration*` - Meta-data tables used by Knex Framework engine. -- A `centralSwitchEndpoint` must be associated to the `OracleEndpoint` by the Admin API upon insertion of a new `OracleEndpoint` record. If the `centralSwitchEndpoint` is not provided as part of the API Request, then it must be defaulted. - -![Acount Lookup Service ERD](./assets/entities/AccountLookupService-schema.png) - -* [Acount Lookup Service DBeaver ERD](./assets/entities/AccountLookupDB-schema-DBeaver.erd) -* [Acount Lookup Service MySQL Workbench Export](./assets/entities/AccountLookup-ddl-MySQLWorkbench.sql) - -## 5. ALS Oracle Design - -Detail design for the Oracle is out of scope for this document. The Oracle design and implementation is specific to each Oracle's requirements. - -### 5.1. API Specification - -Refer to **ALS Oracle API** in the [API Specifications](../../api/README.md#als-oracle-api) section. diff --git a/mojaloop-technical-overview/account-lookup-service/als-del-participants.md b/mojaloop-technical-overview/account-lookup-service/als-del-participants.md deleted file mode 100644 index 6070b84fc..000000000 --- a/mojaloop-technical-overview/account-lookup-service/als-del-participants.md +++ /dev/null @@ -1,11 +0,0 @@ -# DEL Participants - -Design for the deletion of a Participant by a DFSP. - -## Notes -- Reference section 6.2.2.4 - Note: The ALS should verify that it is the Party’s current FSP that is deleting the FSP information. ~ This has been addressed in the design by insuring that the Party currently belongs to the FSPs requesting the deletion of the record. Any other validations are out of scope for the Switch and should be addressed at the schema level. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/account-lookup-service/als-get-participants.md b/mojaloop-technical-overview/account-lookup-service/als-get-participants.md deleted file mode 100644 index 506868de0..000000000 --- a/mojaloop-technical-overview/account-lookup-service/als-get-participants.md +++ /dev/null @@ -1,8 +0,0 @@ -# GET Participants - -Design for the retrieval of a Participant by a DFSP. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/account-lookup-service/als-get-parties.md b/mojaloop-technical-overview/account-lookup-service/als-get-parties.md deleted file mode 100644 index f71acd30f..000000000 --- a/mojaloop-technical-overview/account-lookup-service/als-get-parties.md +++ /dev/null @@ -1,8 +0,0 @@ -# GET Parties - -Design for the retrieval of a Party by a DFSP. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/account-lookup-service/als-post-participants-batch.md b/mojaloop-technical-overview/account-lookup-service/als-post-participants-batch.md deleted file mode 100644 index 03718e473..000000000 --- a/mojaloop-technical-overview/account-lookup-service/als-post-participants-batch.md +++ /dev/null @@ -1,14 +0,0 @@ -# Sequence Diagram for POST Participants (Batch) - -Design for the creation of a Participant by a DFSP via a batch request. - -## Notes -- Operation only supports requests which contain: - - All Participant's FSPs match the FSPIOP-Source - - All Participant's will be of the same Currency as per the [Mojaloop {{ book.importedVars.mojaloop.spec.version }} Specification]({{ book.importedVars.mojaloop.spec.uri.doc }}) -- Duplicate POST Requests with matching TYPE and optional CURRENCY will be considered an __update__ operation. The existing record must be completely **replaced** in its entirety. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/account-lookup-service/als-post-participants.md b/mojaloop-technical-overview/account-lookup-service/als-post-participants.md deleted file mode 100644 index e954183ec..000000000 --- a/mojaloop-technical-overview/account-lookup-service/als-post-participants.md +++ /dev/null @@ -1,3 +0,0 @@ -# Sequence Diagram for POST Participants - -Coming soon. diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml b/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml deleted file mode 100644 index c3f3bf96f..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml +++ /dev/null @@ -1,219 +0,0 @@ -/'***** - License - -------------- - Copyright © 2017 Bill & Melinda Gates Foundation - The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - Contributors - -------------- - This is the official list of the Mojaloop project contributors for this file. - Names of the original copyright holders (individuals or organizations) - should be listed with a '*' in the first column. People who have - contributed from an organization can be listed under the organization - that actually holds the copyright for their contributions (see the - Gates Foundation organization for an example). Those individuals should have - their names indented and be marked with a '-'. Email address can be added - optionally within square brackets . - * Gates Foundation - - Name Surname - - * Samuel Kummary - -------------- - ******'/ - -@startuml -' declare title -title 1.1.0. DFSP1 sends a Bulk Prepare Transfer request to DFSP2 - -autonumber - -' Actor Keys: -' boundary - APIs/Interfaces, etc -' collections - Kafka Topics -' control - Kafka Consumers -' entity - Database Access Objects -' database - Database Persistance Store - -' declare actors -actor "DFSP1\nPayer" as DFSP1 -actor "DFSP2\nPayee" as DFSP2 -boundary "ML API Adapter" as MLAPI -control "ML API Notification \nHandler" as NOTIFY_HANDLER -collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE -boundary "Central Service API" as CSAPI -collections "topic-\nbulk-prepare" as TOPIC_BULK_PREPARE -control "Bulk Prepare\nHandler" as BULK_PREP_HANDLER -collections "topic-\ntransfer-prepare" as TOPIC_TRANSFER_PREPARE -control "Prepare Handler" as PREP_HANDLER -collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION -control "Position Handler" as POS_HANDLER -collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING -control "Bulk Processing\nHandler" as BULK_PROC_HANDLER -collections "topic-\nnotifications" as TOPIC_NOTIFICATIONS - -box "Financial Service Providers" #lightGray - participant DFSP1 - participant DFSP2 -end box - -box "ML API Adapter Service" #LightBlue - participant MLAPI - participant NOTIFY_HANDLER -end box - -box "Central Service" #LightYellow - participant OBJECT_STORE - participant CSAPI - participant TOPIC_BULK_PREPARE - participant BULK_PREP_HANDLER - participant TOPIC_TRANSFER_PREPARE - participant PREP_HANDLER - participant TOPIC_TRANSFER_POSITION - participant POS_HANDLER - participant TOPIC_BULK_PROCESSING - participant BULK_PROC_HANDLER - participant TOPIC_NOTIFICATIONS -end box - -' start flow -activate NOTIFY_HANDLER -activate BULK_PREP_HANDLER -activate PREP_HANDLER -activate POS_HANDLER -activate BULK_PROC_HANDLER -group DFSP1 sends a Bulk Prepare Transfer request to DFSP2 - note right of DFSP1 #yellow - Headers - transferHeaders: { - Content-Length: , - Content-Type: , - Date: , - FSPIOP-Source: , - FSPIOP-Destination: , - FSPIOP-Encryption: , - FSPIOP-Signature: , - FSPIOP-URI: , - FSPIOP-HTTP-Method: - } - - Payload - bulkTransferMessage: - { - bulkTransferId: , - bulkQuoteId: , - payeeFsp: , - payerFsp: , - individualTransfers: [ - { - transferId: , - transferAmount: - { - currency: , - amount: - }, - ilpPacket: , - condition: , - extensionList: { extension: [ - { key: , value: } - ] } - } - ], - extensionList: { extension: [ - { key: , value: } - ] }, - expiration: - } - end note - DFSP1 ->> MLAPI: POST - /bulkTransfers - activate MLAPI - MLAPI -> MLAPI: Validate incoming message\nError codes: 3000-3002, 3100-3107 - MLAPI -> OBJECT_STORE: Persist incoming bulk message to\nobject store: **MLOS.individualTransfers** - activate OBJECT_STORE - OBJECT_STORE --> MLAPI: Return messageId reference to the stored object(s) - deactivate OBJECT_STORE - note right of MLAPI #yellow - Message: - { - id: - to: , - from: , - type: "application/json" - content: { - headers: , - payload: { - bulkTransferId: , - bulkQuoteId": , - payerFsp: , - payeeFsp: , - expiration: , - hash: - } - }, - metadata: { - event: { - id: , - type: "bulk-prepare", - action: "bulk-prepare", - createdAt: , - state: { - status: "success", - code: 0 - } - } - } - } - end note - MLAPI -> TOPIC_BULK_PREPARE: Route & Publish Bulk Prepare event \nfor Payer\nError code: 2003 - activate TOPIC_BULK_PREPARE - TOPIC_BULK_PREPARE <-> TOPIC_BULK_PREPARE: Ensure event is replicated \nas configured (ACKS=all)\nError code: 2003 - TOPIC_BULK_PREPARE --> MLAPI: Respond replication acknowledgements \nhave been received - deactivate TOPIC_BULK_PREPARE - MLAPI -->> DFSP1: Respond HTTP - 202 (Accepted) - deactivate MLAPI - ||| - TOPIC_BULK_PREPARE <- BULK_PREP_HANDLER: Consume message - BULK_PREP_HANDLER -> OBJECT_STORE: Retrieve individual transfers by key:\n**MLOS.individualTransfers.messageId** - activate OBJECT_STORE - OBJECT_STORE --> BULK_PREP_HANDLER: Stream bulk's individual transfers - deactivate OBJECT_STORE - ref over TOPIC_BULK_PREPARE, BULK_PREP_HANDLER, TOPIC_TRANSFER_PREPARE: Bulk Prepare Handler Consume \n - alt Success - BULK_PREP_HANDLER -> TOPIC_TRANSFER_PREPARE: Produce (stream) single transfer message\nfor each individual transfer [loop] - else Failure - BULK_PREP_HANDLER --> TOPIC_NOTIFICATIONS: Produce single message for the entire bulk - end - ||| - TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume message - ref over TOPIC_TRANSFER_PREPARE, PREP_HANDLER, TOPIC_TRANSFER_POSITION: Prepare Handler Consume\n - alt Success - PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message - else Failure - PREP_HANDLER --> TOPIC_BULK_PROCESSING: Produce message - end - ||| - TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message - ref over TOPIC_TRANSFER_POSITION, POS_HANDLER, TOPIC_BULK_PROCESSING: Position Handler Consume\n - POS_HANDLER -> TOPIC_BULK_PROCESSING: Produce message - ||| - TOPIC_BULK_PROCESSING <- BULK_PROC_HANDLER: Consume message - ref over TOPIC_BULK_PROCESSING, BULK_PROC_HANDLER, TOPIC_NOTIFICATIONS: Bulk Processing Handler Consume\n - BULK_PROC_HANDLER -> OBJECT_STORE: Persist bulk message by destination to the\nobject store: **MLOS.bulkTransferResults** - activate OBJECT_STORE - OBJECT_STORE --> BULK_PROC_HANDLER: Return the reference to the stored \nnotification object(s): **messageId** - deactivate OBJECT_STORE - BULK_PROC_HANDLER -> TOPIC_NOTIFICATIONS: Send Bulk Prepare notification - ||| - TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message - NOTIFY_HANDLER -> OBJECT_STORE: Retrieve bulk notification(s) by reference & destination:\n**MLOS.bulkTransferResults.messageId + destination** - activate OBJECT_STORE - OBJECT_STORE --> NOTIFY_HANDLER: Return notification(s) payload - deactivate OBJECT_STORE - ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n - NOTIFY_HANDLER -> DFSP2: Send Bulk Prepare notification to Payee - ||| -end -deactivate POS_HANDLER -deactivate BULK_PREP_HANDLER -deactivate PREP_HANDLER -deactivate BULK_PROC_HANDLER -deactivate NOTIFY_HANDLER -@enduml diff --git a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml b/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml deleted file mode 100644 index 8cd357671..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml +++ /dev/null @@ -1,369 +0,0 @@ -/'***** - License - -------------- - Copyright © 2017 Bill & Melinda Gates Foundation - The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - Contributors - -------------- - This is the official list of the Mojaloop project contributors for this file. - Names of the original copyright holders (individuals or organizations) - should be listed with a '*' in the first column. People who have - contributed from an organization can be listed under the organization - that actually holds the copyright for their contributions (see the - Gates Foundation organization for an example). Those individuals should have - their names indented and be marked with a '-'. Email address can be added - optionally within square brackets . - * Gates Foundation - - Name Surname - - * Samuel Kummary - -------------- - ******'/ - -@startuml -' declare title -title 1.1.1. Bulk Prepare Handler Consume - -autonumber - -' Actor Keys: -' boundary - APIs/Interfaces, etc -' collections - Kafka Topics -' control - Kafka Consumers -' entity - Database Access Objects -' database - Database Persistance Store - -' declare actors -collections "topic-\nbulk-prepare" as TOPIC_BULK_PREPARE -collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE -control "Bulk Prepare \nHandler" as BULK_PREP_HANDLER -collections "topic-\ntransfer-prepare" as TOPIC_TRANSFER_PREPARE -collections "topic-event" as TOPIC_EVENTS -collections "topic-\nnotification" as TOPIC_NOTIFICATIONS -collections "topic-bulk-\nprocessing" as TOPIC_BULK_PROCESSING -entity "Bulk DAO" as BULK_DAO -entity "Participant DAO" as PARTICIPANT_DAO -database "Central Store" as DB - -box "Central Service" #LightYellow - participant OBJECT_STORE - participant TOPIC_BULK_PREPARE - participant BULK_PREP_HANDLER - participant TOPIC_TRANSFER_PREPARE - participant TOPIC_EVENTS - participant TOPIC_NOTIFICATIONS - participant TOPIC_BULK_PROCESSING - participant BULK_DAO - participant PARTICIPANT_DAO - participant DB -end box - -' start flow -activate BULK_PREP_HANDLER -group Bulk Prepare Handler Consume - TOPIC_BULK_PREPARE <- BULK_PREP_HANDLER: Consume Bulk Prepare message - activate TOPIC_BULK_PREPARE - deactivate TOPIC_BULK_PREPARE - - break - group Validate Event - BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Validate event - Rule: type == 'bulk-prepare' && action == 'bulk-prepare'\nError codes: 2001 - end - end - - group Persist Event Information - ||| - BULK_PREP_HANDLER -> TOPIC_EVENTS: Publish event information - ref over BULK_PREP_HANDLER, TOPIC_EVENTS : Event Handler Consume\n - ||| - end - - group Validate Bulk Prepare Transfer - BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Schema validation of the incoming message - BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Verify the message's signature (to be confirmed in future requirement) - note right of BULK_PREP_HANDLER #lightgrey - The above validation steps are already handled by the - Bulk-API-Adapter for the open source implementation. - It may need to be added in future for custom adapters. - end note - - group Validate Duplicate Check - note right of BULK_PREP_HANDLER #cyan - The Specification doesn't touch on the duplicate handling - of bulk transfers, so the current design mostly follows the - strategy used for individual transfers, except in two places: - - 1. For duplicate requests where hash matches, the current design - includes only the status of the bulk & timestamp (if completed), - but not the individual transfers (for which a GET should be used). - - 2. For duplicate requests where hash matches, but are not in a - finalized state, only the state of the bulkTransfer is sent. - end note - ||| - BULK_PREP_HANDLER -> DB: Request Duplicate Check - ref over BULK_PREP_HANDLER, DB: Request Duplicate Check (using message.content.payload.hash)\n - DB --> BULK_PREP_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } - end - - alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE - break - BULK_PREP_HANDLER -> BULK_DAO: Request to retrieve Bulk Transfer state & completedTimestamp\nError code: 2003 - activate BULK_DAO - BULK_DAO -> DB: Query database - hnote over DB #lightyellow - bulkTransfer - bulkTransferFulfilment - bulkTransferStateChange - end note - activate DB - BULK_DAO <-- DB: Return resultset - deactivate DB - BULK_DAO --> BULK_PREP_HANDLER: Return **bulkTransferStateId** & **completedTimestamp** (not null when completed) - deactivate BULK_DAO - - note right of BULK_PREP_HANDLER #yellow - Message: - { - id: - from: , - to: , - type: application/json - content: { - headers: , - payload: { - bulkTransferState: , - completedTimestamp: - } - }, - metadata: { - event: { - id: , - responseTo: , - type: "notification", - action: "bulk-prepare-duplicate", - createdAt: , - state: { - status: "success", - code: 0 - } - } - } - } - end note - BULK_PREP_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event for Payer - activate TOPIC_NOTIFICATIONS - deactivate TOPIC_NOTIFICATIONS - end - else hasDuplicateId == TRUE && hasDuplicateHash == FALSE - note right of BULK_PREP_HANDLER #yellow - { - id: , - from: , - to: , - type: "application/json", - content: { - headers: , - payload: { - errorInformation: { - errorCode: "3106", - errorDescription: "Modified request", - extensionList: { - extension: [ - { - key: "_cause", - value: - } - ] - } - }, - uriParams: { - id: - } - } - }, - metadata: { - correlationId: , - event: { - id: , - type: "notification", - action: "bulk-prepare", - createdAt: , - state: { - status: "error", - code: "3106", - description: "Modified request" - }, - responseTo: - } - } - } - end note - BULK_PREP_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError codes: 3106 - activate TOPIC_NOTIFICATIONS - deactivate TOPIC_NOTIFICATIONS - else hasDuplicateId == FALSE - group Validate Payer - BULK_PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payer Participant details (if it exists) - activate PARTICIPANT_DAO - PARTICIPANT_DAO -> DB: Request Participant details - hnote over DB #lightyellow - participant - participantCurrency - end note - activate DB - PARTICIPANT_DAO <-- DB: Return Participant details if it exists - deactivate DB - PARTICIPANT_DAO --> BULK_PREP_HANDLER: Return Participant details if it exists - deactivate PARTICIPANT_DAO - BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Validate Payer\nError codes: 3202 - end - group Validate Payee - BULK_PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payee Participant details (if it exists) - activate PARTICIPANT_DAO - PARTICIPANT_DAO -> DB: Request Participant details - hnote over DB #lightyellow - participant - participantCurrency - end note - activate DB - PARTICIPANT_DAO <-- DB: Return Participant details if it exists - deactivate DB - PARTICIPANT_DAO --> BULK_PREP_HANDLER: Return Participant details if it exists - deactivate PARTICIPANT_DAO - BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Validate Payee\nError codes: 3203 - end - BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Validate crypto-condition\nError codes: 3100 - - alt Validate Bulk Prepare Transfer (success) - group Persist Bulk Transfer State (with bulkTransferState='RECEIVED') - BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer\nError codes: 2003 - activate BULK_DAO - BULK_DAO -> DB: Persist bulkTransfer - hnote over DB #lightyellow - bulkTransfer - bulkTransferExtension - bulkTransferStateChange - end note - activate DB - deactivate DB - BULK_DAO --> BULK_PREP_HANDLER: Return success - deactivate BULK_DAO - end - else Validate Bulk Prepare Transfer (failure) - group Persist Bulk Transfer State (with bulkTransferState='INVALID') (Introducing a new status INVALID to mark these entries) - BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer\n(when Payee/Payer/crypto-condition validation fails)\nError codes: 2003 - activate BULK_DAO - BULK_DAO -> DB: Persist transfer - hnote over DB #lightyellow - bulkTransfer - bulkTransferExtension - bulkTransferStateChange - bulkTransferError - end note - activate DB - deactivate DB - BULK_DAO --> BULK_PREP_HANDLER: Return success - deactivate BULK_DAO - end - end - end - end - alt Validate Bulk Prepare Transfer (success) - loop for each individual transfer in the bulk - BULK_PREP_HANDLER -> OBJECT_STORE: Retrieve individual transfers from the bulk using\nreference: **MLOS.individualTransfers.messageId** - activate OBJECT_STORE - note right of OBJECT_STORE #lightgrey - Add elements such as Expiry time, Payer FSP, Payee FSP, etc. to each - transfer to make their format similar to a single transfer - end note - OBJECT_STORE --> BULK_PREP_HANDLER: Stream bulk's individual transfers - deactivate OBJECT_STORE - - group Insert Bulk Transfer Association (with bulkProcessingState='RECEIVED') - BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer association\nError codes: 2003 - activate BULK_DAO - BULK_DAO -> DB: Insert bulkTransferAssociation - hnote over DB #lightyellow - bulkTransferAssociation - end note - activate DB - deactivate DB - BULK_DAO --> BULK_PREP_HANDLER: Return success - deactivate BULK_DAO - end - - note right of BULK_PREP_HANDLER #yellow - Message: - { - id: - from: , - to: , - type: application/json - content: { - headers: , - payload: - }, - metadata: { - event: { - id: , - responseTo: , - type: "prepare", - action: "bulk-prepare", - createdAt: , - state: { - status: "success", - code: 0, - description:"action successful" - } - } - } - } - end note - BULK_PREP_HANDLER -> TOPIC_TRANSFER_PREPARE: Route & Publish Prepare event to the Payer for the Individual Transfer\nError codes: 2003 - activate TOPIC_TRANSFER_PREPARE - deactivate TOPIC_TRANSFER_PREPARE - end - else Validate Bulk Prepare Transfer (failure) - note right of BULK_PREP_HANDLER #yellow - Message: - { - id: - from: , - to: , - type: "application/json", - content: { - headers: , - payload: { - "errorInformation": { - "errorCode": - "errorDescription": "", - "extensionList": - } - }, - metadata: { - event: { - id: , - responseTo: , - type: "bulk-processing", - action: "bulk-abort", - createdAt: , - state: { - status: "error", - code: - description: - } - } - } - } - end note - BULK_PREP_HANDLER -> TOPIC_BULK_PROCESSING: Publish Processing (failure) event for Payer\nError codes: 2003 - activate TOPIC_BULK_PROCESSING - deactivate TOPIC_BULK_PROCESSING - end -end -deactivate BULK_PREP_HANDLER -@enduml - diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md deleted file mode 100644 index 75f248785..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md +++ /dev/null @@ -1,16 +0,0 @@ -# Bulk Prepare Transfer Request [Overview] [includes individual transfers in a bulk] - -Sequence design diagram for Prepare Transfer Request process. - -## References within Sequence Diagram - -* [Bulk Prepare Handler Consume (1.1.1)](1.1.1-bulk-prepare-handler-consume.md) -* [Prepare Handler Consume (1.2.1)](1.2.1-prepare-handler-consume-for-bulk.md) -* [Position Handler Consume (1.3.0)](1.3.0-position-handler-consume-overview.md) -* [Bulk Processing Handler Consume (1.4.1)](1.4.1-bulk-processing-handler.md) -* [Send notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md deleted file mode 100644 index 3ae05112f..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md +++ /dev/null @@ -1,12 +0,0 @@ -# Bulk Prepare handler consume - -Sequence design diagram for Bulk Prepare Handler Consume process - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md deleted file mode 100644 index faaa73cec..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md +++ /dev/null @@ -1,12 +0,0 @@ -# Prepare handler consume [that includes individual transfers in a bulk] - -Sequence design diagram for Prepare Handler Consume process - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md deleted file mode 100644 index 8c3c80e3f..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md +++ /dev/null @@ -1,15 +0,0 @@ -# Position Handler Consume [that includes individual transfers in a bulk] - -Sequence design diagram for Position Handler Consume process - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) -* [Prepare Position Handler Consume (1.3.1)](1.3.1-prepare-position-handler-consume.md) -* [Fufil Position Handler Consume (2.2.1)](2.2.1-fulfil-commit-for-bulk.md) -* [Abort Position Handler Consume (2.2.2)](2.2.2-fulfil-abort-for-bulk.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md deleted file mode 100644 index 883ed0f87..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md +++ /dev/null @@ -1,8 +0,0 @@ -# Prepare Position Handler Consume [that includes individual transfers in a bulk] - -Sequence design diagram for Prepare Position Handler Consume process - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md deleted file mode 100644 index be712867f..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md +++ /dev/null @@ -1,8 +0,0 @@ -# Bulk Processing Handler Consume - -Sequence design diagram for Bulk Processing Handler Consume process - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md deleted file mode 100644 index f2af1e970..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md +++ /dev/null @@ -1,16 +0,0 @@ -# Bulk Fulfil Transfer Request Overview - -Sequence design diagram for the Bulk Fulfil Transfer request - -## References within Sequence Diagram - -* [Bulk Fulfil Handler Consume (Success) (2.1.1)](2.1.1-bulk-fulfil-handler-consume.md) -* [Fulfil Handler Consume (Success) (2.2.1)](2.2.1-fulfil-commit-for-bulk.md) -* [Position Handler Consume (Success) (2.3.1)](2.3.1-fulfil-position-handler-consume.md) -* [Bulk Processing Handler Consume (1.4.1)](1.4.1-bulk-processing-handler.md) -* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md deleted file mode 100644 index 3ce237bfd..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md +++ /dev/null @@ -1,14 +0,0 @@ -# Bulk Fulfil Handler Consume - -Sequence design diagram for the Bulk Fulfil Handler Consume process - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) -* [seq-signature-validation](../../central-event-processor/signature-validation.md) -* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md deleted file mode 100644 index e5a1af9d6..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md +++ /dev/null @@ -1,12 +0,0 @@ -# Payee sends a Bulk Fulfil Transfer request - Bulk is broken down into individual transfers - -Sequence design diagram for the Bulk Fulfil Transfer for the Commit option - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md deleted file mode 100644 index 2511cf3b7..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md +++ /dev/null @@ -1,14 +0,0 @@ -# Payee sends a Bulk Fulfil Transfer request - Bulk is broken down into individual transfers - -Sequence design diagram for the Fulfil Handler Consume Reject/Abort process - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) -* [seq-signature-validation](../../central-event-processor/signature-validation.md) -* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md deleted file mode 100644 index a25cbe70f..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md +++ /dev/null @@ -1,12 +0,0 @@ -# Fulfil Position Handler Consume [that includes individual transfers in a bulk] - -Sequence design diagram for the Fulfil Position Handler Consume process - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md deleted file mode 100644 index 7209b1b8e..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md +++ /dev/null @@ -1,8 +0,0 @@ -# Position Handler Consume for Fulfil aborts at individual transfer level - -Sequence design diagram for Fulfil Position Handler Consume process - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md deleted file mode 100644 index 8100587c9..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md +++ /dev/null @@ -1,8 +0,0 @@ -## Transfer Timeout [includes individual transfers in a Bulk] - -Sequence design diagram for the Transfer Timeout process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md b/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md deleted file mode 100644 index c82f4792e..000000000 --- a/mojaloop-technical-overview/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md +++ /dev/null @@ -1,8 +0,0 @@ -# TimeOut Handler - -Sequence design diagram for Timeout Handler process - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-event-processor/5.1.1-notification-handler-for-rejections.md b/mojaloop-technical-overview/central-event-processor/5.1.1-notification-handler-for-rejections.md deleted file mode 100644 index 8ffd4c195..000000000 --- a/mojaloop-technical-overview/central-event-processor/5.1.1-notification-handler-for-rejections.md +++ /dev/null @@ -1,13 +0,0 @@ -# Notification Handler for Rejections - -Sequence design diagram for the Notification Handler for Rejections process. - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](9.1.0-event-handler-placeholder.md) -* [Get Participant Callback Details (3.1.0)](../central-ledger/admin-operations/3.1.0-post-participant-callback-details.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-event-processor/9.1.0-event-handler-placeholder.md b/mojaloop-technical-overview/central-event-processor/9.1.0-event-handler-placeholder.md deleted file mode 100644 index 38b7b87ca..000000000 --- a/mojaloop-technical-overview/central-event-processor/9.1.0-event-handler-placeholder.md +++ /dev/null @@ -1,8 +0,0 @@ -# Event Handler Placeholder - -Sequence design diagram for the Event Handler process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-event-processor/signature-validation.md b/mojaloop-technical-overview/central-event-processor/signature-validation.md deleted file mode 100644 index a6c9df9ba..000000000 --- a/mojaloop-technical-overview/central-event-processor/signature-validation.md +++ /dev/null @@ -1,8 +0,0 @@ -# Signature Validation - -Sequence design diagram for the Signature Validation process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-event-processor/assets/diagrams/sequence/seq-signature-validation.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/README.md b/mojaloop-technical-overview/central-ledger/README.md deleted file mode 100644 index 259d6ebf4..000000000 --- a/mojaloop-technical-overview/central-ledger/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# Central-Ledger Services - -The central ledger is a series of services that facilitate clearing and settlement of transfers between DFSPs, including the following functions: - -* Brokering real-time messaging for funds clearing -* Maintaining net positions for a deferred net settlement -* Propagating scheme-level and off-transfer fees - -## 1. Central Ledger Process Design - -### 1.1 Architecture overview - -![Central-Ledger Architecture](assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg) - -## 2. Transfers End-to-End Architecture - -![Transfers Architecture](assets/diagrams/architecture/Transfers-Arch-End-to-End.svg) - -## 3. Database Design - -### Note - -The tables *Grey* colored tables are specific to the transfer process. The *Blue* and *Green* color tables are used for reference purposes during the Transfer process. - -Summary of the tables specific to the transfer process; - -- `transfer` - stores data related to the transfer; -- `transferDuplicateCheck` - used to identify duplication during the transfer requests process; -- `transferError` - stores information on transfer errors encountered during the transfer process; -- `transferErrorDuplicateCheck` - used to identify duplication error transfer processes; -- `transferExtensions` - stores information on the transfer extension data; -- `transferFulfilment` - stores data for transfers that have completed the prepare transfer process; -- `transferFulfilmentDuplicateCheck` - used the identify duplicate transfer fulfil requests; -- `transferParticipant` - participant information related to the transfer process; -- `transferStateChange` - use to track state changes of each individual transfer, creating and audit trail for a specific transfer request; -- `transferTimeout` - stores information of transfers that encountered a timeout exception during the process; -- `ilpPacket` - stores the ilp package for the transfer; - -The remaining tables in the below ERD are either lookup (blue) or settlement-specific (red) and are included as direct or indirect dependencies to depict the relation between the transfer specific entities and the transfer tables. - -The **Central Ledger** database schema definition [Central-Ledger Database Schema Definition](assets/database/central-ledger-ddl-MySQLWorkbench.sql). - -![Central-Ledger Database Diagram](assets/database/central-ledger-schema.png) - -## 4. API Specification - -Refer to **Central Ledger API** in the [API Specifications](../../api/README.md#central-ledger-api) section. diff --git a/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-health-check.md b/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-health-check.md deleted file mode 100644 index 272865cc9..000000000 --- a/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-health-check.md +++ /dev/null @@ -1,268 +0,0 @@ -# GET Health Check - -Design discussion for new Health Check implementation. - - -## Objectives - -The goal for this design is to implement a new Health check for mojaloop switch services that allows for a greater level of detail. - -It Features: -- Clear HTTP Statuses (no need to inspect the response to know there are no issues) -- ~Backwards compatibility with existing health checks~ - No longer a requirement. See [this discussion](https://github.com/mojaloop/project/issues/796#issuecomment-498350828). -- Information about the version of the API, and how long it has been running for -- Information about sub-service (kafka, logging sidecar and mysql) connections - -## Request Format -`/health` - -Uses the newly implemented health check. As discussed [here](https://github.com/mojaloop/project/issues/796#issuecomment-498350828) since there will be no added connection overhead (e.g. pinging a database) as part of implementing the health check, there is no need to complicate things with a simple and detailed version. - -Responses Codes: -- `200` - Success. The API is up and running, and is sucessfully connected to necessary services. -- `502` - Bad Gateway. The API is up and running, but the API cannot connect to necessary service (eg. `kafka`). -- `503` - Service Unavailable. This response is not implemented in this design, but will be the default if the api is not and running - -## Response Format - -| Name | Type | Description | Example | -| --- | --- | --- | --- | -| `status` | `statusEnum` | The status of the service. Options are `OK` and `DOWN`. _See `statusEnum` below_. | `"OK"` | -| `uptime` | `number` | How long (in seconds) the service has been alive for. | `123456` | -| `started` | `string` (ISO formatted date-time) | When the service was started (UTC) | `"2019-05-31T05:09:25.409Z"` | -| `versionNumber` | `string` (semver) | The current version of the service. | `"5.2.5"` | -| `services` | `Array` | A list of services this service depends on, and their connection status | _see below_ | - -### serviceHealth - -| Name | Type | Description | Example | -| --- | --- | --- | --- | -| `name` | `subServiceEnum` | The sub-service name. _See `subServiceEnum` below_. | `"broker"` | -| `status` | `enum` | The status of the service. Options are `OK` and `DOWN` | `"OK"` | - -### subServiceEnum - -The subServiceEnum enum describes a name of the subservice: - -Options: -- `datastore` -> The database for this service (typically a MySQL Database). -- `broker` -> The message broker for this service (typically Kafka). -- `sidecar` -> The logging sidecar sub-service this service attaches to. -- `cache` -> The caching sub-service this services attaches to. - - -### statusEnum - -The status enum represents status of the system or sub-service. - -It has two options: -- `OK` -> The service or sub-service is healthy. -- `DOWN` -> The service or sub-service is unhealthy. - -When a service is `OK`: the API is considered healthy, and all sub-services are also considered healthy. - -If __any__ sub-service is `DOWN`, then the entire health check will fail, and the API will be considered `DOWN`. - -## Defining Sub-Service health - -It is not enough to simply ping a sub-service to know if it is healthy, we want to go one step further. These criteria will change with each sub-service. - -### `datastore` - -For `datastore`, a status of `OK` means: -- An existing connection to the database -- The database is not empty (contains more than 1 table) - - -### `broker` - -For `broker`, a status of `OK` means: -- An existing connection to the kafka broker -- The necessary topics exist. This will change depending on which service the health check is running for. - -For example, for the `central-ledger` service to be considered healthy, the following topics need to be found: -``` -topic-admin-transfer -topic-transfer-prepare -topic-transfer-position -topic-transfer-fulfil -``` - -### `sidecar` - -For `sidecar`, a status of `OK` means: -- An existing connection to the sidecar - - -### `cache` - -For `cache`, a status of `OK` means: -- An existing connection to the cache - - -## Swagger Definition - ->_Note: These will be added to the existing swagger definitions for the following services:_ -> - `ml-api-adapter` -> - `central-ledger` -> - `central-settlement` -> - `central-event-processor` -> - `email-notifier` - -```json -{ - /// . . . - "/health": { - "get": { - "operationId": "getHealth", - "tags": [ - "health" - ], - "responses": { - "default": { - "schema": { - "$ref": "#/definitions/health" - }, - "description": "Successful" - } - } - } - }, - // . . . - "definitions": { - "health": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "OK", - "DOWN" - ] - }, - "uptime": { - "description": "How long (in seconds) the service has been alive for.", - "type": "number", - }, - "started": { - "description": "When the service was started (UTC)", - "type": "string", - "format": "date-time" - }, - "versionNumber": { - "description": "The current version of the service.", - "type": "string", - "example": "5.2.3", - }, - "services": { - "description": "A list of services this service depends on, and their connection status", - "type": "array", - "items": { - "$ref": "#/definitions/serviceHealth" - } - }, - }, - }, - "serviceHealth": { - "type": "object", - "properties": { - "name": { - "description": "The sub-service name.", - "type": "string", - "enum": [ - "datastore", - "broker", - "sidecar", - "cache" - ] - }, - "status": { - "description": "The connection status with the service.", - "type": "string", - "enum": [ - "OK", - "DOWN" - ] - } - } - } - } -} -``` - - -### Example Requests and Responses: - -__Successful Legacy Health Check:__ - -```bash -GET /health HTTP/1.1 -Content-Type: application/json - -200 SUCCESS -{ - "status": "OK" -} -``` - - -__Successful New Health Check:__ - -``` -GET /health?detailed=true HTTP/1.1 -Content-Type: application/json - -200 SUCCESS -{ - "status": "OK", - "uptime": 0, - "started": "2019-05-31T05:09:25.409Z", - "versionNumber": "5.2.3", - "services": [ - { - "name": "broker", - "status": "OK", - } - ] -} -``` - -__Failed Health Check, but API is up:__ - -``` -GET /health?detailed=true HTTP/1.1 -Content-Type: application/json - -502 BAD GATEWAY -{ - "status": "DOWN", - "uptime": 0, - "started": "2019-05-31T05:09:25.409Z", - "versionNumber": "5.2.3", - "services": [ - { - "name": "broker", - "status": "DOWN", - } - ] -} -``` - -__Failed Health Check:__ - -``` -GET /health?detailed=true HTTP/1.1 -Content-Type: application/json - -503 SERVICE UNAVAILABLE -``` - - -## Sequence Diagram - -Sequence design diagram for the GET Health - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.plantuml" %} -{% enduml %} - -![](../assets/diagrams/sequence/seq-get-health-1.0.0.svg) \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md b/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md deleted file mode 100644 index 7303b7b5c..000000000 --- a/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md +++ /dev/null @@ -1,8 +0,0 @@ -# GET Participant Limit Details For All Participants - -Sequence design diagram for the GET Participant Limit Details For All Participants process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md b/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md deleted file mode 100644 index 06822896a..000000000 --- a/mojaloop-technical-overview/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md +++ /dev/null @@ -1,8 +0,0 @@ -# Create initial position and limits for Participant - -Sequence design diagram for the POST (create) Participant Initial Position and Limit process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md b/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md deleted file mode 100644 index 555eb5aa6..000000000 --- a/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md +++ /dev/null @@ -1,8 +0,0 @@ -# Request Participant Position and Limit Details - -Sequence design diagram for the Request Participant Position and Limit Details process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-post-participant-limits.md b/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-post-participant-limits.md deleted file mode 100644 index f62de5e7a..000000000 --- a/mojaloop-technical-overview/central-ledger/admin-operations/1.1.0-post-participant-limits.md +++ /dev/null @@ -1,8 +0,0 @@ -# Adjust Participant Limit for a certain Currency - -Sequence design diagram for the POST (manage) Participant Limit Details process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/admin-operations/1.1.5-get-transfer-status.md b/mojaloop-technical-overview/central-ledger/admin-operations/1.1.5-get-transfer-status.md deleted file mode 100644 index 20b722a29..000000000 --- a/mojaloop-technical-overview/central-ledger/admin-operations/1.1.5-get-transfer-status.md +++ /dev/null @@ -1,8 +0,0 @@ -# Request transfer status - -Sequence design diagram for the GET Transfer Status process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md b/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md deleted file mode 100644 index 1a26bf67d..000000000 --- a/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md +++ /dev/null @@ -1,8 +0,0 @@ -# 3.1.0 Get Participant Callback Details - -Sequence design diagram for the GET Participant Callback Details process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md b/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md deleted file mode 100644 index 3182dacd2..000000000 --- a/mojaloop-technical-overview/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md +++ /dev/null @@ -1,8 +0,0 @@ -# 3.1.0 Add Participant Callback Details - -Sequence design diagram for the POST (Add) Participant Callback Details process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/admin-operations/4.1.0-get-participant-position-details.md b/mojaloop-technical-overview/central-ledger/admin-operations/4.1.0-get-participant-position-details.md deleted file mode 100644 index 1d43a103d..000000000 --- a/mojaloop-technical-overview/central-ledger/admin-operations/4.1.0-get-participant-position-details.md +++ /dev/null @@ -1,8 +0,0 @@ -# Get Participant Position Details - -Sequence design diagram for the GET Participant Position Details process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md b/mojaloop-technical-overview/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md deleted file mode 100644 index 2e52dbd82..000000000 --- a/mojaloop-technical-overview/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md +++ /dev/null @@ -1,8 +0,0 @@ -# Get Position Details for all Participants - -Sequence design diagram for the Get Positions of all Participants process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/admin-operations/README.md b/mojaloop-technical-overview/central-ledger/admin-operations/README.md deleted file mode 100644 index ad1133844..000000000 --- a/mojaloop-technical-overview/central-ledger/admin-operations/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Mojaloop HUB/Switch operations. - -Operational processes normally initiated by a HUB/Switch operator. diff --git a/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-schema-DBeaver.erd b/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-schema-DBeaver.erd deleted file mode 100644 index dc18f82f2..000000000 --- a/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-schema-DBeaver.erd +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - COLOR LEGEND: -Green - subject specific entity -Gray - transfer specific entity -Brown - bulk transfer entity -Red - settlement specific entity -Blue - enumeration entity -Purple - to be removed -Cyan - impl. specific -Yellow - tbd - - \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-schema.png b/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-schema.png deleted file mode 100644 index 6ae8e2e18..000000000 Binary files a/mojaloop-technical-overview/central-ledger/assets/database/central-ledger-schema.png and /dev/null differ diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml b/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml deleted file mode 100644 index 517a6c490..000000000 --- a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml +++ /dev/null @@ -1,283 +0,0 @@ -/'***** - License - -------------- - Copyright © 2017 Bill & Melinda Gates Foundation - The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - Contributors - -------------- - This is the official list of the Mojaloop project contributors for this file. - Names of the original copyright holders (individuals or organizations) - should be listed with a '*' in the first column. People who have - contributed from an organization can be listed under the organization - that actually holds the copyright for their contributions (see the - Gates Foundation organization for an example). Those individuals should have - their names indented and be marked with a '-'. Email address can be added - optionally within square brackets . - * Gates Foundation - - Name Surname - - * Georgi Georgiev - * Rajiv Mothilal - * Miguel de Barros - -------------- - ******'/ - -@startuml -' declate title -title 1.3.1. Prepare Position Handler Consume - -autonumber - -' Actor Keys: -' boundary - APIs/Interfaces, etc -' collections - Kafka Topics -' control - Kafka Consumers -' entity - Database Access Objects -' database - Database Persistence Store - -' declare actors -control "Position Handler" as POS_HANDLER - -entity "Position\nManagement\nFacade" as POS_MGMT -collections "Notification-Topic" as TOPIC_NOTIFICATIONS -entity "Position DAO" as POS_DAO -database "Central Store" as DB - -box "Central Service" #LightYellow - participant POS_HANDLER - participant TOPIC_NOTIFICATIONS - participant POS_MGMT - participant POS_DAO - participant DB -end box - -' start flow -activate POS_HANDLER -group Prepare Position Handler Consume - POS_HANDLER -> POS_MGMT: Request transfers to be processed - activate POS_MGMT - POS_MGMT -> POS_MGMT: Check 1st transfer to select the Participant and Currency - group DB TRANSACTION - ' DB Trans: This is where 1st DB Transaction would start in 2 DB transacation future model for horizontal scaling - POS_MGMT -> POS_MGMT: Loop through batch and build list of transferIds and calculate sumTransfersInBatch,\nchecking all in Batch are for the correct Paricipant and Currency\nError code: 2001, 3100 - POS_MGMT -> DB: Retrieve current state of all transfers in array from DB with select whereIn\n(FYI: The two DB transaction model needs to add a mini-state step here (RECEIVED_PREPARE => RECEIVDED_PREPARE_PROCESSING) so that the transfers are left alone if processing has started) - activate DB - hnote over DB #lightyellow - transferStateChange - transferParticipant - end note - DB --> POS_MGMT: Return current state of all selected transfers from DB - deactivate DB - POS_MGMT <-> POS_MGMT: Validate current state (transferStateChange.transferStateId == 'RECEIVED_PREPARE')\nError code: 2001 against failing transfers\nBatch is not rejected as a whole. - - note right of POS_MGMT #lightgray - List of transfers used during processing - **reservedTransfers** is list of transfers to be processed in the batch - **abortedTransfers** is the list of transfers in the incorrect state going into the process. Currently the transferStateChange is set to ABORTED - this should only be done if not already in a final state (idempotency) - **processedTransfers** is the list of transfers that have gone through the position management algorithm. Both successful and failed trasnfers appear here as the order and "running position" against each is necessary for reconciliation - - Scalar intermidate values used in the algorithm - **transferAmount** = payload.amount.amount - **sumTransfersInBatch** = SUM amount against each Transfer in batch - **currentPosition** = participantPosition.value - **reservedPosition** = participantPosition.{original}reservedValue - **effectivePosition** = currentPosition + reservedPosition - **heldPosition** = effectivePosition + sumTransfersInBatch - **availablePosition** = participantLimit(NetDebitCap) - effectivePosition - **sumReserved** = SUM of transfers that have met rule criteria and processed - end note - note over POS_MGMT,DB - Going to reserve the sum of the valid transfers in the batch against the Participants Positon in the Currency of this batch - and calculate the available position for the Participant to use - end note - POS_MGMT -> DB: Select effectivePosition FOR UPDATE from DB for Payer - activate DB - hnote over DB #lightyellow - participantPosition - end note - DB --> POS_MGMT: Return effectivePosition (currentPosition and reservedPosition) from DB for Payer - deactivate DB - POS_MGMT -> POS_MGMT: Increment reservedValue to heldPosition\n(reservedValue = reservedPosition + sumTransfersInBatch) - POS_MGMT -> DB: Persist reservedValue - activate DB - hnote over DB #lightyellow - UPDATE **participantPosition** - SET reservedValue += sumTransfersInBatch - end note - deactivate DB - ' DB Trans: This is where 1st DB Transaction would end in 2 DB transacation future model for horizontal scaling - - - POS_MGMT -> DB: Request position limits for Payer Participant - activate DB - hnote over DB #lightyellow - FROM **participantLimit** - WHERE participantLimit.limitTypeId = 'NET-DEBIT-CAP' - AND participantLimit.participantId = payload.payerFsp - AND participantLimit.currencyId = payload.amount.currency - end note - DB --> POS_MGMT: Return position limits - deactivate DB - POS_MGMT <-> POS_MGMT: **availablePosition** = participantLimit(netDebitCap) - effectivePosition (same as = netDebitCap - currentPosition - reservedPosition) - note over POS_MGMT,DB - For each transfer in the batch, validate the availablility of position to meet the transfer amount - this will be as per the position algorithm documented below - end note - POS_MGMT <-> POS_MGMT: Validate availablePosition for each tranfser (see algorithm below)\nError code: 4001 - note right of POS_MGMT #lightgray - 01: sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED - 02: sumProcessed =0 // Record the sum of the transfers already processed in this batch - 03: processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position - 04: foreach transfer in reservedTransfers - 05: sumProcessed += transfer.amount // the total processed so far **(NEED TO UPDATE IN CODE)** - 06: if availablePosition >= transfer.amount - 07: transfer.state = "RESERVED" - 08: availablePosition -= preparedTransfer.amount - 09: sumRESERVED += preparedTransfer.amount - 10: else - 11: preparedTransfer.state = "ABORTED" - 12: preparedTransfer.reason = "Net Debit Cap exceeded by this request at this time, please try again later" - 13: end if - 14: runningPosition = currentPosition + sumReserved // the initial value of the Participants position plus the total value that has been accepted in the batch so far - 15: runningReservedValue = sumTransfersInBatch - sumProcessed + reservedPosition **(NEED TO UPDATE IN CODE)** // the running down of the total reserved value at the begining of the batch. - 16: Add transfer to the processedTransfer list recording the transfer state and running position and reserved values { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue } - 16: end foreach - end note - note over POS_MGMT,DB - Once the outcome for all transfers is known,update the Participant's position and remove the reserved amount associated with the batch - (If there are any alarm limits, process those returning limits in which the threshold has been breached) - Do a bulk insert of the trasnferStateChanges associated with processing, using the result to complete the participantPositionChange and bulk insert of these to persist the running position - end note - POS_MGMT->POS_MGMT: Assess any limit thresholds on the final position\nadding to alarm list if triggered - - ' DB Trans: This is where 2nd DB Transaction would start in 2 DB transacation future model for horizontal scaling - POS_MGMT->DB: Persist latest position **value** and **reservedValue** to DB for Payer - hnote over DB #lightyellow - UPDATE **participantPosition** - SET value += sumRESERVED, - reservedValue -= sumTransfersInBatch - end note - activate DB - deactivate DB - - POS_MGMT -> DB: Bulk persist transferStateChange for all processedTransfers - hnote over DB #lightyellow - batch INSERT **transferStateChange** - select for update from transfer table where transferId in ([transferBatch.transferId,...]) - build list of transferStateChanges from transferBatch - - end note - activate DB - deactivate DB - - POS_MGMT->POS_MGMT: Populate batchParticipantPositionChange from the resultant transferStateChange and the earlier processedTransfer list - - note right of POS_MGMT #lightgray - Effectively: - SET transferStateChangeId = processedTransfer.transferStateChangeId, - participantPositionId = preparedTransfer.participantPositionId, - value = preparedTransfer.positionValue, - reservedValue = preparedTransfer.positionReservedValue - end note - POS_MGMT -> DB: Bulk persist the participant position change for all processedTransfers - hnote over DB #lightyellow - batch INSERT **participantPositionChange** - end note - activate DB - deactivate DB - ' DB Trans: This is where 2nd DB Transaction would end in 2 DB transacation future model for horizontal scaling - end - POS_MGMT --> POS_HANDLER: Return a map of transferIds and their transferStateChanges - deactivate POS_MGMT - alt Calculate & Validate Latest Position Prepare (success) - note right of POS_HANDLER #yellow - Message: - { - id: - from: , - to: , - type: application/json - content: { - headers: , - payload: - }, - metadata: { - event: { - id: , - responseTo: , - type: transfer, - action: prepare, - createdAt: , - state: { - status: "success", - code: 0 - } - } - } - } - end note - POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 - activate TOPIC_NOTIFICATIONS - deactivate TOPIC_NOTIFICATIONS - else Calculate & Validate Latest Position Prepare (failure) - note right of POS_HANDLER #red: Validation failure! - - group Persist Transfer State (with transferState='ABORTED' on position check fail) - POS_HANDLER -> POS_DAO: Request to persist transfer\nError code: 2003 - activate POS_DAO - note right of POS_HANDLER #lightgray - transferStateChange.state = "ABORTED", - transferStateChange.reason = "Net Debit Cap exceeded by this request at this time, please try again later" - end note - POS_DAO -> DB: Persist transfer state - hnote over DB #lightyellow - transferStateChange - end note - activate DB - deactivate DB - POS_DAO --> POS_HANDLER: Return success - deactivate POS_DAO - end - - note right of POS_HANDLER #yellow - Message: - { - id: - from: , - to: , - type: application/json - content: { - headers: , - payload: { - "errorInformation": { - "errorCode": 4001, - "errorDescription": "Payer FSP insufficient liquidity", - "extensionList": - } - }, - metadata: { - event: { - id: , - responseTo: , - type: notification, - action: prepare, - createdAt: , - state: { - status: 'error', - code: - description: - } - } - } - } - end note - POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError code: 2003 - activate TOPIC_NOTIFICATIONS - deactivate TOPIC_NOTIFICATIONS - deactivate POS_HANDLER - end -end -deactivate POS_HANDLER -@enduml diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml b/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml deleted file mode 100644 index 647cd0d20..000000000 --- a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml +++ /dev/null @@ -1,182 +0,0 @@ -/'***** - License - -------------- - Copyright © 2017 Bill & Melinda Gates Foundation - The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - Contributors - -------------- - This is the official list of the Mojaloop project contributors for this file. - Names of the original copyright holders (individuals or organizations) - should be listed with a '*' in the first column. People who have - contributed from an organization can be listed under the organization - that actually holds the copyright for their contributions (see the - Gates Foundation organization for an example). Those individuals should have - their names indented and be marked with a '-'. Email address can be added - optionally within square brackets . - * Gates Foundation - - Name Surname - - * Georgi Georgiev - * Miguel de Barros - -------------- - ******'/ - -@startuml -' declate title -title 1.1.1.b. Prepare Handler Consume (batch messages) - -autonumber - -' Actor Keys: -' boundary - APIs/Interfaces, etc -' collections - Kafka Topics -' control - Kafka Consumers -' entity - Database Access Objects -' database - Database Persistance Store - -' declare actors -collections "topic-transfer-prepare" as TOPIC_TRANSFER_PREPARE -control "Prepare Event Handler" as PREP_HANDLER -collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION -collections "Event-Topic" as TOPIC_EVENTS -collections "Notification-Topic" as TOPIC_NOTIFICATIONS -entity "Position DAO" as POS_DAO -entity "Participant DAO" as PARTICIPANT_DAO -database "Central Store" as DB - -box "Central Service" #LightYellow - participant TOPIC_TRANSFER_PREPARE - participant PREP_HANDLER - participant TOPIC_TRANSFER_POSITION - participant TOPIC_EVENTS - participant TOPIC_NOTIFICATIONS - participant POS_DAO - participant PARTICIPANT_DAO - participant DB -end box - -' start flow -activate PREP_HANDLER -group Prepare Handler Consume - TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume Prepare event batch of messages for Payer - activate TOPIC_TRANSFER_PREPARE - deactivate TOPIC_TRANSFER_PREPARE - group Persist Event Information - ||| - PREP_HANDLER -> TOPIC_EVENTS: Publish event information - ref over PREP_HANDLER, TOPIC_EVENTS : Event Handler Consume\n - ||| - end - - group Fetch batch Payer information - PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve batch of Payer Participant details (if it exists) - activate PARTICIPANT_DAO - PARTICIPANT_DAO -> DB: Request Participant details - hnote over DB #lightyellow - participant - end note - activate DB - PARTICIPANT_DAO <-- DB: Return Participant details if it exists - deactivate DB - PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists - deactivate PARTICIPANT_DAO - PREP_HANDLER <-> PREP_HANDLER: Validate Payer - PREP_HANDLER -> PREP_HANDLER: store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYER - end - - group Fetch batch Payee information - PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve batch of Payee Participant details (if it exists) - activate PARTICIPANT_DAO - PARTICIPANT_DAO -> DB: Request Participant details - hnote over DB #lightyellow - participant - end note - activate DB - PARTICIPANT_DAO <-- DB: Return Participant details if it exists - deactivate DB - PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists - deactivate PARTICIPANT_DAO - PREP_HANDLER <-> PREP_HANDLER: Validate Payee - PREP_HANDLER -> PREP_HANDLER: store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYEE - end - - group Fetch batch of transfers - PREP_HANDLER -> POS_DAO: Request to retrieve batch of Transfers (if it exists) - activate POS_DAO - POS_DAO -> DB: Request batch of Transfers - hnote over DB #lightyellow - transfer - end note - activate DB - POS_DAO <-- DB: Return batch of Transfers (if it exists) - deactivate DB - POS_DAO --> PREP_HANDLER: Return batch of Transfer (if it exists) - deactivate POS_DAO - PREP_HANDLER -> PREP_HANDLER: store result set in var: $LIST_TRANSFERS - end - - loop for each message in batch - - group Validate Prepare Transfer - group Validate Payer - PREP_HANDLER <-> PREP_HANDLER: Validate Payer against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYER - end - group Validate Payee - PREP_HANDLER <-> PREP_HANDLER: Validate Payee against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYEE - end - group Duplicate check - PREP_HANDLER <-> PREP_HANDLER: Validate duplicate Check against in-memory var $LIST_TRANSFERS - end - PREP_HANDLER <-> PREP_HANDLER: Validate amount - PREP_HANDLER <-> PREP_HANDLER: Validate crypto-condition - PREP_HANDLER <-> PREP_HANDLER: Validate message signature (to be confirmed in future requirement) - end - - group Persist Transfer State (with transferState='RECEIVED' on validation pass) - PREP_HANDLER -> POS_DAO: Request to persist transfer - activate POS_DAO - POS_DAO -> DB: Persist transfer - hnote over DB #lightyellow - transferStateChange - end note - activate DB - deactivate DB - POS_DAO --> PREP_HANDLER: Return success - deactivate POS_DAO - end - - note right of PREP_HANDLER #yellow - Message: - { - id: - from: , - to: , - type: application/json - content: { - headers: , - payload: - }, - metadata: { - event: { - id: , - responseTo: , - type: position, - action: prepare, - createdAt: , - state: { - status: "success", - code: 0 - } - } - } - } - end note - PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer - activate TOPIC_TRANSFER_POSITION - deactivate TOPIC_TRANSFER_POSITION - end -end -deactivate PREP_HANDLER -@enduml diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml b/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml deleted file mode 100644 index a312d219d..000000000 --- a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml +++ /dev/null @@ -1,145 +0,0 @@ -/'***** - License - -------------- - Copyright © 2017 Bill & Melinda Gates Foundation - The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - Contributors - -------------- - This is the official list of the Mojaloop project contributors for this file. - Names of the original copyright holders (individuals or organizations) - should be listed with a '*' in the first column. People who have - contributed from an organization can be listed under the organization - that actually holds the copyright for their contributions (see the - Gates Foundation organization for an example). Those individuals should have - their names indented and be marked with a '-'. Email address can be added - optionally within square brackets . - * Gates Foundation - - Name Surname - - * Georgi Georgiev - * Miguel de Barros - -------------- - ******'/ - -@startuml -' declate title -title 1.1.2.b. Position Handler Consume (batch messages) - -autonumber - -' Actor Keys: -' boundary - APIs/Interfaces, etc -' collections - Kafka Topics -' control - Kafka Consumers -' entity - Database Access Objects -' database - Database Persistance Store - -' declare actors -collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION -control "Position Event Handler" as POS_HANDLER -collections "Transfer-Topic" as TOPIC_TRANSFERS -entity "Position DAO" as POS_DAO -entity "Event-Topic" as TOPIC_EVENTS -collections "Notification-Topic" as TOPIC_NOTIFICATIONS -entity "Transfer DAO" as TRANS_DAO -database "Central Store" as DB - -box "Central Service" #LightYellow - participant TOPIC_TRANSFER_POSITION - participant POS_HANDLER - participant TOPIC_TRANSFERS - participant TOPIC_EVENTS - participant TOPIC_NOTIFICATIONS - participant POS_DAO - participant TRANS_DAO - participant DB -end box - -' start flow -activate POS_HANDLER -group Position Handler Consume - TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event batch of messages for Payer - activate TOPIC_TRANSFER_POSITION - deactivate TOPIC_TRANSFER_POSITION - - group Persist Event Information - ||| - POS_HANDLER -> TOPIC_EVENTS: Publish event information - ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n - ||| - end - - loop for each message in batch - group Calculate position and persist change - POS_HANDLER -> POS_DAO: Request latest position from DB for Payer - activate POS_DAO - POS_DAO -> DB: Retrieve latest position from DB for Payer - hnote over DB #lightyellow - transferPosition - end note - activate DB - deactivate DB - POS_DAO --> POS_HANDLER: Return latest position - deactivate POS_DAO - - POS_HANDLER <-> POS_HANDLER: Calculate latest position (lpos) by incrementing transfer for prepare - POS_HANDLER <-> POS_HANDLER: Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap - - POS_HANDLER -> POS_DAO: Request to persist latest position for Payer - activate POS_DAO - POS_DAO -> DB: Persist latest position to DB for Payer - hnote over DB #lightyellow - transferPosition - end note - activate DB - deactivate DB - POS_DAO --> POS_HANDLER: Return success - deactivate POS_DAO - end - group Persist Transfer State (with transferState='RESERVED' on position check pass) - POS_HANDLER -> TRANS_DAO: Request to persist batch transfer - activate TRANS_DAO - TRANS_DAO -> DB: Persist batch transfer - hnote over DB #lightyellow - transferStateChange - end note - activate DB - deactivate DB - TRANS_DAO --> POS_HANDLER: Return success - deactivate TRANS_DAO - end - note right of POS_HANDLER #yellow - Message: - { - id: - from: , - to: , - type: application/json - content: { - headers: , - payload: - }, - metadata: { - event: { - id: , - responseTo: , - type: transfer, - action: prepare, - createdAt: , - state: { - status: "success", - code: 0 - } - } - } - } - end note - POS_HANDLER -> TOPIC_TRANSFERS: Publish Transfer event - activate TOPIC_TRANSFERS - deactivate TOPIC_TRANSFERS - end -end -deactivate POS_HANDLER -@enduml diff --git a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml b/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml deleted file mode 100644 index ec71dbe29..000000000 --- a/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml +++ /dev/null @@ -1,104 +0,0 @@ -/'***** - License - -------------- - Copyright © 2017 Bill & Melinda Gates Foundation - The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - Contributors - -------------- - This is the official list of the Mojaloop project contributors for this file. - Names of the original copyright holders (individuals or organizations) - should be listed with a '*' in the first column. People who have - contributed from an organization can be listed under the organization - that actually holds the copyright for their contributions (see the - Gates Foundation organization for an example). Those individuals should have - their names indented and be marked with a '-'. Email address can be added - optionally within square brackets . - * Gates Foundation - - Name Surname - - * Georgi Georgiev - * Miguel de Barros - -------------- - ******'/ - -@startuml -' declate title -title 1.1.4.b. Send notification to Participant (Payer/Payee) (batch messages) - -autonumber - -' Actor Keys: -' boundary - APIs/Interfaces, etc -' collections - Kafka Topics -' control - Kafka Consumers -' entity - Database Access Objects -' database - Database Persistance Store - -' declare actors -actor "DFSP(n)\nParticipant" as DFSP -control "ML API Notification Event Handler" as NOTIFY_HANDLER -boundary "Central Service API" as CSAPI -collections "Notification-Topic" as TOPIC_NOTIFICATIONS -collections "Event-Topic" as TOPIC_EVENTS -entity "Notification DAO" as NOTIFY_DAO -database "Central Store" as DB - -box "Financial Service Provider" #lightGray - participant DFSP -end box - -box "ML API Adapter Service" #LightBlue - participant NOTIFY_HANDLER -end box - -box "Central Service" #LightYellow -participant TOPIC_NOTIFICATIONS - participant CSAPI - participant TOPIC_EVENTS - participant EVENT_DAO - participant NOTIFY_DAO - participant DB -end box - -' start flow -activate NOTIFY_HANDLER -group Send notification to Participant - TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: **Consume Notifications event batch of messages for Participant** - activate TOPIC_NOTIFICATIONS - deactivate TOPIC_NOTIFICATIONS - loop for each message in batch - group Persist Event Information - NOTIFY_HANDLER -> CSAPI: Request to persist event information - POST - /events - activate CSAPI - CSAPI -> TOPIC_EVENTS: Publish event information - activate TOPIC_EVENTS - ||| - ref over TOPIC_EVENTS : Event Handler Consume\n - ||| - TOPIC_EVENTS --> CSAPI: Return success - deactivate TOPIC_EVENTS - CSAPI --> NOTIFY_HANDLER: Return success - deactivate CSAPI - end - NOTIFY_HANDLER -> CSAPI: Request Notifications details for Participant - GET - /notifications/DFPS(n) - activate CSAPI - CSAPI -> NOTIFY_DAO: Fetch Notifications details for Participant - activate NOTIFY_DAO - NOTIFY_DAO -> DB: Fetch Notifications details for Participant - activate DB - hnote over DB #lightyellow - transferPosition - end note - DB --> NOTIFY_DAO: Retrieved Notification details for Participant - 'deactivate DB - NOTIFY_DAO --> CSAPI: Return Notifications details for Participant - deactivate NOTIFY_DAO - CSAPI --> NOTIFY_HANDLER: Return Notifications details for Participant - deactivate CSAPI - NOTIFY_HANDLER --> DFSP: Callback with Prepare result to Participant to specified URL - PUT - />/transfers - end -end -deactivate NOTIFY_HANDLER -@enduml diff --git a/mojaloop-technical-overview/central-ledger/transfers/1.1.0-prepare-transfer-request.md b/mojaloop-technical-overview/central-ledger/transfers/1.1.0-prepare-transfer-request.md deleted file mode 100644 index b9e886f76..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/1.1.0-prepare-transfer-request.md +++ /dev/null @@ -1,17 +0,0 @@ -# Prepare Transfer Request - -Sequence design diagram for Prepare Transfer Request process. - -## References within Sequence Diagram - -* [Prepare Handler Consume (1.1.1.a)](1.1.1.a-prepare-handler-consume.md) -* [Prepare Handler Consume (1.1.1.b)](1.1.1.b-prepare-handler-consume.md) -* [Position Handler Consume (1.1.2.a)](1.1.2.a-position-handler-consume.md) -* [Position Handler Consume (1.1.2.b)](1.1.2.b-position-handler-consume.md) -* [Send notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) -* [Send notification to Participant (1.1.4.b)](1.1.4.b-send-notification-to-participant.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md b/mojaloop-technical-overview/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md deleted file mode 100644 index 1dba54a81..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md +++ /dev/null @@ -1,12 +0,0 @@ -# Prepare handler consume - -Sequence design diagram for Prepare Handler Consume process. - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md b/mojaloop-technical-overview/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md deleted file mode 100644 index b010006d0..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md +++ /dev/null @@ -1,12 +0,0 @@ -# Prepare handler consume - -Sequence design diagram for Prepare Handler Consume process. - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/1.1.2.a-position-handler-consume.md b/mojaloop-technical-overview/central-ledger/transfers/1.1.2.a-position-handler-consume.md deleted file mode 100644 index 960c51ca7..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/1.1.2.a-position-handler-consume.md +++ /dev/null @@ -1,12 +0,0 @@ -# Position handler consume - -Sequence design diagram for Position Handler Consume process. - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/1.1.2.b-position-handler-consume.md b/mojaloop-technical-overview/central-ledger/transfers/1.1.2.b-position-handler-consume.md deleted file mode 100644 index d3173f66d..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/1.1.2.b-position-handler-consume.md +++ /dev/null @@ -1,12 +0,0 @@ -# Position handler consume - -Sequence design diagram for Position Handler Consume process. - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md b/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md deleted file mode 100644 index ab3653ed0..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md +++ /dev/null @@ -1,12 +0,0 @@ -# Send Notification to Participant - -Sequence design diagram for the Send Notification to Participant request. - -## References within Sequence Diagram - -* [9.1.0-event-handler-consume](../../central-event-processor/9.1.0-event-handler-placeholder.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md b/mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md deleted file mode 100644 index bac639f0c..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md +++ /dev/null @@ -1,12 +0,0 @@ -# Send Notification to Participant - -Sequence design diagram for the Send Notification to Participant request. - -## References within Sequence Diagram - -* [9.1.0-event-handler-consume](../../central-event-processor/9.1.0-event-handler-placeholder.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.md b/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.md deleted file mode 100644 index aa37559a3..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/1.3.0-position-handler-consume.md +++ /dev/null @@ -1,15 +0,0 @@ -# Position Handler Consume - -Sequence design diagram for Position Handler Consume process. - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) -* [Prepare Position Handler Consume (1.3.1)](1.3.1-prepare-position-handler-consume.md) -* [Fufil Position Handler Consume (1.3,2)](1.3.2-fulfil-position-handler-consume.md) -* [Abort Position Handler Consume (1.3,3)](1.3.3-abort-position-handler-consume.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md b/mojaloop-technical-overview/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md deleted file mode 100644 index 79689403a..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md +++ /dev/null @@ -1,8 +0,0 @@ -# Prepare Position Handler Consume - -Sequence design diagram for Prepare Position Handler Consume process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md b/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md deleted file mode 100644 index 9320beb8f..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md +++ /dev/null @@ -1,8 +0,0 @@ -# Fulfil Position Handler Consume - -Sequence design diagram for Fulfil Position Handler Consume process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-ledger/transfers/1.3.3-abort-position-handler-consume.md b/mojaloop-technical-overview/central-ledger/transfers/1.3.3-abort-position-handler-consume.md deleted file mode 100644 index 1089efeb4..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/1.3.3-abort-position-handler-consume.md +++ /dev/null @@ -1,8 +0,0 @@ -# Abort Position Handler Consume - -Sequence design diagram for Abort Position Handler Consume process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request.md b/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request.md deleted file mode 100644 index 53dbce24f..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/2.1.0-fulfil-transfer-request.md +++ /dev/null @@ -1,14 +0,0 @@ -# Fulfil Transfer Request success - -Sequence design diagram for the Fulfil Success Transfer request. - -## References within Sequence Diagram - -* [Fulfil Handler Consume (Success) (2.1.1)](2.1.1-fulfil-handler-consume.md) -* [Position Handler Consume (Success) (1.3.2)](1.3.2-fulfil-position-handler-consume.md) -* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume.md b/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume.md deleted file mode 100644 index b702f8366..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/2.1.1-fulfil-handler-consume.md +++ /dev/null @@ -1,14 +0,0 @@ -# Fulfil Handler Consume (Success) - -Sequence design diagram for the Fulfil Handler Consume process. - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) -* [seq-signature-validation](../../central-event-processor/signature-validation.md) -* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md b/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md deleted file mode 100644 index d31ba9ce2..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md +++ /dev/null @@ -1,14 +0,0 @@ -# Payee sends a Fulfil Reject Transfer request - -Sequence design diagram for the Fulfil Reject Transfer process. - -## References within Sequence Diagram - -* [Fulfil Handler Consume (Reject/Abort)(2.2.1)](2.2.1-fulfil-reject-handler.md) -* [Position Handler Consume (Reject)(1.3.3)](1.3.3-abort-position-handler-consume.md) -* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md b/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md deleted file mode 100644 index 55f445174..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md +++ /dev/null @@ -1,14 +0,0 @@ -# Payee sends a PUT call on /error end-point for a Transfer request - -Sequence design diagram for the Fulfil Reject Transfer process. - -## References within Sequence Diagram - -* [Fulfil Handler Consume (Reject/Abort)(2.2.1)](2.2.1-fulfil-reject-handler.md) -* [Position Handler Consume (Reject)(1.3.3)](1.3.3-abort-position-handler-consume.md) -* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler.md b/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler.md deleted file mode 100644 index 65bce91aa..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/2.2.1-fulfil-reject-handler.md +++ /dev/null @@ -1,14 +0,0 @@ -## Fulfil Handler Consume (Reject/Abort) - -Sequence design diagram for the Fulfil Handler Consume Reject/Abort process. - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) -* [seq-signature-validation](../../central-event-processor/signature-validation.md) -* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/2.3.0-transfer-timeout.md b/mojaloop-technical-overview/central-ledger/transfers/2.3.0-transfer-timeout.md deleted file mode 100644 index 28ecf4ab7..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/2.3.0-transfer-timeout.md +++ /dev/null @@ -1,14 +0,0 @@ -## Transfer Timeout - -Sequence design diagram for the Transfer Timeout process. - -## References within Sequence Diagram - -* [Timeout Handler Consume (2.3.1)](2.3.1-timeout-handler-consume.md) -* [Position Handler Consume (Timeout)(1.3.3)](1.3.3-abort-position-handler-consume.md) -* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/2.3.1-timeout-handler-consume.md b/mojaloop-technical-overview/central-ledger/transfers/2.3.1-timeout-handler-consume.md deleted file mode 100644 index a77dd359e..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/2.3.1-timeout-handler-consume.md +++ /dev/null @@ -1,12 +0,0 @@ -## Timeout Handler Consume - -Sequence design diagram for the Timeout Handler Consume process. - -## References within Sequence Diagram - -* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-ledger/transfers/README.md b/mojaloop-technical-overview/central-ledger/transfers/README.md deleted file mode 100644 index 6d770e2fd..000000000 --- a/mojaloop-technical-overview/central-ledger/transfers/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Mojaloop Transfer operations. - -Operational processes that is the core of the transfer operational process; - -- Prepare process -- Fulfil process -- Notifications process -- Reject/Abort process \ No newline at end of file diff --git a/mojaloop-technical-overview/central-settlements/README.md b/mojaloop-technical-overview/central-settlements/README.md deleted file mode 100644 index ff260b960..000000000 --- a/mojaloop-technical-overview/central-settlements/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Central-Settlements Service - -The Central Settlements service is part of the Mojaloop project and deployment. - -* The central settlements service exposes Settlement API to manage the settlements between FSPs and the Central Hub. -* The service manages Settlement Windows and Settlements Event Triggers and provides information about FSPs accounts and settlements. - -## 1. Settlement Process Design - -### 1.1. Architecture overview - -![The Settlements Architecture](./assets/diagrams/architecture/Arch-Mojaloop-Settlements-PI4.svg) - -## 2. Funds In/Out - -Record Funds In and Record Funds Out operations are used respectively to deposit and withdraw funds into participant SETTLEMENT ledgers. The balance of the SETTLEMENT account relates to the NET_DEBIT_CAP set by the switch for every participant of the scheme. NET_DEBIT_CAP value is always lower or equal to the SETTLEMENT value. On the other side, the balance of the participant's POSITION account is limited to the value of the NET_DEBIT_CAP. - -## 3. API Specification - -Refer to **Central Settlements API** in the [API Specifications](../../api/README.md#central-settlements-api) section. diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/funds-in-prepare-reserve-commit.md b/mojaloop-technical-overview/central-settlements/funds-in-out/funds-in-prepare-reserve-commit.md deleted file mode 100644 index 64288328a..000000000 --- a/mojaloop-technical-overview/central-settlements/funds-in-out/funds-in-prepare-reserve-commit.md +++ /dev/null @@ -1,8 +0,0 @@ -# Funds In - Prepare, Reserve, Commit - -Funds In operation performs all the stages of the transfer (prepare, reserve and commit) at once. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.1-in.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-abort.md b/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-abort.md deleted file mode 100644 index ad93a4b73..000000000 --- a/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-abort.md +++ /dev/null @@ -1,8 +0,0 @@ -# Funds Out - Abort - -Funds out abort of a prepared reconciliation transfer. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.3-out-abort.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-commit.md b/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-commit.md deleted file mode 100644 index 5a10b0a3d..000000000 --- a/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-commit.md +++ /dev/null @@ -1,8 +0,0 @@ -# Funds Out - Commit - -Funds out commit of a prepared reconciliation transfer. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.2-out-commit.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-prepare-reserve.md b/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-prepare-reserve.md deleted file mode 100644 index 5fb1ad08e..000000000 --- a/mojaloop-technical-overview/central-settlements/funds-in-out/funds-out-prepare-reserve.md +++ /dev/null @@ -1,9 +0,0 @@ -# Funds Out - Prepare & Reserve - -Funds Out operation performs the prepare and reserve stages of the transfer at once. But the commit of the transfer or the abort operation are separate processes. - -## Sequence Diagram - - -{% uml src="mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.2.1-out-prepare-reserve.plantuml" %} -{% enduml %} \ No newline at end of file diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/reconciliation-transfer-prepare.md b/mojaloop-technical-overview/central-settlements/funds-in-out/reconciliation-transfer-prepare.md deleted file mode 100644 index b4c76a93f..000000000 --- a/mojaloop-technical-overview/central-settlements/funds-in-out/reconciliation-transfer-prepare.md +++ /dev/null @@ -1,8 +0,0 @@ -# Reconciliation Transfer Prepare - -Design for Reconciliation Transfer Prepare sub-process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.a-reconciliationTransferPrepare.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/funds-in-out/transfer-state-and-position-change.md b/mojaloop-technical-overview/central-settlements/funds-in-out/transfer-state-and-position-change.md deleted file mode 100644 index 65188d67f..000000000 --- a/mojaloop-technical-overview/central-settlements/funds-in-out/transfer-state-and-position-change.md +++ /dev/null @@ -1,8 +0,0 @@ -# Transfer State and Position Change - -Design for Transfer State and Position Change sub-process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/funds-in-out/assets/diagrams/sequence/seq-recfunds-5.1.0.b-transferStateAndPositionChange.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/README.md b/mojaloop-technical-overview/central-settlements/settlement-process/README.md deleted file mode 100644 index 978920e87..000000000 --- a/mojaloop-technical-overview/central-settlements/settlement-process/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# Settlement Process - -## 1. Database Design - -### Notes: - -- `settlementWindow` - a table where all settlement windows are stored; -- `settlementWindowStateChange` - stores information regarding settlement windows state; -- `settlement` - keeps data regarding all settlements; -- `settlementSettlementWindow` - association table for settlements and settlement windows, providing connection many-to-many; -- `settlementStateChange` - tracks the settlement state change; -- `settlementTransferParticipant` - this table is used for staging data for all transfers which are to be included in a settlement; -- `settlementParticipantCurrency` - stores grouped information by participant and currency. For calculation of netAmount, the summarized data from `settlementTransferParticipant` is used; -- `settlementParticipantCurrencyStateChange` - used to track the state change of each individual settlement participant account. - -The remaining tables in the below ERD are either transfer-specific (gray) or lookup (blue) and are included as direct dependencies to depict the relation between the settlement tables and transfer specific entities. - -![Central Settlements. Service ERD](./assets/entities/central-settlements-db-schema.png) - -* [Central Settlements Service DBeaver ERD](./assets/entities/central-settlements-db-schema-dbeaver.erd) - -## 2. Sequence diagrams - -### 2.1. Settlement Windows By Params - -Used for acquiring information regarding Settlement Windows. E.g.: -1. Find the ID of the current OPEN window by querying by state and later use the information for closing that window; -2. Find all CLOSED and/or ABORTED windows to be used for creating a settlement; -3. Other reporting needs. -- [Sequence Diagram for Get Settlement Windows by Parameters](get-settlement-windows-by-params.md) - -### 2.2. Settlement Windows By Params - -Used for acquiring settlement window information when ID is present. -- [Sequence Diagram for Request Settlement Window by Id](get-settlement-window-by-id.md) - -### 2.3. Close Settlement Window - -There is always one open settlement window which groups all ongoing transfers. This functionality is used to close the currently opened window and create the next one. -- [Sequence Diagram for Close Settlement Window](post-close-settlement-window.md) - -### 2.4. Create Settlement - -The creation of settlement is possible when at least one OPEN or ABORTED window is provided. The data from all transfers in all provided windows is summarized and as a result the settlement amount is calculated per participant and currency. Depending on its sign we distinct 3 types of participants in regards to the newly created settlement: SETTLEMENT_NET_RECIPIENT, SETTLEMENT_NET_SENDER and SETTLEMENT_NET_ZERO. Newly generated id of type bigint is returned as a response together it all other information. -- [Sequence Diagram for Trigger Settlement Event](post-create-settlement.md) - -### 2.5. Request Settlement - -This endpoint is used for acquiring information regarding a settlement and all included windows and accounts/positions. The ID from the previous request is being utilized for that purpose. -- [Sequence Diagram for Get Settlement by Id](get-settlement-by-id.md) - -### 2.6. Settlement Transfer Acknowledgment - -It is used to advance the settlement through all the states initiated with the creation and finilized by settle or abort. The actual state flow is: -- PENDING_SETTLEMENT: The net settlement report for this window has been taken, with the parameter set to indicate that settlement is to be processed; -- PS_TRANSFERS_RECORDED: Record transfer entries against the Position Account and the Multi-lateral Net Settlement Account, these are the "multi-lateral net  settlement transfers" (MLNS transfers). An identifier might be provided to be past to the reference bank; -- PS_TRANSFERS_RESERVED: All the debit entries for the MLNS transfers are reserved; -- PS_TRANSFERS_COMMITTED: All the credit entries for the MLNS transfers are committed. An identifier might be received and recorded from the Settlement bank to allow reconciliation; -- SETTLING: If all accounts are not yet SETTLED, the Status of the settlement is moved to SETTLING. Note: applies only on settlement level; -- SETTLED: Final state when all outstanding accounts are SETTLED, the entire Settlement is moved to SETTLED. - -[Sequence Diagram for Acknowledgement of Settlement Transfer](put-settlement-transfer-ack.md) - -### 2.7. Settlement Abort - -- ABORTED: Final state when the settlement is not possible. Please, note the settlement might be aborted up to when no account/position has been marked as PS_TRANSFERS_COMMITTED. Also there is no possibility to mark an individual account as ABORTED, but rahter the entire settlement is ABORTED. After performing such operation there is possibility to create a new settlement by including only non-problematic ABORTED accounts - -[Sequence Diagram for Settlement Abort](put-settlement-abort.md) - -### 2.8. Request Settlement By SPA - -Used to request drill-down information regarding a settlement, participant and account. Even though participant and account are optional, the order settlement/{id}/participant/{id}/account/{id} is mandatory. - -- [Sequence Diagram for Get Settlement by Settlement/Participant/Account](get-settlement-by-spa.md) - -### 2.9. Request Settlements By Params - -This endpoint enables advanced reporting capabilities. - -- [Sequence Diagram for Query Settlements by Parameters](get-settlements-by-params.md) diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/assets/entities/central-settlements-db-schema-dbeaver.erd b/mojaloop-technical-overview/central-settlements/settlement-process/assets/entities/central-settlements-db-schema-dbeaver.erd deleted file mode 100644 index f1875c51b..000000000 --- a/mojaloop-technical-overview/central-settlements/settlement-process/assets/entities/central-settlements-db-schema-dbeaver.erd +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - COLOR LEGEND: -Green - subject specific entity -Gray - transfer specific entity -Red - settlement specific entity -Blue - lookup entity - - \ No newline at end of file diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/assets/entities/central-settlements-db-schema.png b/mojaloop-technical-overview/central-settlements/settlement-process/assets/entities/central-settlements-db-schema.png deleted file mode 100644 index 0b1e60f06..000000000 Binary files a/mojaloop-technical-overview/central-settlements/settlement-process/assets/entities/central-settlements-db-schema.png and /dev/null differ diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-id.md b/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-id.md deleted file mode 100644 index 6e086a50c..000000000 --- a/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-id.md +++ /dev/null @@ -1,8 +0,0 @@ -# Request Settlement - -Design for Get Settlement by Id process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.4.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-spa.md b/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-spa.md deleted file mode 100644 index bebda59db..000000000 --- a/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-by-spa.md +++ /dev/null @@ -1,8 +0,0 @@ -# Request Settlement By SPA - -Design for Get Settlement by Settlement/Participant/Account process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.3.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-window-by-id.md b/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-window-by-id.md deleted file mode 100644 index 75ad34793..000000000 --- a/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-window-by-id.md +++ /dev/null @@ -1,8 +0,0 @@ -# Request Settlement Window - -Design for Request Settlement Window by Id process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.1.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-windows-by-params.md b/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-windows-by-params.md deleted file mode 100644 index 4c2dcfe26..000000000 --- a/mojaloop-technical-overview/central-settlements/settlement-process/get-settlement-windows-by-params.md +++ /dev/null @@ -1,8 +0,0 @@ -# Settlement Windows By Params - -Design for Get Settlement Windows by Parameters process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.3.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/get-settlements-by-params.md b/mojaloop-technical-overview/central-settlements/settlement-process/get-settlements-by-params.md deleted file mode 100644 index 0458a88ab..000000000 --- a/mojaloop-technical-overview/central-settlements/settlement-process/get-settlements-by-params.md +++ /dev/null @@ -1,8 +0,0 @@ -# Request Settlements By Params - -Design for Query Settlements by Parameters process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.2.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/post-close-settlement-window.md b/mojaloop-technical-overview/central-settlements/settlement-process/post-close-settlement-window.md deleted file mode 100644 index 20f9d1617..000000000 --- a/mojaloop-technical-overview/central-settlements/settlement-process/post-close-settlement-window.md +++ /dev/null @@ -1,8 +0,0 @@ -# Close Settlement Window - -Design for Close Settlement Window process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-setwindow-6.1.2.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/post-create-settlement.md b/mojaloop-technical-overview/central-settlements/settlement-process/post-create-settlement.md deleted file mode 100644 index 07ab60084..000000000 --- a/mojaloop-technical-overview/central-settlements/settlement-process/post-create-settlement.md +++ /dev/null @@ -1,8 +0,0 @@ -# Create Settlement - -Design for Trigger Settlement Event process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.1.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-abort.md b/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-abort.md deleted file mode 100644 index b43b0646c..000000000 --- a/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-abort.md +++ /dev/null @@ -1,8 +0,0 @@ -# Settlement Abort - -Design for Settlement Abort process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.6.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-transfer-ack.md b/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-transfer-ack.md deleted file mode 100644 index 3c29eb012..000000000 --- a/mojaloop-technical-overview/central-settlements/settlement-process/put-settlement-transfer-ack.md +++ /dev/null @@ -1,8 +0,0 @@ -# Settlement Transfer Acknowledgment - -Design for Acknowledgement of Settlement Transfer process. - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/central-settlements/settlement-process/assets/diagrams/sequence/seq-settlement-6.2.5.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/event-framework/README.md b/mojaloop-technical-overview/event-framework/README.md deleted file mode 100644 index 2f8a9d3fb..000000000 --- a/mojaloop-technical-overview/event-framework/README.md +++ /dev/null @@ -1,231 +0,0 @@ -# Event Framework - -The purpose of the Event Framework is to provide a standard unified architecture to capture all Mojaloop events. - -_Disclaimer: This is experimental and is being implemented as a PoC. As such the design may change based on the evolution of the PoC's implementation, and any lessons learned._ - - -## 1. Requirements - -- Events will be produced by utilising a standard common library that will publish events to a sidecar component utilising a light-weight highly performant protocol (e.g. gRPC). -- Sidecar module will publish events to a singular Kafka topic that will allow for multiple handlers to consume and process the events as required. -- Kafka partitions will be determined by the event-type (e.g. log, audit, trace, errors etc). -- Each Mojaloop component will have its own tightly coupled Sidecar. -- Event messages will be produced to Kafka using the Trace-Id as the message key. This will ensure that all the messages part of the same trace (transaction) are stored in the same partition in order. - - -## 2. Architecture - -### 2.1 Overview - -![Event Framework Architecture](./assets/diagrams/architecture/architecture-event-framework.svg) - -### 2.2 Micro Service Pods - -![Pod Architecture](./assets/diagrams/architecture/architecture-event-sidecar.svg) - -### 2.3 Event Flow - -![Tracing Architecture](./assets/diagrams/architecture/architecture-event-trace.svg) - - -## 3. Event Envelope Model - -## 3.1 JSON Example - -```JSON -{ - "from": "noresponsepayeefsp", - "to": "payerfsp", - "id": "aa398930-f210-4dcd-8af0-7c769cea1660", - "content": { - "headers": { - "content-type": "application/vnd.interoperability.transfers+json;version=1.0", - "date": "2019-05-28T16:34:41.000Z", - "fspiop-source": "noresponsepayeefsp", - "fspiop-destination": "payerfsp" - }, - "payload": "data:application/vnd.interoperability.transfers+json;version=1.0;base64,ewogICJmdWxmaWxtZW50IjogIlVObEo5OGhaVFlfZHN3MGNBcXc0aV9VTjN2NHV0dDdDWkZCNHlmTGJWRkEiLAogICJjb21wbGV0ZWRUaW1lc3RhbXAiOiAiMjAxOS0wNS0yOVQyMzoxODozMi44NTZaIiwKICAidHJhbnNmZXJTdGF0ZSI6ICJDT01NSVRURUQiCn0" - }, - "type": "application/json", - "metadata": { - "event": { - "id": "3920382d-f78c-4023-adf9-0d7a4a2a3a2f", - "type": "trace", - "action": "span", - "createdAt": "2019-05-29T23:18:32.935Z", - "state": { - "status": "success", - "code": 0, - "description": "action successful" - }, - "responseTo": "1a396c07-47ab-4d68-a7a0-7a1ea36f0012" - }, - "trace": { - "service": "central-ledger-prepare-handler", - "traceId": "bbd7b2c7-3978-408e-ae2e-a13012c47739", - "parentSpanId": "4e3ce424-d611-417b-a7b3-44ba9bbc5840", - "spanId": "efeb5c22-689b-4d04-ac5a-2aa9cd0a7e87", - "startTimestamp": "2015-08-29T11:22:09.815479Z", - "finishTimestamp": "2015-08-29T11:22:09.815479Z", - "tags": { - "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", - "transctionType": "transfer", - "parentEventType": "bulk-prepare", - "parentEventAction": "prepare" - } - } - } -} -``` - -## 3.2 Schema Definition - -### 3.2.1 Object Definition: EventMessage - -| Name | Type | Mandatory (Y/N) | Description | Example | -| --- | --- | --- | --- | --- | -| id | string | Y | The id references the related message. | | -| from | string | N | If the value is not present in the destination, it means that the notification was generated by the connected node (server). | | -| to | string | Y | Mandatory for the sender and optional in the destination. The sender can ommit the value of the domain. | | -| pp | string | N | Optional for the sender, when is considered the identity of the session. Is mandatory in the destination if the identity of the originator is different of the identity of the from property. | | -| metadata | object `` | N | The sender should avoid to use this property to transport any kind of content-related information, but merely data relevant to the context of the communication. Consider to define a new content type if there's a need to include more content information into the message. | | -| type | string | Y | `MIME` declaration of the content type of the message. | | -| content | object \ | Y | The representation of the content. | | - -##### 3.2.1.1 Object Definition: MessageMetadata - -| Name | Type | Mandatory (Y/N) | Description | Example | -| --- | --- | --- | --- | --- | -| event | object `` | Y | Event information. | | -| trace | object `` | Y | Trace information. | | - -##### 3.2.1.2 Object Definition: EventMetadata - -| Name | Type | Mandatory (Y/N) | Description | Example | -| --- | --- | --- | --- | --- | -| id | string | Y | Generated UUIDv4 representing the event. | 3920382d-f78c-4023-adf9-0d7a4a2a3a2f | -| type | enum `` | Y | Type of event. | [`log`, `audit`, `error` `trace`] | -| action | enum `` | Y | Type of action. | [ `start`, `end` ] | -| createdAt | timestamp | Y | ISO Timestamp. | 2019-05-29T23:18:32.935Z | -| responseTo | string | N | UUIDv4 id link to the previous parent event. | 2019-05-29T23:18:32.935Z | -| state | object `` | Y | Object describing the state. | | - -##### 3.2.1.3 Object Definition: EventStateMetadata - -| Name | Type | Mandatory (Y/N) | Description | Example | -| --- | --- | --- | --- | --- | -| status | enum `` | Y | The id references the related message. | success | -| code | number | N | The error code as per Mojaloop specification. | 2000 | -| description | string | N | Description for the status. Normally used to include an description for an error. | Generic server error to be used in order not to disclose information that may be considered private. | - -##### 3.2.1.4 Object Definition: EventTraceMetaData - -| Name | Type | Mandatory (Y/N) | Description | Example | -| --- | --- | --- | --- | --- | -| service | string | Y | Name of service producing trace | central-ledger-prepare-handler | -| traceId | 32HEXDIGLC | Y | The end-to-end transaction identifier. | 664314d5b207d3ba722c6c0fdcd44c61 | -| spanId | 16HEXDIGLC | Y | Id for a processing leg identifier for a component or function. | 81fa25e8d66d2e88 | -| parentSpanId | 16HEXDIGLC | N | The id references the related message. | e457b5a2e4d86bd1 | -| sampled | number | N | Indicator if event message should be included in the trace `1`. If excluded it will be left the consumer to decide on sampling. | 1 | -| flags | number | N | Indicator if event message should be included in the trace flow. ( Debug `1` - this will override the sampled value ) | 0 | -| startTimestamp | datetime | N | ISO 8601 with the following format `yyyy-MM-dd'T'HH:mm:ss.SSSSSSz`. If not included the current timestamp will be taken. Represents the start timestamp of a span.| 2015-08-29T11:22:09.815479Z | -| finishTimestamp | datetime | N | ISO 8601 with the following format `yyyy-MM-dd'T'HH:mm:ss.SSSSSSz`. If not included the current timestamp will be taken. Represents the finish timestamp of a span | 2015-08-29T11:22:09.815479Z | -| tags | object `` | Y | The id references the related message. | success | - -_Note: HEXDIGLC = DIGIT / "a" / "b" / "c" / "d" / "e" / "f" ; lower case hex character. Ref: [WC3 standard for trace-context](https://www.w3.org/TR/trace-context/#field-value)._ - -##### 3.2.1.5 Object Definition: EventTraceMetaDataTags - -| Name | Type | Mandatory (Y/N) | Description | Example | -| --- | --- | --- | --- | --- | -| transactionId | string | N | Transaction Id representing either a transfer, quote, etc | 659ee338-c8f8-4c06-8aff-944e6c5cd694 | -| transactionType | string | N | The transaction type represented by the transactionId. E.g. (transfer, quote, etc) | transfer | -| parentEventType | string | N | The event-type of the parent Span. | bulk-prepare | -| parentEventAction | string | N | The event-action of the parent Span. | prepare | -| tracestate | string | N | This tag is set if EventSDK environmental variable `EVENT_SDK_TRACESTATE_HEADER_ENABLED` is `true` or if parent span context has the `tracestate` header or tag included. The tag holds updated `tracestate` header value as per the W3C trace headers specification. [More here](#411-wc3-http-headers)| `congo=t61rcWkgMzE,rojo=00f067aa0ba902b7` | -| `` | string | N | Arbitary Key-value pair for additional meta-data to be added to the trace information. | n/a | - -##### 3.2.1.6 Enum: EventStatusType - -| Enum | Description | -| --- | --- | -| success | Event was processed successfully | -| fail | Event was processed with a failure or error | - -##### 3.2.1.7 Enum: EventType - -| Enum | Description | -| --- | --- | -| log | Event representing a general log entry. | -| audit | Event to be signed and persisted into the audit store. | -| trace | Event containing trace context information to be persisted into the tracing store. | - -##### 3.2.1.8 Enum: LogEventAction - -| Enum | Description | -| --- | --- | -| info | Event representing an `info` level log entry. | -| debug | Event representing a `debug` level log entry. | -| error | Event representing an `error` level log entry. | -| verbose | Event representing a `verbose` level log entry. | -| warning | Event representing a `warning` level log entry. | -| performance | Event representing a `performance` level log entry. | - -##### 3.2.1.9 Enum: AuditEventAction - -| Enum | Description | -| --- | --- | -| default | Standard audit action. | -| start | Audit action to represent the start of a process. | -| finish | Audit action to represent the end of a process. | -| ingress | Audit action to capture ingress activity. | -| egress | Audit action to capture egress activity. | - -##### 3.2.1.10 Enum: TraceEventAction - -| Enum | Description | -| --- | --- | -| span | Event action representing a span of a trace. | - - -## 4. Tracing Design - -### 4.1 HTTP Transports - -Below find the current proposed standard HTTP Transport headers for tracing. - -Mojaloop has yet to standardise on either standard, or if it will possible support both. - -#### 4.1.1 W3C Http Headers - -Refer to the following publication for more information: https://w3c.github.io/trace-context/ - -| Header | Description | Example | -| --- | --- | --- | -| traceparent | Dash delimited string of tracing information: \-\-\-\ | 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00 | -| tracestate | Comma delimited vendor specific format captured as follows: \=\| congo=t61rcWkgMzE,rojo=00f067aa0ba902b7 | - -Note: Before this specification was written, some tracers propagated X-B3-Sampled as true or false as opposed to 1 or 0. While you shouldn't encode X-B3-Sampled as true or false, a lenient implementation may accept them. - -#### 4.1.2 B3 HTTP Headers - -Refer to the following publication for more information: https://github.com/apache/incubator-zipkin-b3-propagation - -| Header | Description | Example | -| --- | --- | --- | -| X-B3-TraceId | Encoded as 32 or 16 lower-hex characters. | a 128-bit TraceId header might look like: X-B3-TraceId: 463ac35c9f6413ad48485a3953bb6124. Unless propagating only the Sampling State, the X-B3-TraceId header is required. | -| X-B3-SpanId | Encoded as 16 lower-hex characters. | a SpanId header might look like: X-B3-SpanId: a2fb4a1d1a96d312. Unless propagating only the Sampling State, the X-B3-SpanId header is required. | -| X-B3-ParentSpanId | header may be present on a child span and must be absent on the root span. It is encoded as 16 lower-hex characters. | A ParentSpanId header might look like: X-B3-ParentSpanId: 0020000000000001 | -| X-B3-Sampled | An accept sampling decision is encoded as `1` and a deny as `0`. Absent means defer the decision to the receiver of this header. | A Sampled header might look like: X-B3-Sampled: 1. | -| X-B3-Flags | Debug is encoded as `1`. Debug implies an accept decision, so don't also send the X-B3-Sampled header. | | - -### 4.2 Kafka Transports - -Refer to `Event Envelope Model` section. This defines the message that will be sent through the Kafka transport. - -Alternatively the tracing context could be stored in Kafka headers which are only supports v0.11 or later. Note that this would break support for older versions of Kafka. - -### 4.3 Known limitations - -- Transfer tracing would be limited to each of the transfer legs (i.e. Prepare and Fulfil) as a result of the Mojaloop API specification not catering for tracing information. The trace information will be send as part of the callbacks by the Switch, but the FSPs will not be required to respond appropriately with a reciprocal trace headers. diff --git a/mojaloop-technical-overview/event-stream-processor/README.md b/mojaloop-technical-overview/event-stream-processor/README.md deleted file mode 100644 index 427b3246d..000000000 --- a/mojaloop-technical-overview/event-stream-processor/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Event Stream Processor Service - -Event Stream Processor consumes event messages from the `topic-events` topic as a result of messages published by the [event-sidecar](https://github.com/mojaloop/event-sidecar) service. Refer to [Event Framework](../event-framework/README.md) for more information on the overall architecture. - -The Service delivers logs, including audits, and traces to EFK stack with enabled APM plugin. Based on the event message type, the messages are delivered to different indexes in the Elasticsearch. - -## 1. Prerequisites - -The service logs all the events to Elasticsearch instance with enabled APM plugin. Sample docker-compose of the Elastic stack is available [here](https://github.com/mojaloop/event-stream-processor/blob/master/test/util/scripts/docker-efk/docker-compose.yml). The logs and audits are created under custom index template, while the trace data is stored to the default `apm-*` index. -Please, ensure that you have created the `mojatemplate` as it is described into the [event-stream-processor](https://github.com/mojaloop/event-stream-processor#111-create-template) service documentation. - -## 2. Architecture overview - -### 2.1. Flow overview -![Event Stream Processor flow overview](./assets/diagrams/architePcture/event-stream-processor-overview.svg) - - -### 2.2 Trace processing flow sequence diagram -{% uml src="./mojaloop-technical-overview/event-stream-processor/assets/diagrams/sequence/process-flow.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/overview/README.md b/mojaloop-technical-overview/overview/README.md deleted file mode 100644 index 78e405de9..000000000 --- a/mojaloop-technical-overview/overview/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Mojaloop Hub - -There are several components that make up the Mojaloop ecosystem. The Mojaloop Hub is the primary container and reference we use to describe the core Mojaloop components. - -The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture: - -![Current Mojaloop Architecture Overview](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg) - -_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ - -These consist of: - -* The **Mojaloop API Adapters** (**ML-API-Adapter**) provide the standard set of interfaces a DFSP can implement to connect to the system for Transfers. A DFSP that wants to connect up can adapt our example code or implement the standard interfaces into their own software. The goal is for it to be as straightforward as possible for a DFSP to connect to the interoperable network. -* The **Central Services** (**CS**) provide the set of components required to move money from one DFSP to another through the Mojaloop API Adapters. This is similar to how money moves through a central bank or clearing house in developed countries. The Central Services contains the core Central Ledger logic to move money but also will be extended to provide fraud management and enforce scheme rules. -* The **Account Lookup Service** (**ALS**) provides mechanism to resolve FSP routing information through the Particpant API or orchestrate a Party request based on an internal Participant look-up. The internal Participant look-up is handled by a number of standard Oracle adapter or services. Example Oracle adapter/service would be to look-up Participant information from Pathfinder or a Merchant Registry. These Oracle adapter or services can easily be added depending on the schema requirements. -* The **Quoting Service** (**QA**) provides Quoting is the process that determines any fees and any commission required to perform a financial transaction between two FSPs. It is always initiated by the Payer FSP to the Payee FSP, which means that the quote flows in the same way as a financial transaction. -* The **Simulator** (**SIM**) mocks several DFSP functions as follows: - - Oracle end-points for Oracle Participant CRUD operations using in-memory cache; - - Participant end-points for Oracles with support for parameterized partyIdTypes; - - Parties end-points for Payer and Payee FSPs with associated callback responses; - - Transfer end-points for Payer and Payee FSPs with associated callback responses; and - - Query APIs to verify transactions (requests, responses, callbacks, etc) to support QA testing and verification. - -On either side of the Mojaloop Hub there is sample open source code to show how a DFSP can send and receive payments and the client that an existing DFSP could host to connect to the network. diff --git a/mojaloop-technical-overview/overview/components-PI8.md b/mojaloop-technical-overview/overview/components-PI8.md deleted file mode 100644 index 383a75614..000000000 --- a/mojaloop-technical-overview/overview/components-PI8.md +++ /dev/null @@ -1,7 +0,0 @@ -# Mojaloop Hub Legacy Components - PI8 - -The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI8: - -![Mojaloop Architecture Overview PI8](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg) - -_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/mojaloop-technical-overview/quoting-service/README.md b/mojaloop-technical-overview/quoting-service/README.md deleted file mode 100644 index a6077be69..000000000 --- a/mojaloop-technical-overview/quoting-service/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Quoting Service -The **Quoting Service** (**QS**) _(refer to section `5.1`)_ as per the [Mojaloop {{ book.importedVars.mojaloop.spec.version }} Specification]({{ book.importedVars.mojaloop.spec.uri.doc }}) implements the following use-cases: -* P2P Transfers - -_Note: other use-cases as per [Mojaloop {{ book.importedVars.mojaloop.spec.version }} Specification]({{ book.importedVars.mojaloop.spec.uri.doc }}) are yet to be verified_ - -## Sequence Diagram - -{% uml src="mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml" %} -{% enduml %} diff --git a/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml b/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml deleted file mode 100644 index 38ece23b0..000000000 --- a/mojaloop-technical-overview/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml +++ /dev/null @@ -1,66 +0,0 @@ -@startuml -Title Quoting Service Sequences -participant "Payer DFSP" -participant "Switch\nQuoting\nService" as Switch -participant "Payee DFSP" - -autonumber -note over "Payer DFSP", Switch: Payer DFSP requests quote from Payee DFSP -"Payer DFSP" -\ Switch: POST /quotes -Switch --/ "Payer DFSP": 202 Accepted -Switch -> Switch: Validate Quote Request -alt quote is valid - Switch -> Switch: Persist Quote Data - note over Switch, "Payee DFSP": Switch forwards quote request to Payee DFSP\n - Switch -\ "Payee DFSP": POST /quotes - "Payee DFSP" --/ Switch: 202 Accepted - "Payee DFSP" -> "Payee DFSP": Calculate Fees/Charges - - alt Payee DFSP successfully calculates quote - - note over "Payee DFSP", Switch: Payee DFSP responds to quote request - "Payee DFSP" -\ Switch: PUT /quotes/{ID} - Switch --/ "Payee DFSP": 200 Ok - - Switch -> Switch: Validate Quote Response - - alt response is ok - - Switch -> Switch: Persist Response Data - - note over Switch, "Payer DFSP": Switch forwards quote response to Payer DFSP\n - - Switch -\ "Payer DFSP": PUT /quotes/{ID} - "Payer DFSP" --/ Switch: 200 Ok - - note over "Payer DFSP" #3498db: Payer DFSP continues\nwith transfer if quote\nis acceptable... - else response invalid - - note over Switch, "Payee DFSP": Switch returns error to Payee DFSP - - Switch -\ "Payee DFSP": PUT /quotes/{ID}/error - "Payee DFSP" --/ Switch : 200 Ok - - note over Switch, "Payee DFSP" #ec7063: Note that under this\nscenario the Payer DFSP\nmay not receive a response - - end - else Payee DFSP calculation fails or rejects the request - - note over "Payee DFSP", Switch: Payee DFSP returns error to Switch - - "Payee DFSP" -\ Switch: POST quotes/{ID}/error - Switch --/ "Payee DFSP": 202 Accepted - Switch -> Switch: Persist error data - - note over "Payer DFSP", Switch: Switch returns error to Payer DFSP - - Switch -\ "Payer DFSP": POST quotes/{ID}/error - "Payer DFSP" --/ Switch: 202 Accepted - - end -else quote invalid - note over "Payer DFSP", Switch: Switch returns error to Payer DFSP - Switch -\ "Payer DFSP": POST quotes/{ID}/error - "Payer DFSP" --/ Switch: 202 Accepted -end -@enduml diff --git a/package-lock.json b/package-lock.json index 2d26d05a8..f932d65c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9396 +1,20666 @@ { - "name": "documentation", - "version": "9.1.0", - "lockfileVersion": 1, + "name": "mojaloop-docs-vuepress", + "version": "1.0.0", + "lockfileVersion": 3, "requires": true, - "dependencies": { - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" + "packages": { + "": { + "name": "mojaloop-docs-vuepress", + "version": "1.0.0", + "license": "Apache-2.0", + "devDependencies": { + "@vuepress/plugin-back-to-top": "^1.9.10", + "@vuepress/plugin-medium-zoom": "^1.9.10", + "got": "^14.4.7", + "husky": "^9.1.7", + "markdownlint-cli": "^0.45.0", + "npm-check-updates": "^18.0.1", + "plantuml-encoder": "^1.4.0", + "svgo": "^4.0.0", + "vuepress": "^1.9.10", + "vuepress-plugin-mermaidjs": "^2.0.0-beta.2", + "vuepress-plugin-versioning": "git+https://github.com/mojaloop/vuepress-plugin-versioning.git#dcb14962a69b8e5aaf184d2d1a31ae4f43870bc1", + "vuepress-theme-titanium": "^4.11.2" } }, - "@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==" - }, - "@types/node": { - "version": "12.7.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.7.tgz", - "integrity": "sha512-4jUncNe2tj1nmrO/34PsRpZqYVnRV1svbU78cKhuQKkMntKB/AmdLyGgswcZKjFHEHGpiY8pVD8CuVI55nP54w==", - "optional": true + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } }, - "abab": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", - "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=", - "optional": true + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "accepts": { - "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.24", - "negotiator": "0.6.2" + "node_modules/@babel/compat-data": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", + "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "dev": true, + "engines": { + "node": ">=6.9.0" } }, - "acorn": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", - "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", - "optional": true + "node_modules/@babel/core": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } }, - "acorn-globals": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", - "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=", - "optional": true, - "requires": { - "acorn": "^2.1.0" + "node_modules/@babel/generator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz", + "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.3", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" } }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } }, - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" } }, - "apache-crypt": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/apache-crypt/-/apache-crypt-1.2.1.tgz", - "integrity": "sha1-1vxyqm0n2ZyVqU/RiNcx7v/6Zjw=", - "requires": { - "unix-crypt-td-js": "^1.0.0" + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", + "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "apache-md5": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.2.tgz", - "integrity": "sha1-7klza2ObTxCLbp5ibG2pkwa0FpI=" + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz", + "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "requires": { - "arr-flatten": "^1.0.1" + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" } }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "optional": true + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } }, - "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=" + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dev": true, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, + "engines": { + "node": ">=6.9.0" } }, - "bash-color": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/bash-color/-/bash-color-0.0.4.tgz", - "integrity": "sha1-6b6M4zVAytpIgXaMWb1jhlc26RM=" - }, - "basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "requires": { - "safe-buffer": "5.1.2" + "node_modules/@babel/helpers": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz", + "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" - }, - "bluebird": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", - "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==" - }, - "body-parser": { - "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.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", + "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" } }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "optional": true, - "requires": { - "hoek": "2.x.x" + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.23.0.tgz", + "integrity": "sha512-kYsT+f5ARWF6AdFmqoEEp+hpqxEB8vGmRWfw2aj78M2vTwS2uHW91EF58iFm1Z9U8Y/RrLu2XKJn46P9ca1b0w==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/plugin-syntax-decorators": "^7.22.10" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "bootprint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bootprint/-/bootprint-1.0.2.tgz", - "integrity": "sha512-zrbDC1VVvOuOAf85Vc2Ni1AQxyQr0LqV6xJ8CAUCKRGo+EN1gWjTzmGfmRbeVIBsAouGSwYUcPonhHgbQct5+A==", - "requires": { - "commander": "^2.6.0", - "customize-engine-handlebars": "^1.0.0", - "customize-engine-less": "^1.0.1", - "customize-engine-uglify": "^1.0.0", - "customize-watch": "^1.0.0", - "customize-write-files": "^1.0.0", - "debug": "^2.1.2", - "get-promise": "^1.3.1", - "js-yaml": "^3.8.2", - "live-server": "^1.2.0", - "q": "^1.4.1", - "trace-and-clarify-if-possible": "^1.0.3" - } - }, - "bootprint-base": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/bootprint-base/-/bootprint-base-1.1.0.tgz", - "integrity": "sha1-svYgtki/pvxuAnGzhxz8nPeM0DA=", - "requires": { - "bootstrap": "^3.3.2", - "cheerio": "^0.19.0", - "handlebars": "^3.0.0", - "highlight.js": "^8.4.0", - "jquery": "^2", - "json-stable-stringify": "^1.0.0", - "marked": "^0.3.3" - } - }, - "bootprint-json-schema": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/bootprint-json-schema/-/bootprint-json-schema-1.1.0.tgz", - "integrity": "sha1-UI6PoRINyW0Lwsa6g0HrzdVFhSg=", - "requires": { - "bootprint-base": "^1.0.0", - "lodash": "^4.17.2" + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "bootprint-swagger": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bootprint-swagger/-/bootprint-swagger-1.0.1.tgz", - "integrity": "sha1-ykYPsXnZDXVymWwBaFJXroDNHDM=", - "requires": { - "bootprint-json-schema": "^1.0.0", - "highlight.js": "^8.9.1", - "json-stable-stringify": "^1.0.1", - "lodash": "^3.9.3", - "m-io": "^0.3.1" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "bootstrap": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz", - "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==" + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.22.10.tgz", + "integrity": "sha512-z1KTVemBjnz+kSEilAsI4lbkPOl5TvJH7YDSY1CTIzvLWJ+KHXp+mRe8VPmfnyvqOPqar1V2gid2PleKzRUstQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==" + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", + "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "dev": true, "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "cheerio": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz", - "integrity": "sha1-dy5wFfLuKZZQltcepBdbdas1SSU=", - "requires": { - "css-select": "~1.0.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "~3.8.1", - "lodash": "^3.2.0" + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "clarify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clarify/-/clarify-2.1.0.tgz", - "integrity": "sha512-sWdsTozdtoFQbmncCXqCKeUzQbEZul/WJ8xYGVJgfIf4xMEM5q0La+Gjo2MFNOVL0FfTFteHqw6JX+9M71dAdQ==", - "optional": true, - "requires": { - "stack-chain": "^2.0.0" + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" - } + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "optional": true + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "combined-stream": { - "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" + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.15.tgz", + "integrity": "sha512-jBm1Es25Y+tVoTi5rfd5t1KLmL8ogLKpXszboWOTTtGFGz2RKnQe2yn7HbZ+kb/B8N0FVSGQo874NSlOU1T4+w==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", + "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", + "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz", + "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" } }, - "content-disposition": { - "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" + "node_modules/@babel/plugin-transform-classes": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", + "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==" + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", + "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz", + "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "optional": true, - "requires": { - "boom": "2.x.x" + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz", + "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "crypto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", - "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==" + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", + "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "css-select": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz", - "integrity": "sha1-sRIcpRhI3SZOIkTQWM7iVN7rRLA=", - "requires": { - "boolbase": "~1.0.0", - "css-what": "1.0", - "domutils": "1.4", - "nth-check": "~1.0.0" + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", + "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "css-what": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz", - "integrity": "sha1-18wt9FGAZm+Z0rFEYmOUaeAPc2w=" + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz", + "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "optional": true + "node_modules/@babel/plugin-transform-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "cssstyle": { - "version": "0.2.37", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", - "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=", - "optional": true, - "requires": { - "cssom": "0.3.x" + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz", + "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "customize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/customize/-/customize-1.1.0.tgz", - "integrity": "sha1-jn3hMVqxV336ISTqmQbs6oijyS0=", - "requires": { - "debug": "^2.2.0", - "deep-aplus": "^1.0.4", - "jsonschema": "^1.0.2", - "jsonschema-extra": "^1.2.0", - "lodash": "^3.9.3", - "m-io": "^0.3.1", - "minimatch": "^3.0.0", - "q": "^1.4.1" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "customize-engine-handlebars": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/customize-engine-handlebars/-/customize-engine-handlebars-1.0.1.tgz", - "integrity": "sha1-SAElQInR6IRi4/1vIXMpk6p7+ZY=", - "requires": { - "debug": "^2.2.0", - "handlebars": "^3.0.3", - "lodash": "^3.9.3", - "m-io": "^0.3.1", - "promised-handlebars": "^1.0.0", - "q": "^1.4.1", - "q-deep": "^1.0.1" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz", + "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "customize-engine-less": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/customize-engine-less/-/customize-engine-less-1.0.1.tgz", - "integrity": "sha1-rl//DPOSgGx9Dx1NqPfUsuZRCSk=", - "requires": { - "less": "^2.7.1", - "lodash": "^3.10.1", - "q": "^1.4.1" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", + "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "customize-engine-uglify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/customize-engine-uglify/-/customize-engine-uglify-1.0.0.tgz", - "integrity": "sha1-Eb3Mqslhn4zHCZHHGtB2K0cB+ug=", - "requires": { - "lodash": "^3.10.1", - "q": "^1.4.1", - "uglify-js": "^2.7.5" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz", + "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "customize-watch": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/customize-watch/-/customize-watch-1.0.0.tgz", - "integrity": "sha1-D6nLpHG+/6Kb+U5lVN8FwN7A9YA=", - "requires": { - "chokidar": "^1.2.0", - "customize": "^1.0.0", - "debug": "^2.2.0", - "deep-aplus": "^1.0.4", - "lodash": "^3.10.1", - "m-io": "^0.3.1", - "q": "^1.4.1" + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dev": true, "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "customize-write-files": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/customize-write-files/-/customize-write-files-1.1.0.tgz", - "integrity": "sha1-zCd89CCNT6OXJgUeQ8Z7G3QQU54=", - "requires": { - "debug": "^2.2.0", - "deep-aplus": "^1.0.4", - "m-io": "^0.3.1", - "q": "^1.4.1", - "stream-equal": "^0.1.12" + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz", + "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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" + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz", + "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz", + "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "deep-aplus": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/deep-aplus/-/deep-aplus-1.0.4.tgz", - "integrity": "sha1-4exMEKALUEa1ng3dBRnRAa4xXo8=", - "requires": { - "lodash.isplainobject": "^4.0.6" + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz", + "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "optional": true + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz", + "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", + "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", + "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "dev": true, "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz", + "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.15.tgz", + "integrity": "sha512-tEVLhk8NRZSmwQ0DJtxxhTrCht1HVo8VaMzYT4w6lwyKBuHsgoioAUA7/6eT2fRfc5/23fuGdlwIxXhRVgWr4g==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.5", + "babel-plugin-polyfill-corejs3": "^0.8.3", + "babel-plugin-polyfill-regenerator": "^0.5.2", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", - "requires": { - "domelementtype": "1" + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "domutils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.4.3.tgz", - "integrity": "sha1-CGVRN5bGswYDGFDhdVFrr4C3Km8=", - "requires": { - "domelementtype": "1" + "node_modules/@babel/plugin-transform-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "optional": true, - "requires": { - "prr": "~1.0.1" + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", + "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", + "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "escodegen": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", - "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", - "optional": true, - "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" + "node_modules/@babel/preset-env": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.20.tgz", + "integrity": "sha512-11MY04gGC4kSzlPHRfvVkNAZhUxOvm7DCJ37hPDnUENwe06npjIRAfInEMTGSb4LZK5ZgDFkv5hw0lGebHeTyg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.20", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.22.15", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.22.15", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.11", + "@babel/plugin-transform-classes": "^7.22.15", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.22.15", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.11", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.11", + "@babel/plugin-transform-for-of": "^7.22.15", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.11", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.15", + "@babel/plugin-transform-modules-systemjs": "^7.22.11", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-numeric-separator": "^7.22.11", + "@babel/plugin-transform-object-rest-spread": "^7.22.15", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.22.15", + "@babel/plugin-transform-parameters": "^7.22.15", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.10", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.10", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "@babel/types": "^7.22.19", + "babel-plugin-polyfill-corejs2": "^0.4.5", + "babel-plugin-polyfill-corejs3": "^0.8.3", + "babel-plugin-polyfill-regenerator": "^0.5.2", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "optional": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true - } + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "optional": true + "node_modules/@babel/template": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "optional": true + "node_modules/@babel/traverse": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz", + "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.3", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.3", + "@babel/types": "^7.23.3", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "requires": { - "fill-range": "^2.1.0" - } - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "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.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "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" + "node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "node_modules/@braintree/sanitize-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-3.1.0.tgz", + "integrity": "sha512-GcIY79elgB+azP74j8vqkiXz8xLFfIzbQJdlwOPisgbKT00tviJQuEghOXSMVxJ00HoYJbGswr4kcllUc4xCcg==", + "deprecated": "Potential XSS vulnerability patched in v6.0.0.", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "requires": { - "is-extglob": "^1.0.0" - } - }, - "extract-zip": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", - "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", - "requires": { - "concat-stream": "1.6.2", - "debug": "2.6.9", - "mkdirp": "0.5.1", - "yauzl": "2.4.1" + "node_modules/@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + }, + "engines": { + "node": ">=4" } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "node_modules/@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } }, - "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=" + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.0.1.tgz", + "integrity": "sha512-QWLl2P+rsCJeofkDNIT3WFmb6NrRud1SUYW8dIhXK/46XFV8Q/g7Bsvib0Askb0reRLe+WYPeeE+l5cH7SlkuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } }, - "fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.1" }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } + "@types/connect": "*", + "@types/node": "*" } }, - "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=" + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "optional": true + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } }, - "faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", - "requires": { - "websocket-driver": ">=0.5.1" + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" } }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "requires": { - "pend": "~1.2.0" + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" } }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + "node_modules/@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } }, - "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" } }, - "finalhandler": { - "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.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" + "node_modules/@types/highlight.js": { + "version": "9.12.4", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.4.tgz", + "integrity": "sha512-t2szdkwmg2JJyuCM20e8kR2X59WCE5Zkl4bzm1u1Oukjm79zpbiAv+QjnwLnuuV0WHEcX2NgUItu0pAMKuOPww==", + "dev": true + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.11", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", + "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", + "dev": true, + "dependencies": { + "@types/node": "*" } }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + "node_modules/@types/json-schema": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", + "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "dev": true }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "requires": { - "for-in": "^1.0.1" + "node_modules/@types/katex": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-10.0.3.tgz", + "integrity": "sha512-daHJk22isOUvNssVGF2zDnnSyxHhFYhtjeX4oQaKD6QzL3ZR1QSgiD1g+Q6/WSWYVogNXYDXODtbgW/WiFCtyw==", + "dev": true, + "dependencies": { + "@types/highlight.js": "^9.7.0", + "@types/linkify-it": "*", + "@types/mdurl": "*", + "highlight.js": "^9.7.0" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "node_modules/@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", + "dev": true }, - "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" + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", + "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==", + "dev": true + }, + "node_modules/@types/q": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.6.tgz", + "integrity": "sha512-IKjZ8RjTSwD4/YG+2gtj7BPFRB/lNbWKTiSj3M7U/TD2B7HfYCxvp2Zz6xA2WIY7pAuL1QOUPw8gQRbUrrq4fQ==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", + "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", + "dev": true, + "dependencies": { + "@types/mime": "*", + "@types/node": "*" } }, - "forwarded": { + "node_modules/@types/source-list-map": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" + "node_modules/@types/tapable": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", + "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==", + "dev": true + }, + "node_modules/@types/uglify-js": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.17.1.tgz", + "integrity": "sha512-GkewRA4i5oXacU/n4MA9+bLgt5/L3F1mKrYvFGm7r2ouLXhRKjuWwo9XHNnbx6WF3vlGW21S3fCvgqxvxXXc5g==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" } }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/webpack": { + "version": "4.41.33", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.33.tgz", + "integrity": "sha512-PPajH64Ft2vWevkerISMtnZ8rTs4YmRbs+23c402J0INmxDKCrhZNvwZYtzx96gY2wAtXdrK1BS2fiC8MlLr3g==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tapable": "^1", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "anymatch": "^3.0.0", + "source-map": "^0.6.0" + } }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + "node_modules/@types/webpack-dev-server": { + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/@types/webpack-dev-server/-/webpack-dev-server-3.11.6.tgz", + "integrity": "sha512-XCph0RiiqFGetukCTC3KVnY1jwLcZ84illFRMbyFzCcWl90B/76ew0tSqF46oBhnLC4obNDG7dMO0JfTN0MgMQ==", + "dev": true, + "dependencies": { + "@types/connect-history-api-fallback": "*", + "@types/express": "*", + "@types/serve-static": "*", + "@types/webpack": "^4", + "http-proxy-middleware": "^1.0.0" + } }, - "fs-extra": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", - "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^3.0.0", - "universalify": "^0.1.0" + "node_modules/@types/webpack-sources": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.7.3" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "node_modules/@types/webpack-sources/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } }, - "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha1-P17WZYPM1vQAtaANtvfoYTY+OI8=", - "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" + "node_modules/@vue/babel-helper-vue-jsx-merge-props": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz", + "integrity": "sha512-JkqXfCkUDp4PIlFdDQ0TdXoIejMtTHP67/pvxlgeY+u5k3LEdKuWZ3LK6xkxo52uDoABIVyRwqVkfLQJhk7VBA==", + "dev": true + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.1.5.tgz", + "integrity": "sha512-SgUymFpMoAyWeYWLAY+MkCK3QEROsiUnfaw5zxOVD/M64KQs8D/4oK6Q5omVA2hnvEOE0SCkH2TZxs/jnnUj7w==", + "dev": true + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.5.tgz", + "integrity": "sha512-nKs1/Bg9U1n3qSWnsHhCVQtAzI6aQXqua8j/bZrau8ywT1ilXQbK4FwEJGmU8fV7tcpuFvWmmN7TMmV1OBma1g==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5", + "@vue/babel-helper-vue-transform-on": "^1.1.5", + "camelcase": "^6.3.0", + "html-tags": "^3.3.1", + "svg-tags": "^1.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-plugin-jsx/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vue/babel-plugin-transform-vue-jsx": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.4.0.tgz", + "integrity": "sha512-Fmastxw4MMx0vlgLS4XBX0XiBbUFzoMGeVXuMV08wyOfXdikAFqBTuYPR0tlk+XskL19EzHc39SgjrPGY23JnA==", + "dev": true, "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "optional": 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" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0", + "html-tags": "^2.0.0", + "lodash.kebabcase": "^4.1.1", + "svg-tags": "^1.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-plugin-transform-vue-jsx/node_modules/html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@vue/babel-preset-app": { + "version": "4.5.19", + "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-4.5.19.tgz", + "integrity": "sha512-VCNRiAt2P/bLo09rYt3DLe6xXUMlhJwrvU18Ddd/lYJgC7s8+wvhgYs+MTx4OiAXdu58drGwSBO9SPx7C6J82Q==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.0", + "@babel/helper-compilation-targets": "^7.9.6", + "@babel/helper-module-imports": "^7.8.3", + "@babel/plugin-proposal-class-properties": "^7.8.3", + "@babel/plugin-proposal-decorators": "^7.8.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.11.0", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.0", + "@vue/babel-plugin-jsx": "^1.0.3", + "@vue/babel-preset-jsx": "^1.2.4", + "babel-plugin-dynamic-import-node": "^2.3.3", + "core-js": "^3.6.5", + "core-js-compat": "^3.6.5", + "semver": "^6.1.0" + }, + "peerDependencies": { + "@babel/core": "*", + "core-js": "^3", + "vue": "^2 || ^3.0.0-0" + }, + "peerDependenciesMeta": { + "core-js": { "optional": true }, - "yallist": { - "version": "3.0.3", - "bundled": true, + "vue": { "optional": true } } }, - "get-promise": { + "node_modules/@vue/babel-preset-jsx": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-promise/-/get-promise-1.4.0.tgz", - "integrity": "sha1-RDBFyGUwvrvtIihh7+0TwNNv9qA=", - "requires": { - "lodash": "^3.8.0", - "q": "^1.2.0" - }, + "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.4.0.tgz", + "integrity": "sha512-QmfRpssBOPZWL5xw7fOuHNifCQcNQC1PrOo/4fu6xlhlKJJKSA3HqX92Nvgyx8fqHZTUGMPHmFA+IDqwXlqkSA==", + "dev": true, "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.4.0", + "@vue/babel-sugar-composition-api-inject-h": "^1.4.0", + "@vue/babel-sugar-composition-api-render-instance": "^1.4.0", + "@vue/babel-sugar-functional-vue": "^1.4.0", + "@vue/babel-sugar-inject-h": "^1.4.0", + "@vue/babel-sugar-v-model": "^1.4.0", + "@vue/babel-sugar-v-on": "^1.4.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0", + "vue": "*" + }, + "peerDependenciesMeta": { + "vue": { + "optional": true } } }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" + "node_modules/@vue/babel-sugar-composition-api-inject-h": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.4.0.tgz", + "integrity": "sha512-VQq6zEddJHctnG4w3TfmlVp5FzDavUSut/DwR0xVoe/mJKXyMcsIibL42wPntozITEoY90aBV0/1d2KjxHU52g==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "gitbook-cli": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/gitbook-cli/-/gitbook-cli-2.3.2.tgz", - "integrity": "sha512-eyGtkY7jKHhmgpfuvgAP5fZcUob/FBz4Ld0aLRdEmiTrS1RklimN9epzPp75dd4MWpGhYvSbiwxnpyLiv1wh6A==", - "requires": { - "bash-color": "0.0.4", - "commander": "2.11.0", - "fs-extra": "3.0.1", - "lodash": "4.17.4", - "npm": "5.1.0", - "npmi": "1.0.1", - "optimist": "0.6.1", - "q": "1.5.0", - "semver": "5.3.0", - "tmp": "0.0.31", - "user-home": "2.0.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" - } + "node_modules/@vue/babel-sugar-composition-api-render-instance": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.4.0.tgz", + "integrity": "sha512-6ZDAzcxvy7VcnCjNdHJ59mwK02ZFuP5CnucloidqlZwVQv5CQLijc3lGpR7MD3TWFi78J7+a8J56YxbCtHgT9Q==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "gitbook-plugin-back-to-top-button": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/gitbook-plugin-back-to-top-button/-/gitbook-plugin-back-to-top-button-0.1.4.tgz", - "integrity": "sha1-5iGDOLDvGdWOb2YAmUNQt26ANd8=" - }, - "gitbook-plugin-changelog": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gitbook-plugin-changelog/-/gitbook-plugin-changelog-1.0.1.tgz", - "integrity": "sha512-X1wDTUfBRLiuS29SBN6e4X2A08JsGMh/KsAqBblrPQ2ltbM2Ivb6i2k9FinH4AVCdvdXEuM+KgQI8Q2tQzujtQ==", - "requires": { - "lodash": "^4.17.4", - "moment": "^2.18.1" + "node_modules/@vue/babel-sugar-functional-vue": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.4.0.tgz", + "integrity": "sha512-lTEB4WUFNzYt2In6JsoF9sAYVTo84wC4e+PoZWSgM6FUtqRJz7wMylaEhSRgG71YF+wfLD6cc9nqVeXN2rwBvw==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "gitbook-plugin-collapsible-chapters": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/gitbook-plugin-collapsible-chapters/-/gitbook-plugin-collapsible-chapters-0.1.8.tgz", - "integrity": "sha1-dxVcYcrBlRch2L9Es/ImphoeZcU=" + "node_modules/@vue/babel-sugar-inject-h": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.4.0.tgz", + "integrity": "sha512-muwWrPKli77uO2fFM7eA3G1lAGnERuSz2NgAxuOLzrsTlQl8W4G+wwbM4nB6iewlKbwKRae3nL03UaF5ffAPMA==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "gitbook-plugin-editlink": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/gitbook-plugin-editlink/-/gitbook-plugin-editlink-1.0.2.tgz", - "integrity": "sha1-ej2Bk/guYfCUF83w52h2MfW2GV4=" + "node_modules/@vue/babel-sugar-v-model": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.4.0.tgz", + "integrity": "sha512-0t4HGgXb7WHYLBciZzN5s0Hzqan4Ue+p/3FdQdcaHAb7s5D9WZFGoSxEZHrR1TFVZlAPu1bejTKGeAzaaG3NCQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.4.0", + "camelcase": "^5.0.0", + "html-tags": "^2.0.0", + "svg-tags": "^1.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "gitbook-plugin-fontsettings": { + "node_modules/@vue/babel-sugar-v-model/node_modules/html-tags": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gitbook-plugin-fontsettings/-/gitbook-plugin-fontsettings-2.0.0.tgz", - "integrity": "sha1-g1+QCuPdERCG/n7UQl7j3gJIYas=" - }, - "gitbook-plugin-include": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/gitbook-plugin-include/-/gitbook-plugin-include-0.1.0.tgz", - "integrity": "sha1-w1/0dlYKXv/e+tv2OYIknBy8dNw=", - "requires": { - "q": "*" + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==", + "dev": true, + "engines": { + "node": ">=4" } }, - "gitbook-plugin-insert-logo": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/gitbook-plugin-insert-logo/-/gitbook-plugin-insert-logo-0.1.5.tgz", - "integrity": "sha1-2q6N2kGiNtVPE5MeVwsmcpVXiFo=" - }, - "gitbook-plugin-page-toc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/gitbook-plugin-page-toc/-/gitbook-plugin-page-toc-1.1.1.tgz", - "integrity": "sha512-0ii4d4gxaLsZuWvSFyz2eLQvpjB3Sjg8pTBW8P6mT0j1jw3ifS5Jx8HvQLYrOPyolktUqmd0AebrKCur667zfw==" - }, - "gitbook-plugin-plantuml-svg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gitbook-plugin-plantuml-svg/-/gitbook-plugin-plantuml-svg-1.0.1.tgz", - "integrity": "sha512-YP3nmYI+6j2aUPk3hKkWkggIlORgGwLhvaoReZvdyVM5cvomyd9iq4leRMvxBUSwuD6I1fXyYLMGqunOIjkXbw==", - "requires": { - "js-base64": "^2.4.0", - "lodash": "^4.17.4", - "request": "^2.83.0", - "request-promise": "^4.2.2" + "node_modules/@vue/babel-sugar-v-on": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.4.0.tgz", + "integrity": "sha512-m+zud4wKLzSKgQrWwhqRObWzmTuyzl6vOP7024lrpeJM4x2UhQtRDLgYjXAw9xBXjCwS0pP9kXjg91F9ZNo9JA==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.4.0", + "camelcase": "^5.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "gitbook-plugin-search": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/gitbook-plugin-search/-/gitbook-plugin-search-2.2.1.tgz", - "integrity": "sha1-bSW1p3aZD6mP39+jfeMx944PaxM=" - }, - "gitbook-plugin-swagger": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/gitbook-plugin-swagger/-/gitbook-plugin-swagger-0.2.0.tgz", - "integrity": "sha1-g33zIY/9q9/LVu2Xr9SVYinZ0h0=", - "requires": { - "bootprint": "^1.0.0", - "bootprint-swagger": "^1.0.1" + "node_modules/@vue/compiler-sfc": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz", + "integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.23.5", + "postcss": "^8.4.14", + "source-map": "^0.6.1" + }, + "optionalDependencies": { + "prettier": "^1.18.2 || ^2.0.0" } }, - "gitbook-plugin-theme-api": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/gitbook-plugin-theme-api/-/gitbook-plugin-theme-api-1.1.2.tgz", - "integrity": "sha1-jBRaS61JoSE8AlApC5vZtyrqiPw=", - "requires": { - "cheerio": "0.20.0", - "gitbook-plugin-search": ">=2.0.0", - "lodash": "4.12.0", - "q": "1.4.1", - "q-plus": "0.0.8" - }, - "dependencies": { - "cheerio": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz", - "integrity": "sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU=", - "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "~3.8.1", - "jsdom": "^7.0.2", - "lodash": "^4.1.0" - } - }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "lodash": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.12.0.tgz", - "integrity": "sha1-K9bcRqBA9Z5obJcu0h2T3FkFMlg=" - }, - "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=" + "node_modules/@vue/compiler-sfc/node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" } }, - "gitbook-plugin-uml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gitbook-plugin-uml/-/gitbook-plugin-uml-1.0.1.tgz", - "integrity": "sha512-j9kWSFsfF7Y53LcfegQSkRUSc0cKcA93v0Sxg4wVzca7A9V1ridXiXcSeaKy7OZi386FB2mG+KihViUVZwfcCA==", - "requires": { - "crypto": "^1.0.1", - "fs-extra": "^4.0.1", - "node-plantuml": "^0.6.2", - "q": "^1.5.0" - }, - "dependencies": { - "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - } + "node_modules/@vue/component-compiler-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", + "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "consolidate": "^0.15.1", + "hash-sum": "^1.0.2", + "lru-cache": "^4.1.2", + "merge-source-map": "^1.1.0", + "postcss": "^7.0.36", + "postcss-selector-parser": "^6.0.2", + "source-map": "~0.6.1", + "vue-template-es2015-compiler": "^1.9.0" + }, + "optionalDependencies": { + "prettier": "^1.18.2 || ^2.0.0" } }, - "gitbook-plugin-variables": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gitbook-plugin-variables/-/gitbook-plugin-variables-1.1.0.tgz", - "integrity": "sha512-+G97YsciufqZQenG1TziLfKEAIpKwnxiipBOtWM0lZu8OxSR2WG4n/9zGPq3RqYAfzb1BxD6m6i0LmxmOF0vPA==", - "requires": { - "fast-glob": "^2.2.2", - "fs-extra": "^7.0.0", - "js-yaml": "^3.12.0", - "lodash": "^4.17.10", - "native-require": "^1.1.4" - }, - "dependencies": { - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - } + "node_modules/@vuepress/core": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/core/-/core-1.9.10.tgz", + "integrity": "sha512-H9ddo5fSinPb8QYl8OJFbZikMpOW84bm/U3Drzz8CnCXNtpda7CU2wX/XzOhe98G8jp45xhtZRkxOrqzBBAShA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.8.4", + "@vue/babel-preset-app": "^4.1.2", + "@vuepress/markdown": "1.9.10", + "@vuepress/markdown-loader": "1.9.10", + "@vuepress/plugin-last-updated": "1.9.10", + "@vuepress/plugin-register-components": "1.9.10", + "@vuepress/shared-utils": "1.9.10", + "@vuepress/types": "1.9.10", + "autoprefixer": "^9.5.1", + "babel-loader": "^8.0.4", + "bundle-require": "2.1.8", + "cache-loader": "^3.0.0", + "chokidar": "^2.0.3", + "connect-history-api-fallback": "^1.5.0", + "copy-webpack-plugin": "^5.0.2", + "core-js": "^3.6.4", + "cross-spawn": "^6.0.5", + "css-loader": "^2.1.1", + "esbuild": "0.14.7", + "file-loader": "^3.0.1", + "js-yaml": "^3.13.1", + "lru-cache": "^5.1.1", + "mini-css-extract-plugin": "0.6.0", + "optimize-css-assets-webpack-plugin": "^5.0.1", + "portfinder": "^1.0.13", + "postcss-loader": "^3.0.0", + "postcss-safe-parser": "^4.0.1", + "toml": "^3.0.0", + "url-loader": "^1.0.1", + "vue": "^2.6.10", + "vue-loader": "^15.7.1", + "vue-router": "^3.4.5", + "vue-server-renderer": "^2.6.10", + "vue-template-compiler": "^2.6.10", + "vuepress-html-webpack-plugin": "^3.2.0", + "vuepress-plugin-container": "^2.0.2", + "webpack": "^4.8.1", + "webpack-chain": "^6.0.0", + "webpack-dev-server": "^3.5.1", + "webpack-merge": "^4.1.2", + "webpackbar": "3.2.0" + }, + "engines": { + "node": ">=8.6" } }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "node_modules/@vuepress/core/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" + "node_modules/@vuepress/core/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" } }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "requires": { - "is-glob": "^2.0.0" + "node_modules/@vuepress/core/node_modules/js-yaml": { + "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, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" - }, - "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" + "node_modules/@vuepress/core/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } }, - "handlebars": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-3.0.7.tgz", - "integrity": "sha512-Pb/VCTFwbcm3KbD5rIzVVsbVBk7XMfhS4ZIJUfXdMF7H+UngtsofnUBfop/i24GSr3HCDG1PL0KoIX0YqEsXTg==", - "requires": { - "optimist": "^0.6.1", - "source-map": "^0.1.40", - "uglify-js": "^2.6" + "node_modules/@vuepress/core/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" } }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "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==", - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" + "node_modules/@vuepress/core/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" } }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, + "node_modules/@vuepress/core/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "has-values": { + "node_modules/@vuepress/core/node_modules/shebang-regex": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "hasha": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", - "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", - "requires": { - "is-stream": "^1.0.1", - "pinkie-promise": "^2.0.0" + "node_modules/@vuepress/core/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "optional": true, - "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" - } - }, - "highlight.js": { - "version": "8.9.1", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-8.9.1.tgz", - "integrity": "sha1-uKnFSTISqTkvAiK2SclhFJfr+4g=" - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "optional": true + "node_modules/@vuepress/core/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@vuepress/markdown": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/markdown/-/markdown-1.9.10.tgz", + "integrity": "sha512-sXTLjeZzH8SQuAL5AEH0hhsMljjNJbzWbBvzaj5yQCCdf+3sp/dJ0kwnBSnQjFPPnzPg5t3tLKGUYHyW0KiKzA==", + "dev": true, + "dependencies": { + "@vuepress/shared-utils": "1.9.10", + "markdown-it": "^8.4.1", + "markdown-it-anchor": "^5.0.2", + "markdown-it-chain": "^1.3.0", + "markdown-it-emoji": "^1.4.0", + "markdown-it-table-of-contents": "^0.4.0", + "prismjs": "^1.13.0" + } }, - "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", - "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - }, - "dependencies": { - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } + "node_modules/@vuepress/markdown-loader": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/markdown-loader/-/markdown-loader-1.9.10.tgz", + "integrity": "sha512-94BlwKc+lOaN/A5DkyA9KWHvMlMC1sWunAXE3Tv0WYzgYLDs9QqCsx7L5kLkpcOOVVm/8kBJumnXvVBwhqJddw==", + "dev": true, + "dependencies": { + "@vuepress/markdown": "1.9.10", + "loader-utils": "^1.1.0", + "lru-cache": "^5.1.1" } }, - "http-auth": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/http-auth/-/http-auth-3.1.3.tgz", - "integrity": "sha1-lFz63WZSHq+PfISRPTd9exXyTjE=", - "requires": { - "apache-crypt": "^1.1.2", - "apache-md5": "^1.0.6", - "bcryptjs": "^2.3.0", - "uuid": "^3.0.0" - } - }, - "http-errors": { - "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.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "node_modules/@vuepress/markdown-loader/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" } }, - "http-parser-js": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", - "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=" + "node_modules/@vuepress/markdown-loader/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "node_modules/@vuepress/markdown/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "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" - } - }, - "image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", - "optional": true + "node_modules/@vuepress/markdown/node_modules/entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" + "node_modules/@vuepress/markdown/node_modules/linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" + "node_modules/@vuepress/markdown/node_modules/markdown-it": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" } }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "requires": { - "binary-extensions": "^1.0.0" + "node_modules/@vuepress/plugin-active-header-links": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-active-header-links/-/plugin-active-header-links-1.9.10.tgz", + "integrity": "sha512-2dRr3DE2UBFXhyMtLR3sGTdRyDM8YStuY6AOoQmoSgwy1IHt7PO7ypOuf1akF+1Nv8Q2aISU06q6TExZouu3Mw==", + "dev": true, + "dependencies": { + "@vuepress/types": "1.9.10", + "lodash.debounce": "^4.0.8" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "^3.0.2" + "node_modules/@vuepress/plugin-back-to-top": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-back-to-top/-/plugin-back-to-top-1.9.10.tgz", + "integrity": "sha512-iInIp66wu717CAnT2pyd9Bs/vAgrUBOBIQ7WMnfJo07cW/ZIothpyrSHnpCRSsfJ/jLivMPqW0pviqppt64BzQ==", + "dev": true, + "dependencies": { + "@vuepress/types": "1.9.10", + "lodash.debounce": "^4.0.8" } }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, + "node_modules/@vuepress/plugin-last-updated": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-last-updated/-/plugin-last-updated-1.9.10.tgz", + "integrity": "sha512-YxzWGF/OfU6WsHSynZFn74NGGp7dY27Bjy9JyyFo8wF5+2V1gpyDjveHKHGKugS/pMXlxfjzhv9E2Wmy9R7Iog==", + "dev": true, "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } + "@vuepress/types": "1.9.10", + "cross-spawn": "^6.0.5" } }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "requires": { - "is-primitive": "^2.0.0" + "node_modules/@vuepress/plugin-last-updated/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" - }, - "is-glob": { + "node_modules/@vuepress/plugin-last-updated/node_modules/path-key": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "requires": { - "is-extglob": "^1.0.0" + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" } }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "requires": { - "kind-of": "^3.0.2" + "node_modules/@vuepress/plugin-last-updated/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" } }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "^3.0.1" - }, + "node_modules/@vuepress/plugin-last-updated/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-typedarray": { + "node_modules/@vuepress/plugin-last-updated/node_modules/shebang-regex": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + "node_modules/@vuepress/plugin-last-updated/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "node_modules/@vuepress/plugin-medium-zoom": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-medium-zoom/-/plugin-medium-zoom-1.9.10.tgz", + "integrity": "sha512-/MsICWZ/mUTs+ZdqqA1AVtWAtNL5ksgnnGR2X24LnXaPJp+M1IB2ETcyNKh264YVODSrmVsS/Y+kbCRK0qKkdg==", + "dev": true, + "dependencies": { + "@vuepress/types": "1.9.10", + "medium-zoom": "^1.0.4" + } }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "node_modules/@vuepress/plugin-nprogress": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-nprogress/-/plugin-nprogress-1.9.10.tgz", + "integrity": "sha512-I1kkm6yWUQd7vwiV3lEDVpVP0Lr04K0zlczU502lDUa1RufSZ7vt+mlF5fOM28GqT+pKTEToWmm+VNT/R3qvMQ==", + "dev": true, + "dependencies": { + "@vuepress/types": "1.9.10", + "nprogress": "^0.2.0" + } }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" + "node_modules/@vuepress/plugin-register-components": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-register-components/-/plugin-register-components-1.9.10.tgz", + "integrity": "sha512-sgdJ5OydTPZAoTkselpvVP3Xsd6bfZ0FpaxOTinal0gJ99h49lvLu9bvzMx13rdGRFO/kRXn0qQQpwKTAfTPqA==", + "dev": true, + "dependencies": { + "@vuepress/shared-utils": "1.9.10", + "@vuepress/types": "1.9.10" } }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "node_modules/@vuepress/plugin-search": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-search/-/plugin-search-1.9.10.tgz", + "integrity": "sha512-bn2XJikaRgQZXvu8upCjOWrxbLHIRTqnJ3w7G0mo6jCYWGVsHNo6XhVpqylpLR2PWnHT/ImO2bGo38/5Bag/tQ==", + "dev": true, + "dependencies": { + "@vuepress/types": "1.9.10" + } }, - "jquery": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz", - "integrity": "sha1-LInWiJterFIqfuoywUUhVZxsvwI=" + "node_modules/@vuepress/shared-utils": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/shared-utils/-/shared-utils-1.9.10.tgz", + "integrity": "sha512-M9A3DocPih+V8dKK2Zg9FJQ/f3JZrYsdaM/vQ9F48l8bPlzxw5NvqXIYMK4kKcGEyerQNTWCudoCpLL5uiU0hg==", + "dev": true, + "dependencies": { + "chalk": "^2.3.2", + "escape-html": "^1.0.3", + "fs-extra": "^7.0.1", + "globby": "^9.2.0", + "gray-matter": "^4.0.1", + "hash-sum": "^1.0.2", + "semver": "^6.0.0", + "toml": "^3.0.0", + "upath": "^1.1.0" + } }, - "js-base64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", - "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==" + "node_modules/@vuepress/shared-utils/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } }, - "js-quantities": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/js-quantities/-/js-quantities-1.7.4.tgz", - "integrity": "sha512-mjwSQ+1XwSTqStOQNocgRgwebWZYc4CDhoe9DFY51u0n23B/VQmwCb4z1GTn9vxz/gMXHTnnyCdXBGrCMbMy8g==" - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "node_modules/@vuepress/shared-utils/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "node_modules/@vuepress/shared-utils/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "jsdom": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz", - "integrity": "sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4=", - "optional": true, - "requires": { - "abab": "^1.0.0", - "acorn": "^2.4.0", - "acorn-globals": "^1.0.4", - "cssom": ">= 0.3.0 < 0.4.0", - "cssstyle": ">= 0.2.29 < 0.3.0", - "escodegen": "^1.6.1", - "nwmatcher": ">= 1.3.7 < 2.0.0", - "parse5": "^1.5.1", - "request": "^2.55.0", - "sax": "^1.1.4", - "symbol-tree": ">= 3.1.0 < 4.0.0", - "tough-cookie": "^2.2.0", - "webidl-conversions": "^2.0.0", - "whatwg-url-compat": "~0.6.5", - "xml-name-validator": ">= 2.0.1 < 3.0.0" - } - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "node_modules/@vuepress/shared-utils/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "requires": { - "jsonify": "~0.0.0" + "node_modules/@vuepress/theme-default": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/theme-default/-/theme-default-1.9.10.tgz", + "integrity": "sha512-XnXn9t+pYCIhWi3cZXJlighuy93FFm5yXdISAAlFlcNkshuGtqamkjacHV8q/QZMfOhSIs6wX7Hj88u2IsT5mw==", + "dev": true, + "dependencies": { + "@vuepress/plugin-active-header-links": "1.9.10", + "@vuepress/plugin-nprogress": "1.9.10", + "@vuepress/plugin-search": "1.9.10", + "@vuepress/types": "1.9.10", + "docsearch.js": "^2.5.2", + "lodash": "^4.17.15", + "stylus": "^0.54.8", + "stylus-loader": "^3.0.2", + "vuepress-plugin-container": "^2.0.2", + "vuepress-plugin-smooth-scroll": "^0.0.3" } }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "node_modules/@vuepress/types": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@vuepress/types/-/types-1.9.10.tgz", + "integrity": "sha512-TDNQn4og85onmBpLTTXXmncW3rUnYGr2MkuI8OIFJZetDNM49t1WbjNVlrT+kx7C6qXi6okDQgrHGYXajHZWfg==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^10.0.0", + "@types/webpack-dev-server": "^3", + "webpack-chain": "^6.0.0" + } }, - "jsonfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", - "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", - "requires": { - "graceful-fs": "^4.1.6" + "node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true }, - "jsonschema-extra": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/jsonschema-extra/-/jsonschema-extra-1.2.0.tgz", - "integrity": "sha1-52eGotlQdb4ja5izuAUrD2wVTXs=", - "requires": { - "js-quantities": "^1.5.0", - "lodash.isplainobject": "^2.4.1" - }, - "dependencies": { - "lodash.isplainobject": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-2.4.1.tgz", - "integrity": "sha1-rHOF4uqawDIfMNw7gDKm0iMagBE=", - "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimisplainobject": "~2.4.1" - } - } - } + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" + "node_modules/@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "dependencies": { + "@webassemblyjs/wast-printer": "1.9.0" } }, - "kew": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", - "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=" + "node_modules/@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" + "node_modules/@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0" } }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "requires": { - "graceful-fs": "^4.1.9" - } + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" - }, - "less": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", - "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==", - "requires": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "mime": "^1.2.11", - "mkdirp": "^0.5.0", - "promise": "^7.1.1", - "request": "2.81.0", - "source-map": "^0.5.3" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "optional": true, - "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "optional": true - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "optional": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.12" - } - }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", - "optional": true - }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", - "optional": true, - "requires": { - "ajv": "^4.9.1", - "har-schema": "^1.0.5" - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "optional": true, - "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "optional": true - }, - "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", - "optional": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "optional": true - }, - "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", - "optional": true - }, - "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", - "optional": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.1.1", - "har-validator": "~4.2.1", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "oauth-sign": "~0.8.1", - "performance-now": "^0.2.0", - "qs": "~6.4.0", - "safe-buffer": "^5.0.1", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.0.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "optional": true - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "optional": true, - "requires": { - "punycode": "^1.4.1" - } - } + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" } }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "optional": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "node_modules/@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" } }, - "live-server": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/live-server/-/live-server-1.2.1.tgz", - "integrity": "sha512-Yn2XCVjErTkqnM3FfTmM7/kWy3zP7+cEtC7x6u+wUzlQ+1UW3zEYbbyJrc0jNDwiMDZI0m4a0i3dxlGHVyXczw==", - "requires": { - "chokidar": "^2.0.4", - "colors": "^1.4.0", - "connect": "^3.6.6", - "cors": "^2.8.5", - "event-stream": "3.3.4", - "faye-websocket": "0.11.x", - "http-auth": "3.1.x", - "morgan": "^1.9.1", - "object-assign": "^4.1.1", - "opn": "^6.0.0", - "proxy-middleware": "^0.15.0", - "send": "^0.17.1", - "serve-index": "^1.9.1" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "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==" - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "send": { - "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", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - } - } + "node_modules/@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" } }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "node_modules/@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true }, - "lodash._basebind": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._basebind/-/lodash._basebind-2.4.1.tgz", - "integrity": "sha1-6UC5690nwyfgqNqxtVkWxTQelXU=", - "requires": { - "lodash._basecreate": "~2.4.1", - "lodash._setbinddata": "~2.4.1", - "lodash._slice": "~2.4.1", - "lodash.isobject": "~2.4.1" + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" } }, - "lodash._basecreate": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-2.4.1.tgz", - "integrity": "sha1-+Ob1tXip405UEXm1a47uv0oofgg=", - "requires": { - "lodash._isnative": "~2.4.1", - "lodash.isobject": "~2.4.1", - "lodash.noop": "~2.4.1" + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" } }, - "lodash._basecreatecallback": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._basecreatecallback/-/lodash._basecreatecallback-2.4.1.tgz", - "integrity": "sha1-fQsmdknLKeehOdAQO3wR+uhOSFE=", - "requires": { - "lodash._setbinddata": "~2.4.1", - "lodash.bind": "~2.4.1", - "lodash.identity": "~2.4.1", - "lodash.support": "~2.4.1" + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" } }, - "lodash._basecreatewrapper": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._basecreatewrapper/-/lodash._basecreatewrapper-2.4.1.tgz", - "integrity": "sha1-TTHy595+E0+/KAN2K4FQsyUZZm8=", - "requires": { - "lodash._basecreate": "~2.4.1", - "lodash._setbinddata": "~2.4.1", - "lodash._slice": "~2.4.1", - "lodash.isobject": "~2.4.1" + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" } }, - "lodash._createwrapper": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._createwrapper/-/lodash._createwrapper-2.4.1.tgz", - "integrity": "sha1-UdaVeXPaTtVW43KQ2MGhjFPeFgc=", - "requires": { - "lodash._basebind": "~2.4.1", - "lodash._basecreatewrapper": "~2.4.1", - "lodash._slice": "~2.4.1", - "lodash.isfunction": "~2.4.1" + "node_modules/@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" } }, - "lodash._isnative": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=" - }, - "lodash._objecttypes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", - "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=" - }, - "lodash._setbinddata": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._setbinddata/-/lodash._setbinddata-2.4.1.tgz", - "integrity": "sha1-98IAzRuS7yNrOZ7s9zxkjReqlNI=", - "requires": { - "lodash._isnative": "~2.4.1", - "lodash.noop": "~2.4.1" + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" } }, - "lodash._shimisplainobject": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._shimisplainobject/-/lodash._shimisplainobject-2.4.1.tgz", - "integrity": "sha1-AeyTsu5j5Z8aqDiZrG+gkFrHWW8=", - "requires": { - "lodash.forin": "~2.4.1", - "lodash.isfunction": "~2.4.1" - } + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true }, - "lodash._slice": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._slice/-/lodash._slice-2.4.1.tgz", - "integrity": "sha1-dFz0GlNZexj2iImFREBe+isG2Q8=" + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true }, - "lodash.bind": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-2.4.1.tgz", - "integrity": "sha1-XRn6AFyMTSNvr0dCx7eh/Kvikmc=", - "requires": { - "lodash._createwrapper": "~2.4.1", - "lodash._slice": "~2.4.1" + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" } }, - "lodash.forin": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.forin/-/lodash.forin-2.4.1.tgz", - "integrity": "sha1-gInq7X0lsIZyt8Zv0HrFXQYjIOs=", - "requires": { - "lodash._basecreatecallback": "~2.4.1", - "lodash._objecttypes": "~2.4.1" + "node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" } }, - "lodash.identity": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.identity/-/lodash.identity-2.4.1.tgz", - "integrity": "sha1-ZpTP+mX++TH3wxzobHRZfPVg9PE=" + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } }, - "lodash.isfunction": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.4.1.tgz", - "integrity": "sha1-LP1XXHPkmKtX4xm3f6Aq3vE6lNE=" + "node_modules/ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true, + "peerDependencies": { + "ajv": ">=5.0.0" + } }, - "lodash.isobject": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", - "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "requires": { - "lodash._objecttypes": "~2.4.1" + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" } }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "lodash.noop": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.4.1.tgz", - "integrity": "sha1-T7VPgWZS5a4Q6PcvcXo4jHMmU4o=" - }, - "lodash.support": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.support/-/lodash.support-2.4.1.tgz", - "integrity": "sha1-Mg4LZwMWc8KNeiu12eAzGkUkBRU=", - "requires": { - "lodash._isnative": "~2.4.1" + "node_modules/algoliasearch": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-3.35.1.tgz", + "integrity": "sha512-K4yKVhaHkXfJ/xcUnil04xiSrB8B8yHZoFEhWNpXg23eiCnqvTZw1tn/SqvdsANlYHLJlKl0qi3I/Q2Sqo7LwQ==", + "dev": true, + "dependencies": { + "agentkeepalive": "^2.2.0", + "debug": "^2.6.9", + "envify": "^4.0.0", + "es6-promise": "^4.1.0", + "events": "^1.1.0", + "foreach": "^2.0.5", + "global": "^4.3.2", + "inherits": "^2.0.1", + "isarray": "^2.0.1", + "load-script": "^1.0.0", + "object-keys": "^1.0.11", + "querystring-es3": "^0.2.1", + "reduce": "^1.0.1", + "semver": "^5.1.0", + "tunnel-agent": "^0.6.0" + }, + "engines": { + "node": ">=0.8" } }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + "node_modules/algoliasearch/node_modules/agentkeepalive": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-2.2.0.tgz", + "integrity": "sha512-TnB6ziK363p7lR8QpeLC8aMr8EGYBKZTpgzQLfqTs3bR0Oo5VbKdwKf8h0dSzsYrB7lSCgfJnMZKqShvlq5Oyg==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } }, - "m-io": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/m-io/-/m-io-0.3.1.tgz", - "integrity": "sha1-SgeSJG9oGfdFyLxdlzzeiC8NHvs=", - "requires": { - "mkdirp": "^0.5.1", - "q": "^1.4.1", - "rimraf": "^2.5.3" + "node_modules/algoliasearch/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" } }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + "node_modules/algoliasearch/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/algoliasearch/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" + "node_modules/alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ==", + "dev": true }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "requires": { - "object-visit": "^1.0.0" + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" } }, - "marked": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", - "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==" + "node_modules/ansi-align/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "math-random": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "node_modules/ansi-align/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "node_modules/ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "merge2": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", - "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==" + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "requires": { - "mime-db": "1.40.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "moment": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } }, - "morgan": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", - "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", - "requires": { - "basic-auth": "~2.0.0", - "debug": "2.6.9", - "depd": "~1.1.2", - "on-finished": "~2.3.0", - "on-headers": "~1.0.1" + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha1-eBj3IgJ7JFmobwKV1DTR/CM2xSw=", - "optional": true + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "license": "MIT", "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "native-require": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/native-require/-/native-require-1.1.4.tgz", - "integrity": "sha512-fOB7diEP3ErNZnMh+Zqdufw79rIPrcAbHanixB5WoWpfU06ZfoUjynGDDQ22uKBhkpgzcI3WXQglhzpWBPKKGA==" + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node-nailgun-client": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/node-nailgun-client/-/node-nailgun-client-0.1.2.tgz", - "integrity": "sha512-OC611lR0fsDUSptwnhBf8d3sj4DZ5fiRKfS2QaGPe0kR3Dt9YoZr1MY7utK0scFPTbXuQdSBBbeoKYVbME1q5g==", - "requires": { - "commander": "^2.8.1" + "node_modules/array.prototype.reduce": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.6.tgz", + "integrity": "sha512-UW+Mz8LG/sPSU8jRDCjVr6J/ZKAGpHfwrZ6kWTG5qCxIEiXdVshqGnu5vEZA8S1y6X4aCSbQZ0/EEsfvEvBiSg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node-nailgun-server": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/node-nailgun-server/-/node-nailgun-server-0.1.4.tgz", - "integrity": "sha512-e0Hbh6XPb/7GqATJ45BePaUEO5AwR7InRW/pGeMKHH1cqPMBFCeqdBNfvi+bkVLnsbYOOQE+pAek9nmNoD8sYw==", - "requires": { - "commander": "^2.8.1" + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node-plantuml": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/node-plantuml/-/node-plantuml-0.6.2.tgz", - "integrity": "sha512-4/nf/gBvKVm4+EbBgFQZf0n8N3jfAA7mRExs3NfgujSsaouktZwYkUzBUqUR8nRzIWDmJ4hA1QiWOjpEArTiZQ==", - "requires": { - "commander": "^2.8.1", - "node-nailgun-client": "^0.1.0", - "node-nailgun-server": "^0.1.3", - "plantuml-encoder": "^1.2.5" + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" } }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" } }, - "npm": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-5.1.0.tgz", - "integrity": "sha512-pt5ClxEmY/dLpb60SmGQQBKi3nB6Ljx1FXmpoCUdAULlGqGVn2uCyXxPCWFbcuHGthT7qGiaGa1wOfs/UjGYMw==", - "requires": { - "JSONStream": "~1.3.1", - "abbrev": "~1.1.0", - "ansi-regex": "~3.0.0", - "ansicolors": "~0.3.2", - "ansistyles": "~0.1.3", - "aproba": "~1.1.2", - "archy": "~1.0.0", - "bluebird": "~3.5.0", - "cacache": "~9.2.9", - "call-limit": "~1.1.0", - "chownr": "~1.0.1", - "cmd-shim": "~2.0.2", - "columnify": "~1.5.4", - "config-chain": "~1.1.11", - "debuglog": "*", - "detect-indent": "~5.0.0", - "dezalgo": "~1.0.3", - "editor": "~1.0.0", - "fs-vacuum": "~1.2.10", - "fs-write-stream-atomic": "~1.0.10", - "fstream": "~1.0.11", - "fstream-npm": "~1.2.1", - "glob": "~7.1.2", - "graceful-fs": "~4.1.11", - "has-unicode": "~2.0.1", - "hosted-git-info": "~2.5.0", - "iferr": "~0.1.5", - "imurmurhash": "*", - "inflight": "~1.0.6", - "inherits": "~2.0.3", - "ini": "~1.3.4", - "init-package-json": "~1.10.1", - "lazy-property": "~1.0.0", - "lockfile": "~1.0.3", - "lodash._baseindexof": "*", - "lodash._baseuniq": "~4.6.0", - "lodash._bindcallback": "*", - "lodash._cacheindexof": "*", - "lodash._createcache": "*", - "lodash._getnative": "*", - "lodash.clonedeep": "~4.5.0", - "lodash.restparam": "*", - "lodash.union": "~4.6.0", - "lodash.uniq": "~4.5.0", - "lodash.without": "~4.4.0", - "lru-cache": "~4.1.1", - "mississippi": "~1.3.0", - "mkdirp": "~0.5.1", - "move-concurrently": "~1.0.1", - "node-gyp": "~3.6.2", - "nopt": "~4.0.1", - "normalize-package-data": "~2.4.0", - "npm-cache-filename": "~1.0.2", - "npm-install-checks": "~3.0.0", - "npm-package-arg": "~5.1.2", - "npm-registry-client": "~8.4.0", - "npm-user-validate": "~1.0.0", - "npmlog": "~4.1.2", - "once": "~1.4.0", - "opener": "~1.4.3", - "osenv": "~0.1.4", - "pacote": "~2.7.38", - "path-is-inside": "~1.0.2", - "promise-inflight": "~1.0.1", - "read": "~1.0.7", - "read-cmd-shim": "~1.0.1", - "read-installed": "~4.0.3", - "read-package-json": "~2.0.9", - "read-package-tree": "~5.1.6", - "readable-stream": "~2.3.2", - "readdir-scoped-modules": "*", - "request": "~2.81.0", - "retry": "~0.10.1", - "rimraf": "~2.6.1", - "safe-buffer": "~5.1.1", - "semver": "~5.3.0", - "sha": "~2.0.1", - "slide": "~1.1.6", - "sorted-object": "~2.0.1", - "sorted-union-stream": "~2.1.3", - "ssri": "~4.1.6", - "strip-ansi": "~4.0.0", - "tar": "~2.2.1", - "text-table": "~0.2.0", - "uid-number": "0.0.6", - "umask": "~1.1.0", - "unique-filename": "~1.1.0", - "unpipe": "~1.0.0", - "update-notifier": "~2.2.0", - "uuid": "~3.1.0", - "validate-npm-package-license": "*", - "validate-npm-package-name": "~3.0.0", - "which": "~1.2.14", - "worker-farm": "~1.3.1", - "wrappy": "~1.0.2", - "write-file-atomic": "~2.1.0" - }, - "dependencies": { - "JSONStream": { - "version": "1.3.1", - "bundled": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "dependencies": { - "jsonparse": { - "version": "1.3.1", - "bundled": true - }, - "through": { - "version": "2.3.8", - "bundled": true - } - } - }, - "abbrev": { - "version": "1.1.0", - "bundled": true - }, - "ansi-regex": { - "version": "3.0.0", - "bundled": true - }, - "ansicolors": { - "version": "0.3.2", - "bundled": true - }, - "ansistyles": { - "version": "0.1.3", - "bundled": true - }, - "aproba": { - "version": "1.1.2", - "bundled": true - }, - "archy": { - "version": "1.0.0", - "bundled": true - }, - "bluebird": { - "version": "3.5.0", - "bundled": true - }, - "cacache": { - "version": "9.2.9", - "bundled": true, - "requires": { - "bluebird": "^3.5.0", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^1.3.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.1", - "ssri": "^4.1.6", - "unique-filename": "^1.1.0", - "y18n": "^3.2.1" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.1", - "bundled": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - }, - "dependencies": { - "pseudomap": { - "version": "1.0.2", - "bundled": true - }, - "yallist": { - "version": "2.1.2", - "bundled": true - } - } - }, - "y18n": { - "version": "3.2.1", - "bundled": true - } - } - }, - "call-limit": { - "version": "1.1.0", - "bundled": true - }, - "chownr": { - "version": "1.0.1", - "bundled": true - }, - "cmd-shim": { - "version": "2.0.2", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "mkdirp": "~0.5.0" - } - }, - "columnify": { - "version": "1.5.4", - "bundled": true, - "requires": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - }, - "wcwidth": { - "version": "1.0.1", - "bundled": true, - "requires": { - "defaults": "^1.0.3" - }, - "dependencies": { - "defaults": { - "version": "1.0.3", - "bundled": true, - "requires": { - "clone": "^1.0.2" - }, - "dependencies": { - "clone": { - "version": "1.0.2", - "bundled": true - } - } - } - } - } - } - }, - "config-chain": { - "version": "1.1.11", - "bundled": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - }, - "dependencies": { - "proto-list": { - "version": "1.2.4", - "bundled": true - } - } - }, - "debuglog": { - "version": "1.0.1", - "bundled": true - }, - "detect-indent": { - "version": "5.0.0", - "bundled": true - }, - "dezalgo": { - "version": "1.0.3", - "bundled": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - }, - "dependencies": { - "asap": { - "version": "2.0.5", - "bundled": true - } - } - }, - "editor": { - "version": "1.0.0", - "bundled": true - }, - "fs-vacuum": { - "version": "1.2.10", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "path-is-inside": "^1.0.1", - "rimraf": "^2.5.2" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fstream": { - "version": "1.0.11", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "fstream-npm": { - "version": "1.2.1", - "bundled": true, - "requires": { - "fstream-ignore": "^1.0.0", - "inherits": "2" - }, - "dependencies": { - "fstream-ignore": { - "version": "1.0.5", - "bundled": true, - "requires": { - "fstream": "^1.0.0", - "inherits": "2", - "minimatch": "^3.0.0" - }, - "dependencies": { - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "^1.1.7" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.8", - "bundled": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - } - } - } - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "dependencies": { - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "^1.1.7" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.8", - "bundled": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true - }, - "hosted-git-info": { - "version": "2.5.0", - "bundled": true - }, - "iferr": { - "version": "0.1.5", - "bundled": true - }, - "imurmurhash": { - "version": "0.1.4", - "bundled": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "ini": { - "version": "1.3.4", - "bundled": true - }, - "init-package-json": { - "version": "1.10.1", - "bundled": true, - "requires": { - "glob": "^7.1.1", - "npm-package-arg": "^4.0.0 || ^5.0.0", - "promzard": "^0.3.0", - "read": "~1.0.1", - "read-package-json": "1 || 2", - "semver": "2.x || 3.x || 4 || 5", - "validate-npm-package-license": "^3.0.1", - "validate-npm-package-name": "^3.0.0" - }, - "dependencies": { - "promzard": { - "version": "0.3.0", - "bundled": true, - "requires": { - "read": "1" - } - } - } - }, - "lazy-property": { - "version": "1.0.0", - "bundled": true - }, - "lockfile": { - "version": "1.0.3", - "bundled": true - }, - "lodash._baseindexof": { - "version": "3.1.0", - "bundled": true - }, - "lodash._baseuniq": { - "version": "4.6.0", - "bundled": true, - "requires": { - "lodash._createset": "~4.0.0", - "lodash._root": "~3.0.0" - }, - "dependencies": { - "lodash._createset": { - "version": "4.0.3", - "bundled": true - }, - "lodash._root": { - "version": "3.0.1", - "bundled": true - } - } - }, - "lodash._bindcallback": { - "version": "3.0.1", - "bundled": true - }, - "lodash._cacheindexof": { - "version": "3.0.2", - "bundled": true - }, - "lodash._createcache": { - "version": "3.1.2", - "bundled": true, - "requires": { - "lodash._getnative": "^3.0.0" - } - }, - "lodash._getnative": { - "version": "3.9.1", - "bundled": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "bundled": true - }, - "lodash.restparam": { - "version": "3.6.1", - "bundled": true - }, - "lodash.union": { - "version": "4.6.0", - "bundled": true - }, - "lodash.uniq": { - "version": "4.5.0", - "bundled": true - }, - "lodash.without": { - "version": "4.4.0", - "bundled": true - }, - "lru-cache": { - "version": "4.1.1", - "bundled": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - }, - "dependencies": { - "pseudomap": { - "version": "1.0.2", - "bundled": true - }, - "yallist": { - "version": "2.1.2", - "bundled": true - } - } - }, - "mississippi": { - "version": "1.3.0", - "bundled": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^1.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.0", - "bundled": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - }, - "duplexify": { - "version": "3.5.0", - "bundled": true, - "requires": { - "end-of-stream": "1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "end-of-stream": { - "version": "1.0.0", - "bundled": true, - "requires": { - "once": "~1.3.0" - }, - "dependencies": { - "once": { - "version": "1.3.3", - "bundled": true, - "requires": { - "wrappy": "1" - } - } - } - }, - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "end-of-stream": { - "version": "1.4.0", - "bundled": true, - "requires": { - "once": "^1.4.0" - } - }, - "flush-write-stream": { - "version": "1.0.2", - "bundled": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - }, - "dependencies": { - "cyclist": { - "version": "0.2.2", - "bundled": true - } - } - }, - "pump": { - "version": "1.0.2", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.3.5", - "bundled": true, - "requires": { - "duplexify": "^3.1.2", - "inherits": "^2.0.1", - "pump": "^1.0.0" - } - }, - "stream-each": { - "version": "1.2.0", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "bundled": true - } - } - }, - "move-concurrently": { - "version": "1.0.1", - "bundled": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - }, - "dependencies": { - "copy-concurrently": { - "version": "1.0.3", - "bundled": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "run-queue": { - "version": "1.0.3", - "bundled": true, - "requires": { - "aproba": "^1.1.1" - } - } - } - }, - "node-gyp": { - "version": "3.6.2", - "bundled": true, - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "2", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "^1.1.7" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.8", - "bundled": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - }, - "nopt": { - "version": "3.0.6", - "bundled": true, - "requires": { - "abbrev": "1" - } - } - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "bundled": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "is-builtin-module": { - "version": "1.0.0", - "bundled": true, - "requires": { - "builtin-modules": "^1.0.0" - }, - "dependencies": { - "builtin-modules": { - "version": "1.1.1", - "bundled": true - } - } - } - } - }, - "npm-cache-filename": { - "version": "1.0.2", - "bundled": true - }, - "npm-install-checks": { - "version": "3.0.0", - "bundled": true, - "requires": { - "semver": "^2.3.0 || 3.x || 4 || 5" - } - }, - "npm-package-arg": { - "version": "5.1.2", - "bundled": true, - "requires": { - "hosted-git-info": "^2.4.2", - "osenv": "^0.1.4", - "semver": "^5.1.0", - "validate-npm-package-name": "^3.0.0" - } - }, - "npm-registry-client": { - "version": "8.4.0", - "bundled": true, - "requires": { - "concat-stream": "^1.5.2", - "graceful-fs": "^4.1.6", - "normalize-package-data": "~1.0.1 || ^2.0.0", - "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0", - "npmlog": "2 || ^3.1.0 || ^4.0.0", - "once": "^1.3.3", - "request": "^2.74.0", - "retry": "^0.10.0", - "semver": "2 >=2.2.1 || 3.x || 4 || 5", - "slide": "^1.1.3", - "ssri": "^4.1.2" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.0", - "bundled": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - } - } - }, - "npm-user-validate": { - "version": "1.0.0", - "bundled": true - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - }, - "dependencies": { - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - }, - "dependencies": { - "delegates": { - "version": "1.0.0", - "bundled": true - } - } - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "bundled": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "dependencies": { - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "^1.0.0" - }, - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "bundled": true - } - } - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "requires": { - "string-width": "^1.0.2" - } - } - } - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true - } - } - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1" - } - }, - "opener": { - "version": "1.4.3", - "bundled": true - }, - "osenv": { - "version": "0.1.4", - "bundled": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - }, - "dependencies": { - "os-homedir": { - "version": "1.0.2", - "bundled": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true - } - } - }, - "pacote": { - "version": "2.7.38", - "bundled": true, - "requires": { - "bluebird": "^3.5.0", - "cacache": "^9.2.9", - "glob": "^7.1.2", - "lru-cache": "^4.1.1", - "make-fetch-happen": "^2.4.13", - "minimatch": "^3.0.4", - "mississippi": "^1.2.0", - "normalize-package-data": "^2.4.0", - "npm-package-arg": "^5.1.2", - "npm-pick-manifest": "^1.0.4", - "osenv": "^0.1.4", - "promise-inflight": "^1.0.1", - "promise-retry": "^1.1.1", - "protoduck": "^4.0.0", - "safe-buffer": "^5.1.1", - "semver": "^5.3.0", - "ssri": "^4.1.6", - "tar-fs": "^1.15.3", - "tar-stream": "^1.5.4", - "unique-filename": "^1.1.0", - "which": "^1.2.12" - }, - "dependencies": { - "make-fetch-happen": { - "version": "2.4.13", - "bundled": true, - "requires": { - "agentkeepalive": "^3.3.0", - "cacache": "^9.2.9", - "http-cache-semantics": "^3.7.3", - "http-proxy-agent": "^2.0.0", - "https-proxy-agent": "^2.0.0", - "lru-cache": "^4.1.1", - "mississippi": "^1.2.0", - "node-fetch-npm": "^2.0.1", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^3.0.0", - "ssri": "^4.1.6" - }, - "dependencies": { - "agentkeepalive": { - "version": "3.3.0", - "bundled": true, - "requires": { - "humanize-ms": "^1.2.1" - }, - "dependencies": { - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ms": "^2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "http-cache-semantics": { - "version": "3.7.3", - "bundled": true - }, - "http-proxy-agent": { - "version": "2.0.0", - "bundled": true, - "requires": { - "agent-base": "4", - "debug": "2" - }, - "dependencies": { - "agent-base": { - "version": "4.1.0", - "bundled": true, - "requires": { - "es6-promisify": "^5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "^4.0.3" - }, - "dependencies": { - "es6-promise": { - "version": "4.1.1", - "bundled": true - } - } - } - } - }, - "debug": { - "version": "2.6.8", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "https-proxy-agent": { - "version": "2.0.0", - "bundled": true, - "requires": { - "agent-base": "^4.1.0", - "debug": "^2.4.1" - }, - "dependencies": { - "agent-base": { - "version": "4.1.0", - "bundled": true, - "requires": { - "es6-promisify": "^5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "^4.0.3" - }, - "dependencies": { - "es6-promise": { - "version": "4.1.1", - "bundled": true - } - } - } - } - }, - "debug": { - "version": "2.6.8", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "node-fetch-npm": { - "version": "2.0.1", - "bundled": true, - "requires": { - "encoding": "^0.1.11", - "json-parse-helpfulerror": "^1.0.3", - "safe-buffer": "^5.0.1" - }, - "dependencies": { - "encoding": { - "version": "0.1.12", - "bundled": true, - "requires": { - "iconv-lite": "~0.4.13" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.18", - "bundled": true - } - } - }, - "json-parse-helpfulerror": { - "version": "1.0.3", - "bundled": true, - "requires": { - "jju": "^1.1.0" - }, - "dependencies": { - "jju": { - "version": "1.3.0", - "bundled": true - } - } - } - } - }, - "socks-proxy-agent": { - "version": "3.0.0", - "bundled": true, - "requires": { - "agent-base": "^4.0.1", - "socks": "^1.1.10" - }, - "dependencies": { - "agent-base": { - "version": "4.1.0", - "bundled": true, - "requires": { - "es6-promisify": "^5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "^4.0.3" - }, - "dependencies": { - "es6-promise": { - "version": "4.1.1", - "bundled": true - } - } - } - } - }, - "socks": { - "version": "1.1.10", - "bundled": true, - "requires": { - "ip": "^1.1.4", - "smart-buffer": "^1.0.13" - }, - "dependencies": { - "ip": { - "version": "1.1.5", - "bundled": true - }, - "smart-buffer": { - "version": "1.1.15", - "bundled": true - } - } - } - } - } - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "^1.1.7" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.8", - "bundled": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - }, - "npm-pick-manifest": { - "version": "1.0.4", - "bundled": true, - "requires": { - "npm-package-arg": "^5.1.2", - "semver": "^5.3.0" - } - }, - "promise-retry": { - "version": "1.1.1", - "bundled": true, - "requires": { - "err-code": "^1.0.0", - "retry": "^0.10.0" - }, - "dependencies": { - "err-code": { - "version": "1.1.2", - "bundled": true - } - } - }, - "protoduck": { - "version": "4.0.0", - "bundled": true, - "requires": { - "genfun": "^4.0.1" - }, - "dependencies": { - "genfun": { - "version": "4.0.1", - "bundled": true - } - } - }, - "tar-fs": { - "version": "1.15.3", - "bundled": true, - "requires": { - "chownr": "^1.0.1", - "mkdirp": "^0.5.1", - "pump": "^1.0.0", - "tar-stream": "^1.1.2" - }, - "dependencies": { - "pump": { - "version": "1.0.2", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - }, - "dependencies": { - "end-of-stream": { - "version": "1.4.0", - "bundled": true, - "requires": { - "once": "^1.4.0" - } - } - } - } - } - }, - "tar-stream": { - "version": "1.5.4", - "bundled": true, - "requires": { - "bl": "^1.0.0", - "end-of-stream": "^1.0.0", - "readable-stream": "^2.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "bl": { - "version": "1.2.1", - "bundled": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, - "end-of-stream": { - "version": "1.4.0", - "bundled": true, - "requires": { - "once": "^1.4.0" - } - }, - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - } - } - }, - "path-is-inside": { - "version": "1.0.2", - "bundled": true - }, - "promise-inflight": { - "version": "1.0.1", - "bundled": true - }, - "read": { - "version": "1.0.7", - "bundled": true, - "requires": { - "mute-stream": "~0.0.4" - }, - "dependencies": { - "mute-stream": { - "version": "0.0.7", - "bundled": true - } - } - }, - "read-cmd-shim": { - "version": "1.0.1", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2" - } - }, - "read-installed": { - "version": "4.0.3", - "bundled": true, - "requires": { - "debuglog": "^1.0.1", - "graceful-fs": "^4.1.2", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "slide": "~1.1.3", - "util-extend": "^1.0.1" - }, - "dependencies": { - "util-extend": { - "version": "1.0.3", - "bundled": true - } - } - }, - "read-package-json": { - "version": "2.0.9", - "bundled": true, - "requires": { - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "json-parse-helpfulerror": "^1.0.2", - "normalize-package-data": "^2.0.0" - }, - "dependencies": { - "json-parse-helpfulerror": { - "version": "1.0.3", - "bundled": true, - "requires": { - "jju": "^1.1.0" - }, - "dependencies": { - "jju": { - "version": "1.3.0", - "bundled": true - } - } - } - } - }, - "read-package-tree": { - "version": "5.1.6", - "bundled": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "once": "^1.3.0", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0" - } - }, - "readable-stream": { - "version": "2.3.2", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "safe-buffer": "~5.1.0", - "string_decoder": "~1.0.0", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true - }, - "string_decoder": { - "version": "1.0.3", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - } - } - }, - "readdir-scoped-modules": { - "version": "1.0.2", - "bundled": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "request": { - "version": "2.81.0", - "bundled": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.1.1", - "har-validator": "~4.2.1", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "oauth-sign": "~0.8.1", - "performance-now": "^0.2.0", - "qs": "~6.4.0", - "safe-buffer": "^5.0.1", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.0.0" - }, - "dependencies": { - "aws-sign2": { - "version": "0.6.0", - "bundled": true - }, - "aws4": { - "version": "1.6.0", - "bundled": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true - }, - "combined-stream": { - "version": "1.0.5", - "bundled": true, - "requires": { - "delayed-stream": "~1.0.0" - }, - "dependencies": { - "delayed-stream": { - "version": "1.0.0", - "bundled": true - } - } - }, - "extend": { - "version": "3.0.1", - "bundled": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true - }, - "form-data": { - "version": "2.1.4", - "bundled": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.12" - }, - "dependencies": { - "asynckit": { - "version": "0.4.0", - "bundled": true - } - } - }, - "har-validator": { - "version": "4.2.1", - "bundled": true, - "requires": { - "ajv": "^4.9.1", - "har-schema": "^1.0.5" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "bundled": true, - "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - }, - "dependencies": { - "co": { - "version": "4.6.0", - "bundled": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "bundled": true, - "requires": { - "jsonify": "~0.0.0" - }, - "dependencies": { - "jsonify": { - "version": "0.0.0", - "bundled": true - } - } - } - } - }, - "har-schema": { - "version": "1.0.5", - "bundled": true - } - } - }, - "hawk": { - "version": "3.1.3", - "bundled": true, - "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" - }, - "dependencies": { - "boom": { - "version": "2.10.1", - "bundled": true, - "requires": { - "hoek": "2.x.x" - } - }, - "cryptiles": { - "version": "2.0.5", - "bundled": true, - "requires": { - "boom": "2.x.x" - } - }, - "hoek": { - "version": "2.16.3", - "bundled": true - }, - "sntp": { - "version": "1.0.9", - "bundled": true, - "requires": { - "hoek": "2.x.x" - } - } - } - }, - "http-signature": { - "version": "1.1.1", - "bundled": true, - "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "dependencies": { - "assert-plus": { - "version": "0.2.0", - "bundled": true - }, - "jsprim": { - "version": "1.4.0", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true - }, - "extsprintf": { - "version": "1.0.2", - "bundled": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true - }, - "verror": { - "version": "1.3.6", - "bundled": true, - "requires": { - "extsprintf": "1.0.2" - } - } - } - }, - "sshpk": { - "version": "1.13.1", - "bundled": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "tweetnacl": "~0.14.0" - }, - "dependencies": { - "asn1": { - "version": "0.2.3", - "bundled": true - }, - "assert-plus": { - "version": "1.0.0", - "bundled": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "bundled": true, - "optional": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "optional": true - } - } - } - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true - }, - "mime-types": { - "version": "2.1.15", - "bundled": true, - "requires": { - "mime-db": "~1.27.0" - }, - "dependencies": { - "mime-db": { - "version": "1.27.0", - "bundled": true - } - } - }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true - }, - "performance-now": { - "version": "0.2.0", - "bundled": true - }, - "qs": { - "version": "6.4.0", - "bundled": true - }, - "stringstream": { - "version": "0.0.5", - "bundled": true - }, - "tough-cookie": { - "version": "2.3.2", - "bundled": true, - "requires": { - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "bundled": true - } - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.0.1" - } - } - } - }, - "retry": { - "version": "0.10.1", - "bundled": true - }, - "rimraf": { - "version": "2.6.1", - "bundled": true, - "requires": { - "glob": "^7.0.5" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true - }, - "semver": { - "version": "5.3.0", - "bundled": true - }, - "sha": { - "version": "2.0.1", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "readable-stream": "^2.0.2" - } - }, - "slide": { - "version": "1.1.6", - "bundled": true - }, - "sorted-object": { - "version": "2.0.1", - "bundled": true - }, - "sorted-union-stream": { - "version": "2.1.3", - "bundled": true, - "requires": { - "from2": "^1.3.0", - "stream-iterate": "^1.1.0" - }, - "dependencies": { - "from2": { - "version": "1.3.0", - "bundled": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "~1.1.10" - }, - "dependencies": { - "readable-stream": { - "version": "1.1.14", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "isarray": { - "version": "0.0.1", - "bundled": true - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - } - } - } - } - }, - "stream-iterate": { - "version": "1.2.0", - "bundled": true, - "requires": { - "readable-stream": "^2.1.5", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "ssri": { - "version": "4.1.6", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "requires": { - "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true - } - } - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.2", - "inherits": "2" - }, - "dependencies": { - "block-stream": { - "version": "0.0.9", - "bundled": true, - "requires": { - "inherits": "~2.0.0" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "bundled": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true - }, - "umask": { - "version": "1.1.0", - "bundled": true - }, - "unique-filename": { - "version": "1.1.0", - "bundled": true, - "requires": { - "unique-slug": "^2.0.0" - }, - "dependencies": { - "unique-slug": { - "version": "2.0.0", - "bundled": true, - "requires": { - "imurmurhash": "^0.1.4" - } - } - } - }, - "unpipe": { - "version": "1.0.0", - "bundled": true - }, - "update-notifier": { - "version": "2.2.0", - "bundled": true, - "requires": { - "boxen": "^1.0.0", - "chalk": "^1.0.0", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - }, - "dependencies": { - "boxen": { - "version": "1.1.0", - "bundled": true, - "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^1.1.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^0.1.0", - "widest-line": "^1.0.0" - }, - "dependencies": { - "ansi-align": { - "version": "2.0.0", - "bundled": true, - "requires": { - "string-width": "^2.0.0" - } - }, - "camelcase": { - "version": "4.1.0", - "bundled": true - }, - "cli-boxes": { - "version": "1.0.0", - "bundled": true - }, - "string-width": { - "version": "2.1.0", - "bundled": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "term-size": { - "version": "0.1.1", - "bundled": true, - "requires": { - "execa": "^0.4.0" - }, - "dependencies": { - "execa": { - "version": "0.4.0", - "bundled": true, - "requires": { - "cross-spawn-async": "^2.1.1", - "is-stream": "^1.1.0", - "npm-run-path": "^1.0.0", - "object-assign": "^4.0.1", - "path-key": "^1.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "cross-spawn-async": { - "version": "2.2.5", - "bundled": true, - "requires": { - "lru-cache": "^4.0.0", - "which": "^1.2.8" - } - }, - "is-stream": { - "version": "1.1.0", - "bundled": true - }, - "npm-run-path": { - "version": "1.0.0", - "bundled": true, - "requires": { - "path-key": "^1.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "bundled": true - }, - "path-key": { - "version": "1.0.0", - "bundled": true - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "widest-line": { - "version": "1.0.0", - "bundled": true, - "requires": { - "string-width": "^1.0.1" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "dependencies": { - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "^1.0.0" - }, - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "bundled": true - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - } - } - } - } - } - } - }, - "chalk": { - "version": "1.1.3", - "bundled": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "bundled": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "bundled": true - }, - "has-ansi": { - "version": "2.0.0", - "bundled": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - }, - "supports-color": { - "version": "2.0.0", - "bundled": true - } - } - }, - "configstore": { - "version": "3.1.0", - "bundled": true, - "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - }, - "dependencies": { - "dot-prop": { - "version": "4.1.1", - "bundled": true, - "requires": { - "is-obj": "^1.0.0" - }, - "dependencies": { - "is-obj": { - "version": "1.0.1", - "bundled": true - } - } - }, - "make-dir": { - "version": "1.0.0", - "bundled": true, - "requires": { - "pify": "^2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "bundled": true - } - } - }, - "unique-string": { - "version": "1.0.0", - "bundled": true, - "requires": { - "crypto-random-string": "^1.0.0" - }, - "dependencies": { - "crypto-random-string": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "import-lazy": { - "version": "2.1.0", - "bundled": true - }, - "is-npm": { - "version": "1.0.0", - "bundled": true - }, - "latest-version": { - "version": "3.1.0", - "bundled": true, - "requires": { - "package-json": "^4.0.0" - }, - "dependencies": { - "package-json": { - "version": "4.0.1", - "bundled": true, - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - }, - "dependencies": { - "got": { - "version": "6.7.1", - "bundled": true, - "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - }, - "dependencies": { - "create-error-class": { - "version": "3.0.2", - "bundled": true, - "requires": { - "capture-stack-trace": "^1.0.0" - }, - "dependencies": { - "capture-stack-trace": { - "version": "1.0.0", - "bundled": true - } - } - }, - "duplexer3": { - "version": "0.1.4", - "bundled": true - }, - "get-stream": { - "version": "3.0.0", - "bundled": true - }, - "is-redirect": { - "version": "1.0.0", - "bundled": true - }, - "is-retry-allowed": { - "version": "1.1.0", - "bundled": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true - }, - "lowercase-keys": { - "version": "1.0.0", - "bundled": true - }, - "timed-out": { - "version": "4.0.1", - "bundled": true - }, - "unzip-response": { - "version": "2.0.1", - "bundled": true - }, - "url-parse-lax": { - "version": "1.0.0", - "bundled": true, - "requires": { - "prepend-http": "^1.0.1" - }, - "dependencies": { - "prepend-http": { - "version": "1.0.4", - "bundled": true - } - } - } - } - }, - "registry-auth-token": { - "version": "3.3.1", - "bundled": true, - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - }, - "dependencies": { - "rc": { - "version": "1.2.1", - "bundled": true, - "requires": { - "deep-extend": "~0.4.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "deep-extend": { - "version": "0.4.2", - "bundled": true - }, - "minimist": { - "version": "1.2.0", - "bundled": true - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true - } - } - } - } - }, - "registry-url": { - "version": "3.1.0", - "bundled": true, - "requires": { - "rc": "^1.0.1" - }, - "dependencies": { - "rc": { - "version": "1.2.1", - "bundled": true, - "requires": { - "deep-extend": "~0.4.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "deep-extend": { - "version": "0.4.2", - "bundled": true - }, - "minimist": { - "version": "1.2.0", - "bundled": true - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true - } - } - } - } - } - } - } - } - }, - "semver-diff": { - "version": "2.1.0", - "bundled": true, - "requires": { - "semver": "^5.0.3" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "bundled": true - } - } - }, - "uuid": { - "version": "3.1.0", - "bundled": true - }, - "validate-npm-package-license": { - "version": "3.0.1", - "bundled": true, - "requires": { - "spdx-correct": "~1.0.0", - "spdx-expression-parse": "~1.0.0" - }, - "dependencies": { - "spdx-correct": { - "version": "1.0.2", - "bundled": true, - "requires": { - "spdx-license-ids": "^1.0.2" - }, - "dependencies": { - "spdx-license-ids": { - "version": "1.2.2", - "bundled": true - } - } - }, - "spdx-expression-parse": { - "version": "1.0.4", - "bundled": true - } - } - }, - "validate-npm-package-name": { - "version": "3.0.0", - "bundled": true, - "requires": { - "builtins": "^1.0.3" - }, - "dependencies": { - "builtins": { - "version": "1.0.3", - "bundled": true - } - } - }, - "which": { - "version": "1.2.14", - "bundled": true, - "requires": { - "isexe": "^2.0.0" - }, - "dependencies": { - "isexe": { - "version": "2.0.0", - "bundled": true - } - } - }, - "worker-farm": { - "version": "1.3.1", - "bundled": true, - "requires": { - "errno": ">=0.1.1 <0.2.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - }, - "dependencies": { - "errno": { - "version": "0.1.4", - "bundled": true, - "requires": { - "prr": "~0.0.0" - }, - "dependencies": { - "prr": { - "version": "0.0.0", - "bundled": true - } - } - }, - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - }, - "write-file-atomic": { - "version": "2.1.0", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "slide": "^1.1.5" - } - } + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/assert": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.1.tgz", + "integrity": "sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A==", + "dev": true, + "dependencies": { + "object.assign": "^4.1.4", + "util": "^0.10.4" } }, - "npmi": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npmi/-/npmi-1.0.1.tgz", - "integrity": "sha1-FddpJzVHVF5oCdzwzhiu1IsCkOI=", - "requires": { - "npm": "^2.1.12", - "semver": "^4.1.0" - }, - "dependencies": { - "npm": { - "version": "2.15.12", - "resolved": "https://registry.npmjs.org/npm/-/npm-2.15.12.tgz", - "integrity": "sha1-33w+1aJ3w/nUtdgZsFMR0QogCuY=", - "requires": { - "abbrev": "~1.0.9", - "ansi": "~0.3.1", - "ansi-regex": "*", - "ansicolors": "~0.3.2", - "ansistyles": "~0.1.3", - "archy": "~1.0.0", - "async-some": "~1.0.2", - "block-stream": "0.0.9", - "char-spinner": "~1.0.1", - "chmodr": "~1.0.2", - "chownr": "~1.0.1", - "cmd-shim": "~2.0.2", - "columnify": "~1.5.4", - "config-chain": "~1.1.10", - "dezalgo": "~1.0.3", - "editor": "~1.0.0", - "fs-vacuum": "~1.2.9", - "fs-write-stream-atomic": "~1.0.8", - "fstream": "~1.0.10", - "fstream-npm": "~1.1.1", - "github-url-from-git": "~1.4.0", - "github-url-from-username-repo": "~1.0.2", - "glob": "~7.0.6", - "graceful-fs": "~4.1.6", - "hosted-git-info": "~2.1.5", - "imurmurhash": "*", - "inflight": "~1.0.4", - "inherits": "~2.0.3", - "ini": "~1.3.4", - "init-package-json": "~1.9.4", - "lockfile": "~1.0.1", - "lru-cache": "~4.0.1", - "minimatch": "~3.0.3", - "mkdirp": "~0.5.1", - "node-gyp": "~3.6.0", - "nopt": "~3.0.6", - "normalize-git-url": "~3.0.2", - "normalize-package-data": "~2.3.5", - "npm-cache-filename": "~1.0.2", - "npm-install-checks": "~1.0.7", - "npm-package-arg": "~4.1.0", - "npm-registry-client": "~7.2.1", - "npm-user-validate": "~0.1.5", - "npmlog": "~2.0.4", - "once": "~1.4.0", - "opener": "~1.4.1", - "osenv": "~0.1.3", - "path-is-inside": "~1.0.0", - "read": "~1.0.7", - "read-installed": "~4.0.3", - "read-package-json": "~2.0.4", - "readable-stream": "~2.1.5", - "realize-package-specifier": "~3.0.1", - "request": "~2.74.0", - "retry": "~0.10.0", - "rimraf": "~2.5.4", - "semver": "~5.1.0", - "sha": "~2.0.1", - "slide": "~1.1.6", - "sorted-object": "~2.0.0", - "spdx-license-ids": "~1.2.2", - "strip-ansi": "~3.0.1", - "tar": "~2.2.1", - "text-table": "~0.2.0", - "uid-number": "0.0.6", - "umask": "~1.1.0", - "validate-npm-package-license": "~3.0.1", - "validate-npm-package-name": "~2.2.2", - "which": "~1.2.11", - "wrappy": "~1.0.2", - "write-file-atomic": "~1.1.4" - }, - "dependencies": { - "abbrev": { - "version": "1.0.9", - "bundled": true - }, - "ansi": { - "version": "0.3.1", - "bundled": true - }, - "ansi-regex": { - "version": "2.0.0", - "bundled": true - }, - "ansicolors": { - "version": "0.3.2", - "bundled": true - }, - "ansistyles": { - "version": "0.1.3", - "bundled": true - }, - "archy": { - "version": "1.0.0", - "bundled": true - }, - "async-some": { - "version": "1.0.2", - "bundled": true, - "requires": { - "dezalgo": "^1.0.2" - } - }, - "block-stream": { - "version": "0.0.9", - "bundled": true, - "requires": { - "inherits": "~2.0.0" - } - }, - "char-spinner": { - "version": "1.0.1", - "bundled": true - }, - "chmodr": { - "version": "1.0.2", - "bundled": true - }, - "chownr": { - "version": "1.0.1", - "bundled": true - }, - "cmd-shim": { - "version": "2.0.2", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "mkdirp": "~0.5.0" - } - }, - "columnify": { - "version": "1.5.4", - "bundled": true, - "requires": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" - }, - "dependencies": { - "wcwidth": { - "version": "1.0.0", - "bundled": true, - "requires": { - "defaults": "^1.0.0" - }, - "dependencies": { - "defaults": { - "version": "1.0.3", - "bundled": true, - "requires": { - "clone": "^1.0.2" - }, - "dependencies": { - "clone": { - "version": "1.0.2", - "bundled": true - } - } - } - } - } - } - }, - "config-chain": { - "version": "1.1.10", - "bundled": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - }, - "dependencies": { - "proto-list": { - "version": "1.2.4", - "bundled": true - } - } - }, - "dezalgo": { - "version": "1.0.3", - "bundled": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - }, - "dependencies": { - "asap": { - "version": "2.0.3", - "bundled": true - } - } - }, - "editor": { - "version": "1.0.0", - "bundled": true - }, - "fs-vacuum": { - "version": "1.2.9", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "path-is-inside": "^1.0.1", - "rimraf": "^2.5.2" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.8", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "bundled": true - } - } - }, - "fstream": { - "version": "1.0.10", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "fstream-npm": { - "version": "1.1.1", - "bundled": true, - "requires": { - "fstream-ignore": "^1.0.0", - "inherits": "2" - }, - "dependencies": { - "fstream-ignore": { - "version": "1.0.5", - "bundled": true, - "requires": { - "fstream": "^1.0.0", - "inherits": "2", - "minimatch": "^3.0.0" - } - } - } - }, - "github-url-from-git": { - "version": "1.4.0", - "bundled": true - }, - "github-url-from-username-repo": { - "version": "1.0.2", - "bundled": true - }, - "glob": { - "version": "7.0.6", - "bundled": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "dependencies": { - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "path-is-absolute": { - "version": "1.0.0", - "bundled": true - } - } - }, - "graceful-fs": { - "version": "4.1.6", - "bundled": true - }, - "hosted-git-info": { - "version": "2.1.5", - "bundled": true - }, - "imurmurhash": { - "version": "0.1.4", - "bundled": true - }, - "inflight": { - "version": "1.0.5", - "bundled": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "ini": { - "version": "1.3.4", - "bundled": true - }, - "init-package-json": { - "version": "1.9.4", - "bundled": true, - "requires": { - "glob": "^6.0.0", - "npm-package-arg": "^4.0.0", - "promzard": "^0.3.0", - "read": "~1.0.1", - "read-package-json": "1 || 2", - "semver": "2.x || 3.x || 4 || 5", - "validate-npm-package-license": "^3.0.1", - "validate-npm-package-name": "^2.0.1" - }, - "dependencies": { - "glob": { - "version": "6.0.4", - "bundled": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "dependencies": { - "path-is-absolute": { - "version": "1.0.0", - "bundled": true - } - } - }, - "promzard": { - "version": "0.3.0", - "bundled": true, - "requires": { - "read": "1" - } - } - } - }, - "lockfile": { - "version": "1.0.1", - "bundled": true - }, - "lru-cache": { - "version": "4.0.1", - "bundled": true, - "requires": { - "pseudomap": "^1.0.1", - "yallist": "^2.0.0" - }, - "dependencies": { - "pseudomap": { - "version": "1.0.2", - "bundled": true - }, - "yallist": { - "version": "2.0.0", - "bundled": true - } - } - }, - "minimatch": { - "version": "3.0.3", - "bundled": true, - "requires": { - "brace-expansion": "^1.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.6", - "bundled": true, - "requires": { - "balanced-match": "^0.4.1", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "bundled": true - } - } - }, - "node-gyp": { - "version": "3.6.0", - "bundled": true, - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "2", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "bundled": true - } - } - }, - "nopt": { - "version": "3.0.6", - "bundled": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-git-url": { - "version": "3.0.2", - "bundled": true - }, - "normalize-package-data": { - "version": "2.3.5", - "bundled": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "is-builtin-module": { - "version": "1.0.0", - "bundled": true, - "requires": { - "builtin-modules": "^1.0.0" - }, - "dependencies": { - "builtin-modules": { - "version": "1.1.0", - "bundled": true - } - } - } - } - }, - "npm-cache-filename": { - "version": "1.0.2", - "bundled": true - }, - "npm-install-checks": { - "version": "1.0.7", - "bundled": true, - "requires": { - "npmlog": "0.1 || 1 || 2", - "semver": "^2.3.0 || 3.x || 4 || 5" - } - }, - "npm-package-arg": { - "version": "4.1.0", - "bundled": true, - "requires": { - "hosted-git-info": "^2.1.4", - "semver": "4 || 5" - } - }, - "npm-registry-client": { - "version": "7.2.1", - "bundled": true, - "requires": { - "concat-stream": "^1.5.2", - "graceful-fs": "^4.1.6", - "normalize-package-data": "~1.0.1 || ^2.0.0", - "npm-package-arg": "^3.0.0 || ^4.0.0", - "npmlog": "~2.0.0 || ~3.1.0", - "once": "^1.3.3", - "request": "^2.74.0", - "retry": "^0.10.0", - "semver": "2 >=2.2.1 || 3.x || 4 || 5", - "slide": "^1.1.3" - }, - "dependencies": { - "concat-stream": { - "version": "1.5.2", - "bundled": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "~2.0.0", - "typedarray": "~0.0.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.0.6", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - } - } - }, - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - }, - "retry": { - "version": "0.10.0", - "bundled": true - } - } - }, - "npm-user-validate": { - "version": "0.1.5", - "bundled": true - }, - "npmlog": { - "version": "2.0.4", - "bundled": true, - "requires": { - "ansi": "~0.3.1", - "are-we-there-yet": "~1.1.2", - "gauge": "~1.2.5" - }, - "dependencies": { - "are-we-there-yet": { - "version": "1.1.2", - "bundled": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.0 || ^1.1.13" - }, - "dependencies": { - "delegates": { - "version": "1.0.0", - "bundled": true - } - } - }, - "gauge": { - "version": "1.2.7", - "bundled": true, - "requires": { - "ansi": "^0.3.0", - "has-unicode": "^2.0.0", - "lodash.pad": "^4.1.0", - "lodash.padend": "^4.1.0", - "lodash.padstart": "^4.1.0" - }, - "dependencies": { - "has-unicode": { - "version": "2.0.0", - "bundled": true - }, - "lodash._baseslice": { - "version": "4.0.0", - "bundled": true - }, - "lodash._basetostring": { - "version": "4.12.0", - "bundled": true - }, - "lodash.pad": { - "version": "4.4.0", - "bundled": true, - "requires": { - "lodash._baseslice": "~4.0.0", - "lodash._basetostring": "~4.12.0", - "lodash.tostring": "^4.0.0" - } - }, - "lodash.padend": { - "version": "4.5.0", - "bundled": true, - "requires": { - "lodash._baseslice": "~4.0.0", - "lodash._basetostring": "~4.12.0", - "lodash.tostring": "^4.0.0" - } - }, - "lodash.padstart": { - "version": "4.5.0", - "bundled": true, - "requires": { - "lodash._baseslice": "~4.0.0", - "lodash._basetostring": "~4.12.0", - "lodash.tostring": "^4.0.0" - } - }, - "lodash.tostring": { - "version": "4.1.4", - "bundled": true - } - } - } - } - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1" - } - }, - "opener": { - "version": "1.4.1", - "bundled": true - }, - "osenv": { - "version": "0.1.3", - "bundled": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - }, - "dependencies": { - "os-homedir": { - "version": "1.0.0", - "bundled": true - }, - "os-tmpdir": { - "version": "1.0.1", - "bundled": true - } - } - }, - "path-is-inside": { - "version": "1.0.1", - "bundled": true - }, - "read": { - "version": "1.0.7", - "bundled": true, - "requires": { - "mute-stream": "~0.0.4" - }, - "dependencies": { - "mute-stream": { - "version": "0.0.5", - "bundled": true - } - } - }, - "read-installed": { - "version": "4.0.3", - "bundled": true, - "requires": { - "debuglog": "^1.0.1", - "graceful-fs": "^4.1.2", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "slide": "~1.1.3", - "util-extend": "^1.0.1" - }, - "dependencies": { - "debuglog": { - "version": "1.0.1", - "bundled": true - }, - "readdir-scoped-modules": { - "version": "1.0.2", - "bundled": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "util-extend": { - "version": "1.0.1", - "bundled": true - } - } - }, - "read-package-json": { - "version": "2.0.4", - "bundled": true, - "requires": { - "glob": "^6.0.0", - "graceful-fs": "^4.1.2", - "json-parse-helpfulerror": "^1.0.2", - "normalize-package-data": "^2.0.0" - }, - "dependencies": { - "glob": { - "version": "6.0.4", - "bundled": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "dependencies": { - "path-is-absolute": { - "version": "1.0.0", - "bundled": true - } - } - }, - "json-parse-helpfulerror": { - "version": "1.0.3", - "bundled": true, - "requires": { - "jju": "^1.1.0" - }, - "dependencies": { - "jju": { - "version": "1.3.0", - "bundled": true - } - } - } - } - }, - "readable-stream": { - "version": "2.1.5", - "bundled": true, - "requires": { - "buffer-shims": "^1.0.0", - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "buffer-shims": { - "version": "1.0.0", - "bundled": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - } - } - }, - "realize-package-specifier": { - "version": "3.0.1", - "bundled": true, - "requires": { - "dezalgo": "^1.0.1", - "npm-package-arg": "^4.0.0" - } - }, - "request": { - "version": "2.74.0", - "bundled": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "bl": "~1.1.2", - "caseless": "~0.11.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~1.0.0-rc4", - "har-validator": "~2.0.6", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "node-uuid": "~1.4.7", - "oauth-sign": "~0.8.1", - "qs": "~6.2.0", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "~0.4.1" - }, - "dependencies": { - "aws-sign2": { - "version": "0.6.0", - "bundled": true - }, - "aws4": { - "version": "1.4.1", - "bundled": true - }, - "bl": { - "version": "1.1.2", - "bundled": true, - "requires": { - "readable-stream": "~2.0.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.0.6", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - } - } - } - } - }, - "caseless": { - "version": "0.11.0", - "bundled": true - }, - "combined-stream": { - "version": "1.0.5", - "bundled": true, - "requires": { - "delayed-stream": "~1.0.0" - }, - "dependencies": { - "delayed-stream": { - "version": "1.0.0", - "bundled": true - } - } - }, - "extend": { - "version": "3.0.0", - "bundled": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true - }, - "form-data": { - "version": "1.0.0-rc4", - "bundled": true, - "requires": { - "async": "^1.5.2", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.10" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "bundled": true - } - } - }, - "har-validator": { - "version": "2.0.6", - "bundled": true, - "requires": { - "chalk": "^1.1.1", - "commander": "^2.9.0", - "is-my-json-valid": "^2.12.4", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "bundled": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "bundled": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "bundled": true - }, - "has-ansi": { - "version": "2.0.0", - "bundled": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "bundled": true - } - } - }, - "commander": { - "version": "2.9.0", - "bundled": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - }, - "dependencies": { - "graceful-readlink": { - "version": "1.0.1", - "bundled": true - } - } - }, - "is-my-json-valid": { - "version": "2.13.1", - "bundled": true, - "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "jsonpointer": "2.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "generate-function": { - "version": "2.0.0", - "bundled": true - }, - "generate-object-property": { - "version": "1.2.0", - "bundled": true, - "requires": { - "is-property": "^1.0.0" - }, - "dependencies": { - "is-property": { - "version": "1.0.2", - "bundled": true - } - } - }, - "jsonpointer": { - "version": "2.0.0", - "bundled": true - }, - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - }, - "pinkie-promise": { - "version": "2.0.1", - "bundled": true, - "requires": { - "pinkie": "^2.0.0" - }, - "dependencies": { - "pinkie": { - "version": "2.0.4", - "bundled": true - } - } - } - } - }, - "hawk": { - "version": "3.1.3", - "bundled": true, - "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" - }, - "dependencies": { - "boom": { - "version": "2.10.1", - "bundled": true, - "requires": { - "hoek": "2.x.x" - } - }, - "cryptiles": { - "version": "2.0.5", - "bundled": true, - "requires": { - "boom": "2.x.x" - } - }, - "hoek": { - "version": "2.16.3", - "bundled": true - }, - "sntp": { - "version": "1.0.9", - "bundled": true, - "requires": { - "hoek": "2.x.x" - } - } - } - }, - "http-signature": { - "version": "1.1.1", - "bundled": true, - "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "dependencies": { - "assert-plus": { - "version": "0.2.0", - "bundled": true - }, - "jsprim": { - "version": "1.3.0", - "bundled": true, - "requires": { - "extsprintf": "1.0.2", - "json-schema": "0.2.2", - "verror": "1.3.6" - }, - "dependencies": { - "extsprintf": { - "version": "1.0.2", - "bundled": true - }, - "json-schema": { - "version": "0.2.2", - "bundled": true - }, - "verror": { - "version": "1.3.6", - "bundled": true, - "requires": { - "extsprintf": "1.0.2" - } - } - } - }, - "sshpk": { - "version": "1.9.2", - "bundled": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jodid25519": "^1.0.0", - "jsbn": "~0.1.0", - "tweetnacl": "~0.13.0" - }, - "dependencies": { - "asn1": { - "version": "0.2.3", - "bundled": true - }, - "assert-plus": { - "version": "1.0.0", - "bundled": true - }, - "dashdash": { - "version": "1.14.0", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0" - } - }, - "getpass": { - "version": "0.1.6", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "jodid25519": { - "version": "1.0.2", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0" - } - }, - "jsbn": { - "version": "0.1.0", - "bundled": true, - "optional": true - }, - "tweetnacl": { - "version": "0.13.3", - "bundled": true, - "optional": true - } - } - } - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true - }, - "mime-types": { - "version": "2.1.11", - "bundled": true, - "requires": { - "mime-db": "~1.23.0" - }, - "dependencies": { - "mime-db": { - "version": "1.23.0", - "bundled": true - } - } - }, - "node-uuid": { - "version": "1.4.7", - "bundled": true - }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true - }, - "qs": { - "version": "6.2.1", - "bundled": true - }, - "stringstream": { - "version": "0.0.5", - "bundled": true - }, - "tough-cookie": { - "version": "2.3.1", - "bundled": true - }, - "tunnel-agent": { - "version": "0.4.3", - "bundled": true - } - } - }, - "retry": { - "version": "0.10.0", - "bundled": true - }, - "rimraf": { - "version": "2.5.4", - "bundled": true, - "requires": { - "glob": "^7.0.5" - } - }, - "semver": { - "version": "5.1.0", - "bundled": true - }, - "sha": { - "version": "2.0.1", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "2.0.2", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "process-nextick-args": "~1.0.0", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.1", - "bundled": true - }, - "isarray": { - "version": "0.0.1", - "bundled": true - }, - "process-nextick-args": { - "version": "1.0.3", - "bundled": true - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - }, - "util-deprecate": { - "version": "1.0.1", - "bundled": true - } - } - } - } - }, - "slide": { - "version": "1.1.6", - "bundled": true - }, - "sorted-object": { - "version": "2.0.0", - "bundled": true - }, - "spdx-license-ids": { - "version": "1.2.2", - "bundled": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.2", - "inherits": "2" - } - }, - "text-table": { - "version": "0.2.0", - "bundled": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true - }, - "umask": { - "version": "1.1.0", - "bundled": true - }, - "validate-npm-package-license": { - "version": "3.0.1", - "bundled": true, - "requires": { - "spdx-correct": "~1.0.0", - "spdx-expression-parse": "~1.0.0" - }, - "dependencies": { - "spdx-correct": { - "version": "1.0.2", - "bundled": true, - "requires": { - "spdx-license-ids": "^1.0.2" - } - }, - "spdx-expression-parse": { - "version": "1.0.2", - "bundled": true, - "requires": { - "spdx-exceptions": "^1.0.4", - "spdx-license-ids": "^1.0.0" - }, - "dependencies": { - "spdx-exceptions": { - "version": "1.0.4", - "bundled": true - } - } - } - } - }, - "validate-npm-package-name": { - "version": "2.2.2", - "bundled": true, - "requires": { - "builtins": "0.0.7" - }, - "dependencies": { - "builtins": { - "version": "0.0.7", - "bundled": true - } - } - }, - "which": { - "version": "1.2.11", - "bundled": true, - "requires": { - "isexe": "^1.1.1" - }, - "dependencies": { - "isexe": { - "version": "1.1.2", - "bundled": true - } - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - }, - "write-file-atomic": { - "version": "1.1.4", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "imurmurhash": "^0.1.4", - "slide": "^1.1.5" - } - } - } - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" - } + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" } }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "requires": { - "boolbase": "~1.0.0" + "node_modules/assert/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "dependencies": { + "inherits": "2.0.3" } }, - "nwmatcher": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz", - "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==", - "optional": true + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } }, - "object-assign": { + "node_modules/async-each": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.6.tgz", + "integrity": "sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autocomplete.js": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/autocomplete.js/-/autocomplete.js-0.36.0.tgz", + "integrity": "sha512-jEwUXnVMeCHHutUt10i/8ZiRaCb0Wo+ZyKxeGsYwBDtw6EJHqEeDrq4UwZRD8YBSvp3g6klP678il2eeiVXN2Q==", + "dev": true, + "dependencies": { + "immediate": "^3.2.3" + } + }, + "node_modules/autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "dev": true, + "dependencies": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + }, + "node_modules/autoprefixer/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "dev": true + }, + "node_modules/babel-loader": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", + "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", + "dev": true, + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz", + "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.4.tgz", + "integrity": "sha512-9l//BZZsPR+5XjyJMPtZSK4jv0BsTO1zDac2GC6ygx9WLGlcsnRd1Co0B2zT5fF5Ic6BZy+9m3HNZ3QcOeDKfg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.2", + "core-js-compat": "^3.32.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz", + "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg==", + "dev": true, + "dependencies": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/boxen/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", + "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", + "dev": true, + "dependencies": { + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.4", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.6", + "readable-stream": "^3.6.2", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserslist": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.0.tgz", + "integrity": "sha512-v+Jcv64L2LbfTC6OnRcaxtqJNJuQAVhZKSJfR/6hn7lhnChUXl4amwVviqN1k411BB+3rRoKMitELRn1CojeRA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001539", + "electron-to-chromium": "^1.4.530", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "node_modules/buffer-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-json/-/buffer-json-2.0.0.tgz", + "integrity": "sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw==", + "dev": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true + }, + "node_modules/buffer/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true + }, + "node_modules/bundle-require": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-2.1.8.tgz", + "integrity": "sha512-oOEg3A0hy/YzvNWNowtKD0pmhZKseOFweCbgyMqTIih4gRY1nJWsvrOCT27L9NbIyL5jMjTFrAUpGxxpW68Puw==", + "dev": true, + "peerDependencies": { + "esbuild": ">=0.13" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-3.0.1.tgz", + "integrity": "sha512-HzJIvGiGqYsFUrMjAJNDbVZoG7qQA+vy9AIoKs7s9DscNfki0I589mf2w6/tW+kkFH3zyiknoWV5Jdynu6b/zw==", + "dev": true, + "dependencies": { + "buffer-json": "^2.0.0", + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.2.3", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "schema-utils": "^1.0.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/cache-loader/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cache-loader/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cache-loader/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cache-loader/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cache-loader/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/cache-loader/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cache-loader/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cache-loader/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cache-loader/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cache-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/cache-loader/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-12.0.1.tgz", + "integrity": "sha512-Yo9wGIQUaAfIbk+qY0X4cDQgCosecfBe3V9NSyeY4qPC2SAkbCS4Xj79VP8WOzitpJUZKc/wsRCYF5ariDIwkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "^4.0.4", + "get-stream": "^9.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.4", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.1", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", + "dev": true, + "dependencies": { + "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", + "dev": true, + "dependencies": { + "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", + "dev": true, + "dependencies": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001674", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001674.tgz", + "integrity": "sha512-jOsKlZVRnzfhLojb+Ykb+gyUSp9Xb57So+fAiFlLzzTKpqg8xxSav0e40c8/4F/v9N8QSvrRRaLeVzQbLqomYw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/chalk/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/chokidar/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/chokidar/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/chokidar/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-css": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone-response/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "dependencies": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/coa/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/coa/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/compression/node_modules/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==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/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, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/concat-stream/node_modules/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==", + "dev": true + }, + "node_modules/concat-stream/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", + "dev": true + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "node_modules/consolidate": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", + "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", + "deprecated": "Please upgrade to consolidate v1.0.0+ as it has been modernized with several long-awaited fixes implemented. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/consolidate for updates and release changelog", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.1.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "dependencies": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "node_modules/copy-concurrently/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/copy-concurrently/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/copy-concurrently/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/copy-concurrently/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/copy-concurrently/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/copy-concurrently/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz", + "integrity": "sha512-Uh7crJAco3AjBvgAy9Z75CjK8IG+gxaErro71THQ+vv/bl4HaQcpkexAY8KVW/T6D2W2IRr+couF/knIRkZMIQ==", + "dev": true, + "dependencies": { + "cacache": "^12.0.3", + "find-cache-dir": "^2.1.0", + "glob-parent": "^3.1.0", + "globby": "^7.1.1", + "is-glob": "^4.0.1", + "loader-utils": "^1.2.3", + "minimatch": "^3.0.4", + "normalize-path": "^3.0.0", + "p-limit": "^2.2.1", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "webpack-log": "^2.0.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/copy-webpack-plugin/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/copy-webpack-plugin/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha512-yANWAN2DUcBtuus5Cpd+SKROzXHs2iVXFZt/Ykrfz6SAXqacLX25NZpltE+39ceMexYF4TtEadjuSTw8+3wX4g==", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "node_modules/copy-webpack-plugin/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/copy-webpack-plugin/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/copy-webpack-plugin/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/copy-webpack-plugin/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/copy-webpack-plugin/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/copy-webpack-plugin/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/copy-webpack-plugin/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/copy-webpack-plugin/node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/copy-webpack-plugin/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/core-js": { + "version": "3.32.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.32.2.tgz", + "integrity": "sha512-pxXSw1mYZPDGvTQqEc5vgIb83jGQKFGYWY76z4a7weZXUolw3G+OvpZqSRcfYOoOVUQJYEPsWeQK8pKEnUtWxQ==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.32.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.2.tgz", + "integrity": "sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "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, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + } + }, + "node_modules/css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + }, + "engines": { + "node": ">4" + } + }, + "node_modules/css-loader": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz", + "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==", + "dev": true, + "dependencies": { + "camelcase": "^5.2.0", + "icss-utils": "^4.1.0", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.14", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^2.0.6", + "postcss-modules-scope": "^2.1.0", + "postcss-modules-values": "^2.0.0", + "postcss-value-parser": "^3.3.0", + "schema-utils": "^1.0.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/css-loader/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/css-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha512-UNIFik2RgSbiTwIW1IsFwXWn6vs+bYdq83LKTSOsx7NJR7WII9dxewkHLltfTLVppoUApHV0118a4RZRI9FLwA==", + "dev": true, + "dependencies": { + "css": "^2.0.0" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "node_modules/css-tree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.12.2", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz", + "integrity": "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==", + "dev": true, + "dependencies": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.8", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-preset-default": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz", + "integrity": "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==", + "dev": true, + "dependencies": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.3", + "postcss-unique-selectors": "^4.0.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha512-6RIcwmV3/cBMG8Aj5gucQRsJb4vv4I4rn6YjPbVWd5+Pn/fuG+YseGvXGk00XLkoZkaj31QOD7vMUpNPC4FIuw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha512-JPMZ1TSMRUPVIqEalIBNoBtAYbi8okvcFns4O0YIhcdGebeYZK7dMyHJiQ6GqNBA9kE0Hym4Aqym5rPdsV/4Cw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true + }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", + "dev": true + }, + "node_modules/cyclist": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.2.tgz", + "integrity": "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==", + "dev": true + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "dev": true, + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dev": true, + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dev": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dev": true, + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-collection": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", + "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==", + "dev": true + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dev": true, + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dev": true, + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dev": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dev": true, + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dev": true, + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dev": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "dev": true, + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dev": true, + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dev": true, + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "dev": true, + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dev": true, + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dev": true, + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dev": true, + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dev": true, + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-voronoi": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", + "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==", + "dev": true + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dev": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", + "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", + "dev": true, + "dependencies": { + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, + "node_modules/dagre-d3": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz", + "integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==", + "dev": true, + "dependencies": { + "d3": "^5.14", + "dagre": "^0.8.5", + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, + "node_modules/dagre-d3/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz", + "integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==", + "dev": true, + "dependencies": { + "d3-array": "1", + "d3-axis": "1", + "d3-brush": "1", + "d3-chord": "1", + "d3-collection": "1", + "d3-color": "1", + "d3-contour": "1", + "d3-dispatch": "1", + "d3-drag": "1", + "d3-dsv": "1", + "d3-ease": "1", + "d3-fetch": "1", + "d3-force": "1", + "d3-format": "1", + "d3-geo": "1", + "d3-hierarchy": "1", + "d3-interpolate": "1", + "d3-path": "1", + "d3-polygon": "1", + "d3-quadtree": "1", + "d3-random": "1", + "d3-scale": "2", + "d3-scale-chromatic": "1", + "d3-selection": "1", + "d3-shape": "1", + "d3-time": "1", + "d3-time-format": "2", + "d3-timer": "1", + "d3-transition": "1", + "d3-voronoi": "1", + "d3-zoom": "1" + } + }, + "node_modules/dagre-d3/node_modules/d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-axis": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", + "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-brush": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", + "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", + "dev": true, + "dependencies": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "node_modules/dagre-d3/node_modules/d3-chord": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", + "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", + "dev": true, + "dependencies": { + "d3-array": "1", + "d3-path": "1" + } + }, + "node_modules/dagre-d3/node_modules/d3-color": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", + "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-contour": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", + "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", + "dev": true, + "dependencies": { + "d3-array": "^1.1.1" + } + }, + "node_modules/dagre-d3/node_modules/d3-dispatch": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", + "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-drag": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", + "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", + "dev": true, + "dependencies": { + "d3-dispatch": "1", + "d3-selection": "1" + } + }, + "node_modules/dagre-d3/node_modules/d3-dsv": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", + "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", + "dev": true, + "dependencies": { + "commander": "2", + "iconv-lite": "0.4", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json", + "csv2tsv": "bin/dsv2dsv", + "dsv2dsv": "bin/dsv2dsv", + "dsv2json": "bin/dsv2json", + "json2csv": "bin/json2dsv", + "json2dsv": "bin/json2dsv", + "json2tsv": "bin/json2dsv", + "tsv2csv": "bin/dsv2dsv", + "tsv2json": "bin/dsv2json" + } + }, + "node_modules/dagre-d3/node_modules/d3-ease": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", + "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-fetch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", + "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", + "dev": true, + "dependencies": { + "d3-dsv": "1" + } + }, + "node_modules/dagre-d3/node_modules/d3-force": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", + "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", + "dev": true, + "dependencies": { + "d3-collection": "1", + "d3-dispatch": "1", + "d3-quadtree": "1", + "d3-timer": "1" + } + }, + "node_modules/dagre-d3/node_modules/d3-format": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", + "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-geo": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", + "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", + "dev": true, + "dependencies": { + "d3-array": "1" + } + }, + "node_modules/dagre-d3/node_modules/d3-hierarchy": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", + "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-interpolate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", + "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", + "dev": true, + "dependencies": { + "d3-color": "1" + } + }, + "node_modules/dagre-d3/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-polygon": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", + "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-quadtree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", + "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-random": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", + "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-scale": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", + "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", + "dev": true, + "dependencies": { + "d3-array": "^1.2.0", + "d3-collection": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" + } + }, + "node_modules/dagre-d3/node_modules/d3-scale-chromatic": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", + "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", + "dev": true, + "dependencies": { + "d3-color": "1", + "d3-interpolate": "1" + } + }, + "node_modules/dagre-d3/node_modules/d3-selection": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", + "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "dev": true, + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/dagre-d3/node_modules/d3-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", + "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-time-format": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", + "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", + "dev": true, + "dependencies": { + "d3-time": "1" + } + }, + "node_modules/dagre-d3/node_modules/d3-timer": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", + "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==", + "dev": true + }, + "node_modules/dagre-d3/node_modules/d3-transition": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", + "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", + "dev": true, + "dependencies": { + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" + } + }, + "node_modules/dagre-d3/node_modules/d3-zoom": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", + "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", + "dev": true, + "dependencies": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "node_modules/dagre-d3/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz", + "integrity": "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "dependencies": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", + "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "dependencies": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/del/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/del/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/del/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/globby/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/del/node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/del/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "dev": true, + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", + "dev": true + }, + "node_modules/dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "dev": true, + "dependencies": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ==", + "dev": true, + "dependencies": { + "buffer-indexof": "^1.0.0" + } + }, + "node_modules/docsearch.js": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/docsearch.js/-/docsearch.js-2.6.3.tgz", + "integrity": "sha512-GN+MBozuyz664ycpZY0ecdQE0ND/LSgJKhTLA0/v3arIS3S1Rpf2OJz6A35ReMsm91V5apcmzr5/kM84cvUg+A==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @docsearch/js.", + "dev": true, + "dependencies": { + "algoliasearch": "^3.24.5", + "autocomplete.js": "0.36.0", + "hogan.js": "^3.0.2", + "request": "^2.87.0", + "stack-utils": "^1.0.1", + "to-factory": "^1.0.0", + "zepto": "^1.2.0" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", + "dev": true + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true, + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.5.tgz", + "integrity": "sha512-kD+f8qEaa42+mjdOpKeztu9Mfx5bv9gVLO6K9jRx4uGvh6Wv06Srn4jr1wPNY2OOUGGSKHNFN+A8MA3v0E0QAQ==", + "dev": true + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/duplexify/node_modules/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==", + "dev": true + }, + "node_modules/duplexify/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.531", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.531.tgz", + "integrity": "sha512-H6gi5E41Rn3/mhKlPaT1aIMg/71hTAqn0gYEllSuw9igNWtvQwu185jiCZoZD29n7Zukgh7GVZ3zGf0XvkhqjQ==", + "dev": true + }, + "node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/enhanced-resolve/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/enhanced-resolve/node_modules/memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/enhanced-resolve/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/enhanced-resolve/node_modules/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==", + "dev": true + }, + "node_modules/enhanced-resolve/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envify": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/envify/-/envify-4.1.0.tgz", + "integrity": "sha512-IKRVVoAYr4pIx4yIWNsz9mOsboxlNXiu7TNBnem/K/uTHdkyzXWDzHCK7UTolqBbgaBz0tQHsD3YNls0uIIjiw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.0", + "through": "~2.3.4" + }, + "bin": { + "envify": "bin/envify" + } + }, + "node_modules/envinfo": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", + "dev": true, + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", + "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.7.tgz", + "integrity": "sha512-+u/msd6iu+HvfysUPkZ9VHm83LImmSNnecYPfFI01pQ7TTcsFR+V0BkybZX7mPtIaI7LCrse6YRj+v3eraJSgw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "optionalDependencies": { + "esbuild-android-arm64": "0.14.7", + "esbuild-darwin-64": "0.14.7", + "esbuild-darwin-arm64": "0.14.7", + "esbuild-freebsd-64": "0.14.7", + "esbuild-freebsd-arm64": "0.14.7", + "esbuild-linux-32": "0.14.7", + "esbuild-linux-64": "0.14.7", + "esbuild-linux-arm": "0.14.7", + "esbuild-linux-arm64": "0.14.7", + "esbuild-linux-mips64le": "0.14.7", + "esbuild-linux-ppc64le": "0.14.7", + "esbuild-netbsd-64": "0.14.7", + "esbuild-openbsd-64": "0.14.7", + "esbuild-sunos-64": "0.14.7", + "esbuild-windows-32": "0.14.7", + "esbuild-windows-64": "0.14.7", + "esbuild-windows-arm64": "0.14.7" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.7.tgz", + "integrity": "sha512-9/Q1NC4JErvsXzJKti0NHt+vzKjZOgPIjX/e6kkuCzgfT/GcO3FVBcGIv4HeJG7oMznE6KyKhvLrFgt7CdU2/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/esbuild-darwin-64": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.7.tgz", + "integrity": "sha512-Z9X+3TT/Xj+JiZTVlwHj2P+8GoiSmUnGVz0YZTSt8WTbW3UKw5Pw2ucuJ8VzbD2FPy0jbIKJkko/6CMTQchShQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.7.tgz", + "integrity": "sha512-68e7COhmwIiLXBEyxUxZSSU0akgv8t3e50e2QOtKdBUE0F6KIRISzFntLe2rYlNqSsjGWsIO6CCc9tQxijjSkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.7.tgz", + "integrity": "sha512-76zy5jAjPiXX/S3UvRgG85Bb0wy0zv/J2lel3KtHi4V7GUTBfhNUPt0E5bpSXJ6yMT7iThhnA5rOn+IJiUcslQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.7.tgz", + "integrity": "sha512-lSlYNLiqyzd7qCN5CEOmLxn7MhnGHPcu5KuUYOG1i+t5A6q7LgBmfYC9ZHJBoYyow3u4CNu79AWHbvVLpE/VQQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/esbuild-linux-32": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.7.tgz", + "integrity": "sha512-Vk28u409wVOXqTaT6ek0TnfQG4Ty1aWWfiysIaIRERkNLhzLhUf4i+qJBN8mMuGTYOkE40F0Wkbp6m+IidOp2A==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-64": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.7.tgz", + "integrity": "sha512-+Lvz6x+8OkRk3K2RtZwO+0a92jy9si9cUea5Zoru4yJ/6EQm9ENX5seZE0X9DTwk1dxJbjmLsJsd3IoowyzgVg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-arm": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.7.tgz", + "integrity": "sha512-OzpXEBogbYdcBqE4uKynuSn5YSetCvK03Qv1HcOY1VN6HmReuatjJ21dCH+YPHSpMEF0afVCnNfffvsGEkxGJQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.7.tgz", + "integrity": "sha512-kJd5beWSqteSAW086qzCEsH6uwpi7QRIpzYWHzEYwKKu9DiG1TwIBegQJmLpPsLp4v5RAFjea0JAmAtpGtRpqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.7.tgz", + "integrity": "sha512-mFWpnDhZJmj/h7pxqn1GGDsKwRfqtV7fx6kTF5pr4PfXe8pIaTERpwcKkoCwZUkWAOmUEjMIUAvFM72A6hMZnA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.7.tgz", + "integrity": "sha512-wM7f4M0bsQXfDL4JbbYD0wsr8cC8KaQ3RPWc/fV27KdErPW7YsqshZZSjDV0kbhzwpNNdhLItfbaRT8OE8OaKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.7.tgz", + "integrity": "sha512-J/afS7woKyzGgAL5FlgvMyqgt5wQ597lgsT+xc2yJ9/7BIyezeXutXqfh05vszy2k3kSvhLesugsxIA71WsqBw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ] + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.7.tgz", + "integrity": "sha512-7CcxgdlCD+zAPyveKoznbgr3i0Wnh0L8BDGRCjE/5UGkm5P/NQko51tuIDaYof8zbmXjjl0OIt9lSo4W7I8mrw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/esbuild-sunos-64": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.7.tgz", + "integrity": "sha512-GKCafP2j/KUljVC3nesw1wLFSZktb2FGCmoT1+730zIF5O6hNroo0bSEofm6ZK5mNPnLiSaiLyRB9YFgtkd5Xg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ] + }, + "node_modules/esbuild-windows-32": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.7.tgz", + "integrity": "sha512-5I1GeL/gZoUUdTPA0ws54bpYdtyeA2t6MNISalsHpY269zK8Jia/AXB3ta/KcDHv2SvNwabpImeIPXC/k0YW6A==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/esbuild-windows-64": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.7.tgz", + "integrity": "sha512-CIGKCFpQOSlYsLMbxt8JjxxvVw9MlF1Rz2ABLVfFyHUF5OeqHD5fPhGrCVNaVrhO8Xrm+yFmtjcZudUGr5/WYQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.7.tgz", + "integrity": "sha512-eOs1eSivOqN7cFiRIukEruWhaCf75V0N8P0zP7dh44LIhLl8y6/z++vv9qQVbkBm5/D7M7LfCfCTmt1f1wHOCw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-scope": { + "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, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "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, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/execa/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/execa/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "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==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/fast-glob/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "license": "MIT", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob/node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "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==", + "dev": true + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", + "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", + "dev": true, + "dependencies": { + "loader-utils": "^1.0.2", + "schema-utils": "^1.0.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/flush-write-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/flush-write-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/flush-write-stream/node_modules/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==", + "dev": true + }, + "node_modules/flush-write-stream/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/foreach": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz", + "integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/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==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/from2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/from2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/from2/node_modules/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==", + "dev": true + }, + "node_modules/from2/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "node_modules/fs-write-stream-atomic/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/fs-write-stream-atomic/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/fs-write-stream-atomic/node_modules/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==", + "dev": true + }, + "node_modules/fs-write-stream-atomic/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream/node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz", + "integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "optional": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==", + "dev": true, + "license": "BSD" + }, + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "dev": true, + "dependencies": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, + "node_modules/global-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", + "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "1.3.7" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/globals": { + "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, + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/globby/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/globby/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globby/node_modules/ignore": { + "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, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/globby/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "14.4.7", + "resolved": "https://registry.npmjs.org/got/-/got-14.4.7.tgz", + "integrity": "sha512-DI8zV1231tqiGzOiOzQWDhsBmncFW7oQDH6Zgy6pDPrqJuVZMtoSgPLLsBZQj8Jg4JFfwoOsDA8NGtLQLnIx2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^7.0.1", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^12.0.1", + "decompress-response": "^6.0.0", + "form-data-encoder": "^4.0.2", + "http2-wrapper": "^2.2.1", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^4.0.1", + "responselike": "^3.0.0", + "type-fest": "^4.26.1" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/got/node_modules/form-data-encoder": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-4.0.2.tgz", + "integrity": "sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==", + "dev": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/got/node_modules/p-cancelable": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-4.0.1.tgz", + "integrity": "sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphlib": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + } + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "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, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dev": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", + "dev": true + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, + "node_modules/highlight.js": { + "version": "9.18.5", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.5.tgz", + "integrity": "sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA==", + "deprecated": "Support has ended for 9.x series. Upgrade to @latest", + "dev": true, + "hasInstallScript": true, + "engines": { + "node": "*" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hogan.js": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", + "integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==", + "dev": true, + "dependencies": { + "mkdirp": "0.3.0", + "nopt": "1.0.10" + }, + "bin": { + "hulk": "bin/hulk" + } + }, + "node_modules/hogan.js/node_modules/mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/hogan.js/node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/hpack.js/node_modules/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==", + "dev": true + }, + "node_modules/hpack.js/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha512-M5ezZw4LzXbBKMruP+BNANf0k+19hDQMgpzBIYnya//Al+fjNct9Wf3b1WedLqdEs2hKBvxq/jh+DsHJLj0F9A==", + "dev": true + }, + "node_modules/hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha512-7Wn5GMLuHBjZCb2bTmnDOycho0p/7UVaAeqXZGbHrBCl6Yd/xDhQJAXe6Ga9AXJH2I5zY1dEdYw2u1UptnSBJA==", + "dev": true + }, + "node_modules/html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==", + "dev": true + }, + "node_modules/html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "dev": true, + "dependencies": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + }, + "bin": { + "html-minifier": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/html-minifier/node_modules/commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/htmlparser2/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/htmlparser2/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/htmlparser2/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz", + "integrity": "sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.5", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==", + "dev": true + }, + "node_modules/icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.14" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==", + "dev": true + }, + "node_modules/ignore": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", + "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", + "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", + "dev": true + }, + "node_modules/import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha512-Ew5AZzJQFqrOV5BTW3EIoHAnoie1LojZLXKcCQ/yTRyVZosBhK1x1ViYjHGf5pAFOq8ZyChZp6m/fSN7pJyZtg==", + "dev": true, + "dependencies": { + "import-from": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "dev": true, + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha512-0vdnLL2wSGnhlRmzHJAg5JHjt1l2vYhzJ7tNLGbeVg0fse56tpGaH0uzH+r9Slej+BSXXEHvBKDEnVSLLE9/+w==", + "dev": true, + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "dependencies": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==", + "dev": true + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "dependencies": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/ip": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ipaddr.js": { + "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==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha512-vOx7VprsKyllwjSkLV79NIhpyLfr3jAp7VaTCMXOJHu4m0Ew1CZ2fcjASwmV1jI3BWuWHB013M48eyeldk9gYg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-ci/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha512-H1U8Vz0cfXNujrJzEcvvwMDW9Ra+biSYA3ThdQvAnMLJkEHQXn6bWzLkxHtVYJ+Sdbx0b6finn3jZiaVe7MAHA==", + "dev": true, + "dependencies": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "dependencies": { + "is-path-inside": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-in-cwd/node_modules/is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "node_modules/jackspeak": { +<<<<<<< HEAD + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.0.tgz", + "integrity": "sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==", +======= + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", +>>>>>>> c7f3c7a4a9764c774e274041cae45b9c0f57bf78 + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/javascript-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", + "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", + "dev": true + }, + "node_modules/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, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/katex": { + "version": "0.16.22", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz", + "integrity": "sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==", + "dev": true, + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/khroma": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-1.4.1.tgz", + "integrity": "sha512-+GmxKvmiRuCcUYDgR7g5Ngo0JEDeOsGdNONdU2zsiBQaK4z19Y2NvXqfEDE0ZiIrg45GTZyAnPLVsLZZACYm3Q==", + "dev": true + }, + "node_modules/killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/last-call-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", + "dev": true, + "dependencies": { + "lodash": "^4.17.5", + "webpack-sources": "^1.1.0" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "license": "MIT", + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/linkify-it/node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true + }, + "node_modules/load-script": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", + "integrity": "sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==", + "dev": true + }, + "node_modules/loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/loader-utils/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", + "dev": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "dependencies": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true + }, + "node_modules/loglevel": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz", + "integrity": "sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", + "dev": true + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-anchor": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "dev": true, + "peerDependencies": { + "markdown-it": "*" + } + }, + "node_modules/markdown-it-chain": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-chain/-/markdown-it-chain-1.3.0.tgz", + "integrity": "sha512-XClV8I1TKy8L2qsT9iX3qiV+50ZtcInGXI80CA+DP62sMs7hXlyV/RM3hfwy5O3Ad0sJm9xIwQELgANfESo8mQ==", + "dev": true, + "dependencies": { + "webpack-chain": "^4.9.0" + }, + "engines": { + "node": ">=6.9" + }, + "peerDependencies": { + "markdown-it": ">=5.0.0" + } + }, + "node_modules/markdown-it-chain/node_modules/javascript-stringify": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-1.6.0.tgz", + "integrity": "sha512-fnjC0up+0SjEJtgmmG+teeel68kutkvzfctO/KxE3qJlbunkJYAshgH3boU++gSBHP8z5/r0ts0qRIrHf0RTQQ==", + "dev": true + }, + "node_modules/markdown-it-chain/node_modules/webpack-chain": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-4.12.1.tgz", + "integrity": "sha512-BCfKo2YkDe2ByqkEWe1Rw+zko4LsyS75LVr29C6xIrxAg9JHJ4pl8kaIZ396SUSNp6b4815dRZPSTAS8LlURRQ==", + "dev": true, + "dependencies": { + "deepmerge": "^1.5.2", + "javascript-stringify": "^1.6.0" + } + }, + "node_modules/markdown-it-container": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-2.0.0.tgz", + "integrity": "sha512-IxPOaq2LzrGuFGyYq80zaorXReh2ZHGFOB1/Hen429EJL1XkPI3FJTpx9TsJeua+j2qTru4h3W1TiCRdeivMmA==", + "dev": true + }, + "node_modules/markdown-it-emoji": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz", + "integrity": "sha512-QCz3Hkd+r5gDYtS2xsFXmBYrgw6KuWcJZLCEkdfAuwzZbShCmCfta+hwAMq4NX/4xPzkSHduMKgMkkPUJxSXNg==", + "dev": true + }, + "node_modules/markdown-it-table-of-contents": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.4.tgz", + "integrity": "sha512-TAIHTHPwa9+ltKvKPWulm/beozQU41Ab+FIefRaQV1NRnpzwcV9QOe6wXQS5WLivm5Q/nlo0rl6laGkMDZE7Gw==", + "dev": true, + "engines": { + "node": ">6.4.0" + } + }, + "node_modules/markdown-it/node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true + }, + "node_modules/markdown-it/node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true + }, + "node_modules/markdownlint": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.38.0.tgz", + "integrity": "sha512-xaSxkaU7wY/0852zGApM8LdlIfGCW8ETZ0Rr62IQtAnUMlMuifsg09vWJcNYeL4f0anvr8Vo4ZQar8jGpV0btQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark": "4.0.2", + "micromark-core-commonmark": "2.0.3", + "micromark-extension-directive": "4.0.0", + "micromark-extension-gfm-autolink-literal": "2.1.0", + "micromark-extension-gfm-footnote": "2.1.0", + "micromark-extension-gfm-table": "2.1.1", + "micromark-extension-math": "3.1.0", + "micromark-util-types": "2.0.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + } + }, + "node_modules/markdownlint-cli": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.45.0.tgz", + "integrity": "sha512-GiWr7GfJLVfcopL3t3pLumXCYs8sgWppjIA1F/Cc3zIMgD3tmkpyZ1xkm1Tej8mw53B93JsDjgA3KOftuYcfOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "~13.1.0", + "glob": "~11.0.2", + "ignore": "~7.0.4", + "js-yaml": "~4.1.0", + "jsonc-parser": "~3.3.1", + "jsonpointer": "~5.0.1", + "markdown-it": "~14.1.0", + "markdownlint": "~0.38.0", + "minimatch": "~10.0.1", + "run-con": "~1.3.2", + "smol-toml": "~1.3.4" + }, + "bin": { + "markdownlint": "markdownlint.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/mdn-data": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/medium-zoom": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-1.0.8.tgz", + "integrity": "sha512-CjFVuFq/IfrdqesAXfg+hzlDKu6A2n80ZIq0Kl9kWjoHh9j1N9Uvk5X0/MmN0hOfm5F9YBswlClhcwnmtwz7gA==", + "dev": true + }, + "node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "node_modules/memory-fs/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/memory-fs/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/memory-fs/node_modules/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==", + "dev": true + }, + "node_modules/memory-fs/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/mermaid": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.14.0.tgz", + "integrity": "sha512-ITSHjwVaby1Li738sxhF48sLTxcNyUAoWfoqyztL1f7J6JOLpHOuQPNLBb6lxGPUA0u7xP9IRULgvod0dKu35A==", + "dev": true, + "dependencies": { + "@braintree/sanitize-url": "^3.1.0", + "d3": "^7.0.0", + "dagre": "^0.8.5", + "dagre-d3": "^0.6.4", + "dompurify": "2.3.5", + "graphlib": "^2.1.8", + "khroma": "^1.4.1", + "moment-mini": "^2.24.0", + "stylis": "^4.0.10" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-4.0.0.tgz", + "integrity": "sha512-/C2nqVmXXmiseSSuCdItCMho7ybwwop6RrrRPk0KbOHW21JKoCldC+8rFOaundDoRBUWBnJJcxeA/Kvi34WQXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "dev": true, + "dependencies": { + "dom-walk": "^0.1.0" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz", + "integrity": "sha512-79q5P7YGI6rdnVyIAV4NXpBQJFWdkzJxCim3Kog4078fM0piAaFlwocqbejdWtLW1cEzCexPrh6EdyFsPgVdAw==", + "dev": true, + "dependencies": { + "loader-utils": "^1.1.0", + "normalize-url": "^2.0.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.4.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true + }, + "node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "dependencies": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/moment-mini": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.29.4.tgz", + "integrity": "sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg==", + "dev": true + }, + "node_modules/move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==", + "dev": true, + "dependencies": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "node_modules/move-concurrently/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/move-concurrently/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/move-concurrently/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/move-concurrently/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/move-concurrently/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/move-concurrently/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "dependencies": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==", + "dev": true + }, + "node_modules/nan": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "dev": true, + "optional": true + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "dependencies": { + "lower-case": "^1.1.1" + } + }, + "node_modules/node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "dependencies": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + } + }, + "node_modules/node-libs-browser/node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/node-libs-browser/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/node-libs-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/node-libs-browser/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/node-libs-browser/node_modules/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==", + "dev": true + }, + "node_modules/node-libs-browser/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-check-updates": { + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-18.0.1.tgz", + "integrity": "sha512-MO7mLp/8nm6kZNLLyPgz4gHmr9tLoU+pWPLdXuGAx+oZydBHkHWN0ibTonsrfwC2WEQNIQxuZagYwB67JQpAuw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "ncu": "build/cli.js", + "npm-check-updates": "build/cli.js" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0", + "npm": ">=8.12.1" + } + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==", + "dev": true + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==", + "dev": true + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.7.tgz", + "integrity": "sha512-PrJz0C2xJ58FNn11XV2lr4Jt5Gzl94qpy9Lu0JlfEj14z88sqbSBJCBEzdlNUCzY2gburhbrwOZ5BHCmuNUy0g==", + "dev": true, + "dependencies": { + "array.prototype.reduce": "^1.0.6", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "safe-array-concat": "^1.0.0" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.values": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true, + "bin": { + "opencollective-postinstall": "index.js" + } + }, + "node_modules/opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/optimize-css-assets-webpack-plugin": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.8.tgz", + "integrity": "sha512-mgFS1JdOtEGzD8l+EuISqL57cKO+We9GcoiQEmdCWRqqck+FGNmYJtx9qfAPzEz+lRrlThWMuGDaRkI/yWNx/Q==", + "dev": true, + "dependencies": { + "cssnano": "^4.1.10", + "last-call-webpack-plugin": "^3.0.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true + }, + "node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "dependencies": { + "retry": "^0.12.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/package-json/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json/node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/package-json/node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/package-json/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/package-json/node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/package-json/node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/package-json/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/package-json/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/package-json/node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "dependencies": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "node_modules/parallel-transform/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/parallel-transform/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/parallel-transform/node_modules/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==", + "dev": true + }, + "node_modules/parallel-transform/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", + "dev": true, + "dependencies": { + "no-case": "^2.2.0" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", + "dev": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "dev": true + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "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 + }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", + "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-type/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz", + "integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "create-hash": "~1.1.3", + "create-hmac": "^1.1.7", + "ripemd160": "=2.0.1", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.11", + "to-buffer": "^1.2.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/pbkdf2/node_modules/create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "sha.js": "^2.4.0" + } + }, + "node_modules/pbkdf2/node_modules/hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1" + } + }, + "node_modules/pbkdf2/node_modules/ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^2.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/plantuml-encoder": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/plantuml-encoder/-/plantuml-encoder-1.4.0.tgz", + "integrity": "sha512-sxMwpDw/ySY1WB2CE3+IdMuEcWibJ72DDOsXLkSmEaSzwEUaYBT6DWgOfBiHGCux4q433X6+OEFWjlVqp7gL6g==", + "dev": true + }, + "node_modules/portfinder": { + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", + "dev": true, + "dependencies": { + "async": "^2.6.4", + "debug": "^3.2.7", + "mkdirp": "^0.5.6" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/portfinder/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-calc": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz", + "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + } + }, + "node_modules/postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-colormin/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-convert-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-load-config": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.2.tgz", + "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==", + "dev": true, + "dependencies": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "dev": true, + "dependencies": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dev": true, + "dependencies": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-merge-longhand/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-merge-rules/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-font-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dev": true, + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-gradients/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-params/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-selectors/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz", + "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0", + "postcss-value-parser": "^3.3.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss-modules-values": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz", + "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", + "dev": true, + "dependencies": { + "icss-replace-symbols": "^1.1.0", + "postcss": "^7.0.6" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dev": true, + "dependencies": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-display-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dev": true, + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-positions/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dev": true, + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-repeat-style/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "dev": true, + "dependencies": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-string/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "dev": true, + "dependencies": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-timing-functions/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-unicode/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "dev": true, + "dependencies": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-url/node_modules/normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/postcss-normalize-url/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-whitespace/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "dev": true, + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-ordered-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dev": true, + "dependencies": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-reduce-transforms/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-safe-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz", + "integrity": "sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==", + "dev": true, + "dependencies": { + "postcss": "^7.0.26" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.3.tgz", + "integrity": "sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-svgo/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/postcss-svgo/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo/node_modules/css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "node_modules/postcss-svgo/node_modules/css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/postcss-svgo/node_modules/css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/postcss-svgo/node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/postcss-svgo/node_modules/csso/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/postcss-svgo/node_modules/csso/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "node_modules/postcss-svgo/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/postcss-svgo/node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/postcss-svgo/node_modules/domutils/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "node_modules/postcss-svgo/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/postcss-svgo/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/postcss-svgo/node_modules/js-yaml": { + "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, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/postcss-svgo/node_modules/mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "node_modules/postcss-svgo/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/postcss-svgo/node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "dependencies": { + "boolbase": "~1.0.0" + } + }, + "node_modules/postcss-svgo/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-svgo/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo/node_modules/svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "dev": true, + "dependencies": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/postcss/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "optional": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-error": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", + "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^2.0.4" + } + }, + "node_modules/pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "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==", + "dev": true + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "node_modules/proxy-addr": { + "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==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "dependencies": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/readdirp/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/readdirp/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp/node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/readdirp/node_modules/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==", + "dev": true + }, + "node_modules/readdirp/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/readdirp/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/reduce/-/reduce-1.0.2.tgz", + "integrity": "sha512-xX7Fxke/oHO5IfZSk77lvPa/7bjMh9BuCk4OOoX5XTXrM7s0Z+MkPfSDfz0q7r91BhhGSs8gii/VEN/7zhCPpQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.1.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "license": "MIT", + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "node_modules/renderkid": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", + "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^3.0.1" + } + }, + "node_modules/renderkid/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/renderkid/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "node_modules/resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg==", + "dev": true, + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "dev": true, + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha512-gDK5mkALDFER2YLqH6imYvK6g02gpNGM4ILDZ472EwWfXZnC2ZEpoB2ECXTyOVUKuk/bPJZMzwQPBYICzP+D3w==", + "dev": true + }, + "node_modules/rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg==", + "dev": true + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "dev": true + }, + "node_modules/run-con": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.3.2.tgz", + "integrity": "sha512-CcfE+mYiTcKEzg0IqS08+efdnH0oJ3zV0wSUFBNrMHMuxCtXvBCLzCJHatwuXDcu/RlhjTziTo/a1ruQik6/Yg==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~4.1.0", + "minimist": "^1.2.8", + "strip-json-comments": "~3.1.1" + }, + "bin": { + "run-con": "cli.js" + } + }, + "node_modules/run-con/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==", + "dev": true, + "dependencies": { + "aproba": "^1.1.1" + } + }, + "node_modules/run-queue/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "dev": true + }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selfsigned": { + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz", + "integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==", + "dev": true, + "dependencies": { + "node-forge": "^0.10.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/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==", + "dev": true + }, + "node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/smol-toml": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.3.4.tgz", + "integrity": "sha512-UOPtVuYkzYGee0Bd2Szz8d2G3RfMfJ2t3qVdZUAozZyAk+a0Sxa+QKix0YCwjL/A1RR0ar44nCxaoN9FxdJGwA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/smoothscroll-polyfill": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/smoothscroll-polyfill/-/smoothscroll-polyfill-0.4.4.tgz", + "integrity": "sha512-TK5ZA9U5RqCwMpfoMq/l1mrH0JAR7y7KRvOBx0n2869aLxch+gT9GhN3yUfjiw+d/DiF1mKo14+hd62JyMmoBg==", + "dev": true + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sockjs-client": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.6.1.tgz", + "integrity": "sha512-2g0tjOR+fRs0amxENLi/q5TiJTqY+WXFOzb5UwXndlK6TO3U/mirZznpx6w34HVMoc3g7cY24yC/ZMIYnDlfkw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "eventsource": "^2.0.2", + "faye-websocket": "^0.11.4", + "inherits": "^2.0.4", + "url-parse": "^1.5.10" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://tidelift.com/funding/github/npm/sockjs-client" + } + }, + "node_modules/sockjs-client/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", + "dev": true, + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sort-keys/node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", + "dev": true + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", + "dev": true + }, + "node_modules/stack-utils": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.5.tgz", + "integrity": "sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-2.3.1.tgz", + "integrity": "sha512-eOsoKTWnr6C8aWrqJJ2KAReXoa7Vn5Ywyw6uCXgA/xDhxPoaIsBa5aNJmISY04dLwXPBnDHW4diGM7Sn5K4R/g==", + "dev": true, + "dependencies": { + "ci-info": "^3.1.1" + } + }, + "node_modules/stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-browserify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/stream-browserify/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/stream-browserify/node_modules/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==", + "dev": true + }, + "node_modules/stream-browserify/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/stream-http/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/stream-http/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/stream-http/node_modules/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==", + "dev": true + }, + "node_modules/stream-http/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/stylehacks/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "dev": true + }, + "node_modules/stylus": { + "version": "0.54.8", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", + "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", + "dev": true, + "dependencies": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.6", + "mkdirp": "~1.0.4", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.3.0", + "source-map": "^0.7.3" + }, + "bin": { + "stylus": "bin/stylus" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stylus-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", + "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", + "dev": true, + "dependencies": { + "loader-utils": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "when": "~3.6.x" + }, + "peerDependencies": { + "stylus": ">=0.52.4" + } + }, + "node_modules/stylus/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/stylus/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/stylus/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/stylus/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stylus/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/stylus/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/svgo": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", + "integrity": "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^11.1.0", + "css-select": "^5.1.0", + "css-tree": "^3.0.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.1.1", + "sax": "^1.4.1" + }, + "bin": { + "svgo": "bin/svgo.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/svgo/node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "dev": true, + "license": "ISC" + }, + "node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.6.tgz", + "integrity": "sha512-2lBVf/VMVIddjSn3GqbT90GvIJ/eYXJkt8cTzU7NbjKqK8fwv18Ftr4PlbF46b/e88743iZFL5Dtr/rC4hjIeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/terser-webpack-plugin/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/terser-webpack-plugin/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/terser-webpack-plugin/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/terser-webpack-plugin/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/terser-webpack-plugin/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser-webpack-plugin/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/terser-webpack-plugin/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/terser-webpack-plugin/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/terser-webpack-plugin/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/through2/node_modules/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==", + "dev": true + }, + "node_modules/through2/node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==", + "dev": true + }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", + "dev": true + }, + "node_modules/to-buffer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", + "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-factory": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-factory/-/to-factory-1.0.0.tgz", + "integrity": "sha512-JVYrY42wMG7ddf+wBUQR/uHGbjUHZbLisJ8N62AMm0iTZ0p8YTcZLzdtomU0+H+wa99VbkyvQGB3zxB7NDzgIQ==", + "dev": true + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/to-regex/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", + "dev": true + }, + "node_modules/toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha512-FclLrw8b9bMWf4QlCJuHBEVhSRsqDj6u3nIjAzPeJvgl//1hBlffdlk0MALceL14+koWEdU4ofRAXofbODxQzg==", + "dev": true + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==", + "dev": true + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, + "node_modules/type-fest": { + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", + "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", + "dev": true, + "dependencies": { + "commander": "~2.19.0", + "source-map": "~0.6.1" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uglify-js/node_modules/commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==", + "dev": true + }, + "node_modules/uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ==", + "dev": true + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==", + "dev": true + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-notifier": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", + "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "pupa": "^2.0.1", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==", + "dev": true + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } }, - "object-copy": { + "node_modules/urix": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", + "dev": true + }, + "node_modules/url": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", + "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "dev": true, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } + "punycode": "^1.4.1", + "qs": "^6.11.2" } }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { - "isobject": "^3.0.0" + "node_modules/url-loader": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", + "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==", + "dev": true, + "dependencies": { + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^3.0.0 || ^4.0.0" + } + }, + "node_modules/url-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" } }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" } }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "requires": { - "isobject": "^3.0.1" + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prepend-http": "^2.0.0" }, + "engines": { + "node": ">=4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/url/node_modules/qs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "dev": true, "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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" + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "on-headers": { + "node_modules/util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" + "node_modules/util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" } }, - "opn": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-6.0.0.tgz", - "integrity": "sha512-I9PKfIZC+e4RXZ/qr1RhgyCnGgYX0UEIlXgWnCOVACIvFgaC9rz6Won7xbdhoHrd8IIhV7YEpHjreNUNkqCGkQ==", - "requires": { - "is-wsl": "^1.1.0" + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" } }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" } }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "optional": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - }, - "dependencies": { - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "optional": true - } + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "node_modules/vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "node_modules/vue": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz", + "integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==", + "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-sfc": "2.7.16", + "csstype": "^3.1.0" } }, - "parse5": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", - "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", - "optional": true + "node_modules/vue-hot-reload-api": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", + "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue-loader": { + "version": "15.11.1", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.11.1.tgz", + "integrity": "sha512-0iw4VchYLePqJfJu9s62ACWUXeSqM30SQqlIftbYWM3C+jpPcEHKSPUZBLjSF9au4HTHQ/naF6OGnO3Q/qGR3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/component-compiler-utils": "^3.1.0", + "hash-sum": "^1.0.2", + "loader-utils": "^1.1.0", + "vue-hot-reload-api": "^2.3.0", + "vue-style-loader": "^4.1.0" + }, + "peerDependencies": { + "css-loader": "*", + "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0" + }, + "peerDependenciesMeta": { + "cache-loader": { + "optional": true + }, + "prettier": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + "node_modules/vue-router": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.6.5.tgz", + "integrity": "sha512-VYXZQLtjuvKxxcshuRAwjHnciqZVoXAjTjcqBTz4rKc8qih9g9pI3hbDjmqXaHdgL3v8pV6P8Z335XvHzESxLQ==", + "dev": true + }, + "node_modules/vue-server-renderer": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/vue-server-renderer/-/vue-server-renderer-2.7.16.tgz", + "integrity": "sha512-U7GgR4rYmHmbs3Z2gqsasfk7JNuTsy/xrR5EMMGRLkjN8+ryDlqQq6Uu3DcmbCATAei814YOxyl0eq2HNqgXyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "hash-sum": "^2.0.0", + "he": "^1.2.0", + "lodash.template": "^4.5.0", + "lodash.uniq": "^4.5.0", + "resolve": "^1.22.0", + "serialize-javascript": "^6.0.0", + "source-map": "0.5.6" + } }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + "node_modules/vue-server-renderer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + "node_modules/vue-server-renderer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "node_modules/vue-server-renderer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } }, - "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=" + "node_modules/vue-server-renderer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/vue-server-renderer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "requires": { - "through": "~2.3" + "node_modules/vue-server-renderer/node_modules/hash-sum": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", + "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", + "dev": true + }, + "node_modules/vue-server-renderer/node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" } }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + "node_modules/vue-server-renderer/node_modules/source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "phantomjs-prebuilt": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", - "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", - "requires": { - "es6-promise": "^4.0.3", - "extract-zip": "^1.6.5", - "fs-extra": "^1.0.0", - "hasha": "^2.2.0", - "kew": "^0.7.0", - "progress": "^1.1.8", - "request": "^2.81.0", - "request-progress": "^2.0.1", - "which": "^1.2.10" - }, - "dependencies": { - "fs-extra": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", - "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" - } - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "requires": { - "graceful-fs": "^4.1.6" - } - } + "node_modules/vue-server-renderer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + "node_modules/vue-style-loader": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", + "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-sum": "^1.0.2", + "loader-utils": "^1.0.2" + } }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" + "node_modules/vue-template-compiler": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", + "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" } }, - "plantuml-encoder": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/plantuml-encoder/-/plantuml-encoder-1.4.0.tgz", - "integrity": "sha512-sxMwpDw/ySY1WB2CE3+IdMuEcWibJ72DDOsXLkSmEaSzwEUaYBT6DWgOfBiHGCux4q433X6+OEFWjlVqp7gL6g==" + "node_modules/vue-template-es2015-compiler": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", + "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vuepress": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/vuepress/-/vuepress-1.9.10.tgz", + "integrity": "sha512-UnGm9vjQvG918SZVNvgiUlNimLqawdYPq0aPRXDpEB1VksvqegVFy/GKdA8ShXJaEpOMPSt7YD4uK21jaMs3kA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@vuepress/core": "1.9.10", + "@vuepress/theme-default": "1.9.10", + "@vuepress/types": "1.9.10", + "cac": "^6.5.6", + "envinfo": "^7.2.0", + "opencollective-postinstall": "^2.0.2", + "update-notifier": "^4.0.0" + }, + "bin": { + "vuepress": "cli.js" + }, + "engines": { + "node": ">=8.6" + } }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + "node_modules/vuepress-html-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vuepress-html-webpack-plugin/-/vuepress-html-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-BebAEl1BmWlro3+VyDhIOCY6Gef2MCBllEVAP3NUAtMguiyOwo/dClbwJ167WYmcxHJKLl7b0Chr9H7fpn1d0A==", + "dev": true, + "dependencies": { + "html-minifier": "^3.2.3", + "loader-utils": "^0.2.16", + "lodash": "^4.17.3", + "pretty-error": "^2.0.2", + "tapable": "^1.0.0", + "toposort": "^1.0.0", + "util.promisify": "1.0.0" + }, + "engines": { + "node": ">=6.9" + }, + "peerDependencies": { + "webpack": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0" + } }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "optional": true + "node_modules/vuepress-html-webpack-plugin/node_modules/big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true, + "engines": { + "node": "*" + } }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + "node_modules/vuepress-html-webpack-plugin/node_modules/emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha512-knHEZMgs8BB+MInokmNTg/OyPlAddghe1YBgNwJBc5zsJi/uyIcXoSDsL/W9ymOsBoBGdPIHXYJ9+qKFwRwDng==", + "dev": true, + "engines": { + "node": ">= 0.10" + } }, - "process-nextick-args": { - "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==" + "node_modules/vuepress-html-webpack-plugin/node_modules/json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + } }, - "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=" + "node_modules/vuepress-html-webpack-plugin/node_modules/loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha512-tiv66G0SmiOx+pLWMtGEkfSEejxvb6N6uRrQjfWJIT79W9GMpgKeCAmm9aVBKtd4WEgntciI8CsGqjpDoCWJug==", + "dev": true, + "dependencies": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "optional": true, - "requires": { - "asap": "~2.0.3" + "node_modules/vuepress-plugin-container": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/vuepress-plugin-container/-/vuepress-plugin-container-2.1.5.tgz", + "integrity": "sha512-TQrDX/v+WHOihj3jpilVnjXu9RcTm6m8tzljNJwYhxnJUW0WWQ0hFLcDTqTBwgKIFdEiSxVOmYE+bJX/sq46MA==", + "dev": true, + "dependencies": { + "@vuepress/shared-utils": "^1.2.0", + "markdown-it-container": "^2.0.0" } }, - "promised-handlebars": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/promised-handlebars/-/promised-handlebars-1.0.6.tgz", - "integrity": "sha1-2ZfglDsD9j/oL/I8uQSyes/AUNg=", - "requires": { - "deep-aplus": "^1.0.2", - "q": "^1.4.1" + "node_modules/vuepress-plugin-mermaidjs": { + "version": "2.0.0-beta.2", + "resolved": "https://registry.npmjs.org/vuepress-plugin-mermaidjs/-/vuepress-plugin-mermaidjs-2.0.0-beta.2.tgz", + "integrity": "sha512-0pDJjLFsnMuvy3wc2iEhz0OQy+tQva04ynVdhMKdH6KtetuezxtNbwazEJcRQGzDzyo2r/5rGRLYvA4MhGnj5w==", + "dev": true, + "dependencies": { + "mermaid": "^8.14.0" } }, - "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" + "node_modules/vuepress-plugin-smooth-scroll": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/vuepress-plugin-smooth-scroll/-/vuepress-plugin-smooth-scroll-0.0.3.tgz", + "integrity": "sha512-qsQkDftLVFLe8BiviIHaLV0Ea38YLZKKonDGsNQy1IE0wllFpFIEldWD8frWZtDFdx6b/O3KDMgVQ0qp5NjJCg==", + "dev": true, + "dependencies": { + "smoothscroll-polyfill": "^0.4.3" } }, - "proxy-middleware": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz", - "integrity": "sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY=" + "node_modules/vuepress-plugin-versioning": { + "version": "4.10.2", + "resolved": "git+ssh://git@github.com/mojaloop/vuepress-plugin-versioning.git#dcb14962a69b8e5aaf184d2d1a31ae4f43870bc1", + "integrity": "sha512-8sUoK+REHLrmnF9nzGxljTDS0v6edozzPjhUvNIazsSNfTBRcMMmGgVlzQmS1d6GgSMUex7HyfIDMjamWybgvg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@vuepress/shared-utils": "^1.7.1", + "fs-extra": "^9.0.1" + } }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "optional": true + "node_modules/vuepress-plugin-versioning/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } }, - "psl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", - "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==" + "node_modules/vuepress-plugin-versioning/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "node_modules/vuepress-plugin-versioning/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } }, - "q": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.0.tgz", - "integrity": "sha1-3QG6ydBtMObyGa7LglPunr3DCPE=" + "node_modules/vuepress-theme-titanium": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/vuepress-theme-titanium/-/vuepress-theme-titanium-4.11.2.tgz", + "integrity": "sha512-a/MQ2H4bJKl7D97RT5E4DfBnUWewTmjNcoCKhwI3zrfWUnxeQWuGjnrdaswSm7t6YiUHkJIBrMsCJNPIiHY5EA==", + "dev": true, + "dependencies": { + "@vuepress/plugin-nprogress": "^1.7.1", + "@vuepress/plugin-search": "^1.7.1", + "docsearch.js": "^2.6.3", + "lodash": "^4.17.15", + "stylus": "^0.54.5", + "stylus-loader": "^3.0.2", + "vuepress-plugin-container": "^2.1.5" + } }, - "q-deep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/q-deep/-/q-deep-1.0.3.tgz", - "integrity": "sha1-zQcD2irMuuZXDmAMaKVt5mEHkMs=", - "requires": { - "deep-aplus": "^1.0.1", - "q": "^1.1.2" + "node_modules/watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "optionalDependencies": { + "chokidar": "^3.4.1", + "watchpack-chokidar2": "^2.0.1" } }, - "q-plus": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/q-plus/-/q-plus-0.0.8.tgz", - "integrity": "sha1-TMZssZvRRbQ+nhtUAjYUI3e2Hqs=", - "requires": { - "q": "^1.1.2" + "node_modules/watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "chokidar": "^2.1.8" } }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "node_modules/watchpack/node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } + "node_modules/watchpack/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + "node_modules/watchpack/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, - "raw-body": { - "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.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "node_modules/watchpack/node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "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" + "node_modules/watchpack/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" } }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "requires": { - "graceful-fs": "^4.1.11", + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/webpack": { + "version": "4.47.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.47.0.tgz", + "integrity": "sha512-td7fYwgLSrky3fI1EuU5cneU4+pbH6GgOfuKNS1tNPcfdGinGELAqsb/BP4nnvZyKSG2i/xFGU7+n2PvZA8HJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } + "webpack-command": { + "optional": true } } }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "requires": { - "is-equal-shallow": "^0.1.3" + "node_modules/webpack-chain": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.5.1.tgz", + "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==", + "dev": true, + "dependencies": { + "deepmerge": "^1.5.2", + "javascript-stringify": "^2.0.1" + }, + "engines": { + "node": ">=8" } }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "node_modules/webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "dependencies": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "node_modules/webpack-dev-middleware/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/webpack-dev-server": { + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz", + "integrity": "sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA==", + "dev": true, "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "ansi-html-community": "0.0.8", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.8", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 6.11.5" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true } } }, - "request-progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", - "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", - "requires": { - "throttleit": "^1.0.0" + "node_modules/webpack-dev-server/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "request-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz", - "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==", - "requires": { - "bluebird": "^3.5.0", - "request-promise-core": "1.1.2", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" + "node_modules/webpack-dev-server/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "request-promise-core": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", - "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", - "requires": { - "lodash": "^4.17.11" + "node_modules/webpack-dev-server/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - } + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + }, + "engines": { + "node": ">=4.0.0" } }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "node_modules/webpack-dev-server/node_modules/is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + "node_modules/webpack-dev-server/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "requires": { - "align-text": "^0.1.1" + "node_modules/webpack-dev-server/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "requires": { - "glob": "^7.1.3" + "node_modules/webpack-dev-server/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.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==" + "node_modules/webpack-dev-server/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "requires": { - "ret": "~0.1.10" + "node_modules/webpack-dev-server/node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "optional": true + "node_modules/webpack-dev-server/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } }, - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + "node_modules/webpack-dev-server/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } }, - "send": { - "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", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "node_modules/webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "dependencies": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "dev": true, "dependencies": { - "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==" - } + "lodash": "^4.17.15" } }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, + "node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, "dependencies": { - "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" - } - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - } + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" } }, - "serve-static": { - "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.3", - "send": "0.17.1" + "node_modules/webpack/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "requires": { + "node_modules/webpack/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" } }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "node_modules/webpack/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "node_modules/webpack/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "node_modules/webpack/node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" } }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { - "kind-of": "^3.2.0" + "node_modules/webpack/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" } }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "optional": true, - "requires": { - "hoek": "2.x.x" + "node_modules/webpack/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "requires": { - "amdefine": ">=0.0.4" + "node_modules/webpackbar": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-3.2.0.tgz", + "integrity": "sha512-PC4o+1c8gWWileUfwabe0gqptlXUDJd5E0zbpr2xHP1VSOVlZVPBZ8j6NCR8zM5zbKdxPhctHXahgpNK1qFDPw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.1.0", + "chalk": "^2.4.1", + "consola": "^2.6.0", + "figures": "^3.0.0", + "pretty-time": "^1.1.0", + "std-env": "^2.2.1", + "text-table": "^0.2.0", + "wrap-ansi": "^5.1.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^3.0.0 || ^4.0.0" } }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "node_modules/webpackbar/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" } }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "requires": { - "through": "2" + "node_modules/webpackbar/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "requires": { - "extend-shallow": "^3.0.0" + "node_modules/webpackbar/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "node_modules/webpackbar/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "node_modules/webpackbar/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" } }, - "stack-chain": { + "node_modules/webpackbar/node_modules/is-fullwidth-code-point": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-2.0.0.tgz", - "integrity": "sha512-GGrHXePi305aW7XQweYZZwiRwR7Js3MWoK/EHzzB9ROdc75nCnjSJVi21rdAGxFl+yCx2L2qdfl5y7NO4lTyqg==", - "optional": true + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, + "node_modules/webpackbar/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" } }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "requires": { - "duplexer": "~0.1.1" + "node_modules/webpackbar/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" } }, - "stream-equal": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/stream-equal/-/stream-equal-0.1.13.tgz", - "integrity": "sha1-F8LXz43lVw0P+5njpRQqWMdrxK4=", - "requires": { - "@types/node": "*" + "node_modules/webpackbar/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "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" + "node_modules/webpackbar/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" } }, - "stringstream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "optional": true + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } }, - "svgexport": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/svgexport/-/svgexport-0.3.2.tgz", - "integrity": "sha1-ci8xhAMotIPopdyqc+/4GNiE0QY=", - "requires": { - "async": "^1.0.0", - "phantomjs-prebuilt": "^2.1.4" + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" } }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "optional": true + "node_modules/when": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz", + "integrity": "sha512-d1VUP9F96w664lKINMGeElWdhhb5sC+thXM+ydZGU3ZnaE09Wv6FaS+mpM9570kcDs/xMfcXJBTLsMdHEFYY9Q==", + "dev": true }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=" + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "node_modules/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, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "tmp": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", - "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", - "requires": { - "os-tmpdir": "~1.0.1" + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "requires": { - "kind-of": "^3.0.2" + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "node_modules/widest-line/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, + "node_modules/widest-line/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/widest-line/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - } - } + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "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==", - "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=" - } + "node_modules/widest-line/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "optional": true + "node_modules/worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "dependencies": { + "errno": "~0.1.7" + } }, - "trace": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/trace/-/trace-3.1.1.tgz", - "integrity": "sha512-iVxFnDKps8bCRQ6kXj66rHYFJY3fNkoYPHeFTFZn89YdwmmQ9Hz97IFPf3NdfbCF3zuqUqFpRNTu6N9+eZR2qg==", - "optional": true, - "requires": { - "stack-chain": "^2.0.0" + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "trace-and-clarify-if-possible": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/trace-and-clarify-if-possible/-/trace-and-clarify-if-possible-1.0.5.tgz", - "integrity": "sha512-CmBz2eGrPxQ5miq51B4XnON0iC62q6q7CEzrRaFYZYi8xdX1ivafyk5cYshmVXp6p14cYvK3H4o1drYa3MEJOA==", - "requires": { - "clarify": "^2.1.0", - "trace": "^3.1.1" + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "optional": true, - "requires": { - "prelude-ls": "~1.1.2" + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "type-is": { - "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.24" + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "uglify-to-browserify": { + "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "optional": true + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" } }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "unix-crypt-td-js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unix-crypt-td-js/-/unix-crypt-td-js-1.0.0.tgz", - "integrity": "sha1-HAgkFQSBvHoB1J6Y8exmjYJBLzs=" + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" } }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" - }, - "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==", - "requires": { - "punycode": "^2.1.0" + "node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + "node_modules/yargs/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/yargs/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } }, - "user-home": { + "node_modules/yargs/node_modules/is-fullwidth-code-point": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "requires": { - "os-homedir": "^1.0.0" + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" } }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "node_modules/yargs/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "webidl-conversions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz", - "integrity": "sha1-O/glj30xjHRDw28uFpQCoaZwNQY=", - "optional": true - }, - "websocket-driver": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", - "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", - "requires": { - "http-parser-js": ">=0.4.0 <0.4.11", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" - }, - "whatwg-url-compat": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz", - "integrity": "sha1-AImBEa9om7CXVBzVpFymyHmERb8=", - "optional": true, - "requires": { - "tr46": "~0.0.1" + "node_modules/yargs/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" } }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" + "node_modules/yargs/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" } }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "xml-name-validator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", - "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=", - "optional": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" } }, - "yauzl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", - "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", - "requires": { - "fd-slicer": "~1.0.1" + "node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" } + }, + "node_modules/zepto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zepto/-/zepto-1.2.0.tgz", + "integrity": "sha512-C1x6lfvBICFTQIMgbt3JqMOno3VOtkWat/xEakLTOurskYIHPmzJrzd1e8BnmtdDVJlGuk5D+FxyCA8MPmkIyA==", + "dev": true } } } diff --git a/package.json b/package.json index 3a136d614..2cb071732 100644 --- a/package.json +++ b/package.json @@ -1,47 +1,43 @@ { - "name": "documentation", - "version": "9.1.0", - "description": "Mojaloop Documentation GitBook Project", - "dependencies": { - "express": "4.17.1", - "gitbook-cli": "2.3.2", - "gitbook-plugin-back-to-top-button": "0.1.4", - "gitbook-plugin-changelog": "1.0.1", - "gitbook-plugin-collapsible-chapters": "0.1.8", - "gitbook-plugin-editlink": "1.0.2", - "gitbook-plugin-fontsettings": "2.0.0", - "gitbook-plugin-include": "0.1.0", - "gitbook-plugin-insert-logo": "0.1.5", - "gitbook-plugin-page-toc": "1.1.1", - "gitbook-plugin-plantuml-svg": "1.0.1", - "gitbook-plugin-swagger": "0.2.0", - "gitbook-plugin-theme-api": "1.1.2", - "gitbook-plugin-uml": "1.0.1", - "gitbook-plugin-variables": "1.1.0", - "svgexport": "0.3.2" - }, - "devDependencies": {}, + "name": "mojaloop-docs-vuepress", + "version": "1.0.0", + "description": "Mojaloop Documentation 3.0", + "license": "Apache-2.0", + "contributors": [ + "Sam Kummary ", + "Uduak Obong-Eren ", + "Steven Oderayi ", + "Tony Williams " + ], + "repository": "https://www.github.com/mojaloop/documentation", "scripts": { - "run": "npm run gitbook:serve", - "start": "npm run gitbook:serveNoReload", - "gitbook:install": "gitbook install", - "gitbook:build": "gitbook build", - "gitbook:serve": "gitbook serve --port 8989", - "gitbook:serveNoReload": "gitbook serve --no-live --port 8989", - "gitbook:export:pdf": "gitbook pdf ./", - "docker:build": "docker build --no-cache -t mojaloop/documentation .", - "docker:push": "docker push mojaloop/documentation", - "docker:run": "docker run --rm -it --name mojadoc -p 8989:8989 mojaloop/documentation", - "express:run": "node index.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/mojaloop/documentation.git" + "dev": "NODE_OPTIONS=--openssl-legacy-provider npx npx vuepress dev docs", + "build": "NODE_OPTIONS='--max-old-space-size=8192' npx npx vuepress build docs", + "build:plantuml:all": "./scripts/_build_plantuml.sh", + "build:plantuml:diff": "MODE=STAGED_GIT ./scripts/_build_plantuml.sh", + "lint": "npx markdownlint './docs/**/*.md' --ignore node_modules --config markdownlint.yaml", + "lint:fix": "npm run lint -- --fix", + "dep:check": "npx ncu -e 2", + "dep:update": "npx ncu -u", + "prepare": "npx husky install" }, - "author": "", - "license": "ISC", - "bugs": { - "url": "https://github.com/mojaloop/documentation/issues" + "devDependencies": { + "@vuepress/plugin-back-to-top": "^1.9.10", + "@vuepress/plugin-medium-zoom": "^1.9.10", + "got": "^14.4.7", + "husky": "^9.1.7", + "markdownlint-cli": "^0.45.0", + "npm-check-updates": "^18.0.1", + "plantuml-encoder": "^1.4.0", + "svgo": "^4.0.0", + "vuepress": "^1.9.10", + "vuepress-plugin-mermaidjs": "^2.0.0-beta.2", + "vuepress-plugin-versioning": "git+https://github.com/mojaloop/vuepress-plugin-versioning.git#dcb14962a69b8e5aaf184d2d1a31ae4f43870bc1", + "vuepress-theme-titanium": "^4.11.2" }, - "homepage": "https://github.com/mojaloop/documentation#readme" + "overrides": { + "vuepress": { + "vue-loader": "15.1.1" + } + } } diff --git a/scripts/_build_plantuml.sh b/scripts/_build_plantuml.sh new file mode 100755 index 000000000..6bc5d8684 --- /dev/null +++ b/scripts/_build_plantuml.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + + +## +# _build_plantuml.sh +# +# searches through repo for plantuml sources matching $PUML_MATCH +# and exports them using `node-plantuml`. +# +# In order to build deterministic .svgs, we use a puml docker image that is +# pegged to a specific version +## + +set -eu + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PUML_PORT=9999 +export PUML_BASE_URL=http://localhost:${PUML_PORT} + +# Match filenames ending with .puml or .plantuml by default +PUML_MATCH=${PUML_MATCH:=*.p*uml} + +# if MODE=STAGED_GIT, then search staged git files +# if MODE=ALL, then search the whole repo +MODE=${MODE:=ALL} + +trap ctrl_c INT +function ctrl_c() { + echo "exit early - stopping docker" + docker stop puml-local + exit 1 +} + +# run the docker puml server +docker run -d --rm \ + --name puml-local \ + -p ${PUML_PORT}:8080 \ + plantuml/plantuml-server:jetty-v1.2024.7 + +# Wait for docker to be up +sleep 2 + +echo "Searching for ${MODE} files matching pattern: ${PUML_MATCH}" + +case ${MODE} in + # search only for the staged files - much faster to run as a git hook + STAGED_GIT) + for i in $(git diff --staged --name-only `find ${DIR}/../docs -name ${PUML_MATCH}`); do + echo "rendering .puml -> .svg for diagram diagram: $i" + + # add the .svg file alongside the original + ${DIR}/_render_svg.mjs $i + done + ;; + + # search all files + ALL) + for i in $(find ${DIR}/../docs -name ${PUML_MATCH}); do + echo "rendering .puml -> .svg for diagram diagram: $i" + + # add the .svg file alongside the original + ${DIR}/_render_svg.mjs $i + done + ;; + + *) + echo "unsupported search MODE:${MODE}" + exit 1 + ;; +esac + +docker stop puml-local diff --git a/scripts/_deploy_preview_s3.sh b/scripts/_deploy_preview_s3.sh new file mode 100755 index 000000000..00d169623 --- /dev/null +++ b/scripts/_deploy_preview_s3.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + + +# deploys the preview docs to an s3 bucket +# I manually created the bucket: `mojaloop-docs-preview` +# in the eu-west-2 region +# and followed the guide: https://docs.aws.amazon.com/AmazonS3/latest/userguide/EnableWebsiteHosting.html +# to manually configure the bucket for website hosting +# And this guide: https://aws.amazon.com/premiumsupport/knowledge-center/cloudfront-serve-static-website/ +# to set up Cloudfront and Route53 +# "Using a REST API endpoint as the origin, with access restricted by an OAI" + +# The website should be available at: +# https://docs.mojaloop.io/pr/ + +# Required tools: +# - aws-cli +# - aws-mfa (if running as user, not CI) + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +NVM_DIR=$HOME/.nvm +export AWS_REGION="${AWS_REGION:-eu-west-2}" +export BUCKET_NAME="${BUCKET_NAME:-docs.mojaloop.io-root}" +export DOMAIN="${DOMAIN:-docs.mojaloop.io}" +export IS_PR="${IS_PR:-false}" +export PR_NUMBER="${PR_NUMBER:-}" + +set -e +set -u + +# make sure we can actually list the s3 buckets +aws s3 ls s3://${BUCKET_NAME} + +# build new vuepress site +rm -rf ${DIR}/../build +cd ${DIR}/../ +npm ci +# Pass environment variables to VuePress build +export VUEPRESS_IS_PR="${IS_PR}" +export VUEPRESS_PR_NUMBER="${PR_NUMBER}" +npm run build +mv ${DIR}/../docs/.vuepress/dist ${DIR}/../build + + +# build legacy docs - will be removed once all docs are migrated to v2.0 +# Removing from here! multiple node versions in CI/CD are really hard! +# cd ${DIR}/../legacy +# [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" +# nvm install 10.15.1 +# nvm use 10.15.1 +# npm i +# npm run gitbook:build +# copy to a legacy subfolder +mv ${DIR}/../legacy/_book ${DIR}/../build/legacy + + +# TODO: can we be smart about docs versions here? maybe every minor version we can keep... + +# Determine the target path based on whether this is a PR or not +if [ "$IS_PR" = "true" ] && [ -n "$PR_NUMBER" ]; then + TARGET_PATH="pr/${PR_NUMBER}" +else + TARGET_PATH="" +fi + +# upload built files to s3 +if [ -n "$TARGET_PATH" ]; then + aws s3 sync ${DIR}/../build s3://${BUCKET_NAME}/${TARGET_PATH} \ + --acl public-read +else + aws s3 sync ${DIR}/../build s3://${BUCKET_NAME} \ + --acl public-read +fi + +if [ "$IS_PR" = "true" ] && [ -n "$PR_NUMBER" ]; then + echo "Preview deployment is available at: https://${DOMAIN}/pr/${PR_NUMBER}" +else + echo "Deployment is available at: https://${DOMAIN}" +fi \ No newline at end of file diff --git a/scripts/_render_svg.mjs b/scripts/_render_svg.mjs new file mode 100755 index 000000000..73a529b68 --- /dev/null +++ b/scripts/_render_svg.mjs @@ -0,0 +1,86 @@ +#!/usr/bin/env node + +/** + * NOTES: + * - This file is an ESM Module (thus the extension `.mjs`). This is required for the `got` dependency which only supports ESM! + * - Uses PlantUml server to render a PUML to SVG + */ + +import fs from 'fs' +import path from 'path' +import util from 'util' +import got from 'got' +import * as SVGO from 'svgo' +import * as plantumlEncoder from 'plantuml-encoder' + +const rendererBaseUrl = process.env.PUML_BASE_URL || 'http://www.plantuml.com/plantuml' + +async function main() { + + let [_, _script, inputPath, outputPath] = process.argv + + if (!inputPath) { + console.log("usage: ./_render_svg.mjs []") + process.exit(1) + } + + // If not specified, replace .puml or .plantuml with `.svg` + if (!outputPath) { + outputPath = inputPath.replace('.puml', '.svg') + .replace('.plantuml', '.svg') + } + + const rawPumlContents = fs.readFileSync(inputPath) + const encoded = plantumlEncoder.encode(rawPumlContents.toString()) + const url = path.join(rendererBaseUrl, 'svg', encoded) + let result + try { + result = await got.get(url) + } catch (err) { + console.log('http request failed to render puml with error', err.message) + if (err.message.indexOf('Response code 403') > -1) { + console.log('Note: sometimes the public puml renderer fails when the input diagrams are too large. Try running your own renderer server with docker.') + } + + if (err.message.indexOf('Response code 400') > -1) { + console.log('This could be due to bad syntax in the puml diagram. Url is:') + console.log(url) + } + + process.exit(1) + } + + // Strip comments and prettify svg + // This makes sure that our .svg files are deterministic and diff'able + const formatted = await SVGO.optimize( + result.body, + { + path: outputPath, + multipass: true, + js2svg: { pretty: true, indent: 2 }, + plugins: [ + //// preset-defaults plugin override + // { + // name: 'preset-default', + // params: { + // overrides: { + // Insert overrides here. + // } + // } + // }, + // removeComments plugin + { + name: 'removeComments', + params: { + overrides: { + active: true + } + } + } + ] + } + ) + fs.writeFileSync(outputPath, formatted.data) +} + +main() diff --git a/scripts/_sync_sequence_puml.sh b/scripts/_sync_sequence_puml.sh new file mode 100755 index 000000000..64a0c660c --- /dev/null +++ b/scripts/_sync_sequence_puml.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +## +# The images and puml diagrams for the Mojaloop API come from +# the mojaloop/mojaloop-specification repo +# +# This script copies the latest diagrams from that repo +# into this one. +## + + +set -eu pipefail + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +SOURCE_REPO_URL=git@github.com:mojaloop/mojaloop-specification.git +SOURCE_PATH_TO_COPY=/tmp/mojaloop-specification/assets/diagrams/ +DESTINATION_PATH=${DIR}/../docs/api/assets + +git clone ${SOURCE_REPO_URL} /tmp/mojaloop-specification || echo 'already cloned' + +ls ${SOURCE_PATH_TO_COPY} + +cp -R ${SOURCE_PATH_TO_COPY} ${DESTINATION_PATH} + +# cleanup +rm -rf /tmp/mojaloop-specification \ No newline at end of file diff --git a/tmp-regex.md b/tmp-regex.md new file mode 100644 index 000000000..a3d0b8f4d --- /dev/null +++ b/tmp-regex.md @@ -0,0 +1,16 @@ + +replace the uml line with just the path +find: ^\{%.*(".*").*\n +replace: $1\n + + +Find all uml end tags: +find (plain): {% enduml %} +replace: + +Replace string with image ref: + +find: ^".*plantuml" +replace: ![]($0) + + diff --git a/website/README.md b/website/README.md new file mode 100644 index 000000000..b7d4930aa --- /dev/null +++ b/website/README.md @@ -0,0 +1,7 @@ +# Versioned Docs + +This directory contains previous versions of the documentation. + +Please don't edit them! If you have a fix to make in +the documentation, then make it in `./docs`. We keep the old versions in the same repo to make switching between versions and referencing simple. + diff --git a/website/versioned_docs/v1.0.1/api/README.md b/website/versioned_docs/v1.0.1/api/README.md new file mode 100644 index 000000000..518535f9a --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/README.md @@ -0,0 +1,13 @@ +# API Catalog + +The Mojaloop Family of APIs is a set of several different APIs that cater for several business or transactional functions. So far, the well defined and adopted APIs are: + +- [FSP Interoperability (FSPIOP) APIs](./fspiop/) +- [Administration API]() +- [Settlement API]() +- [Third-party Payment Initiaion (3PPI/PISP) API]() + +There are other APIs that are either in active development and design or on the roadmap: + +- Cross-network API (FX) +- Reporting API diff --git a/website/versioned_docs/v1.0.1/api/administration/README.md b/website/versioned_docs/v1.0.1/api/administration/README.md new file mode 100644 index 000000000..b1851d4be --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/administration/README.md @@ -0,0 +1,14 @@ +## Administration API +The Administration API includes the following documents. + +### Administration Central Ledger API + +[The specification of the Central Ledger API](./central-ledger-api) introduces and describes the **Central Ledger API**. The purpose of the API is to enable Hub Operators to manage admin processes around: + +- Creating/activating/deactivating participants in the Hub +- Adding and updating participant endpoint information +- Managing participant accounts, limits, and positions +- Creating Hub accounts +- Performing Funds In and Funds Out operations +- Creating/updating/viewing settlement models +- Retrieving transfer details \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/administration/central-ledger-api.md b/website/versioned_docs/v1.0.1/api/administration/central-ledger-api.md new file mode 100644 index 000000000..5d3370d99 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/administration/central-ledger-api.md @@ -0,0 +1,1728 @@ +--- +showToc: true +--- +# Central Ledger API + +## Introduction + +This document provides detailed information about the Central Ledger API. The Central Ledger API is a Mojaloop API enabling Hub Operators to manage admin processes around: + +- Creating/activating/deactivating participants in the Hub +- Adding and updating participant endpoint information +- Managing participant accounts, limits, and positions +- Creating Hub accounts +- Performing Funds In and Funds Out operations +- Creating/updating/viewing settlement models +- Retrieving transfer details + + For background information about the participant and settlement model details that the Hub Operator can administer using the Central Ledger API, see section [Basic concepts](#basic-concepts). + +
    + +## Basic concepts + +To provide context for the admin operations that the Central Ledger API enables, this section gives a brief definition of some basic concepts. + +### Participant + +Either the Hub itself or a Digital Financial Service Provider (DFSP) that is a participant in a Mojaloop scheme. + +### Endpoint + +The DFSP callback URL where the Hub routes API callbacks. The URL specified is the endpoint set up in the outbound API gateway. + +### Limit + +Currently, only one type of limit is supported, it is called "_Net Debit Cap (NDC)_". In the future, it is possible to add support for further types of limits. + +The _Net Debit Cap_ represents the liquidity cover available for a specific account (the Position account). It is the total amount of good funds which the scheme attests are available to guarantee that a participant is able to settle the liabilities it incurs on the Position account as a consequence of transferring funds. This amount of good funds is represented as the balance of an account (the Settlement account), which is tied to the Position account by a settlement model. The source of the funds in this account can be either funds recorded by the scheme's administrators as having been deposited to or withdrawn from the Settlement account, or funds which are automatically credited to or debited from the account by the scheme if the account is the Settlement account for an immediate gross settlement model. + +It should also be possible for a participant to specify that an amount, or a proportion, of the funds available in a Settlement account should be excluded from the Net Debit Cap calculation. In cases where a participant is a long-term net beneficiary of funds via settlement, or where participants keep extra funds in their Settlement account to cover periods when it may not be possible to deposit funds to those accounts, it may wish to exclude part of the balance of its Settlement account from use as cover for transfers. + +### Account + +Also called _Ledger_. The Hub maintains a number of internal accounts to keep track of the movement of money (both e-money and real money) between DFSPs. + +### Position + +The Position represents the net of: +- transfers on that account which have cleared but have not yet settled, and +- transfers on that account where: + - the DFSP is the debtor party, and + - the transfer has been accepted for processing by the Hub, but has not yet cleared. + +The Position for a given account is always verifiably up to date. + +When a transfer is requested, the Hub will check that the DFSP has liquidity cover available on that account to cover the amount of the transfer. If it does not, the transfer will be rejected. + +We currently allow liabilities to the participant which have been created as a consequence of transfers on the account where the participant is the beneficiary to reduce the participant's Position as if the liabilities had already been settled. + +### Funds In and Funds Out + +Funds In and Funds Out operations are used to track (in the Hub accounts) money movements related to deposits and withdrawals, as well as settlements. + +Funds In operations record either the deposit of money into a DFSP's settlement bank account or the settlement amount for a receiving DFSP. + +Funds Out operations record either the withdrawal of money from a DFSP's settlement bank account or the settlement amount for a sending DFSP. + +### Settlement model + +Refers to how settlement happens within a scheme. Settlement is the process of transferring funds from one DSFP to another, so that the payer's DFSP reimburses the payee's DFSP for funds given to the payee during a transaction. A settlement model specifies if participants settle with each other separately or settle with the scheme, whether transfers are settled one by one or as a batch, whether transfers are settled immediately or with a delay, and so on. + +
    + +## HTTP details + +This section contains detailed information regarding the use of the application-level protocol HTTP in the API. + +### HTTP header fields + +HTTP headers are generally described in [RFC 7230](https://tools.ietf.org/html/rfc7230). Any headers specific to the Central Ledger API will be standardised in the future. + +### HTTP methods + +The following HTTP methods, as defined in [RFC 7231](https://tools.ietf.org/html/rfc7231#section-4), are supported by the API: + +- `GET` – The HTTP GET method is used from a client to retrieve information about a previously-created object on a server. +- `POST` – The HTTP POST method is used from a client to request an object to be created on the server. +- `PUT` – The HTTP PUT method is used from a client to request an object already existing on the server to be modified (to replace a representation of the target resource with the request payload). + +> **NOTE:** The `DELETE` method is not supported. + +### HTTP response status codes + +The [HTTP response status codes](#http-response-status-codes) table lists the HTTP response status codes that the API supports: + +|Status Code|Reason|Description| +|---|---|---| +|**200**|OK|Standard response for a successful `GET`, `PUT`, or `POST` operation. The response will contain an entity corresponding to the requested resource.| +|**201**|Created|The `POST` request has been fulfilled, resulting in the creation of a new resource. The response will not contain an entity describing or containing the result of the action.| +|**202**|Accepted|The request has been accepted for processing, but the processing has not been completed.| +|**400**|Bad Request|The server could not understand the request due to invalid syntax.| +|**401**|Unauthorized|The request requires authentication in order to be processed.| +|**403**|Forbidden|The request was denied and will be denied in the future.| +|**404**|Not Found|The requested resource is not available at the moment.| +|**405**|Method Not Allowed|An unsupported HTTP method for the request was used.| +|**406**|Not Acceptable|The requested resource is capable of generating only content not acceptable according to the Accept headers sent in the request.| +|**500**|Internal Server Error|A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.| +|**501**|Not Implemented|The server does not support the requested service. The client should not retry.| +|**503**|Service Unavailable|The server is currently unavailable to accept any new service requests. This should be a temporary state, and the client should retry within a reasonable time frame.| + +
    + +## API services + +This section introduces and details all services that the API supports for each resource and HTTP method. + +### High-level API services + +On a high level, the API can be used to perform the following actions: + +- **`/participants`**: View, create, update participant-related details, such as limit (Net Debit Cap), position, or endpoints configured. +- **`/settlementModels`**: View, create, update settlement-model-related details, such as granularity, delay, liquidity check, and so on. +- **`/transactions`**: View transaction details for a particular transfer. + +### Supported API services + +The [Supported API services](#supported-api-services) table includes high-level descriptions of the services that the API provides. For more detailed information, see the sections that follow. + +| URI | HTTP method `GET`| HTTP method `PUT` | HTTP method `POST` | HTTP method `DELETE` | +|---|---|---|---|---| +| **`/participants`** | Get information about all participants | Not supported | Create participants in the Hub | Not supported | +| `/participants/limits` | View limits for all participants | Not supported | Not supported | Not supported | +| `/participants/{name}` | Get information about a particular participant | Update participant details (activate/deactivate a participant) | Not supported | Not supported | +| `/participants/{name}/endpoints` | View participant endpoints | Not supported | Add/Update participant endpoints | Not supported | +| `/participants/{name}/limits` | View participant limits | Adjust participant limits | Not supported | Not supported | +| `/participants/{name}/positions` | View participant positions | Not supported | Not supported | Not supported | +| `/participants/{name}/accounts` | View participant accounts and balances | Not supported | Create Hub accounts | Not supported | +| `/participants/{name}/accounts/{id}` | Not supported | Update participant accounts | Record Funds In or Out of participant account | Not supported | +| `/participants/{name}/accounts/{id}/transfers/{transferId}` | Not supported | Not supported | Record a Transfer as a Funds In or Out transaction for a participant account | Not supported | +| `/participants/{name}/initialPositionAndLimits` | Not supported | Not supported | Add initial participant limits and position | Not supported | +| **`/settlementModels`** | View all settlement models | Not supported | Create a settlement model | Not supported | +| `/settlementModels/{name}` | View settlement model by name | Update a settlement model (activate/deactivate a settlement model) | Not supported | Not supported | +| **`/transactions/{id}`** | Retrieve transaction details by `transferId` | Not supported | Not supported | Not supported | + + +
    + +## API Resource `/participants` + +The services provided by the resource `/participants` are primarily used by the Hub Operator for viewing, creating, and updating participant-related details, such as limit (Net Debit Cap), position, or endpoints configured. + +### GET /participants + +Retrieves information about all participants. + +#### Example request + +``` +curl 'http:///participants' +``` + +#### Example response + +> **NOTE:** In the example below, `dev1-central-ledger.mojaloop.live` indicates where the Central Ledger service of the Mojaloop Hub is running. This detail will be different in your implementation. + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "name": "greenbankfsp", + "id": "dev1-central-ledger.mojaloop.live/participants/greenbankfsp", + "created": "\"2021-03-04T14:20:17.000Z\"", + "isActive": 1, + "links": { + "self": "dev1-central-ledger.mojaloop.live/participants/greenbankfsp" + }, + "accounts": [ + { + "id": 15, + "ledgerAccountType": "POSITION", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 16, + "ledgerAccountType": "SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 21, + "ledgerAccountType": "INTERCHANGE_FEE_SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + } + ] + }, + { + "name": "Hub", + "id": "dev1-central-ledger.mojaloop.live/participants/Hub", + "created": "\"2021-03-04T13:37:25.000Z\"", + "isActive": 1, + "links": { + "self": "dev1-central-ledger.mojaloop.live/participants/Hub" + }, + "accounts": [ + { + "id": 1, + "ledgerAccountType": "HUB_MULTILATERAL_SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 2, + "ledgerAccountType": "HUB_RECONCILIATION", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + } + ] + } +] +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [String](#string) | The identifier of the participant in the form of a fully qualified domain name combined with the participant's `fspId`. | +| `created` | yes | [DateTime](#datetime) | Date and time when the participant was created. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the participant is active. Possible values are `1` and `0`. | +| `links` | yes | [Self](#self) | List of links for a Hypermedia-Driven RESTful Web Service. | +| `accounts` | yes | [Accounts](#accounts) | The list of ledger accounts configured for the participant. | + +
    + +### POST /participants + +Creates a participant in the Hub. + +#### Example request + +``` +curl -X POST -H "Content-Type: application/json" \ + -d '{"name": "payerfsp", "currency": "USD"}' \ + http:///participants +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency that the participant will transact in. | + +#### Example response + +> **NOTE:** In the example below, `dev1-central-ledger.mojaloop.live` indicates where the Central Ledger service of the Mojaloop Hub is running. This detail will be different in your implementation. + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "name": "payerfsp", + "id": "dev1-central-ledger.mojaloop.live/participants/payerfsp", + "created": "\"2021-01-12T10:56:30.000Z\"", + "isActive": 0, + "links": { + "self": "dev1-central-ledger.mojaloop.live/participants/hub" + }, + "accounts": [ + { + "id": 30, + "ledgerAccountType": "POSITION", + "currency": "USD", + "isActive": 0, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 31, + "ledgerAccountType": "SETTLEMENT", + "currency": "USD", + "isActive": 0, + "createdDate": null, + "createdBy": "unknown" + } + ] +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [String](#string) | The identifier of the participant in the form of a fully qualified domain name combined with the participant's `fspId`. | +| `created` | yes | [DateTime](#datetime) | Date and time when the participant was created. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the participant is active. Possible values are `1` and `0`. | +| `links` | yes | [Self](#self) | List of links for a Hypermedia-Driven RESTful Web Service. | +| `accounts` | yes | [Accounts](#accounts) | The list of ledger accounts configured for the participant. | + +
    + +### GET /participants/limits + +Retrieves limits information for all participants. + +#### Query parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | no | [CurrencyEnum](#currencyenum) | The currency of the limit. | +| `limit` | no | [String](#string) | Limit type. | + +#### Example request + +``` +curl 'http:///participants/limits' +``` + +#### Example response + +> **NOTE:** In the example below, `dev1-central-ledger.mojaloop.live` indicates where the Central Ledger service of the Mojaloop Hub is running. This detail will be different in your implementation. + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "name": "payerfsp", + "currency": "USD", + "limit": { + "type": "NET_DEBIT_CAP", + "value": 10000, + "alarmPercentage": 10 + } + }, + { + "name": "payeefsp", + "currency": "USD", + "limit": { + "type": "NET_DEBIT_CAP", + "value": 10000, + "alarmPercentage": 10 + } + } +] +``` + +#### Response data model + +Each limit in the returned list is applied to the specified participant name and currency in each object. + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the participant. | +| `limit` | yes | [ParticipantLimit](#participantlimit) | The limit configured for the participant. | + +
    + +### GET /participants/{name} + +Retrieves information about a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl 'http:///participants/payerfsp' +``` + +#### Example response + +> **NOTE:** In the example below, `dev1-central-ledger.mojaloop.live` indicates where the Central Ledger service of the Mojaloop Hub is running. This detail will be different in your implementation. + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "name": "payerfsp", + "id": "dev1-central-ledger.mojaloop.live/participants/payerfsp", + "created": "\"2021-03-04T13:42:02.000Z\"", + "isActive": 1, + "links": { + "self": "dev1-central-ledger.mojaloop.live/participants/payerfsp" + }, + "accounts": [ + { + "id": 3, + "ledgerAccountType": "POSITION", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 4, + "ledgerAccountType": "SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 24, + "ledgerAccountType": "INTERCHANGE_FEE_SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + } + ] +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [String](#string) | The identifier of the participant in the form of a fully qualified domain name combined with the participant's `fspId`. | +| `created` | yes | [DateTime](#datetime) | Date and time when the participant was created. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the participant is active. Possible values are `1` and `0`. | +| `links` | yes | [Self](#self) | List of links for a Hypermedia-Driven RESTful Web Service. | +| `accounts` | yes | [Accounts](#accounts) | The list of ledger accounts configured for the participant. | + +
    + +### PUT /participants/{name} + +Updates participant details (activates/deactivates a participant). + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl -X PUT -H "Content-Type: application/json" \ + -d '{"isActive": true}' \ + http:///participants/payerfsp +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `isActive` | yes | [Boolean](boolean) | A flag to indicate whether or not the participant is active. | + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "name": "payerfsp", + "id": "dev1-central-ledger.mojaloop.live/participants/payerfsp", + "created": "\"2021-03-04T13:42:02.000Z\"", + "isActive": 1, + "links": { + "self": "dev1-central-ledger.mojaloop.live/participants/payerfsp" + }, + "accounts": [ + { + "id": 3, + "ledgerAccountType": "POSITION", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 4, + "ledgerAccountType": "SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + }, + { + "id": 24, + "ledgerAccountType": "INTERCHANGE_FEE_SETTLEMENT", + "currency": "USD", + "isActive": 1, + "createdDate": null, + "createdBy": "unknown" + } + ] +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [String](#string) | The identifier of the participant in the form of a fully qualified domain name combined with the participant's `fspId`. | +| `created` | yes | [DateTime](#datetime) | Date and time when the participant was created. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the participant is active. Possible values are `1` and `0`. | +| `links` | yes | [Self](#self) | List of links for a Hypermedia-Driven RESTful Web Service. | +| `accounts` | yes | [Accounts](#accounts) | The list of ledger accounts configured for the participant. | + +
    + +### GET /participants/{name}/endpoints + +Retrieves information about the endpoints configured for a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl 'http:///participants/payerfsp/endpoints' +``` + +#### Example response +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{partyIdType}}/{{partyIdentifier}}/{{partySubIdOrType}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{partyIdType}}/{{partyIdentifier}}/{{partySubIdOrType}}/error" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_DELETE", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{partyIdType}}/{{partyIdentifier}}/{{partySubIdOrType}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_GET", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/parties/{{partyIdType}}/{{partyIdentifier}}/{{partySubIdOrType}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/parties/{{partyIdType}}/{{partyIdentifier}}/{{partySubIdOrType}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_PUT_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/parties/{{partyIdType}}/{{partyIdentifier}}/{{partySubIdOrType}}/error" + }, + { + "type": "FSPIOP_CALLBACK_URL_AUTHORIZATIONS", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{partyIdType}}/{{partyIdentifier}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{partyIdType}}/{{partyIdentifier}}/error" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{requestId}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/participants/{{requestId}}/error" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTIES_GET", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/parties/{{partyIdType}}/{{partyIdentifier}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTIES_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/parties/{{partyIdType}}/{{partyIdentifier}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/parties/{{partyIdType}}/{{partyIdentifier}}/error" + }, + { + "type": "FSPIOP_CALLBACK_URL_QUOTES", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000" + }, + { + "type": "FSPIOP_CALLBACK_URL_TRX_REQ_SERVICE", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000" + }, + { + "type": "FSPIOP_CALLBACK_URL_TRANSFER_POST", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/transfers" + }, + { + "type": "FSPIOP_CALLBACK_URL_TRANSFER_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/transfers/{{transferId}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_TRANSFER_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/transfers/{{transferId}}/error" + }, + { + "type": "FSPIOP_CALLBACK_URL_BULK_TRANSFER_POST", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/bulkTransfers" + }, + { + "type": "FSPIOP_CALLBACK_URL_BULK_TRANSFER_PUT", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/bulkTransfers/{{id}}" + }, + { + "type": "FSPIOP_CALLBACK_URL_BULK_TRANSFER_ERROR", + "value": "http://dev1-sim-payerfsp-scheme-adapter:4000/bulkTransfers/{{id}}/error" + }, + { + "type": "NET_DEBIT_CAP_THRESHOLD_BREACH_EMAIL", + "value": "some.email@gmail.com" + }, + { + "type": "NET_DEBIT_CAP_ADJUSTMENT_EMAIL", + "value": "some.email@gmail.com" + }, + { + "type": "SETTLEMENT_TRANSFER_POSITION_CHANGE_EMAIL", + "value": "some.email@gmail.com" + } +] +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `type` | yes | [String](#string) | Type of endpoint. | +| `value` | yes | [String](#string) | Endpoint value. | + +
    + +### POST /participants/{name}/endpoints + +Adds/updates endpoints for a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl -X POST -H "Content-Type: application/json" \ + -d '{"type": "NET_DEBIT_CAP_ADJUSTMENT_EMAIL", "value": "some.email@org.com"}' + http:///participants/payerfsp/endpoints +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `type` | yes | [String](#string) | Type of endpoint. | +| `value` | yes | [String](#string) | Endpoint value. | + +#### Example response + +``` +HTTP/1.1 201 Created +Content-Type: application/json +``` + +
    + + +### GET /participants/{name}/limits + +Retrieves limits information for a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Query parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | no | [CurrencyEnum](#currencyenum) | The currency of the limit. | +| `limit` | no | [String](#string) | Limit type. | + +#### Example request + +``` +curl 'http:///participants/payerfsp/limits' +``` + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "currency": "USD", + "limit": { + "type": "NET_DEBIT_CAP", + "value": 10000, + "alarmPercentage": 10 + } + } +] +``` + +#### Response data model + +Each limit in the returned list is applied to the specified participant name and currency in each object. + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the participant. | +| `limit` | yes | [ParticipantLimit](#participantlimit) | The limit configured for the participant. | + +
    + +### PUT /participants/{name}/limits + +Adjusts limits for a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl -X PUT -H "Content-Type: application/json" \ + -d '{ \ + "currency": "USD", \ + "limit": { \ + "type": NET_DEBIT_CAP", \ + "value": 10000, \ + "alarmPercentage": 20 + } \ + }' \ + http:///participants/payerfsp/limits +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the participant. | +| `limit` | yes | [ParticipantLimit](#participantlimit) | The limit configured for the participant. | + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "currency": "USD", + "limit": { + "type": "NET_DEBIT_CAP", + "value": 10000, + "alarmPercentage": 20 + } +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the participant. | +| `limit` | yes | [ParticipantLimit](#participantlimit) | The limit configured for the participant. | + +
    + +### GET /participants/{name}/positions + +Retrieves the position of a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Query parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | no | [CurrencyEnum](#currencyenum) | The currency of the limit. | + +#### Example request + +``` +curl 'http:///participants/payerfsp/positions' +``` + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "currency": "USD", + "value": 150, + "changedDate": "2021-05-10T08:01:38.000Z" + } +] +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the participant. | +| `value` | yes | [Number](#number) | Position value. | +| `changedDate` | yes | [DateTime](#datetime) | Date and time when the position last changed. | + +
    + +### GET /participants/{name}/accounts + +Retrieves the accounts and balances of a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl 'http:///participants/payerfsp/accounts' +``` + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "id": 3, + "ledgerAccountType": "POSITION", + "currency": "USD", + "isActive": 1, + "value": 150, + "reservedValue": 0, + "changedDate": "2021-05-10T08:01:38.000Z" + }, + { + "id": 4, + "ledgerAccountType": "SETTLEMENT", + "currency": "USD", + "isActive": 1, + "value": -165000, + "reservedValue": 0, + "changedDate": "2021-05-10T14:27:02.000Z" + }, + { + "id": 24, + "ledgerAccountType": "INTERCHANGE_FEE_SETTLEMENT", + "currency": "USD", + "isActive": 1, + "value": 0, + "reservedValue": 0, + "changedDate": "2021-03-30T12:23:06.000Z" + } +] +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `id` | yes | [Integer](#integer) | Identifier of the ledger account. | +| `ledgerAccountType` | yes | [String](#string) | Type of ledger account. | +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency of the ledger account. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the ledger account is active. Possible values are `1` and `0`. | +| `value` | yes | [Number](#number) | Account balance value. | +| `reservedValue` | yes | [Number](#number) | Value reserved in the account. | +| `changedDate` | yes | [DateTime](#datetime) | Date and time when the ledger account last changed. | + +
    + +### POST /participants/{name}/accounts + +Creates accounts in the Hub. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +``` +curl -X POST -H "Content-Type: application/json" \ + -d '{"currency": "USD", "type": "HUB_MULTILATERAL_SETTLEMENT"}' \ + http:///participants/payerfsp/accounts +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency of the participant ledger account. | +| `type` | yes | [String](#string) | Type of ledger account. | + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "name": "hub", + "id": "dev1-central-ledger.mojaloop.live/participants/hub", + "created": "2021-01-12T10:56:30.000Z", + "isActive": 0, + "links": { + "self": "dev1-central-ledger.mojaloop.live/participants/hub" + }, + "accounts": [ + { + "id": 1, + "ledgerAccountType": "HUB_MULTILATERAL_SETTLEMENT", + "currency": "USD", + "isActive": 0, + "createdDate": "2021-01-12T10:56:30.000Z", + "createdBy": "unknown" + } + ] +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String](#string) | The name of the participant. | +| `id` | yes | [String](#string) | The identifier of the participant in the form of a fully qualified domain name combined with the participant's `fspId`. | +| `created` | yes | [DateTime](#datetime) | Date and time when the participant was created. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the participant is active. Possible values are `1` and `0`. | +| `links` | yes | [Self](#self) | List of links for a Hypermedia-Driven RESTful Web Service. | +| `accounts` | yes | [Accounts](#accounts) | The list of ledger accounts configured for the participant. | + +
    + +### POST /participants/{name}/accounts/{id} + +Records Funds In or Out of a participant account. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [Integer](#integer) | Account identifier. | + +#### Example request + +```` +curl -X POST -H "Content-Type: application/json" \ + -d '{ \ + "transferId": "bfd38d14-893f-469d-a6ca-a312a0223949", \ + "externalReference": "660616", \ + "action": "recordFundsIn", \ + "reason": "settlement", \ + "amount": { \ + "amount": "5000", \ + "currency": "USD" \ + }, \ + "extensionList": { \ + "extension": [ \ + { \ + "key": "scheme", \ + "value": "abc" \ + } \ + ] \ + } \ + }' \ + http:///participants/payerfsp/accounts/2 +```` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `transferId` | yes | [UUID](#uuid) | Transfer identifier. | +| `externalReference` | yes | [String](#string) | Reference to any external data, such as an identifier from the settlement bank. | +| `action` | yes | [Enum](#enum) | The action performed on the funds. Possible values are: `recordFundsIn` and `recordFundsOutPrepareReserve`. | +| `reason` | yes | [String](#string) | The reason for the FundsIn or FundsOut action. | +| `amount` | yes | [Money](#money) | The FundsIn or FundsOut amount. | +| `extensionList` | no | [ExtensionList](#extensionlist) | Additional details. | + +#### Example response + +```` +HTTP/1.1 202 Accepted +```` + +
    + +### PUT /participants/{name}/accounts/{id} + +Updates a participant account. Currently, updating only the `isActive` flag is supported. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [Integer](#integer) | Account identifier. | + +#### Example request + +``` +curl -X PUT -H "Content-Type: application/json" \ + -d '{"isActive": true}' \ + http:///participants/payerfsp/account/2 +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `isActive` | yes | [Boolean](boolean) | A flag to indicate whether or not the participant account is active. | + +#### Example response + +``` +HTTP/1.1 200 OK +``` + +
    + +### PUT /participants/{name}/accounts/{id}/transfers/{transferId} + +Records a transfer as a Funds In or Out transaction for a participant account. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | +| `id` | yes | [Integer](#integer) | Account identifier. | +| `transferId` | yes | [UUID](#uuid) | Transfer identifier. | + +#### Example request + +``` +curl -X PUT -H "Content-Type: application/json" \ + -d '{"action": "recordFundsOutCommit", "reason": "fix"}' \ + http:///participants/payerfsp/account/2/transfers/bfd38d14-893f-469d-a6ca-a312a0223949 +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `action` | yes | [Enum](#enum) | The FundsOut action performed. Possible values are: `recordFundsOutCommit` and `recordFundsOutAbort`. | +| `reason` | yes | [String](#string) | The reason for the FundsOut action. | + +#### Example response + +``` +HTTP/1.1 202 Accepted +``` + +
    + +### POST /participants/{name}/initialPositionAndLimits + +Adds initial limits and a position for a particular participant. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String(2..30)](#string) | The name of the participant. | + +#### Example request + +```` +curl -X POST -H "Content-Type: application/json" \ + -d '{ \ + "currency": "USD", \ + "limit": { \ + "type": "NET_DEBIT_CAP", \ + "value": "10000" \ + }, \ + "initialPosition": 0 \ + }' \ + http:///participants/payerfsp/initialPositionAndLimits +```` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency of the participant. | +| `limit` | yes | [ParticipantLimit](#participantlimit) | The limit configured for the participant. | +| `initialPosition` | no | [Number](#number) | Initial Position. | + +#### Example response + +``` +HTTP/1.1 201 Created +``` + +
    + +## API Resource `/settlementModels` + +The services provided by the resource `/settlementModels` are used by the Hub Operator for creating, updating, and viewing settlement models. + +### GET /settlementModels + +Retrieves information about all settlement models. + +#### Example request + +``` +curl 'http:///settlementModels' +``` + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "settlementModelId": 1, + "name": "DEFERREDNETUSD", + "isActive": true, + "settlementGranularity": "NET", + "settlementInterchange": "MULTILATERAL", + "settlementDelay": "DEFERRED", + "currency": "USD", + "requireLiquidityCheck": true, + "ledgerAccountTypeId": "POSITION", + "autoPositionReset": true + }, + { + "settlementModelId": 4, + "name": "DEFERREDNETEUR", + "isActive": true, + "settlementGranularity": "NET", + "settlementInterchange": "MULTILATERAL", + "settlementDelay": "DEFERRED", + "currency": "EUR", + "requireLiquidityCheck": true, + "ledgerAccountTypeId": "SETTLEMENT", + "autoPositionReset": true + } +] +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementModelId` | yes | [Integer](#integer) | Settlement model identifier. | +| `name` | yes | [String](#string) | Settlement model name. | +| `isActive` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model is active.| +| `settlementGranularity` | yes | [String](#string) | Specifies whether transfers are settled one by one or as a batch. Possible values are:
    `GROSS`: Settlement is executed after each transfer is completed, that is, there is a settlement transaction that corresponds to every transaction.
    `NET`: A group of transfers is settled together in a single settlement transaction, with each participant settling the net of all transfers over a given period of time.| +| `settlementInterchange` | yes | [String](#string) | Specifies the type of settlement arrangement between parties. Possible values are:
    `BILATERAL`: Each participant settles its obligations with each other separately, and the scheme is not a party to the settlement.
    `MULTILATERAL`: Each participant settles with the scheme for the net of its obligations, rather than settling separately with each other party.| +| `settlementDelay` | yes | [String](#string) | Specifies if settlement happens immediately after a transfer has completed or with a delay. Possible values are:
    `IMMEDIATE`: Settlement happens immediately after a transfer has completed.
    `DEFERRED`: Settlement is managed by the Hub operator on-demand or via a schedule.| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the settlement model. | +| `requireLiquidityCheck` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires liquidity check. | +| `ledgerAccountTypeId` | yes | [String](#string) | Type of ledger account. Possible values are:
    `INTERCHANGE_FEE`: Tracks the interchange fees charged for transfers.
    `POSITION`: Tracks how much a DFSP owes or is owed.
    `SETTLEMENT`: The DFSP's Settlement Bank Account mirrored in the Hub. Acts as a reconciliation account and mirrors the movement of real funds.| +| `autoPositionReset` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires the automatic reset of the position. | + +
    + +### POST /settlementModels + +Creates a settlement model. + +#### Example request + +``` +curl -X POST -H "Content-Type: application/json" \ + -d '{ \ + "name": "DEFERREDNET", \ + "settlementGranularity": "NET", \ + "settlementInterchange": "MULTILATERAL", \ + "settlementDelay": "DEFERRED", \ + "requireLiquidityCheck": true, \ + "ledgerAccountType": "POSITION", \ + "autoPositionReset": true \ + }' \ + http:///settlementModels +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String](#string) | Settlement model name. | +| `settlementGranularity` | yes | [String](#string) | Specifies whether transfers are settled one by one or as a batch. Possible values are:
    `GROSS`: Settlement is executed after each transfer is completed, that is, there is a settlement transaction that corresponds to every transaction.
    `NET`: A group of transfers is settled together in a single settlement transaction, with each participant settling the net of all transfers over a given period of time.| +| `settlementInterchange` | yes | [String](#string) | Specifies the type of settlement arrangement between parties. Possible values are:
    `BILATERAL`: Each participant settles its obligations with each other separately, and the scheme is not a party to the settlement.
    `MULTILATERAL`: Each participant settles with the scheme for the net of its obligations, rather than settling separately with each other party.| +| `settlementDelay` | yes | [String](#string) | Specifies if settlement happens immediately after a transfer has completed or with a delay. Possible values are:
    `IMMEDIATE`: Settlement happens immediately after a transfer has completed.
    `DEFERRED`: Settlement is managed by the Hub operator on-demand or via a schedule.| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the settlement model. | +| `requireLiquidityCheck` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires liquidity check. | +| `ledgerAccountTypeId` | yes | [String](#string) | Type of ledger account. Possible values are:
    `INTERCHANGE_FEE`: Tracks the interchange fees charged for transfers.
    `POSITION`: Tracks how much a DFSP owes or is owed.
    `SETTLEMENT`: The DFSP's Settlement Bank Account mirrored in the Hub. Acts as a reconciliation account and mirrors the movement of real funds.| +| `settlementAccountType` | yes | [String](#string) | A special type of ledger account into which settlements should be settled. Possible values are:
    `SETTLEMENT`: A settlement account for the principal value of transfers (that is, the amount of money that the Payer wants the Payee to receive).
    `INTERCHANGE_FEE_SETTLEMENT`: A settlement account for the fees associated with transfers. | +| `autoPositionReset` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires the automatic reset of the position. | + +#### Example response + +``` +HTTP/1.1 201 Created +``` + +
    + +### GET /settlementModels/{name} + +Retrieves information about a particular settlement model. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String](#string) | The name of the settlement model. | + +#### Example request + +``` +curl 'http:///settlementModels/DEFERREDNET' +``` + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "settlementModelId": 1, + "name": "DEFERREDNET", + "isActive": true, + "settlementGranularity": "NET", + "settlementInterchange": "MULTILATERAL", + "settlementDelay": "DEFERRED", + "currency": "USD", + "requireLiquidityCheck": true, + "ledgerAccountTypeId": "POSITION", + "autoPositionReset": true +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementModelId` | yes | [Integer](#integer) | Settlement model identifier. | +| `name` | yes | [String](#string) | Settlement model name. | +| `isActive` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model is active. | +| `settlementGranularity` | yes | [String](#string) | Specifies whether transfers are settled one by one or as a batch. Possible values are:
    `GROSS`: Settlement is executed after each transfer is completed, that is, there is a settlement transaction that corresponds to every transaction.
    `NET`: A group of transfers is settled together in a single settlement transaction, with each participant settling the net of all transfers over a given period of time.| +| `settlementInterchange` | yes | [String](#string) | Specifies the type of settlement arrangement between parties. Possible values are:
    `BILATERAL`: Each participant settles its obligations with each other separately, and the scheme is not a party to the settlement.
    `MULTILATERAL`: Each participant settles with the scheme for the net of its obligations, rather than settling separately with each other party.| +| `settlementDelay` | yes | [String](#string) | Specifies if settlement happens immediately after a transfer has completed or with a delay. Possible values are:
    `IMMEDIATE`: Settlement happens immediately after a transfer has completed.
    `DEFERRED`: Settlement is managed by the Hub operator on-demand or via a schedule.| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the settlement model. | +| `requireLiquidityCheck` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires liquidity check. | +| `ledgerAccountTypeId` | yes | [String](#string) | Type of ledger account. Possible values are:
    `INTERCHANGE_FEE`: Tracks the interchange fees charged for transfers.
    `POSITION`: Tracks how much a DFSP owes or is owed.
    `SETTLEMENT`: The DFSP's Settlement Bank Account mirrored in the Hub. Acts as a reconciliation account and mirrors the movement of real funds. | +| `autoPositionReset` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires the automatic reset of the position. | + +
    + +### PUT /settlementModels/{name} + +Updates a settlement model (activates/deactivates a settlement model). + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String](#string) | The name of the settlement model. | + +#### Example request + +``` +curl -X PUT -H "Content-Type: application/json" \ + -d '{"isActive": true}' \ + http:///settlementModels/DEFERREDNET +``` + +#### Request data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `isActive` | yes | [Boolean](#boolean) | A flag to indicate whether or not the settlement model is active. | + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "settlementModelId": 1, + "name": "DEFERREDNET", + "isActive": true, + "settlementGranularity": "NET", + "settlementInterchange": "MULTILATERAL", + "settlementDelay": "DEFERRED", + "currency": "USD", + "requireLiquidityCheck": true, + "ledgerAccountTypeId": "POSITION", + "autoPositionReset": true +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementModelId` | yes | [Integer](#integer) | Settlement model identifier. | +| `name` | yes | [String](#string) | Settlement model name. | +| `isActive` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model is active. | +| `settlementGranularity` | yes | [String](#string) | Specifies whether transfers are settled one by one or as a batch. Possible values are:
    `GROSS`: Settlement is executed after each transfer is completed, that is, there is a settlement transaction that corresponds to every transaction.
    `NET`: A group of transfers is settled together in a single settlement transaction, with each participant settling the net of all transfers over a given period of time.| +| `settlementInterchange` | yes | [String](#string) | Specifies the type of settlement arrangement between parties. Possible values are:
    `BILATERAL`: Each participant settles its obligations with each other separately, and the scheme is not a party to the settlement.
    `MULTILATERAL`: Each participant settles with the scheme for the net of its obligations, rather than settling separately with each other party.| +| `settlementDelay` | yes | [String](#string) | Specifies if settlement happens immediately after a transfer has completed or with a delay. Possible values are:
    `IMMEDIATE`: Settlement happens immediately after a transfer has completed.
    `DEFERRED`: Settlement is managed by the Hub operator on-demand or via a schedule.| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the settlement model. | +| `requireLiquidityCheck` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires liquidity check. | +| `ledgerAccountTypeId` | yes | [String](#string) | Type of ledger account. Possible values are:
    `INTERCHANGE_FEE`: Tracks the interchange fees charged for transfers.
    `POSITION`: Tracks how much a DFSP owes or is owed.
    `SETTLEMENT`: The DFSP's Settlement Bank Account mirrored in the Hub. Acts as a reconciliation account and mirrors the movement of real funds. | +| `autoPositionReset` | yes | [Boolean](boolean) | A flag to indicate whether or not the settlement model requires the automatic reset of the position. | + +
    + +## API Resource `/transactions` + +The services provided by the resource `/transactions` are used by the Hub Operator for retrieving transfer details. + +### GET /transactions/{id} + +Retrieves information about a particular transaction. + +#### Path parameters + +| Name | Required | Type | Description | +|---|---|--|--| +| `id` | yes | [UUID](#uuid) | Transfer identifier. | + +#### Example request + +``` +curl 'http:///transactions/85feac2f-39b2-491b-817e-4a03203d4f14' +``` + +#### Example response + +``` +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "quoteId": "7c23e80c-d078-4077-8263-2c047876fcf6", + "transactionId": "85feac2f-39b2-491b-817e-4a03203d4f14", + "transactionRequestId": "a8323bc6-c228-4df2-ae82-e5a997baf898", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "123456789", + "fspId": "MobileMoneyAbc" + }, + "name": "John Doe", + "personalInfo": { + "complexName": { + "firstName": "John", + "middleName": "William", + "lastName": "Doe" + }, + "dateOfBirth": "1966-06-16" + } + }, + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "987654321", + "fspId": "MobileMoneyXyz" + }, + "name": "Jane Doe", + "personalInfo": { + "complexName": { + "firstName": "Mary", + "middleName": "Jane", + "lastName": "Doe" + }, + "dateOfBirth": "1975-05-15" + } + }, + "amount": { + "currency": "USD", + "amount": "50" + }, + "transactionType": { + "scenario": "DEPOSIT", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + } +} +``` + +#### Response data model + +| Name | Required | Type | Description | +|---|---|--|--| +| `quoteId` | | [UUID](#uuid) | Quote identifier. | +| `transactionId` | | [UUID](#uuid) | Transaction identifier. | +| `transactionRequestId` | | [String](#string) | Identifies an optional previously-sent transaction request. | +| `payee` | | [Party](#party) | Payee details. | +| `payer` | | [Party](#party) | Payer details. | +| `amount` | | [Money](#money) | Transaction amount. | +| `transactionType` | | [TransactionType](#transactiontype) | Transaction details. | +| `note` | | [String](#string) | A memo that will be attached to the transaction. | +| `extensionList` | | [ExtensionList](#extensionlist) | Additional details. | + +
    + +## Data models used by the API + +### Format + +For details on the formats used for element data types used by the API, see section [Element Data Type Formats](../fspiop/logical-data-model#element-data-type-formats) in the Mojaloop FSPIOP API Definition. + +### Element Data Type Formats + +This section defines element data types used by the API. + +#### Amount + +For details, see section [Amount](../fspiop/logical-data-model#amount) in the Mojaloop FSPIOP API Definition. + +#### Boolean + +A `"true"` or `"false"` value. + +#### DateTime + +For details, see section [DateTime](../fspiop/logical-data-model#datetime) in the Mojaloop FSPIOP API Definition. + +#### Enum + +For details, see section [Enum](../fspiop/logical-data-model#enum) in the Mojaloop FSPIOP API Definition. + +#### Integer + +For details, see section [Integer](../fspiop/logical-data-model#integer) in the Mojaloop FSPIOP API Definition. + +#### Number + +The API data type `Number` is a an arbitrary-precision, base-10 decimal number value. + +#### String + +For details, see section [String](../fspiop/logical-data-model#string) in the Mojaloop FSPIOP API Definition. + +#### UUID + +For details, see section [UUID](../fspiop/logical-data-model#uuid) in the Mojaloop FSPIOP API Definition. + +
    + +## Element Definitions + +This section defines element types used by the API. + +#### IsActive + +Data model for the element **IsActive**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not a ledger account / participant is active. Possible values are `1` (active) and `0` (not active). | + +#### IsActiveBoolean + +Data model for the element **IsActiveBoolean**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `isActive` | yes | [Boolean](#boolean) | A flag to indicate whether or not an account / participant / settlement model is active. | + +#### CurrencyEnum + +For details, see section [Currency](../fspiop/logical-data-model#currencycode-enum) enum in the Mojaloop FSPIOP API Definition. + +#### RequireLiquidityCheck + +Data model for the element **RequireLiquidityCheck**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `requireLiquidityCheck` | yes | [Boolean](#boolean) | A flag to indicate whether or not a settlement model requires liquidity check. | + +#### Self + +Data model for the element **Self**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `self` | yes | [String](#string) | Fully qualified domain name combined with the `fspId` of the participant. | + +#### SettlementDelay + +Data model for the element **SettlementDelay**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementDelay` | yes | [Enum](#enum) of String | Specifies if settlement happens immediately after a transfer has completed or with a delay. Allowed values for the enumeration are:
    `IMMEDIATE`: Settlement happens immediately after a transfer has completed.
    `DEFERRED`: Settlement is managed by the Hub operator on-demand or via a schedule. | + +#### SettlementGranularity + +Data model for the element **SettlementGranularity**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementGranularity` | yes | [Enum](#enum) of String | Specifies whether transfers are settled one by one or as a batch. Allowed values for the enumeration are:
    `GROSS`: Settlement is executed after each transfer is completed, that is, there is a settlement transaction that corresponds to every transaction.
    `NET`: A group of transfers is settled together in a single settlement transaction, with each participant settling the net of all transfers over a given period of time. | + +#### SettlementInterchange + +Data model for the element **SettlementInterchange**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementInterchange` | yes | [Enum](#enum) of String | Specifies the type of settlement arrangement between parties. Allowed values for the enumeration are:
    `BILATERAL`: Each participant settles its obligations with each other separately, and the scheme is not a party to the settlement.
    `MULTILATERAL`: Each participant settles with the scheme for the net of its obligations, rather than settling separately with each other party. | + +
    + +## Complex types + +#### Accounts + +The list of ledger accounts configured for the participant. For details on the account object, see [IndividualAccount](#individualaccount). + +#### ErrorInformation + +For details, see section [ErrorInformation](../fspiop/logical-data-model#errorinformation) in the Mojaloop FSPIOP API Definition. + +#### ErrorInformationResponse + +Data model for the complex type object that contains an optional element [ErrorInformation](#errorinformation) used along with 4xx and 5xx responses. + +#### Extension + +For details, see section [Extension](../fspiop/logical-data-model#extension) in the Mojaloop FSPIOP API Definition. + +#### ExtensionList + +For details, see section [ExtensionList](../fspiop/logical-data-model#extensionlist) in the Mojaloop FSPIOP API Definition. + +#### IndividualAccount + +Data model for the complex type **IndividualAccount**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `id` | yes | [Integer](#integer) | Identifier of the ledger account. | +| `ledgerAccountType` | yes | [String](#string) | Type of the ledger account (for example, POSITION). | +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency of the account. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the ledger account is active. Possible values are `1` and `0`. | +| `createdDate` | yes | [DateTime](#datetime) | Date and time when the ledger account was created. | +| `createdBy` | yes | [String](#string) | The entity that created the ledger account. | + +#### Limit + +Data model for the complex type **Limit**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `type` | yes | [String](#string) | Limit type. | +| `value` | yes | a positive [Number](#number) | Limit value. | + +#### Money + +For details, see section [Money](../fspiop/logical-data-model#mondey) in the Mojaloop FSPIOP API Definition. + +#### Participant + +Data model for the complex type **Participant**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `name` | yes | [String](#string) | The name of the participant. | +| `id` | yes | [String](#string) | The identifier of the participant in the form of a fully qualified domain name combined with the participant's `fspId`. | +| `created` | yes | [DateTime](#datetime) | Date and time when the participant was created. | +| `isActive` | yes | [Integer(1)](#integer) | A flag to indicate whether or not the participant is active. Possible values are `1` and `0`. | +| `links` | yes | [Self](#self) | List of links for a Hypermedia-Driven RESTful Web Service. | +| `accounts` | yes | [Accounts](#accounts) | The list of ledger accounts configured for the participant. | + +#### ParticipantFunds + +Data model for the complex type **ParticipantFunds**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `transferId` | yes | [UUID](#uuid) | Transfer identifier. | +| `externalReference` | yes | [String](#string) | Reference to any external data, such as an identifier from the settlement bank. | +| `action` | yes | [Enum](#enum) | The action performed on the funds. Possible values are: `recordFundsIn` and `recordFundsOutPrepareReserve`. | +| `reason` | yes | [String](#string) | The reason for the FundsIn or FundsOut action. | +| `amount` | yes | [Money](#money) | The FundsIn or FundsOut amount. | +| `extensionList` | no | [ExtensionList](#extensionlist) | Additional details. | + +#### ParticipantLimit + +Data model for the complex type **ParticipantLimit**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `type` | yes | [String](#string) | The type of participant limit (for example, `NET_DEBIT_CAP`.) | +| `value` | yes | [Number](#number) | The value of the limit that has been set for the participant. | +| `alarmPercentage` | yes | [Number](#number) | An alarm notification is triggered when a pre-specified percentage of the limit is reached. Specifying an `alarmPercentage` is optional. If not specified, it will default to 10 percent, expressed as `10`. | + +#### ParticipantsNameEndpointsObject + +Data model for the complex type **ParticipantsNameEndpointsObject**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `type` | yes | [String](#string) | The endpoint type. | +| `value` | yes | [String](#string) | The endpoint value. | + +#### ParticipantsNameLimitsObject + +Data model for the complex type **ParticipantsNameLimitsObject**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the participant. | +| `limit` | yes | [ParticipantLimit](#participantlimit) | The limit configured for the participant. | + +#### Party + +For details, see section [Party](../fspiop/logical-data-model#party) in the Mojaloop FSPIOP API Definition. + +#### PartyComplexName + +For details, see section [PartyComplexName](../fspiop/logical-data-model#partycomplexname) in the Mojaloop FSPIOP API Definition. + +#### PartyIdInfo + +For details, see section [PartyIdInfo](../fspiop/logical-data-model#partyidinfo) in the Mojaloop FSPIOP API Definition. + +#### PartyPersonalInfo + +For details, see section [PartyPersonalInfo](../fspiop/logical-data-model#partypersonalinfo) in the Mojaloop FSPIOP API Definition. + +#### RecordFundsOut + +Data model for the complex type **RecordFundsOut**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `action` | yes | [Enum](#enum) | The FundsOut action performed. Possible values are: `recordFundsOutCommit` and `recordFundsOutAbort`. | +| `reason` | yes | [String](#string) | The reason for the FundsOut action. | + +#### Refund + +Data model for the complex type **Refund**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `originalTransactionId` | yes | [UUID](#uuid) | Reference to the original transaction id that is requested to be refunded. | +| `refundReason` | no | [String(1-128)](#string) | Free text indicating the reason for the refund. | + +#### SettlementModelsObject + +Data model for the complex type **SettlementModelsObject**. + +| Name | Required | Type | Description | +|---|---|--|--| +| `settlementModelId` | yes | [Integer](#integer) | Settlement model identifier. | +| `name` | yes | [String](#string) | Settlement model name. | +| `isActive` | yes | [Boolean](#boolean) | A flag to indicate whether or not the settlement model is active. | +| `settlementGranularity` | yes | [String](#string) | Specifies whether transfers are settled one by one or as a batch. Possible values are:
    `GROSS`: Settlement is executed after each transfer is completed, that is, there is a settlement transaction that corresponds to every transaction.
    `NET`: A group of transfers is settled together in a single settlement transaction, with each participant settling the net of all transfers over a given period of time.| +| `settlementInterchange` | yes | [String](#string) | Specifies the type of settlement arrangement between parties. Possible values are:
    `BILATERAL`: Each participant settles its obligations with each other separately, and the scheme is not a party to the settlement.
    `MULTILATERAL`: Each participant settles with the scheme for the net of its obligations, rather than settling separately with each other party.| +| `settlementDelay` | yes | [String](#string) | Specifies if settlement happens immediately after a transfer has completed or with a delay. Possible values are:
    `IMMEDIATE`: Settlement happens immediately after a transfer has completed.
    `DEFERRED`: Settlement is managed by the Hub operator on-demand or via a schedule.| +| `currency` | yes | [CurrencyEnum](#currencyenum) | The currency configured for the settlement model. | +| `requireLiquidityCheck` | yes | [Boolean](#boolean) | A flag to indicate whether or not the settlement model requires liquidity check. | +| `ledgerAccountTypeId` | yes | [String](#string) | Type of ledger account. Possible values are:
    `INTERCHANGE_FEE`: Tracks the interchange fees charged for transfers.
    `POSITION`: Tracks how much a DFSP owes or is owed.
    `SETTLEMENT`: The DFSP's Settlement Bank Account mirrored in the Hub. Acts as a reconciliation account and mirrors the movement of real funds.| +| `autoPositionReset` | yes | [Boolean](#boolean) | A flag to indicate whether or not the settlement model requires the automatic reset of the position. | + +#### TransactionType + +For details, see section [TransactionType](../fspiop/logical-data-model#transactiontype) in the Mojaloop FSPIOP API Definition. \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/assets/figure1-platforms-layout.svg b/website/versioned_docs/v1.0.1/api/assets/figure1-platforms-layout.svg new file mode 100644 index 000000000..8a12de358 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/assets/figure1-platforms-layout.svg @@ -0,0 +1,3 @@ + + +
    CA
    CA
    ALS
    ALS
    FSP-1
    FSP-1
    FSP-2
    FSP-2
    Switch
    Switch
    FSP-3
    FSP-3
    FSP-4
    FSP-4
    Issuer: CN=CA
    O=CA
    Subject: CN=CA
    O=CA
    Issuer: CN=CA...
    Issuer: CN=CA
    O=CA
    Subject: CN=CA
    O=CA
    Issuer: CN=CA...
    Issuer: CN=CA
    O=CA
    Subject: CN=CA
    O=CA
    Issuer: CN=CA...
    Issuer: CN=CA
    O=CA
    Subject: CN=CA
    O=CA
    Issuer: CN=CA...
    Issuer: CN=CA
    O=CA
    Subject: CN=CA
    O=CA
    Issuer: CN=CA...
    Issuer: CN=CA
    O=CA
    Subject: CN=CA
    O=CA
    Issuer: CN=CA...
    Issuer: CN=CA
    O=CA
    Subject: CN=CA
    O=CA
    Issuer: CN=CA...
    Legend:
    Solid lines indicate TLS-secured communication.
    Dashed lines indicate certificate owner.
    Legend:...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/assets/scheme-rules-figure-1-http-timeout.png b/website/versioned_docs/v1.0.1/api/assets/scheme-rules-figure-1-http-timeout.png new file mode 100644 index 000000000..9d3faf74e Binary files /dev/null and b/website/versioned_docs/v1.0.1/api/assets/scheme-rules-figure-1-http-timeout.png differ diff --git a/website/versioned_docs/v1.0.1/api/assets/scheme-rules-figure-2-callback-timeout.png b/website/versioned_docs/v1.0.1/api/assets/scheme-rules-figure-2-callback-timeout.png new file mode 100644 index 000000000..04f5da996 Binary files /dev/null and b/website/versioned_docs/v1.0.1/api/assets/scheme-rules-figure-2-callback-timeout.png differ diff --git a/website/versioned_docs/v1.0.1/api/assets/sequence-diagram-figure-1.png b/website/versioned_docs/v1.0.1/api/assets/sequence-diagram-figure-1.png new file mode 100644 index 000000000..53215785d Binary files /dev/null and b/website/versioned_docs/v1.0.1/api/assets/sequence-diagram-figure-1.png differ diff --git a/website/versioned_docs/v1.0.1/api/fspiop/README.md b/website/versioned_docs/v1.0.1/api/fspiop/README.md new file mode 100644 index 000000000..eed734703 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/README.md @@ -0,0 +1,19 @@ +# FSPIOP API + +The Open API for FSP Interoperability Specification includes the following documents: + +### Logical Documents +* [Logical Data Model](#logical-data-model) +* [Generic Transaction Patterns](#generic-transaction-patterns) +* [Use Cases](#use-cases) + +### Asynchronous REST Binding Documents +* [API Definition](#api-definition) +* [Central Ledger API](#central-ledger-api) +* [JSON Binding Rules](#json-binding-rules) +* [Scheme Rules](#scheme-rules) + +### Data Integrity, Confidentiality, and Non-Repudiation +* [PKI Best Practices](#pki-best-practices) +* [Signature](#signature) +* [Encryption](#encryption) diff --git a/website/versioned_docs/v1.0.1/api/fspiop/definitions.md b/website/versioned_docs/v1.0.1/api/fspiop/definitions.md new file mode 100644 index 000000000..6c2e3c8f1 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/definitions.md @@ -0,0 +1,10 @@ +# FSPIOP API + + +## Versions + +|Version|Date|Change Description| +|---|---|---| +|[1.0](./v1.0/api-definition)|2018-03-13|Initial version| +|[1.1](./v1.1/api-definition)|2020-05-19|1. This version contains a new option for a Payee FSP to request a commit notification from the Switch. The Switch should then send out the commit notification using the new request **PATCH /transfers/**_{ID}_. The option to use commit notification replaces the previous option of using the ”Optional Additional Clearing Check”. The section describing this has been replaced with the new section ”Commit Notification”. As the **transfers** resource has been updated with the new **PATCH** request, this resource has been updated to version 1.1. As part of adding the possibility to use a commit notification, the following changes has been made:
    a. PATCH has been added as an allowed HTTP Method in Section 3.2.2. b. The call flow for **PATCH** is described in Section 3.2.3.5.
    c. Table 6 in Section 6.1.1 has been updated to include **PATCH** as a possible HTTP Method.
    d. Section 6.7.1 contains the new version of the **transfers** resource.
    e. Section 6.7.2.6 contains the process for using commit notifications
    f. Section 6.7.3.3 describes the new **PATCH /transfers**/_{ID}_ request.

    2. In addition to the changes mentioned above regarding the commit notification, the following non-API affecting changes has been made:
    a. Updated Figure 6 as it contained a copy-paste error.
    b. Added Section 6.1.2 to describe a comprehensive view of the current version for each resource.
    c. Added a section for each resource to be able to see the resource version history.
    d. Minor editorial fixes.

    3. The descriptions for two of the HTTP Header fields in Table 1 have been updated to add more specificity and context
    a. The description for the **FSPIOP-Destination** header field has been updated to indicate that it should be left empty if the destination is not known to the original sender, but in all other cases should be added by the original sender of a request.
    b. The description for the **FSPIOP-URI** header field has been updated to be more specific.

    4. The examples used in this document have been updated to use the correct interpretation of the Complex type ExtensionList which is defined in Table 84. This doesn’t imply any change as such.
    a. Listing 5 has been updated in this regard.

    5. The data model is updated to add an optional ExtensionList element to the **PartyIdInfo** complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 103 has been updated. For consistency, the data model for the **POST /participants/**_{Type}/{ID}_ and **POST /participants/**_{Type}/{ID}/{SubId}_ calls in Table 10 has been updated to include the optional ExtensionList element as well.

    6. A new Section 6.5.2.2 is added to describe the process involved in the rejection of a quote.

    7. A note is added to Section 6.7.4.1 to clarify the usage of ABORTED state in **PUT /transfers/**_{ID}_ callbacks.| +|**1.1.1**|2021-09-22|This document version only adds information about optional HTTP headers regarding tracing support in [Table 2](#table-2), see _Distributed Tracing Support for OpenAPI Interoperability_ for more information. There are no changes in any resources as part of this version.| \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/fspiop/generic-transaction-patterns.md b/website/versioned_docs/v1.0.1/api/fspiop/generic-transaction-patterns.md new file mode 100644 index 000000000..8e68d41de --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/generic-transaction-patterns.md @@ -0,0 +1,1851 @@ +# Generic Transaction Patterns + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| + +
    + +## Introduction + +This document introduces the four generic transaction patterns that are supported in a logical version of the Interoperability API. Additionally, all logical services that are part of the API are presented on a high-level. + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](#) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](./json-binding-rules) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](./v1.1/signature) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](./glossary) + +
    + +## Logical API Services + +The Interoperability API consists of a number of logical API resources. Each resource defines one or more services that clients can use to connect to a server that has implemented the API. This section introduces these services. + +**Note:** API services identified in this section may not be relevant to (and therefore may not appear in) the generic transaction patterns identified in [Generic Transaction Patterns](#generic-transaction-patterns). + +For example, some services are used for provisioning of information, are part of error cases, or are for retrieving information that is not necessary in a generic transaction pattern. + +
    + +### Common Functionality + +This section introduces functionality that is used by more than one logical API resource or service. + +#### Party Addressing + +A Party is an entity such as an individual, a business, an organization that has a financial account in one of the FSPs. A party is addressed by a combination of an _ID type_ and an _ID_, and possibly also a _subtype_ or _sub ID_. Some examples of _ID type_ and _ID_ combinations are: + +- _ID type_: **MSISDN**, _ID_: **+123456789** + +- _ID type_: **Email**, _ID_: **john@doe.com** + +#### Interledger + +The API includes basic support for the Interledger Protocol (ILP) by defining a concrete implementation of the Interledger Payment Request protocol[1](https://interledger.org/rfcs/0011-interledger-payment-request)(ILP) in the logical API resources **Quotes** and **Transfers**. More details of the ILP protocol can be found on the Interledger project website[2](https://interledger.org), in the Interledger Whitepaper[3](https://interledger.org/interledger.pdf), and in the Interledger architecture specification[4](https://interledger.org/rfcs/0001-interledger-architecture). + +
    + +### API Resource Participants + +In the API, a _Participant_ is the same as an FSP that is participating in an Interoperability Scheme. The primary purpose of the logical API resource **Participants** is for FSPs to find out in which other FSP a counterparty in an interoperable financial transaction is located. There are also services defined for the FSPs to provision information to a common system. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Lookup Participant Information + +The logical API service request `Lookup Participant Information` is used from an FSP to request from another system, which could be another FSP or a common system, information regarding in which FSP a counterparty in an interoperable financial transaction is located. + +- Successful response: [Return Participant Information](#return-participant-information) + +- Error response: [Return Participant Information Error](#return-participant-information-error) + +##### Create Participant Information + +The logical API service request `Create Participant Information` is used to provision information regarding in which FSP a party is located. + +- Successful response: [Return Participant Information](#return-participant-information) + +- Error response: [Return Participant Information Error](#return-participant-information-error) + +##### Create Bulk Participant Information + +The logical API service request `Create Bulk Participant Information` is used to provision information regarding in which FSP one or more parties are located. + +- Successful response: [Return Bulk Participant Information](#return-bulk-participant-information) + +- Error response: [Return Bulk Participant Information Error](#return-bulk-participant-information-error) + +##### Delete Participant Information + +The logical API service request `Delete Participant Information` is used to remove information regarding in which FSP a party is located. + +- Successful response: [Return Participant Information](#return-participant-information) + +- Error response: [Return Participant Information Error](#return-participant-information-error) + +
    + +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Participant Information + +The logical API service response `Return Participant Information` is used to return information from the requests [Lookup Participant Information](#lookup-participant-information), [Create Participant Information](#create-participant-information) and [Delete Participant Information](#delete-participant-information). + +##### Return Bulk Participant Information + +The logical API service response `Return Bulk Participant Information` is used to return information from the request [Create Bulk Participant Information](#create-bulk-participant-information). + +
    + +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Participant Information Error + +The logical API service error response `Return Participant Information Error` is used to return error information regarding the requests [Lookup Participant Information](#lookup-participant-information), [Create Participant Information](#create-participant-information) and [Delete Participant Information](#delete-participant-information). + +##### Return Bulk Participant Information Error + +The logical API service error response `Return Bulk Participant Information Error` is used to return information from the request [Create Bulk Participant Information](#create-bulk-participant-information). + +
    + +### API Resource Parties + +In the API, a _Party_ is an individual, a business, an organization, or a similar entity, that has a financial account in one of the FSPs. The primary purpose of the logical API resource **Parties** is for FSPs to ascertain information regarding a counterparty in an interoperable financial transaction, such as name and birth date of the Party. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Lookup Party Information + +The logical API service request `Lookup Party Information` is used by an FSP to request from another FSP information regarding a counterparty in an interoperable financial transaction. + +- Successful response: [Return Party Information](#return-party-information). + +- Error response: [Return Party Information Error](#return-party-information-error). + +
    + +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Party Information + +The logical API service response `Return Party Information` is used to return information from the request [Lookup Party Information](#lookup-party-information). + +
    + +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Party Information Error + +The logical API service error response `Return Party Information Error` is used to return error information regarding the request [Lookup Party Information](#lookup-party-information). + +
    + +### API Resource Transaction Requests + +In the API, a _Transaction Request_ is a request from a Payee to a Payer to transfer electronic funds to the Payee, which the Payer can accept or reject. The primary purpose of the logical API resource **Transaction Requests** is for a Payee FSP to send the request to transfer to the Payer FSP. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Perform Transaction Request + +The logical API service request `Perform Transaction Request` is used to send a Transaction Request from a Payee FSP to the Payer FSP; that is, to ask if a Payer will accept or reject a transaction from the Payer to the Payee. + +- Successful response: [Return Transaction Request Information](#return-transaction-request-information) + +- Error response: [Return Transaction Request Information Error](#return-transaction-request-information-error) + +##### Retrieve Transaction Request Information + +The logical API service request `Retrieve Transaction Request Information` is used from a Payee FSP to a Payer FSP to request information regarding a previously-sent Transaction Request. + +- Successful response: [Return Transaction Request Information](#return-transaction-request-information) + +- Error response: [Return Transaction Request Information Error](#return-transaction-request-information-error) + +
    + +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Transaction Request Information + +The logical API service response `Return Transaction Request Information` is used to return information from the requests [Perform Transaction Request](#perform-transaction-request) or [Retrieve Transaction Request Information](#retrieve-transaction-request-information). + +
    + +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Transaction Request Information Error + +The logical API service error response `Return Transaction Request Information Error` is used to return error information regarding the requests [Perform Transaction Request](#perform-transaction-request) or [Retrieve Transaction Request Information](#retrieve-transaction-request-information). + +
    + +### API Resource Quotes + +In the API, a _Quote_ is the price for performing an interoperable financial transaction from the Payer FSP to the Payee FSP. The primary purpose of the logical API resource **Quotes** is for a Payer FSP to request a Payee FSP to calculate the Payee FSP's part of the quote. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Calculate Quote + +The logical API service request `Calculate Quote` is used from a Payer FSP to ask a Payee FSP to calculate the Payee FSP's part of the quote to perform an interoperable financial transaction. The Payee FSP should also create the ILP Packet and the condition (see [Interledger](#interledger) section for links to more information) when receiving the request. + +- Successful response: [Return Quote Information](#return-quote-information) + +- Error response: [Return Quote Information Error](#return-quote-information-error) + +
    + +##### Retrieve Quote Information + +The logical API service request `Retrieve Quote Information` is used by a Payer FSP to request that a Payee FSP ask for information regarding a previously-sent [Calculate Quote](#calculate-quote) request. + +- Successful response: [Return Quote Information](#return-quote-information) + +- Error response: [Return Quote Information Error](#return-quote-information-error) + +
    + +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Quote Information + +The logical API service response `Return Quote Information` is used to return information from the requests [Calculate Quote](#calculate-quote) or [Retrieve Quote Information](#retrieve-quote-information). + +
    + +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Quote Information Error + +The logical API service error response `Return Quote Information Error` is used to return error information regarding the requests [Calculate Quote](#calculate-quote) or [Retrieve Quote Information](#retrieve-quote-information). + +
    + +### API Resource Authorizations + +In the API, an _Authorization_ is an approval from a Payer to perform an interoperable financial transaction by entering the applicable credentials in a Payee FSP system. An example where this kind of approval is used, is when a Payer is using an ATM that is managed by another FSP. The primary purpose of the logical API resource **Authorizations** is for a Payer FSP to request a Payee FSP to ask the Payer to enter the credentials. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Perform Authorization + +The logical API service request `Perform Authorization` is used from a Payer FSP to ask a Payee FSP to enter the applicable credentials to approve an interoperable financial transaction. + +- Successful response: [Return Authorization Result](#return-authorization-result) + +- Error response: [Return Authorization Error](#return-authorization-error) + +
    + +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Authorization Result + +The logical API service response `Return Authorization Result` is used to return information from the request [Perform Authorization](#perform-authorization). + +
    + +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Authorization Error + +The logical API service error response `Return Authorization Error` is used to return error information regarding the request [Perform Authorization](#perform-authorization). + +
    + +### API Resource Transfers + +In the API, a _Transfer_ is hop-to-hop ILP (see [Interledger](#interledger) section for links to more information) transfer of funds. + +The transfer also contains information regarding the end-to-end interoperable financial transaction. The primary purpose of the logical API resource **Transfers** is for an FSP or Switch to request that the next entity in the chain of the ILP Payment perform the transfer involved in the interoperable financial transaction. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Perform Transfer + +The logical API service request `Perform Transfer` is used by an FSP or Switch to request the next entity in the chain of the ILP Payment to reserve the transfer involved in an interoperable financial transaction. + +- Successful response: [Return Transfer Information](#return-transfer-information) + +- Error response: [Return Transfer Information Error](#return-transfer-information-error) + +##### Retrieve Transfer Information + +The logical API service request `Retrieve Transfer Information` is used by an FSP or Switch to request the next entity in the chain of the ILP Payment for information regarding the transfer involved in an interoperable financial transaction. + +- Successful response: [Return Transfer Information](#return-transfer-information) + +- Error response: [Return Transfer Information Error](#return-transfer-information-error) + +
    + +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Transfer Information + +The logical API service response `Return Transfer Information` is used to return information from the requests [Perform Transfer](#perform-transfer) or [Retrieve Transfer Information](#retrieve-transfer-information). On receiving the [Return Transfer Information](#return-transfer-information) response, the FSP or Switch should validate the fulfilment (see [Interledger](#interledger) section for links to more information) and commit the reserved transfer if the validation is successful. + +
    + +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Transfer Information Error + +The logical API service error response `Return Transfer Information Error` is used to return error information regarding the requests [Perform Transfer](#perform-transfer) or [Retrieve Transfer Information](#retrieve-transfer-information). + +
    + +### API Resource Transactions + +In the API, a _Transaction_ is an end-to-end interoperable financial transaction between the Payer FSP and Payee FSP. The primary purpose of the logical API resource **Transactions** is for a Payer FSP to request end-to-end information from the Payee FSP regarding an interoperable financial transaction; for example, in order to get a token or code that the Payer can use to redeem a service or product. + +### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Retrieve Transaction Information + +The logical API service request `Retrieve Transaction Information` is used by a Payer FSP to request that a Payee FSP get information regarding a previously-performed interoperable financial transaction (by using the logical API resource **Transfers**, see [API Resource Tarnsfers](#api-resource-transfers) section). + +- Successful response: [Return Transfer Information](#return-transfer-information) + +- Error response: [Return Transfer Information Error](#return-transfer-information-error) + +
    + +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Transaction Information + +The logical API service response`*Return Transaction Information` is used to return information from the request [Retrieve Transfer Information](#retrieve-transfer-information). + +
    + +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Transaction Information Error + +The logical API service error response `Return Transaction Information Error` is used to return error information regarding the request [Retrieve Transfer Information](#retrieve-transfer-information). + +
    + +### API Resource Bulk Quotes + +In the API, a _Bulk Quote_ is a collection of individual quotes (see [API Resource Quotes](#api-resource-quotes) section for information regarding a single quote) for performing more than one interoperable financial transaction from the Payer FSP to the Payee FSP. + +The primary purpose of the logical API resource **Bulk Quotes** is for a Payer FSP to request a Payee FSP to calculate the Payee FSP's part of the bulk quote. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Calculate Bulk Quote + +The logical API service request `Calculate Bulk Quote` is used by a Payer FSP to request that a Payee FSP calculate the Payee FSP's part of the quotes to perform more than one interoperable financial transaction. + +The Payee FSP should also create the ILP Packet and the condition (see [Interledger](#interledger) section for links to more information) per quote when receiving the request. + +- Successful response: [Return Bulk Quote Information](#return-bulk-quote-information) + +- Error response: [Return Bulk Quote Information Error](#return-bulk-quote-information-error) + +##### Retrieve Bulk Quote Information + +The logical API service request `Retrieve Bulk Quote Information` is used by a Payer FSP to request that a Payee FSP ask for information regarding a previously-sent [Calculate Bulk Quote](#calculate-bulk-quote) request. + +- Successful response: [Return Bulk Quote Information](#return-bulk-quote-information) + +- Error response: [Return Bulk Quote Information Error](#return-bulk-quote-information-error) + +
    + +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Bulk Quote Information + +The logical API service response `Return Bulk Quote Information` is used to return information from the requests [Calculate Bulk Quote](#calculate-bulk-quote) or [Retrieve Bulk Quote Information](#retrieve-bulk-quote-information). + +
    + +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Bulk Quote Information Error + +The logical API service error response `Return Bulk Quote Information Error` is used to return error information regarding the requests [Calculate Bulk Quote](#calculate-bulk-quote) or [Retrieve Bulk Quote Information](#retrieve-bulk-quote-information). + +
    + +### API Resource Bulk Transfers + +In the API, a _Bulk Transfer_ is a collection of hop-to-hop ILP (see [Interledger.](#interledger)section for links to more information) transfers of funds. The transfers also contain information regarding the end-to-end interoperable financial transactions. + +The primary purpose of the logical API resource **Bulk Transfers** is to enable an FSP or Switch to request that the next entity in the chain of the ILP Payment perform the transfers involved in the interoperable financial transactions. + +#### Requests + +This section identifies the logical API service requests that can be sent from a client to a server. + +##### Perform Bulk Transfer + +The logical API service request `Perform Bulk Transfer` is used by an FSP or Switch to request that the next entity in the chain of the ILP Payment reserve the transfer involved in an interoperable financial transaction. + +- Successful response: [Return Bulk Transfer Information](#return-bulk-transfer-information) + +- Error response: [Return Bulk Transfer Information Error](#return-bulk-transfer-information-error) + + +##### Retrieve Bulk Transfer Information + +The logical API service request `Retrieve Bulk Transfer Information` is used from an FSP or Switch to request that the next entity in the chain of the ILP Payment for information regarding the transfer involved in an interoperable financial transaction. + +- Successful response: [Return Bulk Transfer Information](#return-bulk-transfer-information) + +- Error response: [Return Bulk Transfer Information Error](#return-bulk-transfer-information-error) + +
    + +#### Responses + +This section identifies the logical API service responses that can be sent back to a client from a server. + +##### Return Bulk Transfer Information + +The logical API service response `Return Bulk Transfer Information` is used to return information from the requests [Perform Bulk Transfer](#perform-bulk-transfer) or [Retrieve Bulk Transfer Information](#retrieve-bulk-transfer-information). + +On receiving the response **Return Bulk Transfer Information**, the FSP or Switch should validate the fulfilments (see [Interledger](#interledger) section for links to more information) and commit the reserved transfers if the validations are successful. + +
    + +#### Error Responses + +This section identifies the logical API service error responses that can be sent back to a client from a server. + +##### Return Bulk Transfer Information Error + +The logical API service error response `Return Bulk Transfer Information Error` is used to return error information regarding the requests [Perform Bulk Transfer](#perform-bulk-transfer) or [Retrieve Bulk Transfer Information](#retrieve-bulk-transfer-information). + +
    + +## Generic Transaction Patterns + +This section provides information about the three primary transaction patterns defined in the Interoperability API: + +- [Payer-Initiated Transaction](#payer-initiated-transaction) + +- [Payee-Initiated Transaction](#payee-initiated-transaction) + +- [Bulk Transaction](#bulk-transaction) + +Each transaction pattern defines how funds can be transferred from a Payer located in one Financial Service Provider (FSP) to a Payee located in another FSP. + +Both the [Payer-Initiated Transaction](#payer-initiated-transaction) and the [Payee-Initiated Transaction](#payee-initiated-transaction) patterns are intended for a single transfer of funds from one Payer to one Payee. The significant difference between the two patterns is in which of the participants in the transaction is responsible for the initiation of the transaction. + +The [Bulk Transaction](#bulk-transaction) pattern should be used when a single Payer would like to transfer funds to multiple Payees, possibly in different FSPs, in a single transaction. + +This section also provides information about _Payee-Initiated Transaction using OTP_. which is an alternative to the [Payee-Initiated Transaction](#payee-initiated-transaction). + +Additionally, the section provides high-level information about all logical services that are part of the API. + +
    + +### Payer-Initiated Transaction + +In a _Payer-Initiated Transaction_, the `Payer` initiates the transaction. + +#### Business Process Pattern Description + +The _Payer-Initiated Transaction_ pattern should be used whenever a `Payer` would like to transfer funds to another party whose account is not located in the same FSP. + +In most implementations, `Payee` involvement is limited to receiving a notification in the event of a successful transaction. Exceptions in which the Payee is more involved are: + +- In countries that require the `Payee` to confirm receipt of funds. + +- Cases in which the `Payee` should accept the terms of the transaction (for example, Agent-Initiated Cash-In). + +#### Participants and Roles + +The actors in a _Payer-Initiated Transaction_ are: + +- **Payer** -- The payer of funds in a financial transaction. + +- **Payee** -- The recipient of funds in a financial transaction. + + +The intermediary objects used in a _Payer-Initiated Transaction_ to perform the transaction are: + +- **Payer FSP** -- The FSP in which the Payer's account is located. + +- **Switch (optional)** -- An optional entity used for routing of requests between different FSPs. This object can be removed if requests should be routed directly between a Payer and Payee FSP. + +- **Account Lookup System** -- An entity used for retrieving information regarding accounts or participants. Could be hosted in a separate server, in the Switch, or in the different FSPs. + +- **Payee FSP** -- The FSP in which the Payee's account is located. + + +#### Business Process Sequence Diagram + +Figure 1 shows the UML sequence diagram for a _Payer-Initiated Transaction_. + +{% uml src="assets/diagrams/sequence/figure64a.plantuml" %} +{% enduml %} +**Figure 1 -- Payer-Initiated Transaction** + +#### Internal Processing Steps + +This section provides descriptions of and assumptions made for all steps in the sequence shown in [Figure 1](#business-process-sequence-diagram). + +##### Lookup Counterparty + +1. **Description** + + The `Payer` initiates the transaction by requesting to send funds to a `Payee`, using the `Payer FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + None. + +2. **Description** + + The `Payer FSP` tries to find the `Payee` within the FSP system. Because the `Payee` cannot be found in the `Payer FSP` system, the request [Lookup Party Information](#lookup-party-information) is sent by the `Payer FSP` to the optional `Switch` to get information regarding the `Payee`, including in which FSP the `Payee` is located. + + **Assumptions** + + The Payee is assumed to be in a different FSP than the `Payer`. Also, a `Switch` is assumed to be placed between the `Payer FSP` and the `Payee FSP` to route the messages between FSPs. The `Switch` is optional in the process, as the request [Lookup Party Information](#lookup-party-information) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. As the `Payer FSP` should not know in which FSP the `Payee` is located if there is no `Switch` present, the request might need to be sent to more than one FSP. + +3. **Description** + + The `Switch` receives the request [Lookup Party Information](#lookup-party-information). The `Switch` then tries to find in which FSP the `Payee` is located by sending the request [Lookup Participant Information](#lookup-participant-information) to the `Account Lookup System`. + + **Assumptions** + + An `Account Lookup System` is assumed to exist in a different server than the `Switch`. It is possible that the `Account Lookup System` is in the same system as the `Switch`. + +4. **Description** + + The `Account Lookup System` receives the request [Lookup Participant Information](#lookup-participant-information). It then performs an internal lookup to find in which FSP the `Payee` is located. When the lookup is completed, the response [Return Participant Information](#return-participant-information) is sent to inform the Switch about which FSP the `Payee` is located in. + + **Assumptions** + + The `Payee` can be found by the `Account Lookup System`. + +5. **Description** + + The `Switch` receives the response [Return Participant Information](#return-participant-information). As the `Switch` now knows in which FSP the `Payee` is located, the `Switch` sends the request [Lookup Participant Information](#lookup-participant-information) to the `Payee FSP` to get more information about the `Payee`. + + **Assumptions** + + None. + +6. **Description** + + The `Payee FSP` receives the request [Lookup Participant Information](#lookup-participant-information). The `Payee FSP` then does an internal lookup to find more information regarding the `Payee` and sends the response [Return Participant Information](#return-participant-information) to the `Switch`. + + **Assumptions** + + None. + +7. **Description** + + The `Switch` receives the response [Return Party Information](#return-party-information). The `Switch` then routes the [Return Party Information](#return-party-information) response to the `Payer FSP` to send the information about the `Payee`. + + **Assumptions** + + None. + +8. **Description** + + The `Payer FSP` receives the response [Return Party Information](#return-party-information) containing information about the `Payee`. + + **Assumptions** + + None. + +
    + +##### Calculate Quote + +9. **Description** + + Depending on the fee model used, the `Payer FSP` rates the transaction internally and includes the quote information in the request [Calculate Quote](#calculate-quote) to a `Switch` to retrieve the full quote for performing the interoperable financial transaction from the `Payer FSP` to the `Payee FSP`. The transaction details are sent in the parameters of the request to allow for the `Payee FSP` to correctly calculate the quote. + + **Assumptions** + + In this sequence, a `Switch` is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The `Switch` is optional in the process, as the request[Calculate Quote](#calculate-quote) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. + +10. **Description** + + The `Switch` receives the [Calculate Quote](#calculate-quote) request. The `Switch` then routes the request to the `Payee FSP`, using the same parameters. + + **Assumptions** + + None. + +11. **Description** + + The `Payee FSP` receives the [Calculate Quote](#calculate-quote) request. The `Payee FSP` then internally calculates the fees or FSP commission for performing the transaction. It then constructs the ILP Packet containing the ILP Address of the `Payee`, the amount that the `Payee` will receive, and the transaction details. The fulfilment and the condition are then generated out of the ILP Packet combined with a local secret. + + **Assumptions** + + None. + + **Optional procedure: Quote Confirmation by Payee** + + a. **Description** + + Depending on the use case and the fee model used, the `Payee` might be informed of the quote in order to confirm the proposed financial transaction. The quote is in that case sent to the `Payee` using a front-end API (outside the scope of this API). The `Payee` receives the quote including information regarding the transaction including fees and optionally `Payer` name. The `Payee` then confirms the quote using a front-end API (outside the scope of this API), and the `Payee FSP` receives the confirmation from the `Payee`. + + **Assumptions** + + The `Payee` is assumed to accept and confirm the quote. If the `Payee` would reject the quote, an error response would be sent from the `Payee` FSP to the `Payer FSP` via the `Switch` to inform about the rejected quote. + + **End of Optional procedure** + +12. **Description** + + The `Payee FSP` uses the response [Return Quote Information](#return-quote-information) to the `Switch` to return information to the `Payer FSP` about the quote, the ILP Packet, and the condition. The quote has an expiration time, to inform the `Payer FSP` until which point in time the quote is valid. + + **Assumptions** + + None. + +13. **Description** + + The `Switch` receives the response [Return Quote Information](#return-quote-information). The `Switch` will then route the response to the `Payer FSP`. + + **Assumptions** + + None. + +14. **Description** + + The `Payer FSP` receives the response[Return Quote Information](#return-quote-information) from the `Switch`. The `Payer FSP` then informs the `Payer` using a front-end API (outside the scope of this API) about the total fees to perform the transaction, along with the `Payee` name. + + **Assumptions** + + The total quote can be calculated by the `Payer FSP`. Also, the `Payee` name was allowed to be sent during the counterparty lookup (depending on regulation on privacy laws). + +15. **Description** + + The `Payer` receives the transaction information including fees, taxes and optionally `Payee` name. If the `Payer` rejects the transaction, the sequence ends here. + + **Assumptions** + + The `Payer` is assumed to approve the transaction in this sequence. If the `Payer` would reject the transaction at this stage, no response regarding the rejection is sent to the `Payee FSP`. The created quote at the `Payee FSP` should have an expiry time, at which time it is automatically deleted. + +
    + +##### Perform Transfer + +16. **Description** + + The `Payer FSP` receives an approval of the interoperable financial transaction using a front-end API (out of scope of this API). The `Payer FSP` then performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on). If the validations are successful, a transfer of funds is reserved from the `Payer`'s account to either a combined `Switch` account or a `Payee FSP` account, depending on setup. After the transfer has been successfully reserved, the request [Perform Transfer](#perform-transfer) is sent to the `Switch` to request the `Switch` to transfer the funds from the `Payer FSP` account in the Switch to the `Payee FSP` account. The request [Perform Transfer](#perform-transfer) includes a reference to the earlier quote, an expiry of the transfer, the ILP Packet, and the condition that was received from the `Payee FSP`. The interoperable financial transaction is now irrevocable from the `Payer FSP`. + + **Assumptions** + + Internal validations and reservation are assumed to be successful. In this sequence, a `Switch` is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The `Switch` is optional in the process, as the request [Perform Transfer](#perform-transfer) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. + +17. **Description** + + The `Switch` receives the request [Perform Transfer](#perform-transfer). The `Switch` then performs all its applicable internal transfer validations (for example, limit checks blacklist check and so on). If the validations are successful, a transfer is reserved from a `Payer FSP` account to a `Payee FSP` account. After the transfer has been successfully reserved, the request [Perform Transfer](#perform-transfer) is sent to the `Payee FSP`, including the same ILP Packet and condition as was received from the `Payer FSP`. The expiry time should be decreased by the `Switch` so that the `Payee FSP` should answer before the `Switch` answers to the `Payer FSP`. The transfer is now irrevocable from the `Switch`. + + **Assumptions** + + Internal validations and reservation are successful. + +18. **Description** + + The `Payee FSP` receives the request [Perform Transfer](#perform-transfer). The `Payee FSP` then performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on). It also verifies that the amount and ILP Address in the ILP Packet are correct and match the amount and `Payee` in the transaction details stored in the ILP Packet. If all the validations are successful, a transfer of funds is performed from either a combined `Switch` account or a `Payer FSP` account to the `Payee`'s account and the fulfilment of the condition is regenerated, using the same secret as in Step 11. After the interoperable financial transaction has been successfully performed, a transaction notification is sent to the `Payee` using a front-end API (out of scope of this API) and the response **Return Transfer Information** is sent to the `Switch`, including the regenerated fulfilment. The transfer is now irrevocable from the `Payee FSP`. + + **Assumptions** + + Internal validations and transfer of funds are successful. + +19. **Description** + + The `Payee` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +20. **Description** + + The `Switch` receives the response [Return Transfer Information](#return-transfer-information). The `Switch` then validates the fulfilment and commits the earlier reserved transfer. The `Switch` then uses the response [Return Transfer Information](#return-transfer-information) to the `Payer FSP`, using the same parameters. + + **Assumptions** + + The fulfilment is assumed to be correctly validated. + +21. **Description** + + The `Payer FSP` receives the response [Return Transfer Information](#return-transfer-information). The `Payer FSP` then validates the fulfilment and commits the earlier reserved transaction. + + **Assumptions** + + The fulfilment is assumed to be correctly validated. + +**Optional fragment: Get Transaction Details** + +22. **Description** + + In case the interoperable financial transaction contains additional information that is useful for the `Payer` or the `Payer FSP`, such as a code or a voucher token, the `Payer FSP` can use the request [Return Transfer Information](#return-transfer-information) to get the additional transaction information. The request [Retrieve Transaction Information](#retrieve-transaction-information) is sent to the `Switch`. + + **Assumptions** + + None. + +23. **Description** + + The `Switch` receives the request [Retrieve Transaction Information](#retrieve-transaction-information). The `Switch` then routes the [Retrieve Transaction Information](#retrieve-transaction-information) request to the `Payee FSP`. + + **Assumptions** + + None. + +24. **Description** + + The `Payee FSP` receives the request [Retrieve Transaction Information](#retrieve-transaction-information). The `Payee FSP` then collects the requested information and sends the response [Return Transaction Information](#return-transaction-information) to the `Switch`. + + **Assumptions** + + The transaction with the provided ID can be found in the `Payee FSP`. + +25. **Description** + + The `Switch` receives the response [Return Transaction Information](#return-transaction-information). The Switch then routes the [Return Transaction Information](#return-transaction-information) response to the `Payer FSP`. + + **Assumptions** + + None. + +26. **Description** + + The `Payer FSP` receives the response [Return Transaction Information](#return-transaction-information). + + **Assumptions** + + None. + + **End of Optional fragment** + +28. **Description** + + The `Payer FSP` sends a transaction notification to the `Payee` using a front-end API (out of scope of this API), optionally including transaction details retrieved from the `Payee FSP`. + + **Assumptions** + + None. + +29. **Description** + + The `Payer` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +
    + +### Payee-Initiated Transaction + +In a _Payee-Initiated Transaction_, the `Payee` (that is, the recipient of electronic funds) initiates the transaction. + +#### Business Process Pattern Description + +The pattern should be used whenever a `Payee` would like to receive funds from another party whose account is not located in the same FSP. + +In all alternatives to this pattern, the `Payer` must in some way confirm the request of funds. Some possible alternatives for confirming the request are: + +- **Manual approval** -- A transaction request is routed from the Payee to the Payer, the Payer can then either approve or reject the transaction. + +- **Pre-approval of Payee** -- A Payer can pre-approve a specific Payee to request funds, used for automatic approval of, for example, school fees or electric bills. + +Another alternative for approval is to use the business pattern [Payee-Initiated Transaction using OTP](#payee-initiated-transaction-using-otp). + +#### Participants and Roles + +The actors in a _Payee-Initiated Transaction_ are: + +- **Payer** -- The payer of funds in a financial transaction. + +- **Payee** -- The recipient of funds in a financial transaction. + +The intermediary objects used in a _Payee-Initiated Transaction_ to perform the transaction are: + +- **Payer FSP** -- The FSP in which the Payer's account is located. + +- **Switch (optional)** -- An optional entity used for routing of requests between different FSPs. This object can be removed if requests should be routed directly between a Payer and Payee FSP. + +- **Account Lookup System** -- An entity used for retrieving information regarding accounts or participants. Could be hosted in a separate server, in the Switch, or in the different FSPs. + +- **Payee FSP** -- The FSP in which the Payee's account is located. + +#### Business Process Sequence Diagram + +Figure 2 shows the UML sequence diagram for a _Payee-Initiated Transaction_. + +{% uml src="assets/diagrams/sequence/figure65a.plantuml" %} +{% enduml %} +**Figure 2 -- Payee-Initiated Transaction** + +#### Internal Processing Steps + +This section provides descriptions of and assumptions made for all steps in the sequence shown in Figure 2 above. + +##### Lookup Counterparty + +1. **Description** + + The `Payee` initiates the transaction by requesting to receive funds from a `Payer`, using the `Payee FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + None. + +2. **Description** + + The `Payee FSP` tries to find the Payer within the FSP system. Because the `Payer` cannot be found in the `Payee FSP` system, the `Payee FSP` sends the request to the optional `Account Lookup System` to get information regarding in which FSP the `Payer` is located. + + **Assumptions** + + The `Payer` is assumed to be located in a different FSP than the `Payee`. Also, an `Account Lookup System` is assumed to exist. + + The `Account Lookup System` is optional in the process, as the request [Lookup Participant Information](#lookup-participant-information) could also be sent directly to the` Payer FSP` if there is no `Account Lookup System`. As the `Payee FSP` should not know in which FSP the Payer is located if there is no `Account Lookup System` present, the request might need to be sent to more than one FSP. It is also possible that the `Payee FSP` would like more information about the `Payer` before a transaction request is sent; in that case the request [Lookup Participant Information](#lookup-participant-information), either to the Switch or directly to the `Payer FSP`, should be sent instead of [Lookup Participant Information](#lookup-participant-information) to the `Account Lookup System`. + +3. **Description** + + The `Account Lookup System` receives the [Lookup Participant Information](#lookup-participant-information). It then performs an internal lookup to find in which FSP the `Payer` is located. When the lookup is completed, the response [Return Participant Information](#return-participant-information) is sent to inform the `Payee FSP` about which FSP the `Payer` is located. + + **Assumptions** + + The `Payer` can be found by the `Account Lookup System`. + +4. **Description** + + The `Payee FSP` receives the response [Return Participant Information](#return-participant-information). + + **Assumptions** + + None. + + **Transaction Request** + +5. **Description** + + The `Payee FSP` sends the request [Perform Transaction Request](#perform-transaction-request) to the `Switch`. The request contains the transaction details including the amount that the Payee would like to receive. + + **Assumptions** + + In this sequence, a `Switch` is placed between the `Payee FSP` and the `Payer FSP` to route the messages. The `Switch` is optional in the process, as the request [Perform Transaction Request](#perform-transaction-request) could also be sent directly to the `Payer FSP` if there is no Switch in-between. + +6. **Description** + + The `Switch` receives the [Perform Transaction Request](#perform-transaction-request). The `Switch` then routes the request to the `Payer FSP`, using the same parameters. + + **Assumptions** + + None. + +7. **Description** + + The `Payer FSP` receives the request [Perform Transaction Request](#perform-transaction-request). The `Payer FSP` then optionally validates the transaction request (for example, whether the `Payer` exists) and uses the response [Return Transaction Request Information](#return-transaction-request-information) to inform the `Payee FSP` via the `Switch` that the transaction request has been received. + + **Assumptions** + + The optional validation succeeds. + +8. **Description** + + The `Switch` receives the response [Return Transaction Request Information](#return-transaction-request-information). The `Switch` then sends the same response [Return Transaction Request Information](#return-transaction-request-information) to inform the `Payee FSP` about the successfully delivered transaction request to the `Payer FSP`. + + **Assumptions** + + None. + +9. **Description** + + The `Payee FSP` receives the response [Return Transaction Request Information](#return-transaction-request-information) from the `Switch`. + + **Assumptions** + + None. + +
    + +##### Calculate Quote + +10. **Description** + + The `Payer FSP` rates the transaction internally based on the fee model used and includes the quote information in the request[Calculate Quote](#calculate-quote) to a `Switch` to retrieve the full quote for performing the interoperable financial transaction from the `Payer FSP` to the `Payee FSP`. The transaction details, including a reference to the earlier sent transaction request, are sent in the parameters of the request to allow for the `Payee FSP` to correctly calculate the quote. + + **Assumptions** + + In this sequence, a `Switch` is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The `Switch` is optional in the process, as the request [Calculate Quote](#calculate-quote) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. + +11. **Description** + + The `Switch` receives the [Calculate Quote](#calculate-quote) request. The `Switch` then routes the request to the `Payee FSP`. + + **Assumptions** + + None. + +12. **Description** + + The `Payee FSP` receives the [Calculate Quote](#calculate-quote) request. The `Payee FSP` then internally calculates the fees or FSP commission for performing the transaction. It then constructs the ILP Packet containing the ILP Address of the `Payee`, the amount that the `Payee` will receive, and the transaction details. The fulfilment and the condition are then generated out of the ILP Packet combined with a local secret. + + **Assumptions** + + None + +13. **Description** + + Depending on use case and the fee model used, the `Payee` might be informed of the quote so that the `Payee` can confirm the proposed financial transaction. The quote is in that case sent to the `Payee` using a front-end API (outside the scope of this API). The `Payee` receives the quote including information regarding the transaction including fees and optionally Payer name. The `Payee` then confirms the quote using a front-end API (outside the scope of this API). The `Payee FSP` receives the confirmation from the `Payee`. + + **Assumptions** + + The quote is assumed to be sent to the `Payer` for confirmation, and the `Payee` is assumed to accept and confirm the quote. If the `Payee` would reject the quote, an error response would be sent from the `Payee FSP` to the `Payer FSP` via the `Switch` to inform about the rejected quote. + + **End of Optional fragment** + +14. **Description** + + The `Payee FSP` uses the response [Return Quote Information](#return-quote-information) to the `Switch` to return information to the `Payer FSP` about the quote, the ILP Packet, and the condition. The quote has an expiration time, to inform the `Payer FSP` until which point in time the quote is valid. + + **Assumptions** + + None. + +15. **Description** + + The `Switch` receives the response [Return Quote Information](#return-quote-information). The `Switch` then routes the response to the `Payer FSP`. + + **Assumptions** + + None. + +16. **Description** + + The `Payer FSP` receives the response [Return Quote Information](#return-quote-information) from the `Switch`. The `Payer FSP` then informs the `Payer` using a front-end API (outside the scope of this API) about the transaction request from the `Payee`, including the amount and the total fees required to perform the transaction, along with the `Payee` name. + + **Assumptions** + + The total quote can be calculated by the `Payer FSP`. Also, the `Payee` name was allowed to be sent during the counterparty lookup (depending on regulation on privacy laws). + +17. **Description** + + The `Payer` receives the transaction request information including fees, taxes and optionally `Payee` name. + + **Assumptions** + + If the `Payer` rejects the transaction request, the sequence proceeds to Step 18. If the `Payer` approves the transaction request, the sequence proceeds to Step 22. + + **Alternative: Transaction Rejection** + +18. **Description** + + The `Payer FSP` receives the rejection of the transaction request using a front-end API (out of scope of this API). The `Payer FSP` then uses the response [Return Transaction Request Information](#return-transaction-request-information) with a rejected status to inform the `Switch` that the transaction was rejected. + + **Assumptions** + + The `Payer` is assumed to reject the transaction request in Step 17. + +19. **Description** + + The `Switch` receives the response [Return Transaction Request Information](#return-transaction-request-information) from the `Payer FSP`. The `Switch` then routes the response [Return Transaction Request Information](#return-transaction-request-information) to the `Payee FSP`. + + **Assumptions** + + None. + +20. **Description** + + The `Payee FSP` receives the response *[Return Transaction Request Information](#return-transaction-request-information) with a rejected status from the `Switch`. The `Payee FSP` then informs the Payee using a front-end API (outside the scope of this API) about the rejected transaction request. + + **Assumptions** + + None. + +21. **Description** + + The `Payee` receives the notification that the transaction was rejected. The process ends here as the transaction request was rejected and the `Payee` has been informed of the decision. + + **Assumptions** + + None. + + **Alternative: Perform Transfer** + +22. **Description** + + The `Payer FSP` receives an approval of the interoperable financial transaction using a front-end API (out of scope of this API). The `Payer FSP` then performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on). If the validations are successful, a transfer of funds is reserved from the `Payer`'s account to either a combined `Switch` account or a `Payee FSP` account, depending on setup. After the transfer has been successfully reserved, the request [Perform Transfer](#perform-transfer) is sent to the `Switch` to request the `Switch` to transfer the funds from the `Payer FSP` account in the `Switch` to the `Payee FSP` account. The request [Perform Transfer](#perform-transfer) includes a reference to the earlier quote, an expiry of the transfer, the ILP Packet, and the condition that was received from the `Payee FSP`. The interoperable financial transaction is now irrevocable from the `Payer FSP`. + + **Assumptions** + + The `Payer` is assumed to approve the transaction request in Step 17. Internal validations and reservation are assumed to be successful. In this sequence, a `Switch` is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The Switch is optional in the process, as the request [Perform Transfer](#perform-transfer) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. + +23. **Description** + + The `Switch` receives the request [Perform Transfer](#perform-transfer). The `Switch` then performs all its applicable internal transfer validations (for example, limit checks, blacklist check, and so on). If the validations are successful, a transfer is reserved from a `Payer FSP` account to a `Payee FSP` account. After the transfer has been successfully reserved, the request [Perform Transfer](#perform-transfer) is sent to the `Payee FSP`, including the same ILP Packet and condition as was received from the Payer FSP. The expiry time should be decreased by the `Switch`, so that the `Payee FSP` should answer before the `Switch` should answer to the `Payer FSP`. The transfer is now irrevocable from the `Switch`. + + **Assumptions** + + Internal validations and reservation are successful. + +24. **Description** + + The `Payee FSP` receives the request [Perform Transfer](#perform-transfer). The `Payee FSP` then performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on). It also verifies that the amount and ILP Address in the ILP Packet are correct and match the amount and `Payee` in the transaction details stored in the ILP Packet. If all the validations are successful, a transfer of funds is performed from either a combined `Switch` account or a `Payer FSP` account to the `Payee`'s account and the fulfilment of the condition is regenerated, using the same secret as in Step 11. After the interoperable financial transaction has been successfully performed, a transaction notification is sent to the Payee using a front-end API (out of scope of this API) and the response [Return Transfer Information](#return-transfer-information) is sent to the `Switch`, including the regenerated fulfilment. The transfer is now irrevocable from the `Payee FSP`. + + **Assumptions** + + Internal validations and transfer of funds are successful. + +25. **Description** + + The `Payee` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +26. **Description** + + The `Switch` receives the response [Return Transfer Information](#return-transfer-information). The `Switch` then validates the fulfilment and commits the earlier reserved transfer. The `Switch` then uses the response [Return Transfer Information](#return-transfer-information) to the `Payer FSP`, using the same parameters. + + **Assumptions** + + The fulfilment is assumed to be correctly validated. + +27. **Description** + + The `Payer FSP` receives the response [Return Transfer Information](#return-transfer-information). The `Payer FSP` then validates the fulfilment and commits the earlier reserved transaction. + + **Assumptions** + + The fulfilment is assumed to be correctly validated. + + **Optional fragment: Get Transaction Details** + +28. **Description** + + In case the interoperable financial transaction contains additional information that is useful for the `Payer` or the `Payer FSP`; for example, a code or a voucher token, the `Payer FSP` can use the request [Retrieve Transaction Information](#retrieve-transaction-information) to get the additional information. The request [Retrieve Transaction Information](#retrieve-transaction-information) is sent to the `Switch`. + + **Assumptions** + + None. + +29. **Description** + + The `Switch` receives the request [Retrieve Transaction Information](#retrieve-transaction-information). The `Switch` then routes the request [Retrieve Transaction Information](#retrieve-transaction-information) to the `Payee FSP`. + + **Assumptions** + + None. + +30. **Description** + + The `Payee FSP` receives the request [Retrieve Transaction Information](#retrieve-transaction-information). The `Payee FSP` then collects the requested information and uses the response [Retrieve Transaction Information](#retrieve-transaction-information) to the `Switch`. + + **Assumptions** + + The transaction with the provided ID can be found in the Payee FSP. + +31. **Description** + + The `Switch` receives the response [Retrieve Transaction Information](#retrieve-transaction-information). The `Switch` then routes the [Retrieve Transaction Information](#retrieve-transaction-information) response to the `Payer FSP`. + + **Assumptions** + + None. + +32. **Description** + + The `Payer FSP` receives the response [Retrieve Transaction Information](#retrieve-transaction-information) from the `Switch`. + + **Assumptions** + + None. + + **End of Optional fragment** + +33. **Description** + + The `Payer FSP` sends a transaction notification to the `Payee` using a front-end API (out of scope of this API), optionally including transaction details retrieved from the `Payee FSP`. + + **Assumptions** + + None. + +34. **Description** + + The `Payer` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +
    + +### Payee-Initiated Transaction using OTP + +A _Payee-Initiated Transaction using OTP_ is very similar to a [Payee-Initiated Transaction](#payee-initiated-transaction), but the transaction information (including fees and taxes) and approval for the `Payer` is shown/entered on a `Payee` device instead. + +#### Business Process Pattern Description + +The pattern should be used when a `Payee` would like to receive funds from another party whose account is not located in the same FSP, and both the transaction information (including fees and taxes) and approval is shown/entered on a `Payee` device instead. + +- **Approval using OTP** -- A `Payer` can approve a transaction by first creating an OTP in his/her FSP. An alternative to user- initiated creation of OTP is that the OTP is automatically generated and sent by the `Payer FSP`. The same OTP is then entered by the `Payer` in a `Payee` device, usually a POS device or an ATM. The OTP in the transaction request is automatically matched by the `Payer FSP` to either approve or reject the transaction. The OTP does not need to be encrypted as it should only be valid once during a short time period. + +#### Participants and Roles + +The actors in a _Payee-Initiated Transaction using OTP_ are: + +- **Payer** -- The payer of funds in a financial transaction. + +- **Payee** -- The recipient of funds in a financial transaction. + +The intermediary objects used in a _Payee-Initiated Transaction using OTP_ to perform the transaction are: + +- **Payer FSP** -- The FSP in which the Payer's account is located. + +- **Switch (optional)** -- An optional entity used for routing of requests between different FSPs. This object can be removed if requests should be routed directly between a Payer and Payee FSP. + +- **Account Lookup System** -- An entity used for retrieving information regarding accounts or participants. Could be hosted in a separate server, in the Switch, or in the different FSPs. + +- **Payee FSP** -- The FSP in which the Payee's account is located. + +#### Business Process Sequence Diagram + +Figure 3 shows the UML sequence diagram for a _Payee-Initiated Transaction using OTP_. + +{% uml src="assets/diagrams/sequence/figure66a.plantuml" %} +{% enduml %} +**Figure 3 -- Payee-Initiated Transaction using OTP** + +#### Internal Processing Steps + +This section provides descriptions of and assumptions made for all steps in the sequence shown in Figure 3 above. + +##### Optional fragment: Manual OTP request + +1. **Description** + + The `Payer` requests that an OTP be generated, using the `Payer FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + There are two alternatives for generating an OTP; either it is generated upon request by the `Payer` (this option), or it is automatically generated in Step 19. + +2. **Description** + + The `Payer FSP` receives the request to generate an OTP and returns a generated OTP to the `Payer`, using the `Payer FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + None. + +3. **Description** + + `Payer` receives the generated OTP. The OTP can then be used by the `Payer` in Step 25 for automatic approval. + + **Assumptions** + + None. + + **End of Optional fragment** + +###### Lookup Counterparty + +4. **Description** + + The `Payee` initiates the transaction by requesting to receive funds from a `Payer`, using the `Payee FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + None. + +5. **Description** + + The `Payee FSP` tries to find the `Payer` within the FSP system. Because the `Payer` cannot be found in the `Payee FSP` system, the request **Lookup Participant Information** is sent by the `Payee FSP` to the optional Account Lookup System to get information regarding in which FSP the Payer is located. + + **Assumptions** + + The `Payer` is assumed to be in a different FSP than the `Payee`. Also, an `Account Lookup System` is assumed to exist. The `Account Lookup System` is optional in the process, as the request [Lookup Participant Information](#lookup-participant-information) could also be sent directly to the `Payer FSP` if there is no `Account Lookup System`. As the `Payee FSP` should not know in which FSP the `Payer` is located if there is no `Account Lookup System` present, the request might need to be sent to more than one FSP. It is also possible that the `Payee FSP` would like more information about the Payer before a transaction request is sent; in that case the request [Lookup Party Information](#lookup-party-information), either to the `Switch` or directly to the `Payer FSP`, should be sent instead of [Lookup Participant Information](#lookup-participant-information) to the `Account Lookup System`. + +6. **Description** + + The `Account Lookup System` receives the [Lookup Participant Information](#lookup-participant-information). It then performs an internal lookup to find in which FSP the `Payer` is located. When the lookup is completed, the response [Return Participant Information](#return-participant-information) is sent to inform the `Payee FSP` about which FSP the `Payer` is located in. + + **Assumptions** + + The `Payer` can be found by the `Account Lookup System`. + +7. **Description** + + The `Payee FSP` receives the response [Return Participant Information](#return-participant-information). + + **Assumptions** + + None. + +##### Transaction Request + +8. **Description** + + The Payee FSP sends the request [Perform Transaction Request](#perform-transaction-request) to the `Switch`. The request contains the transaction details including the amount that the `Payee` would like to receive, and that the request should be validated using an OTP (possibly a QR code containing a OTP). + + **Assumptions** + + In this sequence, a `Switch` is placed between the `Payee FSP` and the `Payer FSP` to route the messages. The `Switch` is optional in the process, as the request [Perform Transaction Request](#perform-transaction-request) could also be sent directly to the `Payer FSP` if there is no `Switch` in-between. + +9. **Description** + + The `Switch` receives the request [Perform Transaction Request](#perform-transaction-request). The `Switch` then routes the request to the `Payer FSP`, using the same parameters. + + **Assumptions** + + None. + +10. **Description** + + The `Payer FSP` receives the request [Perform Transaction Request](#perform-transaction-request). The `Payer FSP` then optionally validates the transaction request (for example, whether the `Payer` exists or not) and sends the response [Return Transaction Request Information](#return-transaction-request-information) to inform the `Payee FSP` via the `Switch` that the transaction request has been received. + + **Assumptions** + + The optional validation succeeds. + +11. **Description** + + The `Switch` receives the response [Return Transaction Request Information](#return-transaction-request-information). The `Switch` then uses the same response [Return Transaction Request Information](#return-transaction-request-information) to inform the `Payee FSP` about the successfully delivered transaction request to the `Payer FSP`. + + **Assumptions:** + + None. + +12. **Description** + + The `Payee FSP` receives the response [Return Transaction Request Information](#return-transaction-request-information) from the `Switch`. + + **Assumptions** + + None. + + **Calculate Quote** + +13. **Description** + + The `Payer FSP` rates the transaction internally based on the fee model used and includes the quote information in the request [Calculate Quote](#calculate-quote) to a `Switch` to retrieve the full quote for performing the interoperable financial transaction from the `Payer FSP` to the `Payee FSP`. The transaction details, including a reference to the transaction request, are sent in the parameters of the request to allow for the `Payee FSP` to correctly calculate the quote. + + **Assumptions** + + In this sequence, a `Switch` is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The `Switch` is optional in the process, as the request [Calculate Quote](#calculate-quote) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. + +14. **Description** + + The `Switch` receives the [Calculate Quote](#calculate-quote) request. The `Switch` then routes the request to the `Payee FSP`, using the same parameters. + + **Assumptions** + + None. + +15. **Description** + + The `Payee FSP` receives the [Calculate Quote](#calculate-quote) request. The `Payee FSP` then internally calculates the fees or FSP commission for performing the transaction. It then constructs the ILP Packet containing the ILP Address of the `Payee`, the amount that the `Payee` will receive, and the transaction details. The fulfilment and the condition is then generated out of the ILP Packet combined with a local secret. + + **Assumptions** + + None. + + **Optional fragment: Quote Confirmation by Payee** + +16. **Description** + + Depending on the fee model used and which use case it is, the `Payee` might be informed of the quote to be able to confirm the proposed financial transaction. The quote is in that case sent to the `Payee` using a front- end API (outside the scope of this API. The `Payee` receives the quote including information regarding the transaction including fees and optionally `Payer` name. The `Payee` then confirms the quote using a front-end API (outside the scope of this API). The `Payee FSP` receives the confirmation from the `Payee`. + + **Assumptions** + + The quote is assumed to be sent to the Payer for confirmation, and the `Payee` is assumed to accept and confirm the quote. If the `Payee` would reject the quote, an error response would be sent from the `Payee FSP` to the `Payer FSP` via the `Switch` to inform about the rejected quote. + + **End of Optional fragment** + +17. **Description** + + The `Payee FSP` uses the response [Return Quote Information](#return-quote-information) to the `Switch` to return information to the `Payer FSP` about the quote, the ILP Packet, and the condition. The quote has an expiration time, to inform the `Payer FSP` until which point in time the quote is valid. + + **Assumptions** + + None. + +18. **Description** + + The `Switch` receives the response [Return Quote Information](#return-quote-information). The `Switch` will then route the request to the `Payer FSP`. + + **Assumptions** + + None. + +19. **Description** + + The `Payer FSP` receives the response [Return Quote Information](#return-quote-information) from the Switch. + + **Assumptions** + + The total quote can be calculated by the `Payer FSP`. + + **Optional fragment: Automatic OTP generation** + +20. **Description** + + The `Payer FSP` automatically generates an OTP and sends it to the `Payer`, using the `Payer FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + There are two alternatives for generating the OTP. Either it is generated upon request by the `Payer` (Step 1), or it is automatically generated (this option). + +21. **Description** + + The `Payer` receives the automatically-generated OTP. + + **Assumptions** + + None. + + **End of Optional fragment** + +22. **Description** + + The `Payer FSP` sends the request [Perform Authorization](#perform-authorization) to the `Switch`, to get an authorization to perform the transaction from the Payer via a POS, ATM, or similar payment device, in the `Payee FSP`. The request includes the amount to be withdrawn from the `Payer`'s account, and how many retries are left for the `Payer` to retry the OTP. + + **Assumptions** + + None. + +23. **Description** + + The `Switch` receives the request [Perform Authorization](#perform-authorization) from the `Payer FSP`. The `Switch` then routes the [Perform Authorization](#perform-authorization) to the `Payee FSP`. + + **Assumptions** + + None. + +24. **Description** + + The `Payee FSP` receives the request [Perform Authorization](#perform-authorization) from the `Switch`. The `Payee FSP` sends the authorization request to the `Payee` device (POS, ATM, or similar payment device) using the `Payee FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + None. + +25. **Description** + + The `Payee` device receives the authorization request, and the `Payer` can see the amount that will be withdrawn from his or her account. The `Payer` then uses the OTP received in Step 3 or Step 21, depending on whether the OTP was manually requested or automatically generated. The entered or scanned OTP is then sent to the `Payee FSP` using the `Payee FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + The `Payer` has received the OTP in Step 3 or Step 21. + +26. **Description** + + The `Payee FSP` receives the OTP from the `Payee` device. The `Payee FSP` then sends the response [Return Authorization Result](#return-authorization-result) to the Switch containing the OTP from the Payer. + + **Assumptions** + + None. + +27. **Description** + + The `Switch` receives the request [Return Authorization Result](#return-authorization-result) from the `Payee FSP`. The `Switch` then routes the [Return Authorization Result](#return-authorization-result) to the `Payer FSP`. + + **Assumptions** + + None. + +28. **Description** + + The `Payer FSP` receives the request [Return Authorization Result](#return-authorization-result) to the `Switch`. The `Payer FSP` then validates the OTP received from the OTP generated in Step 2 or Step 20. If the `Payer FSP` is unable to validate the OTP (for example, because the OTP is incorrect) and this was the last remaining retry for the Payer, the sequence continues with Step 29. If the `Payer FSP` correctly validates the OTP, the sequence continues with Step 33. + + **Assumptions** + + None. + + **Alternative: OTP validation failed** + +29. **Description** + + The validation in Step 28 fails and this was the final retry for the Payer. The `Payer FSP` then uses the response [Return Transaction Request Information](#return-transation-request-information) with a rejected state to inform the `Switch` that the transaction was rejected. + + **Assumptions** + + The OTP validation in Step 28 is assumed to fail and no more retries remains for the Payer. + +30. **Description** + + The `Switch` receives the response [Return Transaction Request Information](#return-transation-request-information) from the Payer FSP. The `Switch` then routes the [Return Transaction Request Information](#return-transation-request-information) response to the `Payee FSP`. + + **Assumptions** + + None. + +31. **Description** + + The `Payee FSP` receives the response [Return Transaction Request Information](#return-transation-request-information) with a rejected status from the `Switch`. The `Payee FSP` then informs the `Payee` using a front-end API (outside the scope of this API) about the rejected transaction request. + + **Assumptions** + + None. + +32. **Description** + + The `Payee` receives the notification that the transaction was rejected. The process ends here as the transaction request was rejected and the `Payee` has been informed of the decision. The `Payer` is also assumed to receive the notification via the `Payee` device. + + **Assumptions** + + None. + + **Alternative: OTP validation succeed** + +33. **Description** + + The validation in Step 28 is successful. The `Payer FSP` then performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on). If the validations are successful, a transfer of funds is reserved from the `Payer`'s account to either a combined Switch account or a `Payee FSP` account, depending on setup. After the transfer has been successfully reserved, the request [Perform Transfer](#perform-transfer) is sent to the `Switch` to request the `Switch` to transfer the funds from the `Payer FSP` account in the `Switch` to the `Payee FSP` account. The request [Perform Transfer](#perform-transfer) includes a reference to the earlier quote, an expiry of the transfer, the ILP Packet, and the condition that was received from the `Payee FSP`. The interoperable financial transaction is now irrevocable from the `Payer FSP`. + + **Assumptions** + + The OTP validation in Step 28 is assumed to be successful. Internal validations and reservation are assumed to be successful. In this sequence, a Switch is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The Switch is optional in the process, as the request [Perform Transfer](#perform-transfer) could also be sent directly to the `Payee FSP` if there is no Switch in-between. + + 34. **Description** + + The `Switch` receives the request [Perform Transfer](#perform-transfer). The `Switch` then performs all its applicable internal transfer validations (for example, limit checks, blacklist check, and so on). If the validations are successful, a transfer is reserved from a `Payer FSP` account to a `Payee FSP` account. After the transfer has been successfully reserved, the request [Perform Transfer](#perform-transfer) is sent to the Payee FSP, including the same ILP Packet and condition as was received from the Payer FSP. The expiry time should be decreased by the Switch so that the `Payee FSP` should answer before the Switch should answer to the `Payer FSP`. The transfer is now irrevocable from the `Switch`. + + **Assumptions** + + Internal validations and reservation are successful. + +35. **Description** + + The `Payee FSP` receives the [Perform Transfer](#perform-transfer). The `Payee FSP` then performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on). It also verifies that the amount and ILP Address in the ILP Packet are correct, and match the amount and `Payee` in the transaction details stored in the ILP Packet. If all the validations are successful, a transfer of funds is performed from either a combined `Switch` account or a Payer FSP account to the `Payee`'s account and the fulfilment of the condition is regenerated, using the same secret as in Step 11. After the interoperable financial transaction has been successfully performed, a transaction notification is sent to the `Payee` using a front-end API (out of scope of this API) and the response [Return Transfer Information](#return-transfer-information) is sent to the `Switch`, including the regenerated fulfilment. The transfer is now irrevocable from the `Payee FSP`. + + **Assumptions** + + Internal validations and transfer of funds are successful. + +36. **Description** + + The `Payee` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +37. **Description** + + The `Switch` receives the response [Return Transfer Information](#return-transfer-information). The `Switch` then validates the fulfilment and commits the earlier reserved transfer. The `Switch` will then use the response [Return Transfer Information](#return-transfer-information) to the `Payer FSP`, using the same parameters. + + **Assumptions** + + The fulfilment is assumed to be correctly validated. + +38. **Description** + + The `Payer FSP` receives the response [Return Transfer Information](#return-transfer-information). The` Payer FSP` then validates the fulfilment and commits the earlier reserved transaction. + + **Assumptions** + + The fulfilment is assumed to be correctly validated. + + **Optional fragment: Get Transaction Details** + +39. **Description** + + In case the interoperable financial transaction contains additional information that is useful for the `Payer` or the `Payer FSP`, such as a code or a voucher token, the `Payer FSP` can use the request [Retrieve Transaction Information](#retrieve-transaction-information) to get the additional information. The request [Retrieve Transaction Information](#retrieve-transaction-information) is sent to the Switch. + + **Assumptions** + + None. + +40. **Description** + + The `Switch` receives the request [Retrieve Transaction Information](#retrieve-transaction-information). The `Switch` then routes the request[Retrieve Transaction Information](#retrieve-transaction-information) to the `Payee FSP`. + + **Assumptions** + + None. + +41. **Description** + + The `Payee FSP` receives the request *[Retrieve Transaction Information](#retrieve-transaction-information). The `Payee FSP` then collects the requested information and uses the response [Return Transaction Information](#return-transaction-information) to the `Switch`. + + **Assumptions** + + The transaction with the provided ID can be found in the `Payee FSP`. + +42. **Description** + + The `Switch` receives the response [Return Transaction Information](#return-transaction-information). The `Switch` then routes the [Return Transaction Information](#return-transaction-information) response to the `Payer FSP`. + + **Assumptions** + + None. + +43. **Description** + + The `Payer FSP` receives the response [Return Transaction Information](#return-transaction-information) from the `Switch`. + + **Assumptions** + + None. + + **End of Optional fragment** + +44. **Description** + + The `Payer FSP` sends a transaction notification to the `Payee` using a front-end API (out of scope of this API), optionally including transaction details retrieved from the `Payee FSP`. + + **Assumptions** + + None. + +45. **Description** + + The `Payer` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +
    + +### Bulk Transactions + +In a _Bulk Transaction_, the `Payer` (that is, the sender of funds) initiates multiple transactions to multiple Payees, potentially located in different FSPs. + +#### Business Process Pattern Description + +The pattern should be used whenever a `Payer` would like to transfer funds to multiple Payees in the same transaction. The Payees can potentially be located in different FSPs. + +#### Participants and Roles + +The actors in a _Bulk Transaction_ are: + +- **Payer** -- The sender of funds. + +- **Payees** -- The recipients of funds. There should be multiple Payees in a _Bulk Transaction_. + +The intermediary objects used in a _Bulk Transaction_ to perform the transaction are: + +- **Payer FSP** -- The FSP in which the Payer's account is located. + +- **Switch (optional)** -- An optional entity used for routing of transactions between different FSPs. This object can be removed if transactions should be routed directly between a Payer and `Payee FSP`. + +- **Account Lookup System** -- An entity used for retrieving information regarding accounts or participants. Could be hosted in a separate server, in the Switch, or in the different FSPs. + +- **Payee FSP** -- The FSP in which a Payee's account is located. There may be multiple Payee FSPs in a _Bulk Transaction_. + +#### Business Process Sequence Diagram + +Figure 4 below shows the UML sequence diagram for a _Bulk Transaction_. + +{% uml src="assets/diagrams/sequence/figure67a.plantuml" %} +{% enduml %} +**Figure 4 -- Bulk Transaction** + +#### Internal Processing Steps + +This section provides descriptions of and assumptions made for all steps in the sequence shown in Figure 4. + +##### Lookup Counterparties + +1. **Description** + + The `Payer` initiates the bulk transaction process by uploading a bulk file to the `Payer FSP`, using the `Payer FSP`'s front-end API (outside the scope of this API). + + **Assumptions** + + None. + + **Loop for each Transaction in bulk file** + +2. **Description** + + `Payer FSP` tries to find the Payee within the `Payer FSP` system. + + **Assumptions** + + The `Payee` is assumed to be located in a different FSP than the `Payer`. If the `Payee` is within the `Payer FSP`, the transaction can be handled internally in the `Payer FSP` (outside the scope of this API). + +3. **Description** + + The `Payer FSP` sends the request [Lookup Participant Information](#lookup-participant-information) to the optional `Account Lookup System` to get information regarding in which FSP the `Payer` is present in. + + **Assumptions** + + The `Payee` is assumed to in a different FSP than the `Payer`. Also, an `Account Lookup System` is assumed to exist. The `Account Lookup System` is optional in the process, as the request [Lookup Participant Information](#lookup-participant-information) could also be sent directly to the `Payee FSP`s if there is no `Account Lookup System`. As the `Payer FSP `should not know in which FSP the `Payee` is located in if there is no `Account Lookup System` present, the request might need to be sent to more than one FSP. It is also possible that the `Payer FSP` would like more information about the `Payee` before a bulk transaction is executed; for example, for additional verification purposes of the `Payee` name. In that case, the request [Lookup Party Information](#lookup-party-information), either to the `Switch` or directly to the `Payee FSP`, should be sent instead of the request [Lookup Participant Information](#lookup-participant-information) to the `Account Lookup System`. + +4. **Description** + + The `Account Lookup System` receives the request [Lookup Participant Information](#lookup-participant-information) It then performs an internal lookup to find in which FSP the `Payee` is located. When the lookup is completed, the response [Return Participant Information](#return-participant-information) is sent to inform the Payer FSP about which FSP the `Payee` is located in. + + **Assumptions** + + The `Payee` can be found by the `Account Lookup System`. + +5. **Description** + + The `Payer FSP` receives the response [Return Participant Information](#return-participant-information). The `Payee` and the related transaction is then placed in a new bulk file separated per `Payee FSP`. + + **Assumptions** + + None. + + **End of loop for each Transaction** + +##### Calculate Bulk Quote + + **Loop for each `Payee FSP` to Calculate Bulk Quote** + +6. **Description** + + The `Payer FSP` uses the request [Calculate Bulk Quote](#calculate-bulk-quote) on a `Switch` to retrieve a quote for performing the bulk transaction from the `Payer FSP` to the `Payee FSP`. The request contains details for each individual transaction in the bulk transaction. + + **Assumptions** + + In this sequence, a `Switch` is placed between the `Payer FSP` and the `Payee FSP` to route the messages. The Switch is optional in the process, as the request [Calculate Bulk Quote](#calculate-bulk-quote) could also be sent directly to the `Payee FSP` if there is no `Switch` in-between. + +7. **Description** + + The `Switch` receives the [Calculate Bulk Quote](#calculate-bulk-quote) request. The `Switch` then routes the request to the `Payee FSP`, using the same parameters. + + **Assumptions** + + None. + +8. **Description** + + The `Payee FSP` receives the [Calculate Bulk Quote](#calculate-bulk-quote) request. The `Payee FSP` then internally calculates the fees or FSP commission for performing each individual transaction in the bulk transaction. For each individual transaction, the `Payee FSP` then constructs an ILP Packet containing the ILP Address of the `Payee`, the amount that the `Payee` will receive, and the transaction details. The fulfilment and the condition is then generated out of the ILP Packet combined with a local secret. It then uses the response [Return Bulk Quote Information](#return-bulk-quote-information) to the `Switch` to inform the `Payer FSP` about the fees involved in performing the bulk transaction and the ILP Packet and condition. The bulk quote has an expiration date and time, to inform the `Payer FSP` until which time the bulk quote is valid. + + **Assumptions** + + The bulk quote can be calculated by the `Payee FSP`. + +9. **Description** + + The Switch receives the response [Return Bulk Quote Information](#return-bulk-quote-information). The `Switch` then routes the response to the Payer FSP. + + **Assumptions** + + None. + +10. **Description** + + The `Payer FSP` receives the response [Return Bulk Quote Information](#return-bulk-quote-information) from the `Switch`. + + **Assumptions** + + None. + + **End of loop for each `Payee FSP`** + +11. **Description** + + The `Payer FSP` calculates any internal bulk fees and taxes, and informs the `Payer` using a front-end API (outside the scope of this API) about the total fees and taxes to perform the bulk transaction. + + **Assumptions** + + None. + +12. **Description** + + The `Payer` receives the notification about the completed processing of the bulk transaction and the fees and taxes to perform the bulk transaction. The `Payer` then decides to execute the bulk transaction. + + **Assumptions** + + The `Payer` is assumed to execute the bulk transaction. If the `Payer` would reject the bulk transaction at this stage, no response is sent to the `Payee FSP`. The created bulk quote at the `Payee FSP`s should have an expiry date; that is, at which time it's automatically deleted. + +##### Perform Bulk Transfer** + +13. **Description** + + The `Payer FSP` receives the request to execute the bulk transaction from the `Payer`. + + **Assumptions** + + None. + + **Loop for each `Payee FSP` to perform Bulk Transfer** + +14. **Description** + + The `Payer FSP` performs all applicable internal transaction validations (for example, limit checks, blacklist check, and so on) for the bulk transaction to the `Payee FSP`. If the validations are successful, a transfer of funds is reserved from the Payer's account to either a combined `Switch` account or a `Payee FSP` account, depending on setup. After the transfer has been successfully reserved, the request [Perform Bulk Transfer](#perform-bulk-transfer) is sent to the `Switch`. The request [Perform Bulk Transfer](#perform-bulk-transfer) includes a reference to the earlier bulk quote, an expiry of the bulk transfer, and the ILP Packets and condition per transfer that was received from the `Payee FSP`. The interoperable financial transaction is now irrevocable from the Payer FSP. The interoperable bulk transaction is now irrevocable from the Payer FSP. + + **Assumptions** + + In this sequence, a Switch is placed between the `Payer FSP `and the `Payee FSP` to route the messages. The `Switch` is optional in the process, as the request *[Perform Bulk Transfer](#perform-bulk-transfer) could also be sent directly to the `Payee FSP` if there is no Switch in-between. + +15. **Description** + + The Switch receives the request [Perform Bulk Transfer](#perform-bulk-transfer). The Switch then performs all applicable internal transfer validations (such as limit checks, blacklist check, and so on). If the validations are successful, a transfer is reserved from a Payer FSP account to a `Payee FSP` account. After the transfer has been successfully reserved, the request [Perform Bulk Transfer](#perform-bulk-transfer) is sent to the `Payee FSP`, including the same ILP Packets and conditions for each transfer that were received from the `Payer FSP`. The expiry time should be decreased by the Switch so that the `Payee FSP` should answer before the Switch should answer to the `Payer FSP`. The bulk transfer is now irrevocable from the `Switch`. + + **Assumptions** + + Internal validations and reservation are successful. + +16. **Description** + + The `Payee FSP` receives the request [Perform Bulk Transfer](#perform-bulk-transfer). The `Payee FSP` then performs all applicable internal transaction validations (such as limit checks, and blacklist checks) for each individual transaction in the bulk transaction. If the validations are successful, a transfer of funds is performed from either a combined Switch account or a `Payer FSP` account, depending on setup, to each of the Payees' accounts and the fulfilment of each condition is regenerated, using the same secret as in Step 8. After each transfer to a `Payee` has been successfully performed, a transaction notification is sent to the `Payee` using a front-end API (out of scope of this API). After each of the individual transactions in the bulk transaction has been completed, the response [Return Bulk Transfer Information](#return-bulk-transfer-information) is sent to the Switch to inform the Switch and the Payer FSP of the result including each fulfilment. The transactions in the bulk transaction are now irrevocable from the `Payee FSP`. + + **Assumptions** + + Internal validations and transfers of funds are successful. + +17. **Description** + + Each `Payee` receives a transaction notification containing information about the successfully performed transaction. + + **Assumptions** + + None. + +18. **Description** + + The `Switch` receives the response [Return Bulk Transfer Information](#return-bulk-transfer-information). The `Switch` then validates the fulfilments and commits the earlier reserved transfers. The `Switch` then uses the response [Return Bulk Transfer Information](#return-bulk-transfer-information) to the `Payer FSP`, using the same parameters. + + **Assumptions** + + Each individual transaction in the bulk transaction is assumed to be successful in the `Payee FSP`, and the validation of the fulfilments is also assumed to be correct. If one or more of the transactions in the bulk transaction were unsuccessful, the earlier reserved, now unsuccessful, transfer or transfers in the `Switch` would need to be cancelled. + +19. **Description** + + The `Payer FSP` receives the response [Return Bulk Transfer Information](#return-bulk-transfer-information). The `Payer FSP` then commits the earlier reserved transfers. After the bulk transaction has been successfully committed, a transaction notification is sent to the `Payer` using a front-end API (out of scope of this API). + + **Assumptions** + + Each individual transaction in the bulk transaction is assumed to be successful in the `Payee FSP`, and the validation of the fulfilments is also assumed to be correct. If one or more of the transactions in the bulk transaction were unsuccessful, the earlier reserved transfer in the `Payer FSP` would need to be updated with the total amount of all successful transactions before being committed. + + **End of loop for each `Payee FSP`** + +20. **Description** + + After each of the `Payee FSP`s has executed their part of the bulk transaction, a response is sent to the Payer using a front- end API (out of scope for this API). + + **Assumptions** + + None. + +21. **Description** + + The `Payer` receives a bulk transaction notification containing information about the successfully performed bulk transaction. + + **Assumptions** + + None. + +## References + +1 [https://interledger.org/rfcs/0011-interledger-payment-request/ - Interledger Payment Request (IPR)](https://interledger.org/rfcs/0011-interledger-payment-request) + +2 [https://interledger.org/ - Interledger](https://interledger.org) + +3 [https://interledger.org/interledger.pdf - A Protocol for Interledger Payments](https://interledger.org/interledger.pdf) + +4 [https://interledger.org/rfcs/0001-interledger-architecture/ - Interledger Architecture](https://interledger.org/rfcs/0001-interledger-architecture) + + + +**List of Figures** + +[Figure 1 -- Payer-Initiated Transaction](#443-business-process-sequence-diagram) + +[Figure 2 -- Payee-Initiated Transaction](#423-business-process-sequence-diagram) + +[Figure 3 -- Payee-Initiated Transaction using OTP](#433-business-process-sequence-diagram) + +[Figure 4 -- Bulk Transaction](#443-business-process-sequence-diagram) diff --git a/website/versioned_docs/v1.0.1/api/fspiop/glossary.md b/website/versioned_docs/v1.0.1/api/fspiop/glossary.md new file mode 100644 index 000000000..84ac44885 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/glossary.md @@ -0,0 +1,282 @@ +# Glossary + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information. + +| **Type of Information** | **Convention** | **Example** | +| :--- | :--- | :--- | +| **Elements of the API, such as resources** | Boldface | **/authorization** | +| **Variables** | Italics within curled brackets | _{ID}_ | +| **Glossary** | Italics on first occurrence; defined in _Glossary_ | The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of **terms** electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP. | +| **Library documents** | Italics | User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +| **Version** | **Date** | **Change Description** | +| :--- | :--- | :--- | +| **1.0** | 2018-03-13 | Initial version | + +
    + +## Introduction + +This document provides the glossary for the Open API for FSP Interoperability Specification. Terms have been compiled from three sources: + +- ITU-T Digital Financial Services Focus Group Glossary (ITU-T)[ITU-T Digital Financial Services Focus Group Glossary (ITU-T)](https://www.itu.int/dms_pub/itu-t/opb/tut/T-TUT-ECOPO-2018-PDF-E.pdf), + +- Feedback from Technology Service Providers (TSPs) in the Product Development Partnership (PDP) work groups, and + +- Feedback from the L1P IST Reference Implementation team (RI). + +Information is shared in accordance with Creative Commons Licensing[LICENSE](https://github.com/mojaloop/mojaloop-specification/blob/master/LICENSE.md). + + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](./logical-data-model) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](./json-binding-rules) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](./v1.1/signature) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](#) + +
    + + +## API Glossary + +| **Term** | **Alternative and Related Terms** | **Definition** | **Source** | +| --- | --- | --- | --- | +| **Access Channel** | POS ("Point of Sale"), Customer Access Point, ATM, Branch, MFS Access Point | Places or capabilities that are used to initiate or receive a payment. Access channels can include bank branch offices, ATMs, terminals at the POS, agent outlets, mobile phones, and computers. | ITU-T | +| **Account ID** | | A unique identifier assigned by the FSP that created the account. | PDP | +| **Account Lookup System** | | Account Lookup System is an abstract entity used for retrieving information regarding in which FSP an account, wallet, or identity is hosted. The Account Lookup System itself can be hosted in its own server, as part of a financial switch, or in the different FSPs. | PDP | +| **Active User** | | A term used by many providers in describing how many of their account holders are frequent users of their service. | +| **Agent** | Agent Til , Agent Outlet | An entity authorized by the provider to handle various functions such as customer enrollment, cash-in and cash-out using an agent til . | ITU-T | +| **Agent Outlet** | Access Point | A physical location that carries one or more agent tills, enabling it to perform enrollment, cash-in, and cash-out transactions for customers on behalf of one or more providers. National law defines whether an agent outlet may remain exclusive to one provider. Agent outlets may have other businesses and support functions. | ITU-T | +| **Agent Till** | Registered Agent | An agent till is a provider-issued registered “line”, either a special SIM card or a POS machine, used to perform enrollment, cash-in and cash-out transactions for clients. National law dictates which financial service providers can issue agent tills. | ITU-T | +| **Aggregator** | Merchant Aggregator | A specialized form of a merchant services provider, who typically handles payment transactions for a large number of small merchants. Scheme rules often specify what aggregators are allowed to do. | ITU-T | +| **Anti-Money Laundering** | AML; also "Combating the Financing of Terrorism", or CFT | Initiatives to detect and stop the use of financial systems to disguise the use of funds that have been criminally obtained. | ITU-T | +| **API** | Application Programming Interface | A set of clearly defined methods of communication to allow interaction and sharing of data between different software programs. |PDP | +| **Arbitration** | | The use of an arbitrator, rather than courts, to resolve disputes. | ITU-T | +| **Authentication** | Verification, Validation | The process of ensuring that a person or a transaction is valid for the process (account opening, transaction initiation, and so on) being performed. | ITU-T | +| **Authorization** | | A process used during a "pull" payment (such as a card payment), in which the payee requests (through their provider) confirmation from the payer's bank that the transaction is good. | ITU-T | +| **Authorized /institution entity** | | Non-financial institutions that have followed the appropriate authorization by State Bank and/or relevant regulatory authorities to partake in the provisioning of mobile financial services. | PDP | +| **Automated Clearing House** | ACH | An electronic clearing system in which payment orders are exchanged among payment service providers, primarily via magnetic media or telecommunications networks, and then cleared amongst the participants. All operations are handled by a data processing center. An ACH typically clears credit transfers and debit transfers, and in some cases also cheques. | ITU-T | +| **Bank** | Savings Bank, Credit Union, Payments Bank | A chartered financial system within a country that has the ability to ITU-T accept deposits and make and receive payments into customer accounts. | ITU-T | +| **Bank Accounts and Transaction Services** | Mobile Banking, Remote Banking, Digital Banking| A transaction account held at a bank. This account may be accessible by ITU-T a mobile phone, in which case it is sometimes referred to as "mobile banking".| ITU-T | +| **Bank-Led Model** | Bank-Centric Model| A reference to a system in which banks are the primary providers of digital financial services to end users. National law may require this. | ITU-T | +| **Basic Phone** | | Minimum device required to use digital financial services. | PDP | +| **Bill Payment** | C2B, Utility Payments, School Payments | Making a payment for a recurring service, either in person ("face to face") or remotely. | ITU-T | +| **Biometric Authentication** | | The use of a physical characteristic of a person (fingerprint, IRIS, and so on) to authenticate that person. | ITU-T | +| **Biometric Authentication** | | Any process that validates the identity of a user who wishes to sign into a system by measuring some intrinsic characteristic of that user. | ITU-T | +| **Blacklist** | | A list or register of entities (registered users) that are being denied/blocked from a particular privilege, service, mobility, access or recognition. Entities on the list will not be accepted, approved and or recognized. It is the practice of identifying entities that such entities are denied, unrecognized, or ostracized. Where entities are registered users (or user accounts, if granularity allows) and services are informational (for example, balance check), transactional (for example, debit/credit) payments services or lifecycle (for example, registration, closure) services. | PDP | +| **Blockchain** | Digital Currency, Cryptocurrency, Distributed Ledger Technology| The technology underlying bitcoin and other cryptocurrencies—a shared digital ledger, or a continually updated list of all transactions.| ITU-T | +| **Borrowing** | | Borrowing money to finance a short-term or long-term need. | ITU-T | +| **Bulk Payments** | G2C, B2C, G2P, Social Transfers| Making and receiving payments from a government to a consumer: benefits, cash transfers, salaries, pensions, and so on | ITU-T | +| **Bulk Payment Services** | | A service which allows a government agency or an enterprise to make payments to a large number of payees - typically consumers but can be businesses as well | ITU-T | +| **Bulk upload service** | | A service allowing the import of multiple transactions per session, most often via a bulk data transfer file which is used to initiate payments. Example: salary payment file. | ITU-T | +| **Bundling** | Packaging, Tying | A business model in which a provider which groups a collection of services into one product which an end user agrees to buy or use.| ITU-T | +| **Business** | | Entity such as a public limited or limited company or corporation that uses mobile money as a service; for example, making and accepting bill payments and disbursing salaries.| PDP | +| **Cash Management** | Agent Liquidity Management | Management of cash balances at an agent. | ITU-T | +| **Cash-In** | CICO (Cash-In Cash-Out) | Receiving eMoney credit in exchange for physical cash - typically done at an agent. | ITU-T | +| **Cash-Out** | CICO (Cash-In Cash-Out) | Receiving physical cash in exchange for a debit to an eMoney account - typically done at an agent. | ITU-T | +| **Certificate Signing Request** | CSR | Message sent from an applicant to a Certificate Authority in order to apply for a digital identity certificate. | | +| **Chip Card** | EMV Chip Card, Contactless Chip Card | A chip card contains a computer chip: it may be either contactless or contact (requires insertion into terminal). Global standards for chip cards are set by EMV. | ITU-T | +| **Clearing** | | The process of transmitting, reconciling, and, in some cases, confirming transactions prior to settlement, potentially including the netting of transactions and the establishment of final positions for settlement. Sometimes this term is also used (imprecisely) to cover settlement. For the clearing of futures and options, this term also refers to the daily balancing of profits and losses and the daily calculation of collateral requirements. | RI | +| **Clearing House** | | A central location or central processing mechanism through which financial institutions agree to exchange payment instructions or other financial obligations (for example, securities). The institutions settle for items exchanged at a designated time based on the rules and procedures of the clearinghouse. In some cases, the clearinghouse may assume significant counterparty, financial, or risk management responsibilities for the clearing system.| ITU-T | +| **Client Authentication** | TLS | A client authentication certificate is a certificate used to authenticate clients during an SSL handshake. It authenticates users who access a server by exchanging the client authentication certificate. ... This is to verify that the client is who they claim to be (Source: Techopedia). | | +| **Closed-Loop** | | A payment system used by a single provider, or a very tightly constrained group of providers.| ITU-T | +| **Combatting Terrorist Financing** | | Initiatives to detect and stop the use of financial systems to transfer funds to terrorist organizations or people. | ITU-T | +| **Commission** | | An incentive payment made, typically to an agent or other intermediary who acts on behalf of a DFS provider. Provides an incentive for agent. | ITU-T | +| **Commit** | | Part of a 2-phase transfer operation in which the funds that were reserved to be transferred, are released to the payee; the transfer is completed between the originating/payer and destination/payee accounts. | PDP | +| **Condition** | | In the Interledger protocol, a cryptographic lock used when a transfer is reserved. Usually in the form of a SHA-256 hash of a secret preimage. When provided as part of a transfer request the transfer must be reserved such that it is only committed if the fulfillment of the condition (the secret preimage) is provided. | PDP | +| **Counterparty** | Payee, Payer, Borrower, Lender | The other side of a payment or credit transaction. A payee is the counterparty to a payer, and vice-versa. | ITU-T | +| **Coupon** | | A token that entitles the holder to a discount or that may be exchanged for goods or services.| PDP | +| **Credit History** | Credit Bureaus, Credit Files | A set of records kept for an end user reflecting their use of credit, including borrowing and repayment. | ITU-T | +| **Credit Risk Management** | | Tools to manage the risk that a borrower or counterparty will fail to meet its obligations in accordance with agreed terms. | ITU-T | +| **Credit Scoring** | | A process which creates a numerical score reflecting credit worthiness. | ITU-T | +| **Cross Border Trade Finance Services** | | Services which enable one business to sell or buy to businesses or individuals in other countries; may include management of payments transactions, data handling, and financing. | ITU-T | +| **Cross-FX Transfer** | | Transfer involving multiple currencies including a foreign exchange calculation.| PDP | +| **Customer Database Management** | | The practices that providers do to manage customer data: this may be enabled by the payment platform the provider is using. | ITU-T | +| **Customer Financial Data** | Customer Financial Data | Means a set of financial information of the customer, which includes account balances, deposits and data relating to financial transactions, and so on | PDP | +| **Data Controller** | Data Controller | Data Controller shall mean any person, public authority, agency or any other body which alone or jointly with others determines the purposes and means of the processing of personal data; where the purposes and means of processing are determined by national or Community laws or regulations, the controller or the specific criteria for his nomination may be designated by national or Community law. Also, Data Controller is responsible for providing a secure infrastructure in support of the data, including, but not limited to, providing physical security, backup and recovery processes, granting authorized access privileges and implementing and administering controls. | PDP | +| **Data Portability** | Data Portability | Data Portability shall mean a data subject’s ability to request a copy of personal data being processed in a format usable by this person and be able to transmit it electronically to another processing system | PDP | +| **Data Protection** | PCI-DSS | The practices that enterprises do to protect end user data and credentials. "PCI-DSS" is a card industry standard for this. | ITU-T | +| **Deposit Guarantee System** | Deposit Insurance | A fund that insures the deposits of account holders at a provider; often a government function used specifically for bank accounts. | ITU-T | +| **Diffie-Hellman solution** | | A secure mechanism for exchanging a shared symmetric key between two anonymous peers. | | +| **Digital Financial Services** | DFS, Mobile Financial Services | Digital financial services include methods to electronically store and transfer funds; to make and receive payments; to borrow, save, insure and invest; and to manage a person's or enterprise's finances. | ITU-T | +| **Digital Liquidity** | | A state in which a consumer willing to leave funds (eMoney or bank deposits) in electronic form, rather than performing a "cash-out". | ITU-T | +| **Digital Payment** | Mobile Payment, Electronic Funds Transfer | A broad term including any payment which is executed electronically. Includes payments which are initiated by mobile phone or computer. Card payments in some circumstances are considered to be digital payments. The term "mobile payment" is equally broad and includes a wide variety of transaction types which in some way use a mobile phone. | ITU-T | +| **Dispute Resolution** | | A process specified by a provider or by the rules of a payment scheme to resolve issues between end users and providers, or between an end user and its counter party. | ITU-T | +| **Electronic consent** | Electronic consent |Any sound, symbol, or process which is:
    1. Related to technology
      a. Having electrical, digital, magnetic, wireless, optical, electromagnetic, or similar capabilities, including (but not limited to) mobile telephone, facsimile and internet and
      b. Which may only be accessed through a security access code, and


    2. Logically associated with a legally binding agreement or authorization and executed or adopted by a person with the intent to be bound by such agreement or authorization.
    | PDP | +| **Electronic Invoicing, ERP, Digital Accounting, Supply Chain Solutions, Services, Business Intelligence** | | Services which support merchant or business functions relating to DFS services. | ITU-T | +| **eMoney** |eFloat, Float, Mobile Money, Electronic Money, Prepaid Cards, Electronic Funds | A record of funds or value available to a consumer stored on a payment device such as chip, prepaid cards, mobile phones or on computer systems as a non-traditional account with a banking or non-banking entity. | ITU-T | +| **eMoney Accounts and Transaction Services** | Digital Wallet, Mobile Wallet, Mobile Money Account |A transaction account held at a non-bank. The value in such an account is referred to as eMoney. | ITU-T | +| **eMoney Issuer** | Issuer, Provider | A provider (bank or non-bank) who deposits eMoney into an account they establish for an end user. eMoney can be created when the provider receives cash ("cash-in") from the end user (typically at an agent location) or when the provider receives a digital payment from another provider. | ITU-T | +| **Encryption** |Decryption | The process of encoding a message so that it can be read only by the sender and the intended recipient. | ITU-T | +| **End User** |Consumer, Customer, Merchant, Biller | The customer of a digital financial services provider: the customer may be a consumer, a merchant, a government, or another form of enterprise. | ITU-T | +| **External Account** | | An account hosted outside the FSP, regularly accessible by an external provider interface API. | PDP | +| **FATF** | | The Financial Action Task Force is an intergovernmental organization to combat money laundering and to act on terrorism financing. | ITU-T | +| **Feature Phone** | |A mobile telephone without significant computational . | ITU-T | +| **Fees** | | The payments assessed by a provider to their end user. This may either be a fixed fee, a percent-of-value fee, or a mixture. A Merchant Discount Fee is a fee charged by a Merchant Services Provider to a merchant for payments acceptance. Payments systems or schemes, as well as processors, also charge fees to their customer (typically the provider.) | ITU-T | +| **Financial Inclusion** | | The sustainable provision of affordable digital financial services that bring the poor into the formal economy.| ITU-T | +| **Financial Literacy** | |Consumers and businesses having essential financial skills, such as preparing a family budget or an understanding of concepts such as the time value of money, the use of a DFS product or service, or the ability to apply for such a service. | ITU-T | +| **FinTech** | |A term that refers to the companies providing software, services, and products for digital financial services: often used in reference to newer technologies. | ITU-T | +| **Float** | |This term can mean a variety of different things. In banking, float is created when one party's account is debited or credited at a different time than the counterparty to the transaction. eMoney, as an obligation of a non-bank provider, is sometimes referred to as float. | ITU-T | +| **Fraud** | Fraud Management, Fraud Detection, Fraud Prevention | Criminal use of digital financial services to take funds from another individual or business, or to damage that party in some other way. | ITU-T | +| **Fraud Risk Management** | | Tools to manage providers' risks, and at times user's risks (for example, for merchants or governments) in providing and/or using DFS services. | ITU-T | +| **FSP** | Provider, Financial Service Provider (FSP), Payment Service Provider, Digital Financial Services Provider (DFSP) | The entity that provides a digital financial service to an end user (either a consumer, a business, or a government.) In a closed-loop payment system, the Payment System Operator is also the provider. In an open- loop payment system, the providers are the banks or non-banks which participate in that system. | ITU-T | +| **FSP On-boarding** | | The process of adding a new FSP to this financial network. | RI | +| **Fulfillment** | | In the Interledger protocol, a secret that is the preimage of a SHA-256 hash, used as a condition on a transfer. The preimage is required in the commit message to trigger the transfer to be committed.| PDP | +| **FX** | | Foreign Exchange | PDP | +| **Government Payments Acceptance Services** | | Services which enable governments to collect taxes and fees from individuals and businesses. | ITU-T | +| **HCE** | | Host Card Emulation. A communication technology that enables payment data to be safely stored without using the Secure Element in the phone. | ITU-T | +| **Identity** | National Identity, Financial Identity, Digital Identity |A credential of some sort that identifies an end user. National identities are issued by national governments. In some countries a financial identity is issued by financial service providers. | ITU-T | +| **Immediate Funds Transfer** | Real Time | A digital payment which is received by the payee almost immediately upon the payer having initiated the transaction | ITU-T | +| **Insurance Products** | | A variety of products which allow end user to insure assets or lives that they wish to protect.| ITU-T | +| **Insuring Lives or assets** | | Paying to protect the value of a life or an asset. | ITU-T | +| **Interchange** | Swipe Fee, Merchant Discount Fee | A structure within some payments schemes which requires one provider to pay the other provider a fee on certain transactions. Typically used in card schemes to effect payment of a fee from a merchant to a consumer's card issuing bank. | ITU-T | +| **Interledger** | | The Interledger protocol is a protocol for transferring monetary value across multiple disconnected payment networks using a choreography of conditional transfers on each network. | PDP | +| **International Remittance** | P2P; Remote Cross-Border Transfer of Value, Cross-Border Remittance | Making and receiving payments to another person in another country. | ITU-T | +| **Interoperability** | Interconnectivity | When payment systems are interoperable, they allow two or more proprietary platforms or even different products to interact seamlessly. The result is the ability to exchange payments transactions between and among providers. This can be done by providers participating in a scheme, or by a variety of bilateral or multilateral arrangements. Both technical and business rules issues need to be resolved for interoperability to work. | ITU-T | +| **Interoperability Service for Transfers (IST)** | Switch | An entity which receives transactions from one provider and routes those transactions on to another provider. A switch may be owned or hired by a scheme or be hired by individual providers. A switch may connect to a settlement system for inter-participant settlement and could also implicitly host other services - such as a common account locator service. | ITU-T | +| **Interoperability settlement bank** | | Entity that facilitates the exchange of funds between the FSPs. The settlement bank is one of the main entities involved in any inter-FSP transaction. | PDP | +| **Investment Products** | | A variety of products which allow end users to put funds into investments other than a savings account.| ITU-T | +| **Irrevocable** | |A transaction that cannot be "called back" by the payer; an irrevocable payment, once received by a payee, cannot be taken back by the payer. | ITU-T | +| **JSON** | JavaScript Object Notation | JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999 (Source: www.json.org). | | +| **Know Your Customer** | KYC, Agent and Customer Due Diligence, Tiered KYC, Zero Tier | The process of identifying a new customer at the time of account opening, in compliance with law and regulation. The identification requirements may be lower for low value accounts ("Tiered KYC"). The term is also used in connection with regulatory requirements for a provider to understand, on an ongoing basis, who their customer is and how they are using their account. | ITU-T | +| **Liability** | Agent Liability, Issuer Liability, Acquirer Liability | A legal obligation of one party to another; required by either national law, payment scheme rules, or specific agreements by providers. Some scheme rules transfer liabilities for a transaction from one provider to another under certain conditions. | ITU-T | +| **Liquidity** | Agent Liquidity | The availability of liquid assets to support an obligation. Banks and non-bank providers need liquidity to meet their obligations. Agents need liquidity to meet cash-out transactions by consumers and small merchants.| ITU-T | +| **Loans** | Microfinance, P2P Lending, Factoring, Cash Advances, Credit, Overdraft, Facility | Means by which end users can borrow money. | ITU-T | +| **M2C** | | Merchant to Customer or Consumer. | PDP | +| **mCommerce** | eCommerce | Refers to buying or selling in a remote fashion: by phone or tablet (mCommerce) or by computer (eCommerce). | ITU-T | +| **Merchant** | Payments Acceptor | An enterprise which sells goods or services and receives payments for such goods or services. | ITU-T | +| **Merchant Acquisition** | Onboarding | The process of enabling a merchant for the receipt of electronic payments.| ITU-T | +| **Merchant payment - POS** | C2B, Proximity Payments | Making a payment for a good or service in person ("face to face"); includes kiosks and vending machines. | ITU-T | +| **Merchant payment - Remote** |C2b, eCommerce Payment, Mobile Payment | Making a payment for a good or service remotely; transacting by phone, computer, and so on | ITU-T | +| **Merchant Payments Acceptance Services** | Acquiring Services | A service which enables a merchant or other payment acceptor to accept one or more types of electronic payments. The term "acquiring" is typically used in the card payments systems. | ITU-T | +| **Merchant Service Provider** | Acquirer | A provider (bank or non-bank) who supports merchants or other payments acceptors requirements to receive payments from customers. The term "acquirer" is used specifically in connection with acceptance of card payments transactions. | ITU-T | +| **Mobile Network Operator** | MNO | An enterprise which sells mobile phone services, including voice and data communication. | ITU-T | +| **Money Transfer Operator** | | A specialized provider of DFS who handles domestic and/or international remittances. | ITU-T | +| **MSISDN** | | Number uniquely identifying a subscription in a mobile phone network. These numbers use the E.164 standard that defines numbering plan for a world-wide public switched telephone network (PSTN).| RI | +| **Mutual Authentication** | TLS | Mutual authentication or two-way authentication refers to two parties authenticating each other at the same time, being a default mode of authentication in some protocols (IKE, SSH) and optional in others (TLS) (Source: Wikipedia). | | +| **Near Field Communication** | NFC | A communication technology used within payments to transmit payment data from an NFC equipped mobile phone to a capable terminal.| ITU-T | +| **Netting** | | The offsetting of obligations between or among participants in the settlement arrangement, thereby reducing the number and value of payments or deliveries needed to settle a set of transactions.| RI | +| **Non-Bank** | Payments Institution, Alternative Lender | An entity that is not a chartered bank, but which is providing financial services to end users. The requirements of non-banks to do this, and the limitations of what they can do, are specified by national law| ITU-T | +| **Non-Bank-Led Model** | MNO-Led Model | A reference to a system in which non-banks are the providers of digital financial services to end users. Non-banks typically need to meet criteria established by national law and enforced by regulators.| ITU-T | +| **Non-repudiation** | | Ability to prove the authenticity of a transaction, such as by validating a digital signature.| PDP | +| **Nostro Account** | | From the Payer's perspective: Payer FSP funds/accounts held/hosted at Payee FSP.| PDP | +| **Notification** | | Notice to a payer or payee regarding the status of transfer. |PDP | +| **Off-Us Payments** | Off-Net Payments | Payments made in a multiple-participant system or scheme, where the payer's provider is a different entity as the payee's provider. | ITU-T | +| **On-Us Payments** | On-Net Payments | Payments made in a multiple-participant system or scheme, where the payer's provider is the same entity as the payee's provider. | ITU-T | +| **Open-Loop** | | A payment system or scheme designed for multiple providers to participate in. Payment system rules or national law may restrict participation to certain classes of providers.| ITU-T | +| **Operations Risk Management** | | Tools to manage providers' risks in operating a DFS system. | ITU-T | +| **Organization** | Business | An entity such as a business, charity or government department that uses mobile money as a service; for example, taking bill payments, making bill payments and disbursing salaries. | PDP | +| **OTP** | One-Time Password | OTP is a credential which by definition can only be used once. It is generated and later validated by the same FSP for automatic approval. The OTP is usually tied to a specific Payer in a Payment. The generated OTP is usually a numeric between 4 and 6 digits. | PDP | +| **Over The Counter Services** | OTC, Mobile to Cash | Services provided by agents when one end party does not have an eMoney account: the (remote) payer may pay the eMoney to the agent's account, who then pays cash to the non- account holding payee. | ITU-T | +| **P2P** | Domestic Remittance, Remote Domestic Transfer of Value| Making and receiving payments to another person in the same country. | ITU-T | +| **Participant** | | A provider who is a member of a payment scheme, and subject to that scheme's rules.| ITU-T | +| **Partner Bank** | | Financial institution supporting the FSP and giving it access to the local banking ecosystem. | PDP | +| **Payee** | Receiver | The recipient of electronic funds in a payment transaction. | ITU-T | +| **Payee FSP** | | Payee's Financial Service Provider. | PDP | +| **Payer** | Sender | The payer of electronic funds in a payment transaction. | ITU-T | +| **Payer FSP** | | Payer's Financial Service Provider. | PDP | +| **Paying for Purchases** | C2B - Consumer to Business | Making payments from a consumer to a business: the business is the "payment acceptor” or merchant. | ITU-T | +| **Payment Device** | ATM (Automated Teller Machine), POS (Point of Sale), Access Point, Point of Sale Device | Payment device is the abstract notion of an electronic device, other than the Payer’s own device, that is capable of letting a Payer accept a transaction through the use of a credential (some kind of OTP). Examples of (Payment) Devices are ATM and POS. | PDP | +| **Payment Instruction** | Payment Instruction | An instruction by a sender to a sender’s payment service provider, transmitted orally, electronically, or in writing, to pay, or to cause another payment service provider to pay, a fixed or determinable amount of money to a payee if:
    a) The instruction does not state a condition of payment to the payee other than time of payment; and

    b) The instruction is transmitted by the sender directly to the sender’s payment service provider or to an agent, electronic fund transfers system or communication system for transmittal to the sender’s payment service provider.
    | PDP | +| **Payment System** | Payment Network, Money Transfer System | ncompasses all payment-related activities, processes, mechanisms, infrastructure, institutions and users in a country or a broader region (for example a common economic area). | ITU-T | +| **Payment System Operator** | Mobile Money Operator, Payment Service Provider | The entity that operates a payment system or scheme. | ITU-T | +| **Peer FSP** | | The counterparty financial service provider. | PDP | +| **PEP** | | Politically Exposed Person. Someone who has been entrusted with a prominent public function. A PEP generally presents a higher risk for potential involvement in bribery and corruption by virtue of their position and the influence that they may hold (for example, ‘senior foreign political figure', 'senior political figure', foreign official', and so on).| PDP | +| **Platform** | Payment Platform, Payment Platform Provider, Mobile Money Platform |A term used to describe the software or service used by a provider, a scheme, or a switch to manage end user accounts and to send and receive payment transactions. | ITU-T | +| **Posting** | Clearing | The act of the provider of entering a debit or credit entry into the end user's account record. | ITU-T | +| **Pre-approval** |Debit Authorization, Mandate |Pre-approval means that a Payer is allowing a specific Payee to withdraw funds without the Payer having to manually accept the payment transaction. The pre-approval can be valid one time, valid during a specific time period or valid until the Payer cancels the pre-approval.| PDP | +| **Prefunding** | | The process of adding funds to Vostro/Nostro accounts. | PDP | +| **Prepaid Cards** | |eMoney product for general purpose use where the record of funds is stored on the payment card (on magnetic stripe or the embedded integrated circuit chip) or a central computer system, and which can be drawn down through specific payment instructions to be issued from the bearer’s payment card. | ITU-T | +| **Processing of Personal/Consumer Data** | Processing of Personal/Consumer Data | Processing of personal/consumer data shall mean any operation or set of operations which is performed upon personal/consumer data, whether or not by automatic means, such as collection, recording, organization, storage, adaptation or alteration, retrieval, consultation, use, disclosure by transmission, dissemination or otherwise making available, alignment or combination, blocking, erasure or destruction. | PDP | +| **Processor** | Gateway | An enterprise that manages, on an out-sourced basis, various functions for a digital financial services provider. These functions may include transaction management, customer database management, and risk management. Processors may also do functions on behalf of payments systems, schemes, or switches. | ITU-T | +| **Promotion** | | FSP marketing initiative offering the user a transaction/service fee discount on goods or services. May be implemented through the use of a coupon. | PDP | +| **Pull Payments** | | A payment type which is initiated by the payee: typically, a merchant or payment acceptor, whose provider "pulls" the funds out of the payer's account at the payer's provider. | ITU-T | +| **Push Payments** | |A payment type which is initiated by the payer, who instructs their provider to debit their account and "push" the funds to the receiving payee at the payee's provider. | ITU-T | +| **Quote** | | Quote can be seen as the price for performing a hypothetical financial transaction. Some factors that can affect a Quote are Fees, FX rate, Commission, and Taxes. A Quote is usually guaranteed a short time period, after that the Quote expires and is no longer valid. | PDP | +| **Reconciliation** | | Cross FSP Reconciliation is the process of ensuring that two sets of records, usually the balances of two accounts, are in agreement between FSPs. Reconciliation is used to ensure that the money leaving an account matches the actual money transferred. This is done by making sure the balances match at the end of a particular accounting period. | PDP | +| **Recourse** | | Rights given to an end user by law, private operating rules, or specific agreements by providers, allowing end users the ability to do certain things (sometimes revoking a transaction) in certain circumstances. | ITU-T | +| **Refund** | | A repayment of a sum of money (i.e. repayment, reimbursement or rebate) to a customer returning the goods/services bought. | PDP | +| **Registration** | Enrollment, Agent Registration, User Creation, User On- Boarding | The process of opening a provider account. Separate processes are used for consumers, merchants’ agents, and so on | ITU-T | +| **Regulator** | | A governmental organization given power through national law to set and enforce standards and practices. Central Banks, Finance and Treasury Departments, Telecommunications Regulators, and Consumer Protection Authorities are all regulators involved in digital financial services. | ITU-T | +| **Reserve** | Prepare | Part of a 2-phase transfer operation in which the funds to be transferred are locked (the funds cannot be used for any purpose until either rolled back or committed). This is usually done for a predetermined duration, the expiration of which results in the reservation being rolled back.| PDP | +| **Reversal** | | The process of reversing a completed transfer. | PDP | +| **Risk Management** | Fraud Management | The practices that enterprises do to understand, detect, prevent, and manage various types of risks. Risk management occurs at providers, at payments systems and schemes, at processors, and at many merchants or payments acceptors.| ITU-T | +| **Risk-based Approach** | | A regulatory and/or business management approach that creates different levels of obligation based on the risk of the underlying transaction or customer. | ITU-T | +| **Roll back** | Reject | Roll back means that the electronic funds that were earlier reserved are put back in the original state. The financial transaction is cancelled. The electronic funds are no longer locked for usage.| PDP | +| **Rollback** | | The process of reversing a transaction - restoring the system (i.e. account balances affected by the transaction) to a previously defined state, typically to recover from an error and via an administrator-level user action. | PDP | +| **Rules** | | The private operating rules of a payments scheme, which bind the direct participants (either providers, in an open-loop system, or end users, in a closed-loop system). | ITU-T | +| **Saving and Investing** | | Keeping funds for future needs and financial return. | ITU-T | +| **Savings Products** | | An account at either a bank or non-bank provider, which stores funds with the design of helping end users save money. | ITU-T | +| **Scheme** | | A set of rules, practices and standards necessary for the functioning of payment services. | ITU-T | +| **Secure Element** | | A secure chip on a phone that can be used to store payment data. | ITU-T | +| **Security Access Code** | Security Access Code | A personal identification number (PIN), password/one-time password (OTP), biometric recognition, code or any other device providing a means of certified access to a customer’s account for the purposes of, among other things, initiating an electronic fund transfer. | PDP | +| **Security Level** | | Security specification of the system which defines effectiveness of risk protection. | ITU-T | +| **Sensitive Consumer Data** | Sensitive Consumer Data |Consumer Sensitive Data means any or all information that is used by a consumer to authenticate identity and gain authorization for performing mobile banking services, including but not limited to User ID, Password, Mobile PIN, Transaction PIN. Also includes data relating to religious or other beliefs, sexual orientation, health, race, ethnicity, political views, trades union membership, criminal record. | PDP | +| **Settlement** | Real Time Gross Settlement (RTGS) | An act that discharges obligations in respect of funds or securities transfers between two or more parties. | RI | +| **Settlement Instruction** | | Means an instruction given to a settlement system by a settlement system participant or by a payment clearing house system operator on behalf of a Central Bank settlement system participant to effect settlement of one or more payment obligations, or to discharge any other obligation of one system participant to another system participant.| PDP | +| **Settlement Obligation** | | Means an indebtedness that is owed by one settlement system participant to another as a result of one or more settlement instructions. | PDP | +| **Settlement System** | Net Settlement, Gross Settlement, RTGS | A system used to facilitate the settlement of transfers of funds, assets or financial instruments. Net settlement system: a funds or securities transfer system which settles net settlement positions during one or more discrete periods, usually at pre-specified times in the course of the business day. Gross settlement system: a transfer system in which transfer orders are settled one by one. | ITU-T | +| **Short Message Service** | | A service for sending short messages between mobile phones. | ITU-T | +| **SIM Card** | SIM ToolKit, Thin SIM | A smart card inside a cellular phone, carrying an identification number unique to the owner, storing personal data, and preventing operation if removed. A SIM Tool Kit is a standard of the GSM system which enables various value-added services. A "Thin SIM" is an additional SIM card put in a mobile phone. | ITU-T | +| **Smart Phone** | | A device that combines a mobile phone with a computer. | ITU-T | +| **Standards Body** | EMV, ISO, ITU, ANSI, GSMA | An organization that creates standards used by providers, payments schemes, and payments systems. | ITU-T | +| **Stored Value Account** | SVA | Account in which funds are kept in a secure, electronic format. May be a bank account or an eMoney account. | PDP | +| **Storing Funds** | Account, Wallet, Cash-In, Deposit | Converting cash into electronic money and keeping funds in secure electronic format. May be a bank account or an eMoney account. | PDP | +| **Super-Agent** | Master Agent | In some countries, agents are managed by Super Agents or Master Agents who are responsible for the actions of their agents to the provider. | ITU-T | +| **Supplier Payment** | B2B - Business to Business, B2G - Business to Government | Making a payment from one business to another for supplies, and so on: may be in-person or remote, domestic or cross border. Includes cross- border trade. | ITU-T | +| **Suspicious Transaction Report** | Suspicious Transaction Report | If a financial institution notes something suspicious about a transaction or activity, it may file a report with the Financial Intelligence Unit that will analyze it and cross check it with other information. The information on an STR varies by jurisdiction. | PDP | +| **Systemic Risk** | | In payments systems, the risk of collapse of an entire financial system or entire market, as opposed to risk associated with any one individual provider or end user. | ITU-T | +| **Tax Payment** | C2G, B2G |Making a payment from a consumer to a government, for taxes, fees, and so on | ITU-T | +| **Tokenization** | | The use of substitute a token ("dummy numbers") in lieu of "real" numbers, to protect against the theft and misuse of the "real" numbers. Requires a capability to map the token to the "real" number. | ITU-T | +| **Trading** | International Trade | The exchange of capital, goods, and services across international borders or territories. | ITU-T | +| **Transaction Accounts** | | Transaction account: broadly defined as an account held with a bank or other authorized and/or regulated service provider (including a non- bank) which can be used to make and receive payments. Transaction accounts can be further differentiated into deposit transaction accounts and eMoney accounts. Deposit transaction account: deposit account held with banks and other authorized deposit-taking financial institutions that can be used for making and receiving payments. Such accounts are known in some countries as current accounts, chequing accounts or other similar terms. | ITU-T | +| **Transaction Cost** | | The cost to a DFS provider of delivering a digital financial service. This could be for a bundle of services (for example, a "wallet") or for individual transactions. | ITU-T | +| **Transaction Request** | Payment Request | Transaction Request is a request sent by a Payee, meant for a Payer to transfer electronic funds to the Payee. The Transaction Request usually requires manual approval by the Payer to perform the financial transaction, but the Payee can also be pre-approved or a credential (usually OTP) can be sent as part of the transaction request for automatic validation and approval. | PDP | +| **Transfer** | | Generic term to describe any financial transaction where value is transferred from one account to another. | PDP | +| **Transfer Funds** | Sending or Receiving Funds | Making and receiving payments to another person. | ITU-T | +| **Transport Layer Security** | TLS, client authentication, mutual authentication | Transport Layer Security (TLS) is a cryptographic protocol that provides communications security over a computer network, used to secure point to point communication (Source: Wikipedia). | | +| **Trust Account** | Escrow, Funds Isolation, Funds Safeguarding, Custodian Account, Trust Account | A means of holding funds for the benefit of another party. eMoney Issuers are usually required by law to hold the value of end users' eMoney accounts at a bank, typically in a Trust Account. This accomplishes the goals of funds isolation and funds safeguarding. | ITU-T | +| **Trusted Execution Environment** | | A development execution environment that has security capabilities and meets certain security-related requirements. | ITU-T | +| **Ubiquity** | | The ability of a payer to reach any (or most) payees in their country, regardless of the provider affiliation of the receiving payee. Requires some type of interoperability. | ITU-T | +| **Unbanked** | Underbanked, Underserved| Unbanked people do not have a transaction account. Underbanked people may have a transaction account but do not actively use it. Underserved is a broad term referring to people who are the targets of financial inclusion initiatives. It is also sometimes used to refer to a person who has a transaction account but does not have additional DFS services. | ITU-T | +| **User ID** | | A unique identifier of a user. This may be an MSISDN, bank account, some form of DFSP-provided ID, national ID, and so on. In a transaction, money is generally addressed to a user ID and not directly to an account ID. | PDP | +| **USSD** | | A communication technology that is used to send text between a mobile phone and an application program in the network. | ITU-T | +| **Vostro Account** | | From the Payee's perspective: Payer FSP funds/accounts held/hosted at Payee FSP. | PDP | +| **Voucher** | | A monetary value instrument commonly used to transfer funds to customers (Payees) who do not have an account at the Payer's FSP. This could be Payees with no account or account at another FSP. | ITU-T | +| **Wallet** | eWallet | Repository of funds for an account. Relationship of Wallet to Account can be many to one. | PDP | +| **Whitelist** | | A list or register of entities (registered users) that are being provided a particular privilege, service, mobility, access or recognition, especially those that were initially blacklisted. Entities on the list will be accepted, approved and/or recognized. Whitelisting is the reverse of blacklisting, the practice of identifying entities that are denied, unrecognized, or ostracized. Where entities are registered users (or user accounts, if granularity allows) and services are informational (for example, balance check), transactional (for example, debit/credit) payments services or lifecycle (for example, registration, closure) services. | PDP | +| **'x'-initiated** | | Used when referring to the side that initiated a transaction; for example, agent-initiated cash-out vs. user-initiated cash-out. | PDP | diff --git a/website/versioned_docs/v1.0.1/api/fspiop/json-binding-rules.md b/website/versioned_docs/v1.0.1/api/fspiop/json-binding-rules.md new file mode 100644 index 000000000..a3f524c77 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/json-binding-rules.md @@ -0,0 +1,1286 @@ +--- +showToc: true +--- +# JSON Binding Rules + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| + +## Introduction + +The purpose of this document is to express the data model used by the Open API for FSP Interoperability (hereafter cited as "the API") in the form of JSON Schema binding rules, along with the validation rules for their corresponding instances. + +This document adds to and builds on the information provided in _Open API for FSP Interoperability Specification._ The contents of the Specification are listed in [FSPIOP API Overview](/). + +The types used in the PDP API fall primarily into three categories: + +- Basic data types and Formats used + +- Element types + +- Complex types + +The various types used in _API Definition_, _Data Model_ and the _Open API Specification_, as well as the JSON transformation rules to which their instances must adhere, are identified in the following sections. + +
    + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](./logical-data-model) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](#) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](./v1.1/signature) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](./glossary) + +
    + +## Keywords and Usage + +The _keywords_ used in the JSON Schemas and rules are derived from _JSON Schema Specification_[1](http://json-schema.org/documentation.html). The types of keywords used are identified in [Validation Keywords](#validation-keywords), [Metadata Keywords](#metadata-keywords) and [Instance-and-$ref](#instance-and-$ref) sections. As discussed in detail later, some of these keywords specify validation parameters whereas others are more descriptive, such as Metadata. The description that follows specifies details such as whether a field MUST[2](https://www.ietf.org/rfc/rfc2119.txt) be present in the definition and whether a certain field is associated with a particular data type. + +### Validation Keywords + +This section[3](http://json-schema.org/latest/json-schema-validation.html) provides descriptions of the keywords used for validation in _API Definition_. Validation keywords in a schema impose requirements for successful validation of an instance. + +#### maxLength + +The value of this keyword MUST be a non-negative integer. A string instance is valid against this keyword if its length is less than, or equal to, the value of this keyword. The length of a string instance is defined as the number of its characters as defined by RFC 7159[RFC7159]. + +#### minLength + +The value of this keyword MUST be a non-negative integer. A string instance is valid against this keyword if its length is greater than, or equal to, the value of this keyword. The length of a string instance is defined as the number of its characters as defined by RFC 7159[RFC7159]. Omitting this keyword has the same behaviour as assigning it a value of **0**. + +#### pattern + +The value of this keyword MUST be a string. This string SHOULD be a valid regular expression, according to the ECMA 262 regular expression dialect. A string instance is considered valid if the regular expression matches the instance successfully. Recall: regular expressions are not implicitly anchored. + +#### items + +The value of `items` MUST be either a valid JSON Schema or an array of valid JSON Schemas. This keyword determines how child instances validate for arrays; it does not directly validate the immediate instance itself. If `items` is a schema, validation succeeds if all elements in the array successfully validate against that schema. If `items` is an array of schemas, validation succeeds if each element of the instance validates against the schema at the same position, if such a schema exists. Omitting this keyword has the same behaviour as specifying an empty schema. + +#### maxItems + +The value of this keyword MUST be a non-negative integer. An array instance is valid against `maxItems` if its size is less than, or equal to, the value of this keyword. + +#### minItems + +The value of this keyword MUST be a non-negative integer. An array instance is valid against `minItems` if its size is greater than, or equal to, the value of this keyword. Omitting this keyword has the same behaviour as a value of **0**. + +#### required + +The value of this keyword MUST be an array. Elements of this array (if there are any) MUST be strings and MUST be unique. An object instance is valid against this keyword if every item in the array is the name of a property in the instance. Omitting this keyword results in the same behaviour as does having the array be empty. + +#### properties + +The value of `properties` MUST be an object. Each value of this object MUST be a valid JSON Schema. This keyword determines how child instances validate for objects; it does not directly validate the immediate instance itself. Validation succeeds if, for each name that appears in both the instance and as a name within this keyword's value, the child instance for that name successfully validates against the corresponding schema. Omitting this keyword results in the same behaviour as does having an empty object. + +#### enum + +The value of this keyword MUST be an array. This array SHOULD have at least one element. Elements in the array SHOULD be unique. An instance validates successfully against this keyword if its value is equal to one of the elements in this keyword's array value. Elements in the array might be of any value, including null. + +#### type + +The value of this keyword MUST be either a string or an array. If it is an array, elements of the array MUST be strings and MUST be unique. String values MUST be one of the six primitive types (null, boolean, object, array, number, or string), or integer which matches any number with a zero-fractional part. An instance validates if and only if the instance is in any of the sets listed for this keyword. + +This specification uses string type for all basic types and element types, but enforces restrictions using regular expressions as `patterns`. Complex types are of object type and contain properties that are either element or object types in turn. Array types are used to specify lists, which are currently only used as part of complex types. + +### Metadata Keywords + +This section provides descriptions of the fields used in the JSON definitions of the types used. The description specifies whether a field MUST be present in the definition and specifies whether a certain field is associated with a primary data type. Validation keywords in a schema impose requirements for successful validation of an instance. + +#### definitions + +This keyword's value MUST be an object. Each member value of this object MUST be a valid JSON Schema. This keyword plays no role in validation. Its role is to provide a standardized location for schema authors to incorporate JSON Schemas into a more general schema. + +#### title and description + +The value of both keywords MUST be a string. Both keywords can be used to provide a user interface with information about the data produced by this user interface. A title will preferably be short, whereas a description will provide explanation about the purpose of the instance described in this schema. + +### Instance and $ref + +Two keywords, **Instance** and **$ref** are used in either the JSON Schema definitions or the transformation rules in this document, which are described in [Instance](#instance) and [Schema References with $ref](#schema-references-with-$ref-keyword) sections. `Instance` is not used in the Open API Specification; this term is used in this document to describe validation and transformation rules. `$ref` contains a URI value as a reference to other types; it is used in the Specification. + +#### Instance + +JSON Schema interprets documents according to a data model. A JSON value interpreted according to this data model is called an `instance`[4](http://json-schema.org/latest/json-schema-core.html\#rfc.section.4.2). An instance has one of six primitive types, and a range of possible values depending on the type: + +- **null**: A JSON `null` production. + +- **boolean**: A `true` or `false` value, from the JSON `true` or `false` productions. + +- **object**: An unordered set of properties mapping a string to an instance, from the JSON `object` production. + +- **array**: An ordered list of instances, from the JSON `array` production. + +- **number**: An arbitrary-precision, base-10 decimal number value, from the JSON `number` production. + +- **string**: A string of Unicode code points, from the JSON `string` production. + +Whitespace and formatting concerns are outside the scope of the JSON Schema. Since an object cannot have two properties with the same key, behaviour for a JSON document that tries to define two properties (the `member` production) with the same key (the `string` production) in a single object is undefined. + +#### Schema references with $ref keyword + +The `$ref`[5](http://json-schema.org/latest/json-schema-core.html\#rfc.section.8) keyword is used to reference a schema and provides the ability to validate recursive structures through self- reference. An object schema with a `$ref` property MUST be interpreted as a `"$ref"` reference. The value of the `$ref` property MUST be a URI Reference. Resolved against the current URI base, it identifies the URI of a schema to use. All other properties in a `"$ref"` object MUST be ignored. + +The URI is not a network locator, only an identifier. A schema need not be downloadable from the address if it is a network- addressable URL, and implementations SHOULD NOT assume they should perform a network operation when they encounter a network-addressable URI. A schema MUST NOT be run into an infinite loop against a schema. For example, if two schemas "#alice" and "#bob" both have an "allOf" property that refers to the other, a naive validator might get stuck in an infinite recursive loop trying to validate the instance. Schemas SHOULD NOT make use of infinite recursive nesting like this; the behavior is undefined. + +It is used with the syntax `"$ref"` and is mapped to an existing definition. From the syntax, the value part of `_$ref_`, `#/definitions/`, indicates that the type being referenced is from the Definitions section of the Open API Specification (Typically, an Open API Specification has sections named Paths, Definitions, Responses and Parameters.). An example for this can be found in [Listing 26](#listing-26), where the types for properties _authentication_ and _authenticationValue_ are provided by using references to `Authenticationtype` and `AuthenticationValue` types, respectively. + +### JSON Definitions and Examples + +JSON definitions and examples are provided after most sections defining the transformation rules, where relevant. These are provided in JSON form, taken from the JSON version of the Open API Specification. The Regular Expressions in the examples may have minor differences (sometimes having an additional '**\\**' symbol) when compared to the ones in rules and descriptions because the regular expressions in the examples are taken from the JSON version whereas the rules and descriptions are from the standard Open API (Swagger) Specification. They are provided in the relevant section as a numbered Listing. For example, [Listing 1](#listing-1) provides the JSON representation of the definition of data type `Amount`. + +For each of the data types, a description of the JSON Schema from the Open API Specification and (where relevant) an example of that type are provided. Following the Schema description are transformation rules that apply to an instance of that particular type. + +
    + +## Element and Basic Data Types + +This section contains the definitions of and transformation rules for the basic formats and _element_ types used by the API as specified in _API Definition_ and _API Data Model_. These definitions are basic in the context of the API specification, but *not* the Open API Technical Specification. Often, these basic data types are derived from the basic types supported by Open API Specification standards, such as string type. + +### Data Type Amount + +This section provides the JSON Schema definition for the data type `Amount`. [Listing 1](#listing-1) provides a JSON Schema for the `Amount` type. + +- JSON value pair with Name "**title**" and Value "**Amount**" + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**pattern**" and Value "**^(\[0\]\|(\[1-9\]\[0-9\]{0,17}))(\[.\]\[0-9\]{0,3}\[1-9\])?\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type Amount is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons. This pattern does not allow any trailing zeroes at all, but allows an amount without a minor currency unit. It also only allows four digits in the minor currency unit; a negative value is not allowed. Using more than 18 digits in the major currency unit is not allowed.**" + +##### Listing 1 + + +```JSON +"Amount": { + "title": "Amount", + "type": "string", + "pattern": + "^([0]|([1-9][0-9]{0,17}))([.][0-9]{0,3}[1-9])?$", + "maxLength": 32, + "description": "The API data type Amount is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons." +} +``` +**Listing 1 -- JSON Schema for Data type Amount** + +The transformation rules for an instance of Amount data type are as follows: + +- A given Instance of `Amount` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^(\[0\]\|(\[1-9\]\[0-9\]{0,17}))(\[.\]\[0-9\]{0,3}\[1-9\])?\$** + +- The length of this instance is restricted by the regular expression above as 23, with 18 digits in the major currency unit and four digits in the minor currency unit. Valid example values for Amount type: **124.45**, **5, 5.5, 4.4444, 0.5, 0, 181818181818181818** + +### Data Type BinaryString + +This section provides the JSON Schema definition for the data type BinaryString. [Listing 2](#listing-2) provides a JSON Schema for the BinaryString type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**BinaryString**" + +- JSON value pair with Name "**pattern**" and Value "**^\[A-Za-z0-9-\_\]+\[=\]{0,2}\$**" + +- JSON value pair with Name "**description**" and Value the content of Property **description** + +##### Listing 2 + +```JSON +"BinaryString":{ + "title":"BinaryString", + "type":"string", + "pattern":"^[A-Za-z0-9-_]+[=]{0,2}$", + "description":"The API data type BinaryString is a JSON String. The string is the base64url encoding of a string of raw bytes, where padding (character '=') is added at the end of the data if needed to ensure that the string is a multiple of 4 characters. The length restriction indicates the allowed number of characters. +} +``` +**Listing 2 -- JSON Schema for Data type BinaryString** + +The section on [BinaryString Type IlpPacket](#binarystring-type-ilppacket) gives an example for `BinaryString` type. + +The transformation rules for an instance of `BinaryString` data type are as follows: + +- A given Instance of `BinaryString` type MUST be of string type. +- The instance MUST be a match for the regular expression **^\[A-Za-z0-9-\_\]+\[=\]{0,2}\$** + +An example value for `BinaryString` type is + +``` +AYIBgQAAAAAAAASwNGxldmVsb25lLmRmc3AxLm1lci45T2RTOF81MDdqUUZERmZlakgyOVc4bXFmNEpLMHlGTFGCAUBQU0svMS4wCk5vbmNlOiB1SXlweUYzY3pYSXBFdzVVc05TYWh3CkVuY3J5cHRpb246IG5vbmUKUGF5bWVudC1JZDogMTMyMzZhM2ItOGZhOC00MTYzLTg0NDctNGMzZWQzZGE5OGE3CgpDb250ZW50LUxlbmd0aDogMTM1CkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbgpTZW5kZXItSWRlbnRpZmllcjogOTI4MDYzOTEKCiJ7XCJmZWVcIjowLFwidHJhbnNmZXJDb2RlXCI6XCJpbnZvaWNlXCIsXCJkZWJpdE5hbWVcIjpcImFsaWNlIGNvb3BlclwiLFwiY3JlZGl0TmFtZVwiOlwibWVyIGNoYW50XCIsXCJkZWJpdElkZW50aWZpZXJcIjpcIjkyODA2MzkxXCJ9Ig +``` + +#### BinaryString Type IlpPacket + +This section provides the JSON Schema definition for the `BinaryString` type `IlpPacket`. [Listing 3](listing-3) provides a JSON Schema for the IlpPacket type. The transformation rules for an instance of `IlpPacket` are the same as those of data type `BinaryString`. + + - JSON value pair with Name "**title**" and Value "**IlpPacket**" + + - JSON value pair with Name "**type**" and Value "**string**" + + - JSON value pair with Name "**pattern**" and Value "**^\[A-Za-z0-9-\_\]+\[=\]{0,2}\$**" + + - JSON value pair with Name "**minLength**" and Value **1** + + - JSON value pair with Name "**pattern**" and Value **32768** + + - JSON value pair with Name "**description**" and Value "**Information for recipient (transport layer information).**" + +##### Listing 3 + +```json +"IlpPacket":{ + "title":"IlpPacket", + "type":"string", + "pattern":"^[A-Za-z0-9-_]+[=]{0,2}$", + "minLength":1 + "maxLength":32768 + "description":"Information for recipient (transport layer information)." +} +``` + +**Listing 3 -- JSON Schema for BinaryString type IlpPacket** + +### Data Type BinaryString32 + +This section provides the JSON Schema definition for the data type `BinaryString32`. [Listing 4](#listing-4) provides a JSON Schema for the `BinaryString32` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**BinaryString32**" + +- JSON value pair with Name "**pattern**" and Value "**^\[A-Za-z0-9-\_\]{43}\$**" + +- JSON value pair with Name "**description**" and Value the content of Property **description** + +##### Listing 4 + +```json +"BinaryString32":{ + "title":"BinaryString32", + "type":"string", + "pattern":"^[A-Za-z0-9-_]{43}$", + "description":"The API data type BinaryString32 is a fixed size version of the API data type BinaryString, where the raw underlying data is always of 32 bytes. The data type BinaryString32 should not use a padding character as the size of the underlying data is fixed." +} +``` + +**Listing 4 -- JSON Schema for Data type BinaryString32** + +The section on [BinaryString32 Type IlpCondition](#binarystring32-type-ilpcondition) gives an example for `BinaryString32` type. Another example in the API of `BinaryString32` type is `IlpFulfilment`. The transformation rules for an instance of `BinaryString32` data type are as follows: + +- A given Instance of `BinaryString32` type MUST be of string type. + +- The instance MUST be a match for the regular expression "**^\[A-Za-z0-9-\_\]{43}\$**". + +An example value for `BinaryString32` type is: + +``` +AYIBgQAAAAAAAASwNGxldmVsb25lLmRmc3AxLm1lci45T2RTOF81MDdqUUZERmZlakgyOVc4bXFmNEpLMHlGTFGCAUBQU0svMS4wCk5vbmNlOiB1SXlweUYzY3pYSXBFdzVVc05TYWh3CkVuY3J5cHRpb246IG5vbmUKUGF5bWVudC1JZDogMTMyMzZhM2ItOGZhOC00MTYzLTg0NDctNGMzZWQzZGE5OGE3CgpDb250ZW50LUxlbmd0aDogMTM1CkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbgpTZW5kZXItSWRlbnRpZmllcjogOTI4MDYzOTEKCiJ7XCJmZWVcIjowLFwidHJhbnNmZXJDb2RlXCI6XCJpbnZvaWNlXCIsXCJkZWJpdE5hbWVcIjpcImFsaWNlIGNvb3BlclwiLFwiY3JlZGl0TmFtZVwiOlwibWVyIGNoYW50XCIsXCJkZWJpdElkZW50aWZpZXJcIjpcIjkyODA2MzkxXCJ9IgA +``` + +#### BinaryString32 Type IlpCondition + +This section provides the JSON Schema definition for the `BinaryString32` type `IlpCondition`. [Listing 5](#listing-5) provides a JSON Schema for the `IlpCondition` type. The transformation rules for an instance of `IlpCondition` are the same as those of data type `BinaryString32`. + +- JSON value pair with Name "**title**" and Value "**IlpCondition**" + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**pattern**" and Value "**^\[A-Za-z0-9-\_\]{43}\$**" + +- JSON value pair with Name "**maxLength**" and Value **48** + +- JSON value pair with Name "**description**" and Value "**Condition that must be attached to the transfer by the Payer.**" + +##### Listing 5 + +```json +"IlpCondition":{ + "title":"IlpCondition", + "type":"string", + "pattern":"^[A-Za-z0-9-_]{43}$", + "maxLength":48, + "description":"Condition that must be attached to the transfer by the Payer." +} +``` + +**Listing 5 -- JSON Schema for BinaryString32 type IlpCondition** + +### Data Type BopCode + +This section provides the JSON Schema definition for the data type `BopCode`. [Listing 6](#listing-6) provides a JSON Schema for the `BopCode` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**BalanceOfPayments**" + +- JSON value pair with Name "**pattern**" and Value "**^\[1-9\]\\d{2}\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type BopCode is a JSON String of 3 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. [https://www.imf.org/external/np/sta/bopcode/](https://www.imf.org/external/np/sta/bopcode/).**" + +#### Listing 6 + +```json +"BalanceOfPayments":{ + "title":"BalanceOfPayments", + "type":"string", + "pattern":"^[1-9]\d{2}$", + "description":"(BopCode) The API data type BopCode is a JSON String of 3 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. https://www.imf.org/external/np/sta/bopcode/" +} +``` + +**Listing 6 -- JSON Schema for Data type BopCode** + +The transformation rules for an instance of `BopCode` data type are as follows: + +- A given Instance of `BopCode` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[1-9\]\\d{2}\$**. + +An example value for `BopCode` type is **124**. + +### Data Type Enum + +This section provides the JSON Schema definition for the data type `Enum`. These are generic characteristics of an `Enum` type, alternately known as `CodeSet`. [Listing 8](#listing-8) provides an example JSON Schema for the data type Enumeration (CodeSet). + +- CodeSet.Name is the name of the JSON object. + +- JSON value pair with Name "**title**" and Value "**CodeSet.Name**" + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**enum**" and Value the array containing all the CodeSetLiteral values of the CodeSet + +- If Property description is not empty, JSON value pair with Name "**description**" and Value the content of Property description An example for Enum/CodeSet type -- "AmountType" can found in the [Enumeration AmountType](#enumeration-amounttype) section. [Listing 7](#listing-7) lists the other Enum types defined and used in the API. + +##### Listing 7 + +``` +AuthenticationType, AuthorizationResponse, BulkTransferState, Currency, PartyIdentifier, PartyIdType, PartySubIdOrType , PersonalIdentifierType, TransactionInitiator, TransactionInitiatorType, TransactionRequestState, TransactionScenario, TransactionState, TransferState. +``` + +**Listing 7 -- List of Enum types specified and used in the API** + +The transformation rules for an instance of Enum data type are as +follows: + +- A given Instance of `Enum` type MUST be of string type. + +- The instance MUST be one of the values specified in the `CodeSetLiteral` values. + +#### Enumeration AmountType + +This section provides the JSON Schema definition for the Enum type `AmountType`. [Listing 8](#listing-8) provides a JSON Schema for the `AmountType` type. + +- CodeSet.Name "**AmountType**" + +- JSON value pair with Name "**title**" and Value "**AmountType**" + +- JSON value pair with Name "**type**"and Value "**string**" + +- JSON value pair with Name **description** and Value "**_Below are the allowed values for the enumeration AmountType_** + - **_SEND The amount the Payer would like to send, i.e. the amount that should be withdrawn from the Payer account including any fees._** + - **_RECEIVE The amount the Payer would like the Payee to receive, i.e. the amount that should be sent to the receiver exclusive fees._**" + +- JSON value pair with Name **enum** and Value the array containing the values: + + → **SEND** + + → **RECEIVE** + +###### Listing 8 + +```json +"AmountType":{ + "title":"AmountType", + "type":"string", + "enum":[ + "SEND", + "RECEIVE" + ], + "description":"Below are the allowed values for the enumeration AmountType - SEND The amount the Payer would like to send, i.e. the amount that should be withdrawn from the Payer account including any fees. - RECEIVE The amount the Payer would like the Payee to receive, i.e. the amount that should be sent to the receiver exclusive fees." +} +``` + +**Listing 8 -- JSON Schema for Enumeration Type AmountType** + +The transformation rules for an instance of `AmountType` data type are as follows (same as those of Data Type Enum, but listing the rules here to demonstrate a valid set of literal values): + +- A given Instance of AmountType type MUST be of string type. + +- The instance MUST be one of the values defined in the set: {"**SEND**", "**RECEIVE**"}. + +An example value for `AmountType` type is "**SEND**". + +### Data Type Date + +This section provides the JSON Schema definition for the data type `Date`. [Listing 9](#listing-9) provides a JSON Schema for the `Date` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**Date**" + +- JSON value pair with Name "**pattern**" and Value "**^(?:\[1-9\]\\d{3}-(?:(?:0\[1-9\]\|1\[0-2\])-(?:0\[1-9\]\|1\\d\|2\[0- 8\])\|(?:0\[13-9\]\|1\[0-2\])-(?:29\|30)\|(?:0\[13578\]\|1\[02\])-31)\|(?:\[1- 9\]\\d(?:0\[48\]\|\[2468\]\[048\]\|\[13579\]\[26\])\|(?:\[2468\]\[048\]\|\[13579\]\[26\])00)-02-29)\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type Date is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. This format is according to ISO 8601 containing a date only. A more readable version of the format is "yyyy-MM-dd", e.g. "1982-05-23" or "1987-08- 05"**." + +##### Listing 9 + +```json +"Date": { + "title": "Date", + "type": "string", + "pattern": "^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$", + "description": "The API data type Date is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. This format is according to ISO 8601 containing a date only. A more readable version of the format is “yyyy-MM-dd”, e.g. "1982-05-23" or "1987-08-05”." +} +``` + +**Listing 9 -- JSON Schema for Data type Date** + +The transformation rules for an instance of `Date` data type are as follows: + +- A given Instance of `Date` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^(?:\[1-9\]\\d{3}-(?:(?:0\[1-9\]\|1\[0-2\])-(?:0\[1-9\]\|1\\d\|2\[0- 8\])\|(?:0\[13-9\]\|1\[0-2\])-(?:29\|30)\|(?:0\[13578\]\|1\[02\])-31)\|(?:\[1- 9\]\\d(?:0\[48\]\|\[2468\]\[048\]\|\[13579\]\[26\])\|(?:\[2468\]\[048\]\|\[13579\]\[26\])00)-02-29)\$**. + +An example value for `Date` type is **1971-12-25**. + +#### Data Type DateOfBirth + +This section provides the JSON Schema definition for the Date type `DateOfBirth`. [Listing 10](#listing-10) provides a JSON Schema for the `DateOfBirth` type. The transformation rules for an instance of `DateOfBirth` are the same as those of data type `Date`. + +- JSON value pair with Name "**title**" and Value "**DateOfBirth (type Date)**" + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**description**" and Value "**Date of Birth for the Party**" + +- JSON value pair with Name "**pattern**" and Value "**^(?:\[1-9\]\\d{3}-(?:(?:0\[1-9\]\|1\[0-2\])-(?:0\[1-9\]\|1\\d\|2\[0- 8\])\|(?:0\[13-9\]\|1\[0-2\])-(?:29\|30)\|(?:0\[13578\]\|1\[02\])-31)\|(?:\[1- 9\]\\d(?:0\[48\]\|\[2468\]\[048\]\|\[13579\]\[26\])\|(?:\[2468\]\[048\]\|\[13579\]\[26\])00)-02-29)\$**" + +##### Listing 10 + +```json +"DateOfBirth": { + "title": "DateOfBirth (type Date)", + "type": "string", + "pattern": "^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$", + "description": "Date of Birth for the Party." +} +``` + +**Listing 10 -- JSON Schema for Date type DateOfBirth** + +### Data Type DateTime + +The JSON Schema definition for this section provides the JSON Schema definition for the data type `DateTime`. [Listing 11](#listing-11) provides a JSON Schema for the `DateTime` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**DateTime**" + +- JSON value pair with Name "**pattern**" and Value "**^(?:\[1-9\]\\d{3}-(?:(?:0\[1-9\]\|1\[0-2\])-(?:0\[1-9\]\|1\\d\|2\[0- 8\])\|(?:0\[13-9\]\|1\[0-2\])-(?:29\|30)\|(?:0\[13578\]\|1\[02\])-31)\|(?:\[1- 9\]\\d(?:0\[48\]\|\[2468\]\[048\]\|\[13579\]\[26\])\|(?:\[2468\]\[048\]\|\[13579\]\[26\])00)-02-29)T(?:\[01\]\\d\|2\[0-3\]):\[0-5\]\\d:\[0-5\]\\d(?:(\\.\\d{3}))(?:Z\|\[+-\]\[01\]\\d:\[0-5\]\\d)\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type DateTime is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. This format is according to ISO 8601, expressed in a combined date, time and time zone format. A more readable version of the format is "yyyy-MM-ddTHH:mm:ss.SSS\[-HH:MM\]", e.g. \"2016-05-24T08:38:08.699-04:00\" or \"2016-05-24T08:38:08.699Z\" (where Z indicates Zulu time zone, same as UTC)**." + +##### Listing 11 + +```json +"DateTime": { + "title":"DateTime", + "type": "string", + "pattern": "^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01\d|2[0-3]):[0-5]\d:[0-5]\d(?:(\.\d{3}))(?:Z|[+-][01]\d:[0-5]\\d)$", + "description": "The API data type DateTime is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. This format is according to ISO 8601, expressed in a combined date, time and time zone format. A more readable version of the format is “yyyy-MM-ddTHH:mm:ss.SSS[-HH:MM]”, e.g. "2016-05-24T08:38:08.699-04:00" or "2016-05-24T08:38:08.699Z" (where Z indicates Zulu time zone, same as UTC)." +} +``` + +**Listing 11 -- JSON Schema for Data type DateTime** + +The transformation rules for an instance of DateTime data type are as follows: + +- A given Instance of type `DateTime` MUST be of string type. + +- The instance MUST be a match for the regular expression **^(?:\[1-9\]\\d{3}-(?:(?:0\[1-9\]\|1\[0-2\])-(?:0\[1-9\]\|1\\d\|2\[0-8\])\|(?:0\[13-9\]\|1\[0-2\])-(?:29\|30)\|(?:0\[13578\]\|1\[02\])-31)\|(?:\[1-9\]\\d(?:0\[48\]\|\[2468\]\[048\]\|\[13579\]\[26\])\|(?:\[2468\]\[048\]\|\[13579\]\[26\])00)-02-29)T(?:\[01\]\\d\|2\[0-3\]):\[0-5\]\\d:\[0-5\]\\d(?:(\\.\\d{3}))(?:Z\|\[+-\]\[01\]\\d:\[0-5\]\\d)\$**. + +An example value for `DateTime` type is **2016-05-24T08:38:08.699-04:00**. + +### Data Type ErrorCode + +This section provides the JSON Schema definition for the data type `ErrorCode`. [Listing 12](#listing-12) provides a JSON Schema for the `ErrorCode` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**ErrorCode**" + +- JSON value pair with Name "**pattern**" and Value "**^\[1-9\]\\d{3}\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type ErrorCode is a JSON String of 4 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. Specific error number in the form _{C}{E}{SS}_ where _{C}_ is a one-digit category _{E}_ is a one-digit error within the category _{SS}_ is a scheme defined two-digit sub-error within the error. Please refer to x.x for the list of the possible category/error codes**". + +##### Listing 12 + +```json +"ErrorCode": { + "title": "ErrorCode", + "type": "string", + "pattern": "^[1-9]\d{3}$", + "description": "The API data type ErrorCode is a JSON String of 4 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. Specific error number in the form {C}{E}{SS} where {C} is a one-digit category {E} is a one-digit error within the category {SS} is a scheme defined two-digit sub-error within the error. Please refer to x.x for the list of the possible category/error codes" +} +``` + +**Listing 12 -- JSON Schema for Data type ErrorCode** + +The transformation rules for an instance of `ErrorCode` data type are as follows: + +- A given Instance of `ErrorCode` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[1-9\]\d{3}\$**. + +An example value for `ErrorCode` type is **5100**. + +### Data Type Integer + +This section provides the JSON Schema definition for the data type `Integer`. [Listing 13](#listing-13) provides a JSON Schema for the Integer type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**Integer**" + +- JSON value pair with Name "**pattern**" and Value "**^\[1-9\]\d\*\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type Integer is a JSON String consisting of digits only. Negative numbers and leading zeroes are not allowed. The data type is always limited by a number of digits.**" + +##### Listing 13 + +```json +"Integer": { + "title": "Integer", + "type": "string", + "pattern": "^[1-9]\d*$", + "description": "The API data type Integer is a JSON String consisting of digits only. Negative numbers and leading zeroes are not allowed. The data type is always limited by a number of digits." +} +``` + +**Listing 13 -- JSON Schema for Data type Integer** + +The transformation rules for an instance of `Integer` data type are as follows: + +- A given Instance of Integer type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[1-9\]\d\*\$**. + +An example value for `Integer` type is **12345**. + +### Data Type Latitude + +This section provides the JSON Schema definition for the data type `Latitude`. [Listing 14](#listing-14) provides a JSON Schema for the `Latitude` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**Latitude**" + +- JSON value pair with Name "**pattern**" and Value "**^(\\+\|-)?(?:90(?:(?:\\.0{1,6})?)\|(?:\[0-9\]\|\[1-8\]\[0-9\])(?:(?:\\.\[0-9\]{1,6})?))\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type Latitude is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons**". + +##### Listing 14 + +```json +"Latitude": { + "title": "Latitude", + "type": "string", + "pattern": "^(\+|-)?(?:90(?:(?:\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\.[0-9]{1,6})?))$", + "description": "The API data type Latitude is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons." +} +``` + +**Listing 14 -- JSON Schema for Data type Latitude** + +The transformation rules for an instance of `Latitude` data type are as follows: + +- A given Instance of `Latitude` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^(\\+\|-)?(?:90(?:(?:\\.0{1,6})?)\|(?:\[0-9\]\|\[1-8\]\[0-9\])(?:(?:\\.\[0-9\]{1,6})?))\$**. + +An example value for `Latitude` type is **+45.4215**. + +### Data Type Longitude + +This section provides the JSON Schema definition for the data type `Longitude`. [Listing 15](#listing-15) provides a JSON Schema for the `Longitude` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**Longitude**" + +- If Property pattern is not empty, JSON value pair with Name "**pattern**" and Value "**^(\\+\|-)?(?:180(?:(?:\\.0{1,6})?)\|(?:\[0-9\]\|\[1-9\]\[0-9\]\|1\[0-7\]\[0-9\])(?:(?:\\.\[0-9\]{1,6})?))\$**". + +- JSON value pair with Name "**description**" and Value "**The API data type Longitude is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons.**" + +##### Listing 15 + +```json +"Longitude": { + "title": "Longitude", + "type": "string", + "pattern": "^(\+|-)?(?:180(?:(?:\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.[0-9]{1,6})?))$", + "description": "The API data type Longitude is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons." +} +``` + +**Listing 15 -- JSON Schema for Data type Longitude** + +The transformation rules for an instance of `Longitude` data type are as follows: + +- A given Instance of `Longitude` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^(\\+\|-)?(?:180(?:(?:\\.0{1,6})?)\|(?:\[0-9\]\|\[1-9\]\[0-9\]\|1\[0-7\]\[0-9\])(?:(?:\\.\[0-9\]{1,6})?))\$**. + +An example value for `Longitude` type is **+75.6972**. + +### Data Type MerchantClassificationCode + +This section provides the JSON Schema definition for the data type `MerchantClassificationCode`. [Listing 16](#listing-16) provides a JSON Schema for the `MerchantClassificationCode` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**MerchantClassificationCode**" + +- JSON value pair with Name "**pattern**" and Value "**^\[\\d\]{1,4}\$**". + +- JSON value pair with Name "**description**" and Value "**A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, etc.**" + +##### Listing 16 + +```json +"MerchantClassificationCode": { + "title": "MerchantClassificationCode", + "type": "string", + "pattern": "^[\d]{1,4}$", + "description": "A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, etc." +} +``` + +**Listing 16 -- JSON Schema for Data type MerchantClassificationCode** + +The transformation rules for an instance of `MerchantClassificationCode` data type are as follows: + +- A given Instance of `MerchantClassificationCode` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[\\d\]{1,4}\$**. + +An example value for `MerchantClassificationCode` type is **99**. + +### Data Type Name + +This section provides the JSON Schema definition for the data type `Name`. [Listing 17](#listing-17) provides the JSON Schema for a `Name` type. [Name Type Firstname](#name-type-firstname) contains an example of `Name` type -- "First Name". Other Name types used in the API are "Middle Name" and "Last Name". + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**Name**" + +- JSON value pair with Name "**minLength**" and Value the content of Property **minLength** + +- JSON value pair with Name "**maxLength**" and Value the content of Property **maxLength** + +- JSON value pair with Name "**pattern**" and Value "**^(?!\\\\s\*\$)\[\\\\w .,'-\]+\$**". + +- JSON value pair with Name "**description**" and Value "**The API data type Name is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. The restriction will not allow a string consisting of whitespace only, all Unicode characters should be allowed, as well as the characters ".", "'" (apostrophe), "-", "," and " " (space). Note - In some programming languages, Unicode support needs to be specifically enabled. As an example, if Java is used the flag UNICODE\_CHARACTER\_CLASS needs to be enabled to allow Unicode characters.**" + +##### Listing 17 + +```json +"Name": { + "title": "Name", + "type": "string", + "pattern": "^(?!\\s*$)[\\w .,'-]+$", + "description": "The API data type Name is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. The restriction will not allow a string consisting of whitespace only, all Unicode characters should be allowed, as well as the characters ".", "'" (apostrophe), "- ", "," and " " (space). Note - In some programming languages, Unicode support needs to be specifically enabled. As an example, if Java is used the flag UNICODE_CHARACTER_CLASS needs to be enabled to allow Unicode characters." +} +``` + +**Listing 17 -- JSON Schema for Data type Name** + +The transformation rules for an instance of `Name` data type are as follows: + +- A given Instance of `Name` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^(?!\\\\s\*\$)\[\\\\w .,'-\]+\$**. + +An example value for `Name` type is **Bob**. + +#### Name Type FirstName + +This section provides the JSON Schema definition for the `Name` type `FirstName`. [Listing 18](#listing-18) provides a JSON Schema for the `FirstName` type. The transformation rules for an instance of `FirstName` are the same as those of data type `Name`. + +- JSON value pair with Name "**title**" and Value "**FirstName**" + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**pattern**" and Value "**^(?!\\s\*\$)\[\\w .,\'-\]+\$**" + +- JSON value pair with Name "**maxLength**" and Value **128** + +- JSON value pair with Name "**minLength**" and Value **1** + +- JSON value pair with Name "**description**" and Value "**First name of the Party (Name type).**" + +##### Listing 18 + +```json +"FirstName": { + "title": "FirstName", + "type": "string", + "minLength": 1, + "maxLength": 128, + "pattern": "^(?!\s*$)[\w .,'-]+$", + "description": "First name of the Party (Name Type)." +} +``` + +**Listing 18 -- JSON Schema for Name type FirstName** + +### Data Type OtpValue + +This section provides the JSON Schema definition for the data type `OtpValue`. [Listing 19](#listing-19) provides a JSON Schema for the `OtpValue` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**OtpValue**" + +- JSON value pair with Name "**pattern**" and Value "**^\\d{3,10}\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type OtpValue is a JSON String of 3 to 10 characters, consisting of digits only. Negative numbers are not allowed. One or more leading zeros are allowed.**" + +##### Listing 19 + +```json +"OtpValue": { + "title": "OtpValue", + "type": "string", + "pattern": "^\d{3,10}$", + "description": "The API data type OtpValue is a JSON String of 3 to 10 characters, consisting of digits only. Negative numbers are not allowed. One or more leading zeros are allowed." +} +``` + +**Listing 19 -- JSON Schema for Data type OtpValue** + +The transformation rules for an instance of `OtpValue` data type are as follows: + +- A given Instance of `OtpValue` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\\d{3,10}\$**. + +An example value for `OtpValue` type is **987345**. + +### Data Type String + +This section provides the JSON Schema definition for the data type `String`. [Listing 21](#listing-21) provides an example JSON Schema for a `String` type. + +- **String.Name** is the name of the JSON object. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**String.Name**" + +- JSON value pair with Name "**minLength**" and Value the content of Property "**minLength**" + +- JSON value pair with Name "**maxLength**" and Value the content of Property "**maxLength**" + +- If Property pattern is not empty, JSON value pair with Name **pattern** and Value the content of Property **pattern**. + +- JSON value pair with Name "**description**" and Value the content of Property **description**. [Below](#string-type-errordescription), is an example for Stri`ng type, `ErrorDescription`. [Listing 20](#listing-20) has other `String` types specified and used in the API. + +##### Listing 20 + +``` +AuthenticationValue, ExtensionKey, ExtensionValue, FspId, Note, PartyName, QRCODE, RefundReason, TransactionSubScenario. +``` + +**Listing 20 -- String types specified and used in the API** + +The transformation rules for an instance of `String` data type are as follows: + +- A given Instance of `String` type MUST be of string type. + +- The length of this instance MUST not be greater than the **maxLength** specified. + +- The length of this instance MUST not be less than the **minLength** specified. + +- The instance MUST be a match for the regular expression specified by a **pattern** property if one is specified. + +An example value for `String` type is **Financial Services for the Poor**. + +### String Type ErrorDescription + +This section provides the JSON Schema definition for the `String` type `ErrorDescription`. [Listing 21](#listing-21) provides a JSON Schema for the `ErrorDescription` type. + +- JSON value pair with Name "**title**" and Value "**ErrorDescription**" + +- JSON value pair with Name "**type**" and Value "**ErrorDescription**" + +- JSON value pair with Name "**description**" and Value "**Error description string**" + +- JSON value pair with Name "**minLength**" and Value **1** + +- JSON value pair with Name "**maxLength**" and Value **128** + +##### Listing 21 + +```json +"ErrorDescription": { + "title": "ErrorDescription", + "type": "string", + "minLength": 1, + "maxLength": 128, + "description": "Error description string." +} +``` + +**Listing 21 -- JSON Schema for Data type ErrorDescription** + +The transformation rules for an instance of `ErrorDescription` data type are as follows (same as those of `Data` Type String, but listing the rules here to demonstrate a valid set of values for length properties): + +- A given Instance of `ErrorDescription` type MUST be of String Type. + +- The length of this instance MUST not be greater than 128. + +- The length of this instance MUST not be less than 1. + +An example value for `ErrorDescription` type is **This is an error description**. + +### Data Type TokenCode + +This section provides the JSON Schema definition for the data type `TokenCode`. [Listing 22](#listing-22) provides a JSON Schema for the `TokenCode` type. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and Value "**TokenCode**" + +- JSON value pair with Name "**pattern**" and Value "**^\[0-9a-zA-Z\]{4,32}\$**" + +- JSON value pair with Name "**description**" and Value "**The API data type TokenCode is a JSON String between 4 and 32 characters, consisting of digits or characters from a to z (case insensitive).**" + +##### Listing 22 + +```json +"TokenCode": { + "title": "TokenCode", + "type": "string", + "pattern": "^[0-9a-zA-Z]{4,32}$", + "description": "The API data type TokenCode is a JSON String between 4 and 32 characters, consisting of digits or characters from a to z (case insensitive)." +} +``` + +**Listing 22 -- JSON Schema for Data type TokenCode** + +The transformation rules for an instance of `TokenCode` data type are as follows: + +- A given Instance of `TokenCode` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[0-9a-zA-Z\]{4,32}\$**. + +An example value for `TokenCode` type is **Test-Code**. + +#### TokenCode Type Code + +This section provides the JSON Schema definition for the `TokenCode` type `Code`. [Listing 23](#listing-23) provides a JSON Schema for the `Code` type. The transformation rules for an instance of `Code` are the same as those of Data Type `TokenCode`. + +- JSON value pair with Name "**title**" and Value "**Code**" + +- JSON value pair with Name "**type**" and Value "**String**" + +- JSON value pair with Name "**pattern**" and Value "**^\[0-9a-zA-Z\]{4,32}\$**" + +- JSON value pair with Name "**description**" and Value "**Any code/token returned by the Payee FSP (TokenCode type).**" + +##### Listing 23 + +```json +"Code": { + "title": "Code", + "type": "string", + "pattern": "^[0-9a-zA-Z]{4,32}$", + "description": "Any code/token returned by the Payee FSP (TokenCode Type)." +} +``` + +**Listing 23 -- JSON Schema for TokenCode type Code** + +### Data Type UndefinedEnum + +This section provides the JSON Schema definition for the data type `UndefinedEnum`. [Listing 24](#listing-24) provides the JSON Schema for the data type `UndefinedEnum` (Enumeration). + +- JSON value pair with Name "**title**" and Value "**UndefinedEnum**" + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**pattern**" and Value "**^\[A-Z\_\]{1,32}\$**" + +- If Property description is not empty, JSON value pair with Name "**description**" and Value "**The API data type UndefinedEnum is a JSON String consisting of 1 to 32 uppercase characters including "\_" (underscore).**" + +##### Listing 24 + +```json +"UndefinedEnum": { + "title": "UndefinedEnum", + "type": "string", + "pattern": "^[A-Z_]{1,32}$", + "description": "The API data type UndefinedEnum is a JSON String consisting of 1 to 32 uppercase characters including "_" (underscore)." +} +``` + +**Listing 24 -- JSON Schema for Data type UndefinedEnum** + +The transformation rules for an instance of `UndefinedEnum` data type are as follows: + +- A given Instance of UndefinedEnum type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[A-Z\_\]{1,32}\$**. + +An example value for `UndefinedEnum` type depends on the list of values specified. + +### Data Type UUID + +This section provides the JSON Schema definition for the data type `UUID`. [Listing 25](#listing-25) provides a JSON Schema for `CorrelationId` which is of `UUID` type. Since `CorrelationId` is an element type in the *API Definition*, it is being used interchangeably with `UUID` in the Open API Specification version. + +- JSON value pair with Name "**type**" and Value "**string**" + +- JSON value pair with Name "**title**" and "**Value CorrelationId**" + +- JSON value pair with Name "**pattern**" and Value "**^\[0-9a-f\]{8}-\[0-9a-f\]{4}-\[1-5\]\[0-9a-f\]{3}-\[89ab\]\[0-9a-f\]{3}-\[0-9a- f\]{12}\$**" + +- JSON value pair with Name "**description**" and Value "**Identifier that correlates all messages of the same sequence. The API data type UUID (Universally Unique Identifier) is a JSON String in canonical format, conforming to RFC 4122, that is restricted by a regular expression for interoperability reasons. An example of a UUID is "b51ec534-ee48-4575-b6a9-ead2955b8069". An UUID is always 36 characters long, 32 hexadecimal symbols and 4 dashes ("-").**" + +##### Listing 25 + +```json +"CorrelationId": { + "title": "CorrelationId", + "type": "string", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a- f]{12}$", + "description": "Identifier that correlates all messages of the same sequence. The API data type UUID (Universally Unique Identifier) is a JSON String in canonical format, conforming to RFC 4122, that is restricted by a regular expression for interoperability reasons. An example of a UUID is "b51ec534-ee48-4575-b6a9- ead2955b8069". An UUID is always 36 characters long, 32 hexadecimal symbols and 4 dashes ("-")." +} +``` + +**Listing 25 -- JSON Schema for Data type UUID** + +The transformation rules for an instance of `UUID` data type are as follows: + +- A given Instance of `UUID` type MUST be of string type. + +- The instance MUST be a match for the regular expression **^\[0-9a-f\]{8}-\[0-9a-f\]{4}-\[1-5\]\[0-9a-f\]{3}-\[89ab\]\[0-9a- f\]{3}-\[0-9a-f\]{12}\$**. + +An example value for `UUID` type is **b51ec534-ee48-4575-b6a9-ead2955b8069**. + +## Complex Types + +This section contains definitions of and transformation characteristics for complex types that are used by the API. Along with the complex types defined in the [API Definition]() and [Data Model]() documents, there are other complex types defined in the PDP Open API Specification based on the objects present in several requests and responses in the **body** section. These are discussed in the [Types of Objects in Requests or Responses](#types-of-objects-in-requests-or-responses) section. + +### Complex Type Definition, Transformation + +This section provides the JSON Schema definition for a complex type. [Listing 26](#listing-26) provides an example JSON Schema for a complex type, `AuthenticationInfo`. Transformation rules specific to a complex type are listed [here](#complex-type-authenticationinfo). + +- JSON value pair with Name "**type**" and Value "**object**" + +- JSON value pair with Name "**title**" and Value "**complextype.Name**" + +- If Property **description** is not empty, JSON value pair with Name "**description**" and Value the content of Property **description**. + +- An array with Name "**required**" and Value the list of properties that MUST be present in an instance of complex type. + +- A JSON object **properties** with the following content: + + - A list of key, value pairs with Name **key.Name** and Value of element, complex or Array type + + - JSON value pair with Name **$ref** and as Value the concatenation of **#/definitions/** with **key.Type** type. An example for a complex type is provided under the [Complex Type AuthenticationInfo](#complex-type-authenticationinfo) section. + +#### Complex Type AuthenticationInfo + +This section provides the JSON Schema definition for the complex type `AuthenticationInfo` can be expressed as follows. [Listing 26](#listing-26) provides the JSON Schema for `AuthenticationInfo`. + +- JSON value pair with Name "**type**" and Value "**object**" + +- JSON value pair with Name "**title**" and Value "**AuthenticationInfo**" + +- JSON value pair with Name "**description**" and Value "**complex type AuthenticationInfo**" + +- An array with Name "**required**" and as Value a list with elements "**authentication**" and "**authenticationValue**" + +- A JSON object **properties** with the following content: + + - A JSON object **authentication** with the following content: + + - JSON value pair with Name "**$ref**" and as Value the concatenation of **#/definitions/** with Authenticationtype type. + + - A JSON object **authenticationValue** with the following content: + + - JSON value pair with Name "**$ref**" and as Value the concatenation of **#/definitions/** with AuthenticationValue type. + +##### Listing 26 + +```json +"AuthenticationInfo": { + "title": "AuthenticationInfo", + "type": "object", + "description": "complex type AuthenticationInfo", + "properties": { + "authentication": { + "$ref": "#/definitions/AuthenticationType", + "description": "The type of authentication." + }, + "authenticationValue":\ { + "$ref": "#/definitions/AuthenticationValue", + "description": " The authentication value." + } + }, + "required": [ + "authentication", + "authenticationValue" + ] +} +``` + +**Listing 26 -- JSON Schema for complex type AuthenticationInfo** + +The transformation rules for an instance of `AuthenticationInfo` complex type are as follows: + +- A given Instance of AuthenticationInfo type MUST be of `Object` type. + +- The instance MUST contain a property with name **authentication**. + +- The JSON object titled **authentication** MUST be an instance of AuthenticationType type, provided in the definitions. + +- The instance MUST contain a property with name **authenticationValue**. + +- The JSON object titled **authenticationValue** MUST be an instance of AuthenticationValue type, provided in the definitions. An example instance for AuthenticationInfo complex type is given in [Listing 27](#listing-27). + +##### Listing 27 + +```json +"authenticationInfo": { + "authentication": "OTP", + "authenticationValue": "1234" +} +``` + +**Listing 27 -- Example instance of AuthenticationInfo complex type** + +#### Complex Types in the API + +The examples for complex type from the API appear in [Listing 28](#listing-28). The list includes complex types defined in [API Definition]() and [Data Model]() documents and does not contain the complex types defined only in the Open API version of the specification which captures the objects in Requests and Reponses. + +##### Listing 28 + +``` +ErrorInformation, Extension, ExtensionList, GeoCode, IndividualQuote, IndividualQuoteResult, IndividualTransfer, IndividualTransferResult, Money, Party, PartyComplexName, PartyIdInfo, PartyPersonalInfo, PartyResult, Refund, Transaction, TransactionType. +``` + +**Listing 28 -- Complex type Examples** + +### Types of Objects in Requests or Responses + +This section contains the definitions and transformation characteristics of the complex types that are used in the API Specification of the PDP API to capture objects in Requests and Responses. These have the same characteristics as the complex data types discussed in the Complex Type section. + +#### Complex Type AuthorizationsIDPutResponse + +This section provides the JSON Schema definition for the complex type `AuthorizationsIDPutResponse`. [Listing 29](#listing-29) provides a JSON Schema for complex type `AuthorizationsIDPutResponse`. + +- JSON value pair with Name "**type**" and Value "**object**" + +- JSON value pair with Name "**title**" and Value "**AuthorizationsIDPutResponse**". + +- JSON value pair with Name "**description**" and Value "**PUT /authorizations/{ID} object**". + +- A JSON object "**properties**" with the following content: + + - If Property "**authenticationInfo**" is present, a JSON object "**authenticationInfo**" with the following content: + + - JSON value pair with Name "**$ref**" and as Value the definition of AuthenticationInfo type, located under **definitions** as indicated by **#/definitions/** + + - A JSON object **responseType** with the following content: + + - JSON value pair with Name "**$ref**" and as Value the definition of AuthorizationResponse type, located under **definitions** as indicated by "**#/definitions/**". + +- An array **required** and as Value a list with single element "**responseType**" + +##### Listing 29 + +```json +"AuthorizationsIDPutResponse": { + "title": "AuthorizationsIDPutResponse", + "type": "object", + "description": "PUT /authorizations/{ID} object", + "properties": { + "authenticationInfo": { + "$ref": "#/definitions/AuthenticationInfo", + "description": "OTP or QR Code if entered, otherwise empty." + } + "responseType": { + "$ref": "#/definitions/AuthorizationResponse", + "description": "Enum containing response information; if the customer entered the authentication value, rejected the transaction, or requested a resend of the authentication value." + } + }, + "required ": [ + "responseType" + ] +} +``` + +**Listing 29 -- JSON Schema for complex type AuthorizationsIDPutResponse** + +The transformation rules for an instance of `AuthorizationsIDPutResponse` complex type are as follows: + +- A given Instance of `AuthorizationsIDPutResponse` type MUST be of object type. + +- The instance MUST contain a property with name "**authenticationInfo**". + +- The JSON object titled "**authenticationInfo**" MUST be an instance of AuthenticationInfo type, provided in the definitions. + +- The instance MUST contain a property with name "**responseType**". + +- The JSON object titled "**responseType**" MUST be an instance of AuthorizationReponse type, provided in the definitions. + +An example instance for `AuthorizationsIDPutResponse` complex type is given in [Listing 30](#listing-30). + +##### Listing 30 + +```json +{ + "authenticationInfo": { + "authentication": "OTP", + "authenticationValue": "1234" + }, + "responseType": "ENTERED" +} +``` + +**Listing 30 -- Example instance of AuthorizationsIDPutResponse complex type** + +**5.2.2 Other Complex types in Requests and Responses** + +Other complex type examples from the API used in Requests or Responses can be found in [Listing 31](#listing-31). + +##### Listing 31 + +``` +BulkQuotesPostRequest, BulkQuotesIDPutResponse, BulkTransfersPostRequest, BulkTransfersIDPutResponse, ErrorInformationObject, ErrorInformationResponse, ParticipantsTypeIDSubIDPostRequest, ParticipantsTypeIDPutResponse, ParticipantsIDPutResponse, ParticipantsPostRequest, QuotesPostRequest, QuotesIDPutResponse, TransactionRequestsIDPutResponse, TransactionsIDPutResponse, TransfersPostRequest, TransactionRequestsPostRequest, TransfersIDPutResponse. +``` + +**Listing 31 -- Complex type Examples for Objects in Requests and Responses in the API** + +## References + +1 The link for this is: [http://json-schema.org/documentation.html](http://json-schema.org/documentation.html) + +2 MUST, MAY, OPTIONAL in this document are to be interpreted as described\ in [RFC2119](https://www.ietf.org/rfc/rfc2119.txt) + +3 Most of the items in this section and the next one, "Metadata Keywords" are taken from: [http://json-schema.org/latest/json-schema-validation.html](http://json-schema.org/latest/json-schema-validation.html). Some changes are made based on Open API limitations or constraints. Also, only relevant keywords are referenced. + +4 The description for "Instance" keyword is taken from: [http://json-schema.org/latest/json-schema-core.html\#rfc.section.4.2](http://json-schema.org/latest/json-schema-core.html\#rfc.section.4.2) + +5 Meaning and usage of \$ref as specified here: [http://json-schema.org/latest/json-schema-core.html\#rfc.section.8](http://json-schema.org/latest/json-schema-core.html\#rfc.section.8) + + + +## Table of Listings + +[Listing 1 -- JSON Schema for Data type Amount](#listing-1) + +[Listing 2 -- JSON Schema for Data type BinaryString](#listing-2) + +[Listing 3 -- JSON Schema for BinaryString type IlpPacket](#listing-3) + +[Listing 4 -- JSON Schema for Data type BinaryString32](#listing-4) + +[Listing 5 -- JSON Schema for BinaryString32 type IlpCondition](#listing-5) + +[Listing 6 -- JSON Schema for Data type BopCode](#listing-6) + +[Listing 7 -- List of Enum types specified and used in the API](#listing-7) + +[Listing 8 -- JSON Schema for Enumeration Type AmountType](#listing-8) + +[Listing 9 -- JSON Schema for Data type Date](#listing-9) + +[Listing 10 -- JSON Schema for Date type DateOfBirth](#listing-10) + +[Listing 11 -- JSON Schema for Data type DateTime](#listing-11) + +[Listing 12 -- JSON Schema for Data type ErrorCode](#listing-12) + +[Listing 13 -- JSON Schema for Data type Integer](#listing-13) + +[Listing 14 -- JSON Schema for Data type Latitude](#listing-14) + +[Listing 15 -- JSON Schema for Data type Longitude](#listing-15) + +[Listing 16 -- JSON Schema for Data type MerchantClassificationCode](#listing-16) + +[Listing 17 -- JSON Schema for Data type Name](#listing-17) + +[Listing 18 -- JSON Schema for Name type FirstName](#listing-18) + +[Listing 19 -- JSON Schema for Data type OtpValue](#listing-19) + +[Listing 20 -- String types specified and used in the API](#listing-20) + +[Listing 21 -- JSON Schema for Data type ErrorDescription](#listing-21) + +[Listing 22 -- JSON Schema for Data type TokenCode](#listing-22) + +[Listing 23 -- JSON Schema for TokenCode type Code](#listing-23) + +[Listing 24 -- JSON Schema for Data type UndefinedEnum](#listing-24) + +[Listing 25 -- JSON Schema for Data type UUID](#listing-25) + +[Listing 26 -- JSON Schema for complex type AuthenticationInfo](#listing-26) + +[Listing 27 -- Example instance of AuthenticationInfo complex type](#listing-27) + +[Listing 28 -- Complex type Examples](#listing-28) + +[Listing 29 -- JSON Schema for complex type AuthorizationsIDPutResponse](#listing-29) + +[Listing 30 -- Example instance of AuthorizationsIDPutResponse complex type](#listing-30) + +[Listing 31 -- Complex type Examples for Objects in Requests and Responses in the API](#listing-31) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/fspiop/logical-data-model.md b/website/versioned_docs/v1.0.1/api/fspiop/logical-data-model.md new file mode 100644 index 000000000..262603287 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/logical-data-model.md @@ -0,0 +1,2437 @@ +# Logical Data Model + + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| + +
    + +## Introduction + +This document specifies the logical data model used by Open API (Application Programming Interface) for FSP (Financial Service Provider) Interoperability (hereafter cited as “the API”). + +The [Services Elements](#api-services-elements) section lists elements used by each service. + +The [Supporting Data Model](#api-supporting-data-model) section describes the data model in terms of basic elements, simple data types and complex data types. + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](#) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](./json-binding-rules) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](./v1.1/signature) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](./glossary) + +
    + +## API Services Elements + +The section identifies and describes elements used by each service. + +### API Resource Participants + +This section describes the data model of services for the resource **Participants**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Participants**. +
    + +##### Lookup Participant Information + +Table 1 contains the data model for _Lookup Participant Information_. + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartyIdSubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party.| + +**Table 1 – Lookup Participant Information data model** + +
    + +##### Create Participant Information + +Table 2 below contains the data model for _Create Participant Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) |The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartyIdSubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party. | +| **fspId** | 1 | [FspId](#fspid-element) | FSP Identifier that the Party belongs to. | +| **currency** | 0..1 | [Currency](#currency-element) | Indicate that the provided Currency is supported by the Party. | + +**Table 2 – Create Participant Information data model** + +
    + +##### Create Bulk Participant Information + +Table 3 below contains the data model for _Create Bulk Participant Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **requestId** | 1 | [CorrelationId](#correlationid-element) | The ID of the request, determined by the client. Used for identification of the callback from the server. | +| **partyList** | 1..10000 | [PartyIdInfo](#partyidinfo) | List of Party elements that the Client would like to update or create FSP information about. | +| **currency** | 0..1 | [Currency](#currency-enum) | Indicate that the provided Currency is supported by each PartyIdInfo in the list. | + +**Table 3 – Create Bulk Participant Information data model** + +
    + +##### Delete Participant Information + +Table 4 below contains the data model for _Delete Participant Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartyIdSubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party. | + +**Table 4 – Delete Participant Information data model** + +
    + +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Participants**. + +##### Return Participant Information + +Table 5 below contains the data model for _Return Participant Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartyIdSubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party. | +| **fspId** | 0..1 | [FspId](#fspid-element) | FSP Identifier that the Party belongs to. | + +**Table 5 – Return Participant Information data model** + +
    + +##### Return Bulk Participant Information + +Table 6 below contains the data model for _Return Bulk Participant Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **requestId** | 1 | [CorrelationId](#correlationid-element) | The ID of the request, determined by the client. Used for identification of the callback from the server. | +| **partyList** | 1..10000 | [PartyResult](#partyresult) | List of PartyResult elements for which creation was attempted (and either succeeded or failed). | +| **Currency** | 0..1 | [Currency](#currency-element) | Indicates that the provided Currency was set to be supported by each successfully added PartyIdInfo. | + +**Table 6 – Return Bulk Participant Information data model** + +
    + +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Participants**. + +##### Return Participant Information Error + +Table 7 below contains the data model for _Return Participant Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartyIdSubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 7 – Return Participant Information Error data model** + +
    + +##### Return Bulk Participant Information Error + +Table 8 below contains the data model for _Return Bulk Participant Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **requestId** | 1 | [CorrelationId](#correlationid-element) | The ID of the request, determined by the client. Used for identification of the callback from the server. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 8 – Return Bulk Participant Information Error data model** + +
    + +### API Resource Parties + +This section describes the data model of services for the resource **Parties**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Parties**. + +##### Lookup Party Information + +Table 9 below contains the data model for _Lookup Party Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartyIdSubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party. | + +**Table 9 – Lookup Party Information data model** + +
    + +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Parties**. + +##### Return Party Information + +Table 10 below contains the data model for _Return Party Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartySubIdOrType](#partysuboridtype-element) | A sub-identifier or sub-type for the Party. | +| **party** | 1 | [Party](#party) | Information regarding the requested Party. | + + +**Table 10 – Return Party Information data model** + + +
    + +#### Error Responses + +##### Return Party Information Error + +Table 11 below contains the data model for _Return Party Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartySubIdOrType](#partysuboridtype-element) | A sub-identifier or sub-type for the Party. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 11 – Return Party Information Error data model** + +
    + +### API Resource Transaction Requests + +This section describes the data model of services for the resource **Transaction Requests**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Transaction Requests**. + +##### Retrieve Transaction Request + +Table 12 below contains the data model for _Retrieve Transaction Request_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionRequestId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the transaction request object, determined by the Payee FSP. The ID should be re-used for re-sends of the same transaction request. A new ID should be generated for each new transaction request. | + +**Table 12 – Retrieve Transaction Request data model** + + +
    + +##### Perform Transaction Request Information + +Table 13 below contains the data model for _Perform Transaction Request Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionRequestId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the transaction request object, determined by the Payee FSP. The ID should be re-used for resends of the same transaction request. A new ID should be generated for each new transaction request. | +| **payee** | 1 | [Party](#party) | Information about the Payee in the proposed financial transaction. | +| **payer** | 1 | [PartyIdInfo](#partyidinfo) | Information about the Payer type, id, subtype/id, FSP Id in the proposed financial transaction. +| **amount** | 1 | [Money](#money) | The requested amount to be transferred from the Payer to Payee. | +| **transactionType** | 1 | [TransactionType](#transactiontype) | The type of transaction. | +| **note** | 0..1 | [Note](#note-element) | Reason for the transaction request, intended to the Payer. | +| **geoCode** | 0..1 | [GeoCode](#geocode) | Longitude and Latitude of the initiating party.

    Can be used to detect fraud.

    | +| **authenticationType** | 0..1 | [AuthenticationType](#authenticationtype-element) | OTP or QR Code, otherwise empty. | +| **expiration** | 0..1 | [DateTime](#datetime) | Expiration is optional. It can be set to get a quick failure in case the peer FSP takes too long to respond. Also useful for notifying Consumer, Agent, Merchant that their request has a time limit. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 13 – Perform Transaction Request Information data model** + +
    + +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Transaction Requests**. + + +##### Return Transaction Request Information + +Table 14 below contains the data model for _Return Transaction Request Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionRequestId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the transaction request object, determined by the Payee FSP. The ID should be re-used for re-sends of the same transaction request. A new ID should be generated for each new transaction request. | +| **transactionId** | 0..1 | [CorrelationId](#correlationid-element) | Identifies related /transactions (if a transaction has been created). | +| **transactionRequestState** | 1 | [TransactionRequestState](#transactionrequeststate-element) | The state of the transaction request. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 14 – Return Transaction Request Information data model** + +
    + +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Transaction Requests**. + +##### Return Transaction Request Information Error + +Table 15 below contains the data model for _Return Transaction Request Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionRequestId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the transaction request object, determined by the Payee FSP. The ID should be re-used for resends of the same transaction request. A new ID should be generated for each new transaction request. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 15 – Return Transaction Request Information Error data model** + +
    + +### API Resource Quotes + +This section describes the data model of services for the resource **Quotes**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Quotes**. + +##### Retrieve Quote Information + +Table 16 bleow contains the data model for _Retrieve Quote Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | Identifies quote message.| + +**Table 16 – Retrieve Quote Information data model** + +
    + +##### Calculate Quote + +Table 17 below contains the data model for _Calculate Quote_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | Identifies quote message. | +| **transactionId** | 1 | [CorrelationId](#correlationid-element) | Identifies transaction message. | +| **transactionRequestId** | 1 | [CorrelationId](#correlationid-element) | Identifies transactionRequest message. | +| **payee** | 1 | [Party](#party) | Information about the Payee in the proposed financial transaction. | +| **payer** | 1 | [Party](#party) | Information about the Payer in the proposed financial transaction. | +| **amountType** | 1 | [AmountType](#amounttype-element) | SEND for sendAmount, RECEIVE for receiveAmount. | +| **amount** | 1 | [Money](#money) | Depending on amountType:
    If SEND: The amount the Payer would like to send, that is, the amount that should be withdrawn from the Payer account including any fees. The amount is updated by each participating entity in the transaction.

    If RECEIVE: The amount the Payee should receive, that is, the amount that should be sent to the receiver exclusive any fees. The amount is not updated by any of the participating entities.
    | +| **fees** | 0..1 | [Money](#money) | The fees in the transaction.
    • The fees element should be empty if fees should be non-disclosed.
    • The fees element should be non-empty if fees should be disclosed.
    | +| **transactionType** | 1 | [TransactionType](#transactiontype) | The type of transaction for which the quote is requested. | +| **geoCode** | 0..1 | [GeoCode](#geocode) | Longitude and Latitude of the initiating party. Can be used to detect fraud. | +| **note** | 0..1 | [Note](#note-element) | A memo that will be attached to the transaction. | +| **expiration** | 0..1 | [DateTime](#datetime) | Expiration is optional. It can be set to get a quick failure in case the peer FSP takes too long to respond. Also useful for notifying Consumer, Agent, Merchant that their request has a time limit. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 17 – Calculate Quote data model** + +
    + +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Quotes**. + +##### Return Quote Information + +Table 18 below contains the data model for _Return Quote Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | Identifies quote message. | +| **transferAmount** | 1 | [Money](#money) | The amount of money that the Payer FSP should transfer to the Payee FSP. | +| **payerReceiveAmount** | 1 | [Money](#money) | The amount of money that the Payee should receive in the end-to-end transaction. Optional, as the Payee FSP might not want to disclose any optional Payee fees. | +| **payeeFspFee** | 0..1 | [Money](#money) | Payee FSP’s part of the transaction fee. | +| **payeeFspCommission** | 0..1 | [Money](#money) | Transaction commission from the Payee FSP. | +| **expiration** | 1 | [DateTime](#datetime) | Date and time until when the quotation is valid and can be honored when used in the subsequent transaction. | +| **geoCode** | 0..1 | [GeoCode](#geocode) | Longitude and Latitude of the Payee. Can be used to detect fraud. | +| **ilpPacket** | 1 | [IlpPacket](#ilppacket-element) | The ILP Packet that must be attached to the transfer by the Payer. | +| **condition** | 1 | [IlpCondition](#ilpcondition-element) | The condition that must be attached to the transfer by the payer. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment | + +**Table 18 – Return Quote Information data model** + +
    + +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Quotes**. + +##### Return Quote Information Error + +Table 19 below contains the data model for _Return Quote Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | Identifies quote message. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 19 – Return Quote Information Error data model** + +
    + +### API Resource Authorizations + +This section describes the data model of services for the resource **Authorizations**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Authorizations**. + +##### Perform Authorization + +Table 20 below contains the data model for _Perform Authorization_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **authorizationId** | 1 | [CorrelationId](#correlationid-element) | Identifies authorization message. | +| **authenticationType** | 0..1 | [AuthenticationType](#authenticationtype-element) | The type of authentication. | +| **retriesLeft** | 0..1 | [NrOfRetries](#nrofretries-element) | Number of retries left. | +| **amount** | 0..1 | [Money](#money) | The authorization amount. | +| **currency** | 0..1 | [CurrencyCode](#currencycode-enum) | The authorization currency. | + +**Table 20 – Perform Authorization data model** + +
    + +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Authorizations**. + +##### Return Authorization Result + +Table 21 below contains the data model for _Return Authorization Result_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **authorizationId** | 1 | [CorrelationId](#correlationid-element) | Identifies authorization message. | +| **authenticationInfo** | 0..1 | [AuthenticationInfo](#authenticationinfo) | OTP or QR Code if entered, otherwise empty. | +| **responseType** | 1 | [AuthorizatonResponse](#authorizationresponse-element) | Enum containing response information, if the customer entered the authentication value, rejected the transaction, or requested a resend of the authentication value. | + +**Table 21 – Return Authorization Result data model** + +
    + +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Authorizations**. + +##### Return Authorization Error + +Table 22 below contains the data model for _Return Authorization Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **authorizationId** | 1 | [CorrelationId](#correlationid-element) | Identifies authorization message. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 22 – Return Authorization Error data model** + +
    + +### API Resource Transfers + +This section describes the data model of services for the resource **Transfers**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Transfers**. + +##### Retrieve Transfer Information + +Table 23 below contains the data model for _Retrieve Transfer Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same transfer. A new ID should be generated for each new transfer. | + +**Table 23 – Retrieve Transfer Information data model** + +
    + +##### Perform Transfer + +Table 24 below contains the data model for _Perform Transfer_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same transfer. A new ID should be generated for each new transfer. | +| **payeeFsp** | 1 | [FspId](#fspid-element) | Payee FSP in the proposed financial transaction. | +| **payerFsp** | 1 | [FspId](#fspid-element) | Payer FSP in the proposed financial transaction. | +| **amount** | 1 | [Money](#money) | The transfer amount to be sent. | +| **ilpPacket** | 1 | [IlpPacket](#ilppacket-element) | The ILP Packet containing the amount delivered to the payee and the ILP Address of the payee and any other end-to-end data. | +| **condition** | 1 | [IlpCondition](#ilpcondition-element) | The condition that must be fulfilled to commit the transfer. | +| **expiration** | 1 | [DateTime](#datetime) | Expiration can be set to get a quick failure Expiration of the transfer. The transfer should be rolled back if no fulfilment is delivered before this time. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 24 – Perform Transfer data model** + +
    + +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Transfers**. + +##### Return Transfer Information + +Table 25 below contains the data model for _Return Transfer Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same transfer. A new ID should be generated for each new transfer. | +| **fulfilment** | 0..1 | [IlpFulfilment](#ilpfulfilment-element) | The fulfilment of the condition specified with the transaction. Mandatory if transfer has completed successfully. | +| **completedTimestamp** | 0..1 | [DateTime](#datetime) | The time and date when the transaction was completed. | +| **transferState** | 1 | [TransferState](#transferstate-enum) | The state of the transfer. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 25 – Return Transfer Information data model** + +
    + +#### Error Responses + +This section describes the data model of error responses used by the server in the API for services provided by the resource **Transfers**. + +##### Return Transfer Information Error + +Table 26 below contains the data model for _Return Transfer Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the transfer object, determined by the Payer FSP. The ID should be reused for re-sends of the same transfer. A new ID should be generated for each new transfer. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 26 – Return Transfer Information Error data model** + +
    + +### API Resource Transactions + +This section describes the data model of services for the resource **Transactions**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Transactions**. + +##### Retrieve Transaction Information + +Table 27 below contains the data model for **Retrieve Transaction Information**. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionId** | 1 | [CorrelationId](#correlationid-element) | Identifies transaction message. | + +**Table 27 – Retrieve Transaction Information data model** + +
    + +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Transactions**. + +##### Return Transaction Information + +Table 28 below contains the data model for _Return Transaction Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionId** | 1 | [CorrelationId](#correlationid-element) | Identifies transaction message. | +| **completedTimestamp** | 0..1 | [DateTime](#datetime) | The time and date when the transaction was completed. | +| **transactionState** | 1 | [TransactionState](#transactionstate-element) | The state of the transaction. | +| **code** | 0..1 | [Code](#code-element) | Optional redemption information provided to Payer after transaction has been completed. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 28 – Return Transaction Information data model** + +
    + +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Transactions**. + +##### Return Transaction Information Error + +Table 29 below contains the data model for _Return Transaction Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionId** | 1 | [CorrelationId](#correlationid-element) | Identifies transaction message. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 29 – Return Transaction Information Error data model** + +
    + +### API Resource Bulk Quotes + +This section describes the data model of services for the resource **Bulk Quotes**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Bulk Quotes**. + +##### Retrieve Bulk Quote Information + +Table 30 below contains the data model for _Retrieve Bulk Quote Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkQuoteId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the bulk quote object, determined by the Payer FSP. The ID should be reused for re-sends of the same bulk quote. A new ID should be generated for each new bulk quote. | + +**Table 30 – Retrieve Bulk Quote data model** + +
    + +##### Calculate Bulk Quote + +Table 31 contains the data model for _Calculate Bulk Quote_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkQuoteId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the bulk quote object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk quote. A new ID should be generated for each new bulk quote. payer 1 PartyIdInfo Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction. | +| **GeoCode** | 0..1 | [GeoCode](#geocode) | Longitude and Latitude of the initiating Party. Can be used to detect fraud. | +| **expiration** | 0..1 | [DateTime](#datetime) | Proposed expiration of the quote. | +| **individualQuotes** | 1..1000 | [IndividualQuote](#individualquote) | List of `IndividualQuote` elements. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 31 – Calculate Bulk Quote data model** + +
    + +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Bulk Quotes**. + +##### Return Bulk Quote Information + +Table 32 below contains the data model for _Return Bulk Quote Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkQuoteId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the bulk quote object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk quote. A new ID should be generated for each new bulk quote. | +| **individualQuoteResults** | 0..1000 | [IndividualQuoteResult](#individualquoteresult) | Fees for each individual transaction (if any are charged per transaction). expiration 1 DateTime Date and time until when the quotation is valid and can be honored when used in the subsequent transaction request. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 32 – Return Bulk Quote Information data model** + +
    + +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Bulk Quotes**. + +##### Return Bulk Quote Information Error + +Table 33 below contains the data model for _Return Bulk Quote Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkQuoteId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs for the bulk quote object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk quote. A new ID should be generated for each new bulk quote. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 33 – Return Bulk Quote Information Error data model** + +
    + +### API Resource Bulk Transfers + +This section describes the data model of services for the resource **Bulk Transfers**. + +#### Requests + +This section describes the data model of services that can be requested by a client in the API for the resource **Bulk Transfers**. + +##### Retrieve Bulk Transfer Information + +Table 34 below contains the data model for _Retrieve Bulk Transfer Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkTransferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the bulk transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk transfer. A new ID should be generated for each new bulk transfer. | + +**Table 34 – Retrieve Bulk Transfer Information data model** + +
    + +##### Perform Bulk Transfer + +Table 35 contains the data model for _Perform Bulk Transfer_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkTransferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the bulk transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk transfer. A new ID should be generated for each new bulk transfer. | +| **bulkQuoteId** | 1 | [CorrelationId](#correlationid-element) | This identifies previous quotation request. The fees specified in the previous quotation will have to be honored in the transfer. | +| **payeeFsp** | 1 | [FspId](#fspid-element) | Payee FSP identifier. | +| **payerFsp** | 1 | [FspId](#fspid-element) | Information about the Payer in the proposed financial transaction. | +| **individualTransfers** | 1..1000 | [IndividualTransfer](#individualtransfer) | List of `IndividualTransfer` elements. | +| **expiration** | 1 | [DateTime](#datetime) | Expiration time of the transfers. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 35 – Perform Bulk Transfer data model** + +
    + +#### Responses + +This section describes the data model of responses used by the server in the API for services provided by the resource **Bulk Transfers**. + +##### Return Bulk Transfer Information + +Table 36 below contains the data model for _Return Bulk Transfer Information_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkTransferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the bulk transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk transfer. A new ID should be generated for each new bulk transfer. | +| **completedTimestamp** | 0..1 | [DateTime](#datetime) | The time and date when the bulk transfer was completed. | +| **individualTransferResults** | 0..1000 | [IndividualTransferResult](#individualtransferresult) | List of `IndividualTransferResult` elements. | +| **bulkTransferState** | 1 | [BulkTransferState](#bulktransferstate-enum) | The state of the bulk transaction. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 36 – Return Bulk Transfer Information data model** + +
    + +#### Error Responses + +This section describes the data model of the error responses used by the server in the API for services provided by the resource **Bulk Transfers**. + +##### Return Bulk Transfer Information Error + +Table 37 below contains the data model for _Return Bulk Transfer Information Error_. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **bulkTransferId** | 1 | [CorrelationId](#correlationid-element) | The common ID between the FSPs and the optional Switch for the bulk transfer object, determined by the Payer FSP. The ID should be re-used for re-sends of the same bulk transfer. A new ID should be generated for each new bulk transfer. | +| **errorInformation** | 1 | [ErrorInformation](#errorinformation) | Error code, category description. | + +**Table 37 – Return Bulk Transfer Information Error data model** + +
    + +## API Supporting Data Model + +This section defines the data model and contains the following sub-sections: + +- [Length Specification](#length-specification) introduces the formats used for the element data types used by the API. + +- [Element Data Type Formats](#element-data-type-formats) defines the element data types used by the API. + +- [Element Defintions](#element-defintions) defines the elements types used by the API. + +- [Complex Types](#complex-types) identifies the complex types used by the API. + +- [Enumerations](#enumerations) identifies the enumerations used by the API. + +
    + +### Length Specification +All element data types have both a minimum and maximum length. These lengths are indicated by one of the following: + +- A minimum and maximum length +- An exact length +- A regular expression limiting the element such that only a specific length or lengths can be used. + +#### Minimum and Maximum Length + +If a minimum and maximum length is used, this will be indicated after the data type in parentheses: First the minimum value (inclusive value), followed by two period characters (..), and then the maximum value (inclusive value). + +Examples: + +- `String(1..32)` – A String that is minimum one character and maximum 32 characters long. +- `Integer(3..10)` - An Integerr that is minimum 3 digits, but maximum 10 digits long. + +#### Exact Length + +If an exact length is used, this will be indicated after the data type in parentheses containing only one exact value. Other lengths are not allowed. + +Examples: + +- `String(3)` – A String that is exactly three characters long. +- `Integer(4)` – An Integer that is exactly four digits long. + +#### Regular Expressions + +Some element data types are restricted using regular expressions. The regular expressions in this document use the standard for syntax and character classes established by the programming language Perl[1](https://perldoc.perl.org/perlre.html#Regular-Expressions). + +
    + +### Element Data Type Formats + +This section contains the definition of element data types used by the API. + +#### String + +The API data type `String` is a normal JSON String[2](https://tools.ietf.org/html/rfc7159#section-7), limited by a minimum and maximum number of characters. + +##### Example Format I + +`String(1..32)` – A String that is minimum *1* character and maximum *32* characters long. + +An example of `String(1..32)` appears below: + +- _This String is 28 characters_ + +##### Example Format II + +`String(1..128)` – A String that is minimum *1* character and maximum *128* characters long. + +An example of `String(32..128)` appears below: + +- _This String is longer than 32 characters, but less than 128_ + +
    + +#### Enum + +The API data type `Enum` is a restricted list of allowed JSON [String](#string)) values; an enumeration of values. Other values than the ones defined in the list are not allowed. + +##### Example Format + +`Enum of String(1..32)` – A String that is minimum one character and maximum 32 characters long and restricted by the allowed list of values. The description of the element contains a link to the enumeration. + +
    + +#### UndefinedEnum + +The API data type `UndefinedEnum` is a JSON String consisting of one to 32 uppercase characters including an underscore character ( _) . + +##### Regular Expression + +The regular expression for restricting the `UndefinedEnum` type appears in Listing 1 below: + +``` +^[A-Z_]{1,32}$ +``` +**Listing 1 – Regular expression for data type UndefinedEnum** + +
    + +#### Name + +The API data type `Name` is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. + +##### Regular Expression + +The regular expression for restricting the `Name` type is shown in Listing 2 below. The restriction will not allow a string consisting of whitespace only, all Unicode[3](http://www.unicode.org/) characters should be allowed, as well as period (.), apostrophe (“), dash (-), comma (,) and space ( ) characters. The maximum number of characters in the **Name** is 128. + +**Note:** In some programming languages, Unicode support needs to be specifically enabled. As an example, if Java is used the flag `UNICODE_CHARACTER_CLASS` needs to be enabled to allow Unicode characters. + +``` +^(?!\s*$)[\w .,'-]{1,128}$ +``` + +**Listing 2 – Regular expression for data type Name** + +
    + +#### Integer + +The API data type `Integer` is a JSON String consisting of digits only. Negative numbers and leading zeroes are not allowed. The data type is always limited by a number of digits. + +##### Regular Expression + +The regular expression for restricting an `Integer` is shown in Listing 3 below. + +``` +^[1-9]\d*$ +``` + +**Listing 3 – Regular expression for data type Integer** + +##### Example Format + +`Integer(1..6)` – An `Integer` that is at minimum one digit long, maximum six digits. + +An example of `Integer(1..6)` appears below: + +- _123456_ + +
    + +#### OtpValue + +The API data type `OtpValue` is a JSON String of three to 10 characters, consisting of digits only. Negative numbers are not allowed. One or more leading zeros are allowed. + +##### Regular Expression + +The regular expression for restricting the `OtpValue` type appears in Listing 4 below. + +``` +^\d{3,10}$ +``` + +**Listing 4 – Regular expression for data type OtpValue** + +
    + +#### BopCode + +The API data type `BopCode` is a JSON String of three characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. + +##### Regular Expression + +The regular expression for restricting the `BopCode` type appears in Listing 5 below. +``` +^[1-9]\d{2}$ +``` + +**Listing 5 – Regular expression for data type BopCode** + +
    + +#### ErrorCode + +The API data type `ErrorCode` is a JSON String of four characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. + +##### Regular Expression + +The regular expression for restricting the `ErrorCode` type appears in Listing 6 below. + +``` +^[1-9]\d{3}$ +``` + +**Listing 6 – Regular expression for data type ErrorCode** + +
    + +#### TokenCode + +The API data type `TokenCode` is a JSON String between four and 32 characters, consisting of digits or upper or lowercase characters from **a** to **z**. + +##### Regular Expression + +The regular expression for restricting the `TokenCode` type appears in Listing 7 below. + +``` +^[0-9a-zA-Z]{4,32}$ +``` + +**Listing 7 – Regular expression for data type TokenCode** + +
    + +#### MerchantClassificationCode + +The API data type `MerchantClassificationCode` is a JSON String consisting of one to four digits. + +##### Regular Expression + +The regular expression for restricting the `MerchantClassificationCode` type appears in Listing 8 below. + +``` +^[\d]{1,4}$ +``` + +**Listing 8 - Regular expression for data type MerchantClassificationCode** + +
    + +#### Latitude + +The API data type `Latitude` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting the `Latitude` type appears in Listing 9 below. + +``` +^(\+|-)?(?:90(?:(?:\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\.[0-9]{1,6})?))$ +``` + +**Listing 9 – Regular expression for data type Latitude** + +
    + +#### Longitude + +The API data type `Longitude` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting the `Longitude` type is shown in Listing 10 below. + +``` +^(\+|-)?(?:180(?:(?:\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.[0- +9]{1,6})?))$ +``` + +**Listing 10 – Regular expression for data type Longitude** + +
    + +#### Amount + +The API data type `Amount` is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting the `Amount` type appears in Listing 11 below. This pattern: + +- Does not allow trailing zeroes. +- Allows an amount without a minor currency unit. +- Allows only four digits in the minor currency unit; a negative value is not allowed. +- Does not allow more than 18 digits in the major currency unit. + +The regular expression for restricting the `Amount` type is shown in Listing 11 below. + +``` +^([0]|([1-9][0-9]*))([.][0-9]{0,3}[1-9])?$ +``` + +**Listing 11 – Regular expression for data type Amount** + +##### Examples + +See [table](#results-for-validated-amount-values) below for validation results for some example `Amount` values using the [regular expression](#regular-expression-11) defined above. + +##### Results for validated Amount values + +| Value | Validation result | +| --- | --- | +| _5_ | Accepted | +| _5.0_ | Rejected | +| _5._ | Rejected | +| _5.00_ | Rejected | +| _5.5_ | Accepted | +| _5.50_ | Rejected | +| _5.5555_ | Accepted | +| _5.55555_ | Rejected | +| _555555555555555555_ | Accepted | +| _5555555555555555555_ | Rejected | +| _-5.5_ | Rejected | +| _0.5_ | Accepted | +| _.5_ | Rejected | +| _00.5_ | Rejected | +| _0_ | Accepted | + +**Table 38 – Example results for different values for Amount type** + +
    + +#### DateTime + +The API data type `DateTime` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting `DateTime` appears in Listing 12 below. The format is according to ISO 8601[4](https://www.iso.org/iso-8601-date-and-time-format.html) , expressed in a combined date, time and time format. A more readable version of the format is `yyyy-MM-dd'T'HH:mm:ss.SSS[-HH:MM]` + +``` +^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])- +(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1- +9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02- +29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:(\.\d{3}))(?:Z|[+-][01]\d:[0-5]\d)$ +``` + +**Listing 12 – Regular expression for data type DateTime** + +##### Examples + +Two examples of the `DateTime` type appear below: + +- _2016-05-24T08:38:08.699-04:00_ + +- _2016-05-24T08:38:08.699Z_ (where **Z** indicates Zulu time zone, which is the same as UTC). + +
    + +#### Date + +The API data type `Date` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting the `Date` type appears in Listing 13 below. This format, as specified in ISO 8601, contains a date only. A more readable version of the format is `yyyy-MM-dd`. + +``` +^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])- +(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1- +9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$ +``` + +**Listing 13 – Regular expression for data type Date** + +##### Examples + +Two examples of the `Date` type appear below: + +- _1982-05-23_ + +- _1987-08-05_ + +
    + +#### UUID + +The API data type `UUID` (Universally Unique Identifier) is a JSON String in canonical format, conforming to RFC 4122[5](https://tools.ietf.org/html/rfc4122), that is restricted by a regular expression for interoperability reasons. A `UUID` is always 36 characters long, 32 hexadecimal symbols and four dashes (-). + +##### Regular Expression + +The regular expression is shown in Listing 14 below. + +``` +^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ +``` + +**Listing 14 – Regular expression for data type UUID** + +##### Example + +An example of a `UUID` type appears below: + +- _a8323bc6-c228-4df2-ae82-e5a997baf898_ + +
    + +#### BinaryString + +The API data type `BinaryString` is a JSON String. The String is the base64url[6](https://tools.ietf.org/html/rfc4648#section-5) encoding of a string of raw bytes. The length restrictions for the `BinaryString` type apply to the underlying binary data, indicating the allowed number of bytes. For data types with a fixed size no padding character is used. + +##### Regular Expression + +The regular expression for restricting the **BinaryString** type appears in Listing 15 below. + +``` +^[A-Za-z0-9-_]+[=]?$ +``` + +**Listing 15 – Regular expression for data type BinaryString** + +##### Example Format + +`BinaryString(32)` –32 bytes of data base64url encoded. + +An example of a `BinaryString(32..256)` appears below. Note that a padding character, `'='` has been added to ensure that the string is a multiple of four characters. + +- _QmlsbCAmIE1lbGluZGEgR2F0ZXMgRm91bmRhdGlvbiE=_ + + +
    + +#### BinaryString32 + +The API data type _BinaryString32_ is a fixed size variation of the API data type `BinaryString` defined [here](#binarystring), in which the raw underlying data is always of 32 bytes. The data type _BinaryString32_ should not use a padding character because the size of the underlying data is fixed. + +##### Regular Expression +The regular expression for restricting the _BinaryString32_ type appears in Listing 16 below. + +``` +^[A-Za-z0-9-_]{43}$ +``` + +**Listing 16 – Regular expression for data type BinaryString32** + +##### Example Format +`BinaryString(32)` – 32 bytes of data base64url encoded. + +An example of a `BinaryString32` appears below. Note that this is the same binary data as the example shown in the [Example Format](#example-format-3) of the `BinaryString` type, but due to the underlying data being fixed size, the padding character `'='` is excluded. + +``` +QmlsbCAmIE1lbGluZGEgR2F0ZXMgRm91bmRhdGlvbiE +``` + +
    + +### Element Definitions + +This section contains the definition of the elements types that are used by the API. + +#### AmountType element + +Table 39 below contains the data model for the element `AmountType`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **AmountType** | 1 | [Enum](#enum) of [String(1..32)](#string) | This element contains the amount type. See [AmountType](#amounttype-enum) enumeration for more information on allowed values. | + +**Table 39 – Element AmountType** + +
    + +#### AuthenticationType element + +Table 40 below contains the data model for the element `AuthenticationType`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Authentication** | 1 | [Enum](#enum) of [String(1..32)](#string) | This element contains the authentication type. See [AuthenticationType](#authenticationtype-enum) enumeration for possible enumeration values. | + +**Table 40 – Element AuthenticationType** + +
    + +#### AuthenticationValue element + +Table 41 below contains the data model for the element `AuthenticationValue`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **AuthenticationValue** | 1 | Depends on [AuthenticationType](#authenticationtype-element).

    If `OTP`: type is [Integer(1..6)](#integer). For example:**123456**

    OtpValue
    If `QRCODE`: type is [String(1..64)](#string) | This element contains the authentication value. The format depends on the authentication type used in the [AuthenticationInfo](#authenticationinfo) complex type. | + +**Table 41 – Element AuthenticationValue** + +
    + +#### AuthorizationResponse element + +Table 42 below contains the data model for the element `AuthorizationResponse`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **AuthorizationResponse** | 1 | [Enum](#enum) of [String(1..32)](#string) | This element contains the authorization response. See [AuthorizationResponse](#authorizationresponse-enum) enumeration for possible enumeration values. | + +**Table 42 – Element AuthorizationResponse** + +
    + +#### BalanceOfPayments element + +Table 43 below contains the data model for the element `BalanceOfPayment`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **BalanceOfPayments** | 1 | [BopCode](#bopcode) | The possible values and meaning are defined in [https://www.imf.org/external/np/sta/bopcode/](https://www.imf.org/external/np/sta/bopcode/) | + +**Table 43 – Element BalanceOfPayments** + +
    + +#### BulkTransferState element + +Table 44 below contains the data model for the element `BulkTransferState`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **BulkTransferState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [BulkTransferState](#bulktransferstate-enum) enumeration for information on allowed values| + +**Table 44 – Element BulkTransferState** + +
    + +#### Code element + +Table 45 below contains the data model for the element `Code`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Code** | 1 | [TokenCode](#tokencode) | Any code/token returned by the Payee FSP. | + +**Table 45 – Element Code** + +
    + +#### CorrelationId element + +Table 46 below contains the data model for the element `CorrelationId`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **CorrelationId** | 1 |[UUID](#uuid) | Identifier that correlates all messages of the same sequence. | + + +**Table 46 – Element CorrelationId** + +
    + +#### Currency element + +Table 47 below contains the data model for the element `Currency`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Currency** | 1 | [Enum](#enum) of [String(3)](#string) | See [Currency](#currencycode-enum) enumeration for information on allowed values | + +**Table 47 – Element Currency** + +
    + +#### DateOfBirth element + +Table 48 below contains the data model for the element `DateOfBirth`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **DateOfBirth** | 1 | Examples

    Two examples of the [DateTime](#datetime) type appear below:

    2016-05-24T08:38:08.699-04:00

    2016-05-24T08:38:08.699Z (where Z indicates Zulu time zone, which is the same as UTC).

    Date

    | Date of Birth of the Party.| + +**Table 48 – Element DateOfBirth** + +
    + +#### ErrorCode element + +Table 49 below contains the data model for the element `ErrorCode`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ErrorCode** | 1 | [ErrorCode](#errorcode) | Four digit error code, see section on [Error Codes](#error-codes) for more information. | + +**Table 49 – Element ErrorCode** + +
    + +#### ErrorDescription element + +Table 50 below contains the data model for the element `ErrorDescription`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ErrorDescription** | 1 | [String(1..128)](#string) | Error description string. | + +**Table 50 – Element ErrorDescription** + +
    + +#### ExtensionKey element + +Table 51 below contains the data model for the element `ExtensionKey`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ExtensionKey** | 1 | [String(1..32)](#string) | The extension key. | + +**Table 51 – Element ExtensionKey** + +
    + +#### ExtensionValue element + +Table 52 below contains the data model for the element `ExtensionValue`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ExtensionValue** | 1 | [String(1..128)](#string) | The extension value. | + +**Table 52 – Element ExtensionValue** + +
    + +#### FirstName element +Table 53 below contains the data model for the element `FirstName`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **FirstName** | 1 | [Name](#name) | First name of the Party | + +**Table 53 – Element FirstName** + +
    + +#### FspId element + +Table 54 below contains the data model for the element `FspId`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **FspId** | 1 | [String(1..32)](#string)| The FSP identifier. | + +**Table 54 – Element FspId** + +
    + +#### IlpCondition element + +Table 55 below contains the data model for the element `IlpCondition`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **IlpCondition** | 1 | [BinaryString32](#binarystring32) | The condition that must be attached to the transfer by the Payer. | + +**Table 55 – Element IlpCondition** + +
    + +#### IlpFulfilment element + +Table 56 below contains the data model for the element `IlpFulfilment`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **IlpFulfilment** | 1 | [BinaryString32](#binarystring32) | The fulfilment that must be attached to the transfer by the Payee. | + +**Table 56 – Element IlpFulfilment** + +
    + +#### IlpPacket element + +Table 57 below cntains the data model for the element `IlpPacket`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **IlpPacket** | 1 | Example

    An example of a [UUID](#uuid) type appears below:

    a8323bc6-c228-4df2-ae82-e5a997baf898

    [BinaryString(1..32768)](#binarystring)

    | Information for recipient (transport layer information). | + +**Table 57 – Element IlpPacket** + +
    + +#### LastName element + +Table 58 below contains the data model for the element `LastName`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **LastName** | 1 | [Name](#name) | Last name of the Party (ISO 20022 definition). | + +**Table 58 – Element LastName** + +
    + +#### MerchantClassificationCode element + +Table 59 below contains the data model for the element `MerchantClassificationCode`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **MerchantClassificationCode** | 1 | [MerchantClassificationCode](#merchantclassificationcode) | A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, and so on. | + +**Table 59 – Element MerchantClassificationCode** + +
    + +#### MiddleName element + +Table 60 below contains the data model for the element `MiddleName`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **MiddleName** | 1 | [Name](#name) | Middle name of the Party (ISO 20022 definition). | + +**Table 60 – Element MiddleName** + +
    + +#### Note element + +Table 61 below contains the data model for the element `Note`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Note** | 1 | [String(1..128)](#string) | Memo assigned to transaction. | + +**Table 61 – Element Note** + +
    + + +#### NrOfRetries element + +Table 62 below contains the data model for the element `NrOfRetries`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **NrOfRetries** | 1 | [Integer(1..2)](#integer) | Number of retries. | + +**Table 62 – Element NrOfRetries** + +
    + +#### PartyIdentifier element + +Table 63 below contains the data model for the element `PartyIdentifier`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartyIdentifier** | 1 | [String(1..128)](#string) | Identifier of the Party.| + +**Table 63 – Element PartyIdentifier** + +
    + +#### PartyIdType element + +Table 64 below contains the data model for the element `PartyIdType`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartyIdType** | 1 | Enum of [String(1..32)](#string) | See [PartyIdType](#partyidtype-enum) enumeration for more information on allowed values. | + +**Table 64 – Element PartyIdType** + +
    + +#### PartyName element + +Table 65 below contains the data model for the element `PartyName`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartyName** | 1 | `Name` | Name of the Party. Could be a real name or a nickname. | + +**Table 65 – Element PartyName** + +
    + +#### PartySubIdOrType element + +Table 66 below contains the data model for the element `PartySubIdOrType`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartySubIdOrType** | 1 | [String(1..128)](#string) | Either a sub-identifier of a [PartyIdentifier](#partyidentifier-element), or a sub-type of the [PartyIdType](#partyidtype-element), normally a `PersonalIdentifierType`. | + +**Table 66 – Element PartySubIdOrType** + +
    + +#### RefundReason element + +Table 67 below contains the data model for the element `RefundReason`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **RefundReason** | 1 | [String(1..128)](#string) | Reason for the refund. | + +**Table 67 – Element RefundReason** + +
    + +#### TransactionInitiator element + +Table 68 below contains the data model for the element `TransactionInitiator`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionInitiator** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionInitiator](#transactioninitiator-enum) enumeration for more information on allowed values. | + +**Table 68 – Element TransactionInitiator** + +
    + +#### TransactionInitiatorType element + +Table 69 below contains the data model for the element `TransactionInitiatorType`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionInitiatorType** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionInitiatorType](#transactioninitiatortype-enum) enumeration for more information on allowed values. | + +**Table 69 – Element TransactionInitiatorType** + +
    + +#### TransactionRequestState element + +Table 70 below contains the data model for the element `TransactionRequestState`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionRequestState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionRequestState](#transactionrequeststate-enum) enumeration for more information on allowed values. | + + +**Table 70 – Element TransactionRequestState** + +
    + +#### TransactionScenario element + +Table 71 below contains the data model for the element `TransactionScenario`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionScenario** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionScenario](#transactionscenario-enum) enumeration for more information on allowed values. | + +**Table 71 – Element TransactionScenario** + +
    + +#### TransactionState element + +Table 72 below contains the data model for the element `TransactionState`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionState](#transactionstate-enum) enumeration for more information on allowed values. | + +**Table 72 – Element TransactionState** + +
    + +#### TransferState element + +Table 73 below contains the data model for the element `TransferState`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransferState](#transferstate-enum) enumeration for more information on allowed values. | + +**Table 73 – Element TransferState** + +
    + +#### TransactionSubScenario element + +Table 74 below contains the data model for the element `TransactionSubScenario`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionSubScenario** | 1 | [UndefinedEnum](#undefinedenum) | Possible sub-scenario, defined locally within the scheme.| + +**Table 74 – Element TransactionSubScenario** + +
    + +### Complex Types + +This section contains the complex types that are used by the API. + +#### AuthenticationInfo + +Table 75 below contains the data model for the complex type `AuthenticationInfo`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **authentication** | 1 | [AuthenticationType](#authenticationtype-element) | The type of authentication. | +| **authenticationValue** | 1 | [AuthenticationValue](#authenticationvalue-element) | The authentication value. | + +**Table 75 – Complex type AuthenticationInfo** + +
    + +#### ErrorInformation + +Table 76 below contains the data model for the complex type `ErrorInformation`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **errorCode** | 1 | [ErrorCode](#errorcode) | Specific error number. | +| **errorDescription** | 1 | [ErrorDescription](#errordescription-element) | Error description string. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional list of extensions, specific to deployment. | + +**Table 76 – Complex type ErrorInformation** + +
    + +#### Extension + +Table 77 below contains the data model for the complex type `Extension`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **key** | 1 | [ExtensionKey](#extensionkey-element) | The extension key. | +| **value** | 1 | [ExtensionValue](#extensionvalue-element) | The extension value. | + +**Table 77 – Complex type Extension** + +
    + +#### ExtensionList + +Table 78 below contains the data model for the complex type `ExtensionList`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **extension** | 1..16 | [Extension](#extension) | A number of Extension elements. | + +**Table 78 – Complex type ExtensionList** + +
    + +#### IndividualQuote + +Table 79 below contains the data model for the complex type `IndividualQuote`. + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | Identifies quote message. | +| **transactionId** | 1 | [CorrelationId](#correlationid-element) | Identifies transaction message. | +| **payee** | 1 | [Party](#party) | Information about the Payee in the proposed financial transaction. | +| **amountType** | 1 | [AmountType](#amounttype-element) | `SEND_AMOUNT` for _sendAmount_,

    `RECEIVE_AMOUNT` for _receiveAmount_.

    +| **amount** | 1 | [Money](#money) | Depending on amountType:

    If `SEND`: The amount the Payer would like to send, that is, the amount that should be withdrawn from the Payer account including any fees. The amount is updated by each participating entity in the transaction.

    If `RECEIVE`: The amount the Payee should receive, that is, the amount that should be sent to the receiver exclusive any fees. The amount is not updated by any of the participating entities. | +| **fees** | 0..1 | [Money](#money) | The fees in the transaction.
    • The fees element should be empty if fees should be non-disclosed.
    • The fees element should be non-empty if fees should be disclosed.
    +| **transactionType** | 1 | [TransactionType](#transactiontype) | The type of transaction that the quote is requested for. | +| **note** | 0..1 | [Note](#note-element) | A memo that will be attached to the transaction. This is sent in the quote so it can be included in the ILP Packet. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 79 – Complex type IndividualQuote** + +
    + +#### IndividualQuoteResult + +Table 80 below contains the data model for the complex type `IndividualQuoteResult`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | Identifies the quote message. | +| **payeeReceiveAmount** | 0..1 | [Money](#money) | Amount that the Payee should receive in the end-toend transaction. Optional as the Payee FSP might not want to disclose any optional Payee fees. | +| **payeeFspFee** | 0..1 | [Money](#money) | Payee FSP’s part of the transaction fee. | +| **payeeFspCommission** | 0..1 | [Money](#money) | Transaction commission from the Payee FSP. | +| **ilpPacket** | 0..1 | [IlpPacket](#ilppacket-element) | The ILP Packet that must be attached to the transfer by the payer. | +| **condition** | 0..1 | [IlpCondition](#ilpcondition-element) | The condition that must be attached to the transfer by the payer. | +| **errorInformation** | 0..1 | [ErrorInformation](#errorinformation) | Error code, category description.

    Note: If errorInformation is set, the following are not set:

    • receiveAmount
    • payeeFspFee
    • payeeFspCommission
    • ilpPacket
    • condtion
    | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment | + +**Table 80 – Complex type IndividualQuoteResult** + +
    + +#### IndividualTransfer + +Table 81 below contains the data model for the complex type `IndividualTransfer`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transferId** | 1 | [CorrelationId](#correlationid-element) | Identifies messages related to the same /transfers sequence. | +| **transferAmount** | 1 | [Money](#money) | The transaction amount to be sent. | +| **ilpPacket** | 1 | [IlpPacket](#ilppacket-element) | The ILP Packet containing the amount delivered to the payee and the ILP Address of the payee and any other end-to-end data. | +| **condition** | 1 | [IlpCondition](#ilpcondition-element) | The condition that must be fulfilled to commit the transfer. +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 81 – Complex type IndividualTransfer** + +
    + +#### IndividualTransferResult + +Table 82 below contains the data model for the complex type `IndividualTransferResult`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transferId** | 1 | [CorrelationId](#correlationid-element) | Identifies messages related to the same /transfers sequence. | +| **fulfilment** | 0..1 | [IlpFulfilment](#ilpfulfilment-element) | The fulfilment of the condition specified with the transaction.

    Note: Either fulfilment is set or errorInformation is set, not both.

    +| **errorInformation** | 0..1 | [ErrorInformation](#errorinformation) | If transactionState is `REJECTED`, error information may be provided.

    Note: Either fulfilment is set or errorInformation is set, not both.

    +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 82 – Complex type IndividualTransferResult** + +#### GeoCode + +Table 83 below contains the data model for the complex type `GeoCode`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **latitude** | 1 | [Latitude](#latitude) | The Latitude of the service initiating Party. | +| **longitude** | 1 | [Longitude](#longitude) | The Longitude of the service initiating Party. | + +**Table 83 – Complex type GeoCode** + +
    + +#### Money + +Table 84 below contains the data model for the complex type `Money`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **currency** | 1 | [Currency](#currency-element) | The currency of the Amount. | +| **amount** | 1 | [Amount](#amount) | The amount of Money. | + +**Table 84 – Complex type Money** + +
    + +#### Party + +Table 85 below contains the data model for the complex type `Party`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdInfo** | 1 | [PartyIdInfo](#partyidinfo) | Party Id type, id, sub ID or type, and FSP Id. | +| **merchantClassificationCode** | 0..1 | [MerchantClassificationCode](#merchantclassificationcode) | Optional: Used in the context of Payee Information, where the Payee happens to be a merchant accepting merchant payments. | +| **name** | 0..1 | [PartyName](#partyname-element) | The name of the party, could be a real name or a nick name. | +| **personalInfo** | 0..1 | [PartyPersonalInfo](#partypersonalinfo) | Personal information used to verify identity of Party such as first, middle, last name and date of birth. | + +**Table 85 – Complex type Party** + +
    + +#### PartyComplexName + +Table 86 below contains the data model for the complex type `PartyComplexName`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **firstName** | 0..1 | [FirstName](#firstname-element) | First name. | +| **middleName** | 0..1 | [MiddleName](#middlename-element) | Middle name. | +| **lastName** | 0..1 | [LastName](#lastname-element) | Last name. | + +**Table 86 – Complex type PartyComplexName** + +
    + +#### PartyIdInfo + +Table 87 below contains the data model for the complex type `PartyIdInfo`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyIdType** | 1 | [PartyIdType](#partyidtype-element) | The type of the identifier. | +| **partyIdentifier** | 1 | [PartyIdentifier](#partyidentifier-element) | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | [PartySubIdOrType](#partysubidortype-element) | A sub-identifier or sub-type for the Party. | +| **fspId** | 0..1 | [FspId](#fspid-element) | The FSP ID (if known) | + +**Table 87 – Complex type PartyIdInfo** + +
    + +#### PartyPersonalInfo + +Table 88 below contains the data model for the complex type `PartyPersonalInfo`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **complexName** | 0..1 | [PartyComplexName](#partycomplexname) | First, middle and last name. | +| **dateOfBirth** | 0..1 | [DateOfBirth](#dateofbirth-element) | Date of birth. | + +**Table 88 – Complex type PartyPersonalInfo** + +
    + +#### PartyResult + +Table 89 below contains the data model for the complex type `PartyResult`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **partyId** | 1 | [PartyIdInfo](#partyidinfo) | Party Id type, id, sub ID or type, and FSP Id. | +| **errorInformation** | 0..1 | [ErrorInformation](#errorinformation) | If the Party failed to be added, error information should be provided. Otherwise, this parameter should be empty to indicate success. | + +**Table 89 – Complex type PartyPersonalInfo** + +
    + +#### Refund + +Table 90 below contains the data model for the complex type `Refund`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **originalTransactionId** | 1 | [CorrelationId](#correlationid-element) | Reference to the original transaction ID that is requested to be refunded.| +| **refundReason** | 0..1 | [RefundReason](#refundreason-element) | Free text indicating the reason for the refund. | + +**Table 90 – Complex type Refund** + +
    + +#### Transaction + +Table 91 below contains the data model for the complex type `Transaction`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **transactionId** | 1 | [CorrelationId](#correlationid-element) | ID of the transaction, the ID is determined by the Payer FSP during the creation of the quote. | +| **quoteId** | 1 | [CorrelationId](#correlationid-element) | ID of the quote, the ID is determined by the Payer FSP during the creation of the quote. | +| **payee** | 1 | [Party](#party) | Information about the Payee in the proposed financial transaction. | +| **payer** | 1 | [Party](#party) | Information about the Payer in the proposed financial transaction. | +| **amount** | 1 | [Money](#money) | The transaction amount to be sent. | +| **transactionType** | 1 | [TransactionType](#transactiontype) | The type of the transaction. | +| **note** | 0..1 | [Note](#note-element) | Memo associated to the transaction,intended to the Payee. | +| **extensionList** | 0..1 | [ExtensionList](#extensionlist) | Optional extension, specific to deployment. | + +**Table 91 – Complex type Transaction** + +#### TransactionType + +Table 92 below contains the data model for the complex type `TransactionType`. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **scenario** | 1 | [TransactionScenario`](#transactionscenario-element) | Deposit, withdrawal, refund, … | +| **subScenario** | 0..1 | [TransactionSubScenario](#transactionsubscenario-element) | Possible sub-scenario, defined locally within the scheme. | +| **initiator** | 1 | [TransactionInitiator](#transactioninitiator-enum) | Who is initiating the transaction: payer or payee | +| **initiatorType** | 1 | [TransactionInitiatorType](#transactioninitiatortype-enum) | Consumer, agent, business, … | +| **refundInfo** | 0..1 | [Refund](#refund) | Extra information specific to a refund scenario. Should only be populated if scenario is `REFUND`. | +| **balanceOfPayments** | 0..1 | [BalanceOfPayments](#balanceofpayments-element) | Balance of Payments code. | + +**Table 92 – Complex type TransactionType** + +
    + + +### Enumerations + +This section contains the enumerations used by the API. + +#### AmountType enum + +Table 93 below contains the allowed values for the enumeration `AmountType`. + +| Name | Description | +| --- | --- | +| **SEND** | The amount the Payer would like to send, that is, the amount that should be withdrawn from the Payer account including any fees. | +| **RECEIVE** | The amount the Payer would like the Payee to receive, that is, the amount that should be sent to the receiver exclusive fees. | + +**Table 93 – Enumeration AmountType** + +
    + +#### AuthenticationType enum + +Table 94 below contains the allowed values for the enumeration `AuthenticationType`. + +| Name | Description | +| --- | ---| +| **OTP** | One-time password, either chosen by the Party, or generated by the Party’s FSP. | +| **QRCODE** | QR code used as One Time Password. | + +**Table 94 – Enumeration AuthenticationType** + +
    + +#### AuthorizationResponse enum + +Table 95 below contains the allowed values for the enumeration `AuthorizationResponse`. + +| Name | Description | +| --- | --- | +| **ENTERED** | Consumer entered the authentication value. | +| **REJECTED** | Consumer rejected the transaction. | +| **RESEND** | Consumer requested to resend the authentication value. | + +**Table 95 – Enumeration AuthorizationResponse** + +
    + +#### BulkTransferState + +Table 96 below contains the allowed values for the enumeration `BulkTransferState`. + +| Name | Description | +| --- | --- | +| **RECEIVED** | Payee FSP has received the bulk transfer from the Payer FSP. | +| **PENDING** | Payee FSP has validated the bulk transfer. | +| **ACCEPTED** | Payee FSP has accepted to process the bulk transfer. | +| **PROCESSING** | Payee FSP has started to transfer fund to the Payees. | +| **COMPLETED** | Payee FSP has completed transfer of funds to the Payees. | +| **REJECTED** | Payee FSP has rejected to process the transfer. | + +**Table 96 – Enumeration BulkTransferState** + +
    + +#### CurrencyCode enum + +The currency codes defined in ISO 4217[7](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic codes are used as the standard naming representation for currencies. The currency codes from ISO 4217 are not is shown in this document, implementers are instead encouraged to use the information provided by the ISO 4217 standard directly. + +
    + +#### PartyIdType enum + +Table 97 below contains the allowed values for the enumeration `PartyIdType`. + +| Name | Description | +| --- | ---| +| **MSISDN** | Used when an MSISDN (Mobile Station International Subscriber Directory Number, that is, the phone number) is used as reference to a participant. The MSISDN identifier should be in international format according to the ITU-T E.164 standard. Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix. | +| **EMAIL** | Used when an email should be used as reference to a participant. The format of the email should be according to the informational RFC 3696. | +| **PERSONAL_ID** | Used when some kind of personal identifier should be used as reference to a participant. Examples of personal identification can be passport number, birth certificate number, national registration number or similar. The identifier number shall be added in the PartyIdentifier element. The personal identifier type shall be added in the PartySubIdOrType element. | +| **BUSINESS** | Used when a specific Business (for example, an Organization or a Company) should be used as reference to a participant. The Business identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the PartySubIdOrType element should be used. | +| **DEVICE** | Used when a specific Device (for example, a POS or ATM) ID connected to a specific Business or Organization should be used as reference to a Party. To use a specific device under a specific Business or Organization, the PartySubIdOrType element should be used. | +| **ACCOUNT_ID** | Used when a bank account number or FSP account ID should be used as reference to a participant. The `ACCOUNT_ID` identifier can be in any format, as formats can greatly differ depending on country and FSP. | +| **IBAN** | Used when a bank account number or FSP account ID should be used as reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without any whitespace. | +| **ALIAS** | Used when an alias should be used as reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias can be username in the FSP system. The `ALIAS` identifier can be in any format. It is also possible to use the PartySubIdOrType element for identifying an account under an Alias defined by the PartyIdentifier. | + +**Table 97 – Enumeration PartyIdType** + +
    + +#### PersonalIdentifierType enum + +Table 98 below contains the allowed values for the enumeration `PersonalIdentifierType`. + +| Name | Description | +| --- | --- | +| **PASSPORT** | Used when a passport number should be used as reference to a Party | +| **NATIONAL_REGISTRATION** | Used when a national registration number should be used as reference to a Party | +| **DRIVING_LICENSE** | Used when a driving license should be used as reference to a Party | +| **ALIEN_REGISTRATION** | Used when an alien registration number should be used as reference to a Party | +| **NATIONAL_ID_CARD** | Used when a national ID card number should be used as reference to a Party | +| **EMPLOYER_ID** | Used when a tax identification number should be used as reference to a Party | +| **TAXI_ID_NUMBER** | Used when a tax identification number should be used as reference to a Party. | +| **SENIOR_CITIZENS_CARD** | Used when a senior citizens card number should be used as reference to a Party | +| **MARRIAGE_CERTIFICATE** | Used when a marriage certificate number should be used as reference to a Party | +| **HEALTH_CARD** | Used when a health card number should be used as reference to a Party | +| **VOTERS_ID** | Used when a voters identification number should be used as reference to a Party | +| **UNITED_NATIONS** | Used when an UN (United Nations) number should be used as reference to a Party | +| **OTHER_ID** | Used when any other type of identification type number should be used as reference to a Party | + +**Table 98 – Enumeration PersonalIdentifierType** + +
    + +#### TransactionInitiator enum + +Table 99 below contains the allowed values for the enumeration `TransactionInitiator`. + +| Name | Description | +| --- | --- | +| **PAYER** | The sender of funds is initiating the transaction. The account to send from is either owned by the Payer or is connected to the Payer in some way. | +| **PAYEE** | The recipient of the funds is also initiating the transaction by sending a transaction request. The Payer must approve the transaction, either automatically by a pre-generated OTP, pre-approval of the Payee, or by manually approving in his or her own Device. | + +**Table 99 – Enumeration TransactionInitiator** + +
    + +#### TransactionInitiatorType enum + +Table 100 below contains the allowed values for the enumeration `TransactionInitiatorType`. + +| Name | Description | +| --- | --- | +| **CONSUMER** | Consumer is the initiator of the transaction. | +| **AGENT** | Agent is the initiator of the transaction. | +| **BUSINESS** | Business is the initiator of the transaction. | +| **DEVICE** | Device is the initiator of the transaction. | + +**Table 100 – Enumeration TransactionInitiatorType** + +
    + +#### TransactionRequestState enum + +Table 101 below contains the allowed values for the enumeration `TransactionRequestState`. + +| Name | Description | +| --- | --- | +| **RECEIVED** | Payer FSP has received the transaction from the Payee FSP. | +| **PENDING** | Payer FSP has sent the transaction request to the Payer. | +| **ACCEPTED** | Payer has approved the transaction. | +| **REJECTED** | Payer has rejected the transaction. | + +**Table 101 – Enumeration TransactionRequestState** + +
    + +#### TransactionScenario enum + +Table 102 below contains the allowed values for the enumeration `TransactionScenario`. + +| Name | Description | +| --- | --- | +| **DEPOSIT** | Used for performing a Cash-In (deposit) transaction, where in the normal case electronic funds are transferred from a Business account to a Consumer account, and physical cash is given from the Consumer to the Business User. | +| **WITHDRAWAL** | Used for performing a Cash-Out (withdrawal) transaction, where in the normal case electronic funds are transferred from a Consumer’s account to a Business account, and physical cash is given from the Business User to the Consumer. | +| **TRANSFER** | Used for performing a P2P (Peer to Peer, or Consumer to Consumer) transaction. | +| **PAYMENT** | Typically used for performing a transaction from a Consumer to a Merchant/Organization, but could also be for a B2B (Business to Business) payment. The transaction could be online to purchase in an Internet store, in a physical store where both the Consumer and Business User are present, a bill payment, a donation, and so on. | +| **REFUND** | Used for performing a refund of transaction. | + +**Table 102 – Enumeration TransactionScenario** + +
    + +#### TransactionState enum + +Table 103 below contains the allowed values for the enumeration `TransactionState`. + +| Name | Description | +| --- | --- | +| **RECEIVED** | Payee FSP has received the transaction from the Payer FSP. | +| **PENDING** | Payee FSP has validated the transaction. | +| **COMPLETED** | Payee FSP has successfully performed the transaction. | +| **REJECTED** | Payee FSP has failed to perform the transaction. | + +**Table 103 – Enumeration TransactionState** + +
    + +#### TransferState enum + +Table 104 below contains the allowed values for the enumeration `TransferState`. + +| Name | Description | +| --- | --- | +| **RECEIVED** | The next ledger has received the transfer. | +| **RESERVED** | The next ledger has reserved the transfer. | +| **COMMITTED** | The next ledger has successfully performed the transfer. | +| **ABORTED** | The next ledger has aborted the transfer due a rejection or failure to perform the transfer. | + +**Table 104 – Enumeration TransferState** + +
    + +### Error Codes + +Each error code in the API is a four-digit number, such as **1234**, where the first number (**1** in the example) represents the highlevel error category, the second number (**2** in the example) represents the low-level error category, and the last two numbers (**34** in the example) represents the specific error. Figure 1 shows the structure of an error code. The following sub-sections contains information and defined error codes per high-level error category. + +![Figure 1 - Error code structure](../assets/sequence-diagram-figure-1.png) + +**Figure 1 – Error code structure** + +Each defined high- and low-level category combination contains a generic error (_x_**0**_xx_), which can be used if there is no specific error, or if the server would not like to return information which is considered private. + +All specific errors below _xx_**40**, that is, _xx_**00** to _xx_**39**, are reserved for future use by the API. All specific errors above and including _xx40_, can be used for scheme-specific errors. If a client receives an unknown scheme-specific error, the unknown scheme-specific error should be interpreted as a generic error for the high- and low-level category combination instead (_xx_**00**). + +#### Communication Errors – 1xxx + +All possible communication or network errors that could arise that cannot be represented by an HTTP status code should use +the high-level error code 1 (error codes **1**_xxx_). Because all services in the API are asynchronous, these error codes should generally be used by a Switch in the Callback to the client FSP if the Peer FSP could not be reached, or if a callback is not received from the Peer FSP within an agreed timeout. + +Low level categories defined under Communication Errors: + +- **Generic Communication Error – 10**_xx_ + +See Table 105 below for all communication errors defined in the API. + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **1000** | Communication error | Generic communication error. | X | X | X | X | X | X | X | X | X | +| **1001** | Destination communication error | The Destination of the request failed to be reached. This usually indicates that a Peer FSP failed to respond from an intermediate entity. | X | X | X | X | X | X | X | X | X | + +**Table 105 – Communication errors – 1xxx** + +
    + +#### Server Errors – 2xxx + +All errors occurring in the server in which the server failed to fulfil an apparently valid request from the client should use the high-level error code 2 (error codes **2**_xxx_). These error codes should indicate that the server is aware that it has encountered an error or is otherwise incapable of performing the requested service. + +Low-level categories defined under server Errors: + +- **Generic server Error – 20**_xx_ + +See Table 106 below for all server errors defined in the API. + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **2000** | Generic server error | Generic server error to be used for not disclosing information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **2001** | Internal server error | A generic unexpected exception. This usually indicates a bug or unhandled error case. | X | X | X | X | X | X | X | X | X | +| **2002** | Not implemented | Service requested is not supported by the server. | X | X | X | X | X | X | X | X | X | +| **2003** | Service currently unavailable | Service requested is currently unavailable on the server. This could be because maintenance is taking place, or because of a temporary failure. | X | X | X | X | X | X | X | X | X | +| **2004** | Server timed out | A time out has occurred, meaning the next Party in the chain did not send a callback in time. This could be because a timeout is set too low or because something took longer than it should. | X | X | X | X | X | X | X | X | X | +| **2005** | Server busy | Server is rejecting requests due to overloading. Try again later. | X | X | X | X | X | X | X | X | X | + +**Table 106 – Server errors – 2xxx** + +
    + +#### Client Errors – 3xxx** + +All possible errors occurring in the server where the server’s opinion is that the client have sent one or more erroneous parameters should use the high-level error code 3 (error codes **3**_xxx_). These error codes should indicate that the server could not perform the service according to the request from the client. The server should provide an explanation why the service could not be performed. + +Low level categories defined under client Errors: +- **Generic Client Error – 30**_xx_ + - See Table 107 for the generic client errors defined in the API. +- **Validation Error – 31**_xx_ + - See Table 108 for the validation errors defined in the API. +- **Identifier Error – 32**_xx_ + - See Table 109 for the identifier errors defined in the API. +- **Expired Error – 33**_xx_ + - See Table 110 for the expired errors defined in the API. + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **3000** | Generic client error | Generic client error, to be used for not disclosing information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **3001** | Unacceptable version requested | Client requested to use a protocol version which is not supported by the server. | X | X | X | X | X | X | X | X | X | +| **3002** | Unknown URI | The provided URI was unknown by the server. | | | | | | | | | | +| **3003** | Add Party information error | An error occurred while adding or updating information regarding a Party. | X | | | | | | | | | | + +**Table 107 – Generic client errors – 30xx** + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **3100** | Generic validation error | Generic validation error to be used for not disclosing information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **3101** | Malformed syntax | The format of the parameter is not valid. For example, amount set to 5.ABC. The error description field should specify which element is erroneous. |X | X | X | X | X | X | X | X | X | +| **3102** | Missing mandatory element | A mandatory element in the data model was missing. | X | X | X | X | X | X | X | X | X | +| **3103** | Too many elements | The number of elements of an array exceeds the maximum number allowed. | X | X | X | X | X | X | X | X | X | +| **3104** | Too large payload | The size of the payload exceeds the maximum size. | X | X | X | X | X | X | X | X | X | +| **3105** | Invalid signature | Some parameters have changed in the message, making the signature invalid. This may indicate that the message may have been modified maliciously. |X | X | X | X | X | X | X | X | X | +| **3106** | Modified request | A request with the same ID has previously been processed where the parameters are not the same. | | | X | X | | X | | X | X | +| **3107** | Missing mandatory extension parameter |A scheme mandatory extension parameter was missing. | | | X | X | X | X | X | X | X | + +**Table 108 – Validation Errors – 31xx** + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **3200** | Generic ID not found | Generic ID error provided by the client. | X | X | X | X | X | X | X | X | X | +| **3201** | Destination FSP Error| The Destination FSP does not exist or cannot be found. | X | X | X | X | X | X | X | X | X | +| **3202** | Payer FSP ID not found | The provided Payer FSP ID not found. | | | | | | X | | X | X | +| **3203** | Payee FSP ID not found | The provided Payer FSP ID not found. | | | | | | X | | X | X | +| **3204** | Party not found | The Party with the provided identifier, identifier type, and optional sub id or type was not found. | X | X | X | X | | | | | | +| **3205** | Quote ID not found | The provided Quote ID was not found in the server. | | | | X | | X | | | | +| **3206** | Transaction request ID not found | The provided Transaction Request ID was not found in the server. | | | X | | | X | | | | +| **3207** | Transaction ID not found | The provided Transaction ID was not found in the server. | | | | | | | X | | | +| **3208** | Transfer ID not found | The provided Transfer ID was not found in the server. | | | | | | X | | | | +| **3209** | Bulk quote ID not found | The provided Bulk Quote ID was not found in the server. | | | | | | | | X | X | +| **3210** | Bulk transfer ID not found | The provided Bulk Transfer ID was not found in the server. | | | | | | | | | X | + +**Table 109 – Identifier Errors – 32xx** + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **3300** |Generic expired error | Generic expired object error, to be used for not disclosing information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **3301** | Transaction request expired | Client requested to use a transaction request that has already expired. | | | | X | | | | | | +| **3302** | Quote expired | Client requested to use a quote that has already expired. | | | | | X | | | X | X | +| **3303** | Transfer expired | Client requested to use a transfer that has already expired. | X | X | X | X | X | X | X | X | X | + +**Table 110 – Expired Errors – 33xx** + +
    + +#### Payer Errors – 4xxx + +All possible errors occurring in the server when the Payer or the Payer FSP is the cause of an error should use the high-level error code 4 (error codes **4**_xxx_). These error codes should indicate that there was no error in the server or in the request from the client, but the request failed for some reason due to the Payer or the Payer FSP. The server should provide an explanation why the service could not be performed. + +Low level categories defined under Payer Errors: +- **Generic Payer Error – 40**_xx_ +- **Payer Rejection Error – 41**_xx_ +- **Payer Limit Error – 42**_xx_ +- **Payer Permission Error – 43**_xx_ +- **Payer Blocked Error – 44**_xx_ + +See Table 111 below for all Payer errors defined in the API. + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **4000** | Generic Payer error | Generic error due to the Payer or Payer FSP, to be used for not disclosing information that may be considered private. | | | X | X | X | X | X | X | X | +| **4001** | Payer FSP insufficient liquidity | The Payer FSP has insufficient liquidity to perform the transfer. | | | | | | X | | | | +| **4100** | Generic Payer rejection | Payer or Payer FSP rejected the request. | | | X | X | X | X | X | X | X | +| **4101** | Payer rejected transaction request | Payer rejected the transaction request from the Payee. | | | X | | | | | | | +| **4102** | Payer FSP unsupported transaction type | The Payer FSP does not support or rejected the requested transaction type | | | X | | | | | | | +| **4103** | Payer unsupported currency | Payer doesn’t have an account which supports the requested currency. | | | X | | | | | | | +| **4200** | Payer limit error | Generic limit error, for example, the Payer is making more payments per day or per month than they are allowed to, or is making a payment that is larger than the allowed maximum per transaction. | | | X | X | | X | | X | X | +| **4300** | Payer permission Error | Generic permission error, the Payer or Payer FSP doesn’t have the access rights to perform the service. | | | X | X | X | X | X | X | X | +| **4400** | Generic Payer blocked error | Generic Payer blocked error, the Payer is blocked or has failed regulatory screenings. | | | X | X | X | X | X | X | X | + +**Table 111 – Payer errors – 4xxx** + + +
    + +#### Payee Errors – 5xxx + +All possible errors occurring in the server when the Payee or the Payee FSP is the cause of an error should use the high-level error code 5 (error codes **5**_xxx_). These error codes should indicate that there was no error in the server or in the request from the client, but the request failed for some reason due to the Payee or the Payee FSP. The server should provide an explanation for why the service could not be performed. + +Low level categories defined under Payee Errors: + +- **Generic Payee Error – 50**_xx_ +- **Payee Rejection Error – 51**_xx_ +- **Payee Limit Error – 52**_xx_ +- **Payee Permission Error – 53**_xx_ +- **Payee Blocked Error – 54**_xx_ + +See Table 112 below for all Payee errors defined in the API. + +| Error Code | Name | Description | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **5000** |Generic Payee error |Generic error due to the Payer or Payer FSP, to be used for not disclosing information that may be considered private. | | | X | X | X | X | X | X | X | +| **5001** | Payee FSP insufficient liquidity | The Payee FSP has insufficient liquidity to perform the transfer. | | | | | | X | | | | +| **5100** | Generic Payee rejection | Payee or Payee FSP rejected the request. | | | X | X | X | X | X | X | X | +| **5101** | Payee rejected quote | Payee does not want to proceed with the financial transaction after receiving a quote. | | | | X | | | | X | | +| **5102** | Payee FSP unsupported transaction type | The Payee FSP either does not support or rejected the requested transaction type. | | | | X | | | | X | | +| **5103** | Payee FSP rejected quote | Payee doesn’t want to proceed with the financial transaction after receiving a quote. | | | | X | | | | X | | +| **5104** | Payee rejected transaction | Payee rejected the financial transaction. | | | | | | X | | | X | +| **5105** | Payee FSP rejected transaction | Payee FSP rejected the financial transaction. | | | | | | X | | | X | +| **5106** | Payee unsupported currency | Payee doesn’t have an account which supports the requested currency. | | | | X | | X | | X | X | +| **5200** | Payee limit error | Generic limit error, for example, the Payee is receiving more payments per day or per month than they are allowed to, or is receiving a payment which is larger than the allowed maximum per transaction. | | | X | X | | X | | X | X | +| **5300** | Payee permission error | Generic permission error; the Payee or Payee FSP does not have the access rights to perform the service. | | | X | X | X | X | X | X | X | +| **5400** | Generic Payee blocked error | Generic Payee Blocked error, the Payee is blocked or has failed regulatory screenings. | | | X | X | X | X | X | X | X | + +**Table 112 – Payee errors – 5xxx** + + +
    + +## References + +1 [https://perldoc.perl.org/perlre.html#Regular-Expressions](https://perldoc.perl.org/perlre.html#Regular-Expressions) - perlre - Perl regular expressions + +2 [https://tools.ietf.org/html/rfc7159#section-7](https://tools.ietf.org/html/rfc7159#section-7) – The JavaScript Object Notation (JSON) Data Interchange Format - Strings + +3 [http://www.unicode.org/](http://www.unicode.org/) - The Unicode Consortium + +4 [https://www.iso.org/iso-8601-date-and-time-format.html](https://www.iso.org/iso-8601-date-and-time-format.html) - Date and time format - ISO 8601 + +5 [https://tools.ietf.org/html/rfc4122](https://tools.ietf.org/html/rfc4122) - A Universally Unique IDentifier (UUID) URN Namespace + +6 [https://tools.ietf.org/html/rfc4648#section-5](https://tools.ietf.org/html/rfc4648#section-5) - The Base16, Base32, and Base64 Data Encodings - Base 64 Encoding with URL +and Filename Safe Alphabet + +7 [https://www.iso.org/iso-4217-currency-codes.html](https://www.iso.org/iso-4217-currency-codes.html) - Currency codes - ISO 4217 + + + + +## List of Figures + +- [Figure 1](#error-codes) – Error code structure + +## List of Tables + +- [Table 1](#lookup-participant-information) – Lookup Participant Information data model +- [Table 2](#create-participant-information) – Create Participant Information data model +- [Table 3](#create-bulk-participant-information) – Create Bulk Participant Information data model +- [Table 4](#delete-participant-information) – Delete Participant Information data model +- [Table 5](#return-participant-information) – Return Participant Information data model +- [Table 6](#return-bulk-participant-information) – Return Bulk Participant Information data model +- [Table 7](#return-participant-information-error) – Return Participant Information Error data model +- [Table 8](#return-bulk-participant-information-error) – Return Bulk Participant Information Error data model +- [Table 9](#lookup-party-information) – Lookup Party Information data model +- [Table 10](#return-party-information) – Return Party Information data model +- [Table 11](#return-party-information-error) – Return Party Information Error data model +- [Table 12](#retrieve-transaction-request) – Retrieve Transaction Request data model +- [Table 13](#perform-transaction-request-information) – Perform Transaction Request Information data model +- [Table 14](#return-transaction-request-information) – Return Transaction Request Information data model +- [Table 15](#return-transaction-request-information-error) – Return Transaction Request Information Error data model +- [Table 16](#retrieve-quote-information) – Retrieve Quote Information data model +- [Table 17](#calculate-quote) – Calculate Quote data model +- [Table 18](#return-quote-information) – Return Quote Information data model +- [Table 19](#return-quote-information-error) – Return Quote Information Error data model +- [Table 20](#perform-authorization) – Perform Authorization data model +- [Table 21](#return-authorization-result) – Return Authorization Result data model +- [Table 22](#return-authorization-error) – Return Authorization Error data model +- [Table 23](#retrieve-transfer-information) – Retrieve Transfer Information data model +- [Table 24](#perform-transfer) – Perform Transfer data model +- [Table 25](#return-transfer-information) – Return Transfer Information data model +- [Table 26](#return-transfer-information-error) – Return Transfer Information Error data model +- [Table 27](#retrieve-transaction-information) – Retrieve Transaction Information data model +- [Table 28](#return-transaction-information) – Return Transaction Information data model +- [Table 29](#return-transaction-information-error) – Return Transaction Information Error data model +- [Table 30](#retrieve-bulk-quote-information) – Retrieve Bulk Quote data model +- [Table 31](#calculate-bulk-quote) – Calculate Bulk Quote data model +- [Table 32](#return-bulk-quote-information) – Return Bulk Quote Information data model +- [Table 33](#return-bulk-quote-information-error) – Return Bulk Quote Information Error data model +- [Table 34](#retrieve-bulk-transfer-information) – Retrieve Bulk Transfer Information data model +- [Table 35](#perform-bulk-transfer) – Perform Bulk Transfer data model +- [Table 36](#return-bulk-transfer-information) – Return Bulk Transfer Information data model +- [Table 37](#return-bulk-transfer-information-error) – Return Bulk Transfer Information Error data model +- [Table 38](#results-for-validated-amount-values) – Example results for different values for Amount type +- [Table 39](#amounttype-element) – Element AmountType +- [Table 40](#authenticationtype-element) – Element AuthenticationType +- [Table 41](#authenticationvalue-element) – Element AuthenticationValue +- [Table 42](#authorizationresponse-element) – Element AuthorizationResponse +- [Table 43](#balanceofpayments-element) – Element BalanceOfPayments +- [Table 44](#bulktransferstate-element) – Element BulkTransferState +- [Table 45](#code-element) – Element Code +- [Table 46](#correlationid-element) – Element CorrelationId +- [Table 47](#currency-element) – Element Currency +- [Table 48](#dateofbirth-element) – Element DateOfBirth +- [Table 49](#errorcode-element) – Element ErrorCode +- [Table 50](#errordescription-element) – Element ErrorDescription +- [Table 51](#extensionkey-element) – Element ExtensionKey +- [Table 52](#extensionvalue-element) – Element ExtensionValue +- [Table 53](#firstname-element) – Element FirstName +- [Table 54](#fspid-element) – Element FspId +- [Table 55](#ilpcondition-element) – Element IlpCondition +- [Table 56](#ilpfulfilment-element) – Element IlpFulfilment +- [Table 57](#ilppacket-element) – Element IlpPacket +- [Table 58](#lastname-element) – Element LastName +- [Table 59](#merchantclassificationcode-element) – Element MerchantClassificationCode +- [Table 60](#middlename-element) – Element MiddleName +- [Table 61](#note-element) – Element Note +- [Table 62](#nrofretries-element) – Element NrOfRetries +- [Table 63](#partyidentifier-element) – Element PartyIdentifier +- [Table 64](#partyidtype-element) – Element PartyIdType +- [Table 65](#partyname-element) – Element PartyName +- [Table 66](#partysubidortype-element) – Element PartySubIdOrType +- [Table 67](#refundreason-element) – Element RefundReason +- [Table 68](#transactioninitiator-element) – Element TransactionInitiator +- [Table 69](#transactioninitiatortype-element) – Element TransactionInitiatorType +- [Table 70](#transactionrequeststate-element) – Element TransactionRequestState +- [Table 71](#transactionscenario-element) – Element TransactionScenario +- [Table 72](#transactionstate-element) – Element TransactionState +- [Table 73](#transferstate-element) – Element TransferState +- [Table 74](#transactionsubscenario-element) – Element TransactionSubScenario +- [Table 75](#authenticationinfo) – Complex type AuthenticationInfo +- [Table 76](#errorinformation) – Complex type ErrorInformation +- [Table 77](#extension) – Complex type Extension +- [Table 78](#extensionlist) – Complex type ExtensionList +- [Table 79](#individualquote) – Complex type IndividualQuote +- [Table 80](#individualquoteresult) – Complex type IndividualQuoteResult +- [Table 81](#individualtransfer) – Complex type IndividualTransfer +- [Table 82](#individualtransferresult) – Complex type IndividualTransferResult +- [Table 83](#geocode) – Complex type GeoCode +- [Table 84](#money) – Complex type Money +- [Table 85](#party) – Complex type Party +- [Table 86](#partycomplexname) – Complex type PartyComplexName +- [Table 87](#partyidinfo) – Complex type PartyIdInfo +- [Table 88](#partypersonalinfo) – Complex type PartyPersonalInfo +- [Table 89](#partyresult) – Complex type PartyResult +- [Table 90](#refund) – Complex type Refund +- [Table 91](#transaction) – Complex type Transaction +- [Table 92](#transactiontype) – Complex type TransactionType +- [Table 93](#amounttype-enum) – Enumeration AmountType +- [Table 94](#authenticationtype-enum) – Enumeration AuthenticationType +- [Table 95](#authorizationresponse-enum) – Enumeration AuthorizationResponse +- [Table 96](#bulktransferstate-enum) – Enumeration BulkTransferState +- [Table 97](#partyIdtype-enum) – Enumeration PartyIdType +- [Table 98](#personalidentifiertype-enum) – Enumeration PersonalIdentifierType +- [Table 99](#transactioninitiator-enum) – Enumeration TransactionInitiator +- [Table 100](#transactioninitiatortype-enum) – Enumeration TransactionInitiatorType +- [Table 101](#transactionrequeststate-enum) – Enumeration TransactionRequestState +- [Table 102](#transactionscenario-enum) – Enumeration TransactionScenario +- [Table 103](#transactionstate-enum) – Enumeration TransactionState +- [Table 104](#transferstate-enum) – Enumeration TransferState +- [Table 105](#461-communication-errors-–-1xxx) – Communication errors – 1xxx +- [Table 106](#462-server-errors-–-2xxx) – Server errors – 2xxx +- [Table 107](#client-errors-–-3xxx) – Generic client errors – 30xx +- [Table 108](#client-errors-–-3xxx) – Validation Errors – 31xx +- [Table 109](#client-errors-–-3xxx) – Identifier Errors – 32xx +- [Table 110](#client-errors-–-3xxx) – Expired Errors – 33xx +- [Table 111](#463-payer-errors-–-4xxx) – Payer errors – 4xxx +- [Table 112](#464-payee-errors-–-5xxx) – Payee errors – 5xxx + + +## Table of Listings +- [Listing 1](#regular-expression) – Regular expression for data type UndefinedEnum +- [Listing 2](#regular-expression-2) – Regular expression for data type Name +- [Listing 3](#regular-expression-3) – Regular expression for data type Integer +- [Listing 4](#regular-expression-4) – Regular expression for data type OtpValue +- [Listing 5](#regular-expression-5) – Regular expression for data type BopCode +- [Listing 6](#regular-expression-6) – Regular expression for data type ErrorCode +- [Listing 7](#regular-expression-7) – Regular expression for data type TokenCode +- [Listing 8](#regular-expression-8) - Regular expression for data type MerchantClassificationCode +- [Listing 9](#regular-expression-9) – Regular expression for data type Latitude +- [Listing 10](#regular-expression-10) – Regular expression for data type Longitude +- [Listing 11](#regular-expression-11) – Regular expression for data type Amount +- [Listing 12](#regular-expression-12) – Regular expression for data type DateTime +- [Listing 13](#regular-expression-13) – Regular expression for data type Date +- [Listing 14](#regular-expression-14) – Regular expression for data type UUID +- [Listing 15](#regular-expression-15) – Regular expression for data type BinaryString +- [Listing 16](#regular-expression-16) – Regular expression for data type BinaryString32 diff --git a/website/versioned_docs/v1.0.1/api/fspiop/pki-best-practices.md b/website/versioned_docs/v1.0.1/api/fspiop/pki-best-practices.md new file mode 100644 index 000000000..8b3b33e82 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/pki-best-practices.md @@ -0,0 +1,703 @@ +# Public Key Infrastructure Best Practices + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| + +## Introduction + +This document explains _Public Key Infrastructure_ (PKI)1 best practices to apply in an _Open API for FSP Interoperability_ (hereafter cited as “the API”) deployment. See [PKI Background](#pki-background) section for more information about PKI. + +The API should be implemented in an environment that consists of either: + +- _Financial Service Providers_ (FSPs) that communicate with other FSPs (in a bilateral setup) or + +- A _Switch_ that acts as an intermediary platform between FSP platforms. There is also an _Account Lookup System_ (ALS) available to identify in which FSP an account holder is located. + +For more information about the environment, see [Network Topology](#network-topology) section. [Certificate Authority PKI Management Strategy](#certificate-authority-pki-management-strategy) and [Platform PKI Management Strategy](#platform-pki-management-strategy) identify management strategies for the CA and for the platform. + +Communication between platforms is performed using a REST (REpresentational State Transfer)-based HTTP protocol (for more information, see _API Definition_). Because this protocol does not provide a means for ensuring either integrity or confidentiality between platforms, extra security layers must be added to protect sensitive information from alteration or exposure to unauthorized parties. + +
    + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](./logical-data-model) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](./json-binding-rules) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](#) + +- [Signature](./v1.1/signature) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](./glossary) + +
    + + +## PKI Background + +Public Key Infrastructure (PKI) is a set of standards, procedures, and software for implementing authentication using public key cryptography. PKI is used to request, install, configure, manage and revoke digital certificates. PKI offers authentication using digital certificates; these digital certificates are signed and provided by _Certificate Authorities_ (CA). + +PKI uses public key cryptography and works with X.509 standard certificates. It also provides features such as: + +- User authentication + +- Certificate production and distribution + +- Certificate maintenance, management, and revocation + +PKI consists of a number of components that enable the infrastructure to work; it is not a single process or algorithm. In addition to authentication, PKI also enables the provision of integrity, non-repudiation and encryption. + +To obtain a public key, a company must obtain a digital certificate. It should request this certificate from a CA or a _Registration Authority_ (RA) - an organization that processes requests on behalf of a CA. All participants must trust the CA to manage and maintain certificates. The CA requires the company to supply a number of details (_Common Name_ (CN), _Organization_ (O), _Country_ (C) and so on) and validate their request before it provides a certificate. This certificate is proof that the company is who it says it is in the digital world (like a passport in the real world). + +PKI combines well with a _Diffie-Hellman solution_ (a secure mechanism for exchanging a shared symmetric key between two anonymous peers) in providing secure key exchanges. Because Diffie-Hellman does not provide authentication, PKI is used with additional protocols, such as _Pretty Good Privacy_ (PGP) and _Transport Layer Security_ (TLS). + +### Layered Protection + +The API should be used with protection at both the transport- and application-level. + +#### Transport-Level Protection + +To protect the transport level, _Transport Layer Security_2 (TLS) should be used. TLS is a fundamental technique used for securing point-to-point communication. It has been proven to be stable and secure when using strong algorithms with the most recent versions of TLS, and is widely used around the world. TLS is a secure mechanism for exchanging a shared symmetric key between two anonymous peers, with identity verification (that is, trusted certificates). It provides _confidentiality_ (no one has read the content) and _integrity_ (no one has changed the content). Using TLS efficiently as-is requires certificate management. + +#### Application-Level Protection + +This layer provides end-to-end integrity and confidentiality. The API uses the JSON Web Signature3 (JWS) standard for integrity and _non-repudiation_ (provide proof of the integrity and origin of data), and the JSON Web Encryption (JWE) 4 standard for confidentiality. An extended version of JWE is used to support field level encryption. + +Using these standards requires certificate management; therefore, _Certificate Authorities_ (CA) and related PKI techniques are needed. For more information, see PKI Background. + +## Network Topology + +This section identifies the platforms that constitute the API. + +### Platforms Point-to-Point Layout + +Figure 1 shows an example platform point-to-point layout. + +![Figure1 Platforms Layout](../assets/figure1-platforms-layout.svg) + +**Figure 1 - Platforms layout** + +All communication between platforms must be TLS-secured using _client authentication_, also known as _mutual authentication_. + +### Platform Roles + +#### Certificate Authority (CA) + +The CA performs the following functions: + +- Sign _Certificate Signing Requests_ (CSRs) - CSRs is a secure mechanism for exchanging a shared symmetric key between two anonymous peers. The CA signs different types of certificates (for example, TLS, Content signature, Content encryption). + +- Revoke certificates – Mark one or more certificates as invalid. + +- Support CRLs – Maintain and provide certificate revocation lists (CRLs) to be downloaded by clients so that they can see which certificates have been revoked. + +- Support Online Certificate Status Protocol (OCSP) – Provide real-time certificate revocation checks. + +#### Account Lookup System (ALS) + +- Holds basic information about account holders. + +- Answer questions like “Where should I send my financial transaction request for account holder with **MSISDN 0123456**?” + +#### Financial Services Provider (FSP) + +Has account holders to which or from which money is transferred. + +#### Switch + +- Relays transaction information to other platforms. + +- Can perform financial services, as specified in _API Definition_. + +## Certificate Authority PKI Management Strategy + +This section describes the PKI management strategy for Certificate Authorities. + +### Certificate Authority Importance and Selection Criteria + +The Certificate Authority (CA) role is important because: + +- The CA provides a single legal entity that is trustworthy for all platforms. + +- The point-to-point TLS protocol depends on certificates. + +- The end-to-end protocols JWS and JWE depend on certificates for proof of non-repudiation and confidentiality. + +#### Reasons Not to Use a Public CA + +- A public CA can revoke the intermediate certificate used for signing our certificates, thus effectively shutting down all communication between platforms. + +- A public CA also signs certificates which are not part of the _Open API for FSP Interoperability_ setup. Because you trust the certificate the CA signed for you, you then trust all certificates signed by that CA. + +- There is no service in the _Open API for FSP Interoperability_ setup that is open to the public, so there is no reason to have a public CA already trusted by public clients (such as web browsers). + +#### Private CA Options + +- Build your own CA from scratch + +- Build a CA using existing tools (for example, _openssl_) + +- Use a full-featured CA (for example, the open source product _EJBCA_) + +### Trusted Certificate Chain + +A centralized CA makes certificate management easier for the involved platforms. By trusting the same CA certificate, each platform need only trust one certificate; the CA’s self-signed root certificate. + +Thus, the CA should sign all types of certificates (TLS, signature, and encryption), but only for the participants in the _Open API for FSP Interoperability_ setup. + +No intermediate CA certificates are required, because a segmented layout is not used in the _Open API for FSP Interoperability_ setup. + +### CA Root Certificate + +- The CA must create a self-signed root certificate to be used for signing all supported types of certificates (TLS, signing, and encryption). + +- The minimum key length of the asymmetric RSA key pair is 4096 bits, and the signature algorithm should be sha512WithRSAEncryption. + +- The _X.509 Basic Constraints_ must have the attribute **CA** set to **TRUE**. + +- The time validity of the CA root certificate should be ten years. After eight years, a new self-signed root certificate should be created by the CA; the asymmetric RSA key pair must be recreated, not reused. This certificate becomes the certificate to use for signing the platforms CSRs. However, the old CA root certificate must still be active until it expires. This gives the platforms a window of two years to change the CA root certificate without disturbing their ongoing secured communication. + +### Signing Platforms CSRs + +The CA must provide a mechanism for the platforms to get their CSRs signed. Common signing methods are by email and by a web page. The chosen solution and policy must be known to the platforms. + +The CA signs three types of platform certificates; TLS (for communication), JWS (for signature) and JWE (for encryption). Common requirements for these certificates are: + +- The minimum key length of the asymmetric RSA key pair is 2048 bits, and the signature algorithm should be sha256WithRSAEncryption. + +- The _X.509 Basic Constraints_ must have the attribute **CA** set to **FALSE**. + +- The subject distinguished names must contain at least the following attributes: + + - _Common Name_ (CN) – This must be the hostname of the platform which has created the certificate. A N can never be the same for two different platforms or organizations. + + - _Organization_ (O) – The name of the organization. + + - _Country_ (C) – The country of the organization. + +- The URL for platforms to download CRLs must be present. + +- The URL for platforms to send OCSP requests must be present. + +- The time validity should be two years. + +Depending on the type of certificate to sign, the _X.509 Key Usage_ and X.509 Extended Key Usage of the platform’s certificate will differ; see Table 1 for more information. + +| Certificate Type | X.509 Key Usage | X.509 Extended Key Usage | +| --- | --- | --- | +| **TLS Certificates** | Digital Signature, Key Encipherment | TLS Web Server Authentication, TLS Web Client Authentication | +| **Signature Certificates** | Digital Signature | | +| **Encryption Certificates** | Key Encipherment | | + +**Table 1 – Certificate type and key usage** + +### Revoking Certificates + +- The CA must be able to revoke a platform’s certificates. Revoking a certificate means that it will no longer be trusted by any party. It will be marked as invalid by the CA and its revocation status published to the platforms, either in a revocation list (CRL) to be downloaded by platforms, or through a real-time HTTP query using _Online Certificate Status Protocol_ (OCSP) requested by platforms. + +- The CA should support both CRL downloads and OCSP queries. + +- The CA should update and sign the CRL daily and should provide (daily) a HTTP URL to the platforms that points to the CRL to be downloaded. The URL should be stored in the _CRL Distribution Points_ for each signed certificate. + +- The OCSP URL should be stored in the _Authority Information Access_ for each signed certificate. An OCSP response must be signed. Nonce values in an OCSP request should be supported to prevent reply attacks. + +- The CA has the right to revoke certificates, but no obligation to inform the platforms about such revocations. The platforms do not have the right to revoke certificates, but they do have an obligation to check regularly for a certificate’s revocation status. + +### Certificate Enrollment and Renewal + +The CA does not support enrollment or renewal of certificates for which an asymmetric key pair is reused. For increased security, the asymmetric key pairs must be recreated every time a certificate is enrolled or renewed through a new CSR. + +## Platform PKI Management Strategy + +This section describes the PKI management strategy for platforms. + +### Keys, Certificates, and Stores + +A certificate provides the identity of its owner through a trusted CA that has signed the certificate. This can be validated through its signed certificate chain. It also provides the technical means to ensure integrity (signature) and confidentiality (encryption) of data using its asymmetric key pair (known as a _public key and private key_). The public key is within the signed certificate, but its corresponding private key must be kept private and protected. A common solution for handling certificates and private keys is to put them into a protected storage area known as a store. A store can be a file, directory, or something else that provides access and confidentiality. + +A single private key and its associated certificate can be used for all cryptographic purposes, but to enhance security, the following set of keys and certificates is required for each platform: + +- One private key and certificate for TLS communication + +- One private key and certificate for end-to-end integrity using JWS + +- One private key and certificate for end-to-end confidentiality using JWE + +Different keys and types of certificates can all be in the same store, but a more common setup is the following: + +- For TLS communication: + + - One protected key store to hold the private key, its associated certificate, and certificate chain. These items are used for server- and client authentication in TLS. + + - One protected certificate store to hold all trusted TLS certificates. These certificates will be trusted by your platform during a TLS handshake, meaning that they will allow secure communication with the owners of the certificates. Since all participants trust the same CA, it is sufficient to keep only the CA’s root certificate here. + +- For signature and encryption: + + - One protected key store to hold your private keys, their associated certificates, and certificate chains used for signatures and encryption. + + - One private key and certificate chain used for signing using JWS, and one private key and certificate chain used for encryption using JWE. + + - One protected certificate store to hold all trusted signature and encryption certificates from other platforms. Here you must store the certificates (signature and encryption certificates) for each platform that you want to trust for end-to-end integrity and confidentiality. + +### Creating a CSR and Obtaining CA Signature + +To be able to communicate with other platforms, you must create a key store (if one does not already exist), an asymmetric key pair, and an associated certificate that identifies your platform. This unsigned certificate must be signed by the CA before it can be trusted by other platforms. The procedure of getting a certificate signed by a CA begins with a CSR (_Certificate Signing Request_). + +When you create your keys, certificates, and CSRs, the following requirements apply: + +- The minimum key length of the asymmetric RSA key pair is 2048 bits, and the signature algorithm is sha256WithRSAEncryption. + +- The following attributes in the subject distinguished names are mandatory: + + - Common Name (CN) – This must be the hostname of the platform who created the certificate. A CN can never be the same for two different platforms or organizations. + + - Organization (O) – The name of the organization. + + - Country (C) – The country of the organization. + +**For examples of how to create a store, certificate, and CSR, see Appendix C – Common PKI Tasks** + +How to create a store, certificate, and CSR. + +Create your CSR and send it to your CA according to their instructions. + +**Note:** The same procedure must be performed for all your different keys and certificates (TLS, signature, and encryption). + +### Importing a Signed CSR + +After signing your CSR, you will have two certificates in your response from the CA. The first certificate is your own signed certificate. The second is the CA’s own root certificate, which was used for signing your certificate. That certificate must now be trusted by you. + +First you must import your signed certificate into your key store. It must replace your unsigned certificate. For examples, see How to import a signed certificate into your key store. + +Then you must import the CA’s root certificate into the same key store to complete the chain between your certificate and the CA. For examples, see How to import the CA certificate into your key store. + +#### TLS Certificates + +For TLS certificates, you must also import the CA’s root certificate into your TLS trust store to automatically trust the other platforms when establishing new communication channels with them. For examples, see How to import the CA certificate into TLS trust store. + +The above procedure should be performed for each of your signed CSRs. Remember to send your signed certificate and the CA’s root certificate to all other platforms with which you need to communicate. + +The CA will create a validity period of two years for your signed certificate. After 18 months, you should create a new CSR to be signed by the same CA. Your newly signed certificate and the CA’s root certificate should once again be imported into your stores and sent to the other platforms. This will give you and your peers a window of six months to make sure that your new signed certificate works. After two years, the old expired certificate can be deleted. + +### Trusting Certificates from Other Platforms + +Just as your peers must have your certificates to be able to trust you, they must send their certificates to you for you to trust them. + +Make sure that you always receive at least two certificates from a trusted peer: + +- The signed certificate of the peer to trust. + +- The root certificate of the CA that signed the peer’s certificate. + +**Note:** A peer’s CA certificate can differ from yours. This can happen if the CA has created a new CA root certificate when the old one is about to expire. + +You should always view a peer’s certificates (check CN, validity period, and so on) and validate the certificate chain (that is, that each certificate is correctly signed by the given CA) before you import them into your trust store. + +For examples, see How to view a certificate. + +Next, import the peer’s certificate and its CA root certificate into your trust store. For examples, see How to import a trusted certificate. + +### Checking Certificate Revocation Status + +Certificates can be revoked by the CA. A revoked certificate is considered not trusted and should be removed from the trust store. A certificate can also be _on hold_, which means that it is in pending state due to investigation and should not be removed. + +All platforms should perform revocation checks on a regular basis. There are two common ways to find out which certificates have been revoked; either through viewing a revocation list (CRL) to be downloaded by platforms, or through a real-time HTTP query (OCSP) requested by platforms. + +#### Certificate Revocation List + +This is a file maintained by a CA. It contains a list of certificate serial numbers that have been revoked by the CA. This file can be downloaded by any platform at any time. The URL to the CRL file to be downloaded is included in the certificate itself and can be found in _CRL Distribution Points_. A CRL is signed by the CA and should be validated. + +A CRL should be downloaded once per day and cached by the platform. + +For examples, see How to verify a certificate through a CRL. + +#### Online Certificate Status Protocol + +The status of a certificate can be retrieved by sending an OCSP request to an _OCSP Responder_ (which can be the CA). The request contains the serial number of the certificate to be checked. The responder sends back a signed response including the status of the certificate. + +The request should contain a nonce value, which the responder will put in the response, for the platform to validate on receipt. This is to prevent reply attacks. + +An OCSP request/response is considered very fast and can be executed for each received client certificate operation, but depending on the load towards the responder, it might have to be cached by the platform as well. + +The OCSP URL is included in the certificate itself and can be found in _Authority Information Access_. + +For examples, see How to verify a certificate through an OCSP request. + +### Renewing Certificates + +Do not renew certificates for which an asymmetric key pair is reused. For increased security, the asymmetric key pairs must be recreated every time through a new CSR. + +## Transport Layer Protection + +This section describes transport layer protection. + +### TLS + +TLS provides point-to-point integrity and confidentiality, and is used for all communication between peers. + +The setup requires both _server authentication_ - meaning that the server presents itself through its own TLS certificate - and _client authentication_ (also known as mutual authentication) in which the client presents itself through its own TLS certificate. + +#### TLS Protocol Versions + +The TLS protocol version used must be 1.2 or higher. + +#### TLS Cipher Suites + +The following cipher suites should be used: + +- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + +- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + +- TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + +- TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + +- TLS_RSA_WITH_AES_256_GCM_SHA384 + +- TLS_RSA_WITH_AES_128_GCM_SHA256 + +## Application Layer Protection + +This section describes the application layer protection. + +### JSON Web Signature + +The _JSON Web Signature_ (JWS) standard is used for providing end-to-end integrity and non-repudiation; that is, to guarantee that the sender is who it claims to be, and that the message was not tampered with. + +The use of JWS is mandatory and certificates should be used. For more information, see _API Signature_. + +### JSON Web Encryption + +The _JSON Web Encryption_ (JWE) standard is used for providing end-to-end confidentiality; that is, to protect data from being read by unauthorized parties. + +The use of JWE is optional and is applied to specific fields. This is to fulfill regulatory requirements that might exist for certain type of data in certain countries. + +For more information about how to apply JWE to fields in messages, see the extended JWE standard specification _API Encryption_. + + +## List of Appendices + +### Appendix A - Key Lengths and Algorithms + +Table 2 contains the required key length and algorithm for each entity. + +| Entity | Algorithm | Key length/hash size | +| --- | --- | --- | +| CA asymmetric keys | RSA | 4096 bits | +| CA signing algorithm | RSA with SHA2 | >= 256 bits | +| TLS asymmetric keys | RSA | 2048 bits | +| TLS signing algorithm | RSA with SHA2 | >= 256 bits | +| Signature asymmetric keys | RSA | 2048 bits | +| Signature algorithm | RSA with SHA2 | >= 256 bits | +| Encryption asymmetric keys | RSA | 2048 bits | +| HMAC | SHA2 - AES | >= 256 bits| +| Symmetric keys | AES | 256 bits | +| Hashing | SHA2 | >= 256 bits | + +**Table 2 – Key lengths and algorithms** + +### Appendix B - Terminology + +| | | +| --- | --- | +| PKI | Public Key Infrastructure +| API | Application Program Interface +| TLS | Transport Layer Security +| JWS | JSON Web Signature +| JWE | JSON Web Encryption +| FSP | Financial Service Provider +| AL | Account Lookup +| CA | Certificate Authority +| CSR | Certificate Signing Request +| CRL | Certificate Revocation List +| OCSP | Online Certificate Status Protocol +| PEM | Privacy Enhanced Mail +| RSA | Rivest, Shamir, & Adleman +| HMA | Hashed Message Authentication Code +| AES | Advanced Encryption Standard +| SHA | Secure Hash Algorithm + +### Appendix C - Common PKI Tasks + +#### Appendix C.1 - How to create a store, certificate, and CSR + +**Using the Java keytool** + +Use the following command to create an asymmetric RSA key pair and associated certificate information to be signed by the +CA. It will automatically create a JKS key store if the given one does not exist: + +``` +keytool -genkey -dname "CN=" -alias -keyalg RSA - +keystore -keysize 2048 +``` + +**Example** + +``` +keytool -genkey -dname "CN=bank-fsp" -alias tlscert -keyalg RSA -keystore +tlskeystore.jks -keysize 2048 +``` + +**Notes:** + +1. The certificate attribute CN specifies the hostname of the host who identifies itself using this certificate during a TLS session. +2. When asked for password, use the same password for the key as the key store. + +Use the following command to create the actual CSR to be signed by the CA: + +``` +keytool -certreq -alias -keystore –file .csr +``` + +**Example** + +``` +keytool -certreq -alias tlscert -keystore tlskeystore.jks -file tlscert.csr +``` + +**Using openssl** + +Use the following command to create an asymmetric RSA key pair, and CSR to be signed by the CA: + +``` +openssl req -new -newkey rsa:2048 -nodes -subj "/CN=" -out +.csr -keyout .key +``` + +**Example** + +``` +openssl req -new -newkey rsa:2048 -nodes -subj "/CN=bank-fsp" -out tlscert.csr - +keyout tlscert.key +``` + +**Note:** The certificate attribute CN specifies the hostname of the host who identifies itself using this certificate during a TLS session. + +Important to note is that the created private key is stored unencrypted. Use the following command to encrypt it: + +``` +openssl rsa -aes256 -in -out +``` + +**Example** + +``` +openssl rsa -aes256 -in tlscert.key -out tlscert_encrypted.key +``` + +#### Appendix C.2 - How to import a signed certificate into your key store + +**Using the Java keytool** + +Import your signed certificate into your key store. This certificate should replace the old unsigned one, so make sure that you use the correct alias. + +``` +keytool -importcert -alias -file -keystore +``` + +**Example** + +``` +keytool -importcert -alias tlscert -file bank-fsp.pem -keystore tlskeystore.jks +``` + +**Using openssl** + +Remove your old CSR file and replace it with the new signed certificate. + +#### Appendix C.3 - How to import the CA certificate into your key store + +**Using Java keytool** + +Import the CA certificate into your key store: + +``` +keytool -importcert -alias -file -keystore +``` + +**Example:** + +``` +keytool -importcert -alias rootca -file rootca.pem -keystore tlskeystore.jks +``` + +When you are asked to trust the imported certificated, answer **yes**: + +``` +Trust this certificate? [no]: yes +Certificate was added to keystore +``` + +**Using openssl** + +Put the CA certificate with your other certificate files + +#### Appendix C.4 - How to import the CA certificate into TLS trust store + +**Using Java keytool** + +Import the CA certificate into your trust store: + +``` +keytool -importcert -alias -file -keystore +``` + +**Example:** + +``` +keytool -importcert -alias rootca -file rootca.pem -keystore tlstruststore.jks +``` + +When you are asked to trust the imported certificated, answer **yes**: + +``` +Trust this certificate? [no]: yes +Certificate was added to keystore +``` +**Using openssl** + +Put the CA certificate with your other certificate files. + +#### Appendix C.5 - How to view a certificate + +**Using Java keytool** + +Use this command to list all certificates stored in a key store in readable format: + +``` +keytool -list -keystore -v +``` + +**Example:** + +``` +keytool -list -keystore tlskeystore.jks -v +``` + +**Using openssl** + +Use this command to show the content of a PEM encoded certificate in readable format: + +``` +openssl x509 -in -text -nout +``` + +**Example:** + +``` +openssl x509 -in rootca.pem -text -nout +``` + +#### Appendix C.6 - How to import a trusted certificate + +**Using Java keytool** + +Import the certificate into your trust store: + +``` +keytool -importcert -alias -file -keystore +``` + +**Example:** + +``` +keytool -importcert -alias trustedcert -file cert.pem -keystore truststore.jks +``` + +When you are asked to trust the imported certificated, answer **yes**: + +``` +Trust this certificate? [no]: yes +Certificate was added to keystore +``` + +**Using openssl** + +Put the trusted certificate with your other certificate files. + +#### Appendix C.7 - How to verify a certificate through a CRL + +**Using Java** + +You can use a specific security library for this (for example, Bouncy Castle), or use the in-built support for it, see: +[https://stackoverflow.com/questions/10043376/java-x509-certificate-parsing-and-validating/10068006#10068006](#https://stackoverflow.com/questions/10043376/java-x509-certificate-parsing-and-validating/10068006#10068006) + +**Using openssl** + +A good example is found at the following link: +[https://raymii.org/s/articles/OpenSSL_manually_verify_a_certificate_against_a_CRL.html](#https://raymii.org/s/articles/OpenSSL_manually_verify_a_certificate_against_a_CRL.html) + +#### Appendix C.8 - How to verify a certificate through an OCSP request + +**Using Java** + +Some Java examples is found in the following link: +[https://stackoverflow.com/questions/5161504/ocsp-revocation-on-client-certificate](#https://stackoverflow.com/questions/5161504/ocsp-revocation-on-client-certificate) + +**Using openssl** + +A good example is found at the following link: +[https://raymii.org/s/articles/OpenSSL_Manually_Verify_a_certificate_against_an_OCSP.html](#https://raymii.org/s/articles/OpenSSL_Manually_Verify_a_certificate_against_an_OCSP.html) + + +1 This term, and other italicized terms, are defined in Glossary for Open API for FSP Interoperability Specification. + +2 [https://tools.ietf.org/html/rfc5246](#https://tools.ietf.org/html/rfc5246) - The Transport Layer Security (TLS) Protocol - Version 1.2 + +3 [https://tools.ietf.org/html/rfc7515](#https://tools.ietf.org/html/rfc7515) - JSON Web Signature (JWS) + +4 [https://tools.ietf.org/html/rfc7516](#https://tools.ietf.org/html/rfc7516) - JSON Web Encryption (JWE) + +
    + +## Table of Figures + +- [Figure 1 - Platforms layout](#platforms-point-to-point-layout) + +
    + +## Table of Tables + +- [Table 1 – Certificate type and key usage](#Table-1–Certificate-type-and-key-usage) + +- [Table 2 – Key lengths and algorithms](#Table-2-Key-lengths-and-algorithms) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/fspiop/sandbox.md b/website/versioned_docs/v1.0.1/api/fspiop/sandbox.md new file mode 100644 index 000000000..e69de29bb diff --git a/website/versioned_docs/v1.0.1/api/fspiop/scheme-rules.md b/website/versioned_docs/v1.0.1/api/fspiop/scheme-rules.md new file mode 100644 index 000000000..7aa2e4e04 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/scheme-rules.md @@ -0,0 +1,216 @@ +# Scheme Rules + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| + +## Introduction + +This document defines scheme rules for Open API for FSP Interoperability (hereafter cited as the API) in three categories. + +1. Business Scheme Rules: + + a. These business rules should be governed by FSPs and an optional regulatory authority implementing the API within a scheme. + + b. The regulatory authority or implementing authority should identify valid values for these business scheme rules in their API policy document. + +2. API implementation Scheme Rules: + + a. These API parameters should be agreed on by FSPs and the optional Switch. These parameters should be part of the implementation policy of a scheme. + + b. All participants should configure these API parameters as indicated by the API-level scheme rules for the implementation with which they are working. + +3. Security and Non-Functional Scheme Rules. + + a. Security and non-functional scheme rules should be determined and identified in the implementation policy of a scheme. + +
    + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](./logical-data-model) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](./json-binding-rules) + +- [Scheme Rules](#) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](./v1.1/signature) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](./glossary) + +
    + +## Business Scheme Rules + +This section describes the business scheme rules. The data model for the parameters in this section can be found in _API Definition._ + +#### Authentication Type + +The authentication type scheme rule controls the authentication types OTP and QR code. It lists the various authentication types available for _Payer_ authentication. A scheme can choose to support all the authentication types mentioned in “AuthenticationTypes” in _API Definition_ or a subset thereof. + +#### Consumer KYC Identification Required + +A scheme can mandate verification of consumer KYC (Know Your Customer) identification by Agent or Merchant at the time of transaction (for example, cash-out, cash-in, merchant payment). The API cannot control this scheme rule; therefore, it should be documented in scheme policy so that it is followed by all participants in a scheme. The scheme can also decide on the valid KYC proof of identification that should be accepted by all FSPs. + +#### Currency + +A scheme may recommend allowing transactions in more than one currency. This scheme may define the list of valid currencies in which transactions can be performed by participants; however, this is not required. A Switch may work as transaction router and doesn’t validate the transaction currency. If a scheme does not define the list of valid currencies, then the Switch works as transaction router and the participating FSP can accept or reject the transaction based on its supported currencies. Foreign exchange is not supported; that is, the transaction currency for the Payer and the _Payee_ should be the same. + +#### FSP ID Format + +A scheme may determine the format of the FSP ID. The FSP ID should be of string type. Each participant will be issued a unique FSP ID by the scheme. Each FSP should prepend the FSP ID to a merchant code (a unique identifier for a merchant) so that the merchant code is unique across all the participants (that is, across the scheme). The scheme can also determine an alternate strategy to ensure that FSP IDs and merchant codes are unique across participating FSPs. + +#### Interoperability Transaction Type + +The API supports the use cases documented in _Use Cases_. A scheme may recommend implementation of all the supported usecases or a subset thereof. A scheme may also recommend to rollout the use cases in phases. Two or more FSPs in the scheme might decide to implement additional use-cases supported by the API. A Switch may work as a transaction router and does not validate transaction type; the FSP can accept or reject the transaction based on its supported transaction types. If a participant FSP initiates a supported API transaction type due to incorrect configuration on the Payer end, then the transaction must be rejected by the peer FSP if the peer FSP doesn’t support the specific transaction type. + +#### Geo-Location Required + +The API supports geolocation of the Payer and the Payee; however, this is optional. A scheme can mandate the geolocation of transactions. In this case, all participants must send the geolocation of their respective party. + +#### Extension Parameters + +The API supports one or more extension parameters. A scheme can recommend that the list of extension parameters be supported. All participants must agree with the scheme rule and support the scheme-mandatory extension parameters. + +#### Merchant Code Format + +The API supports merchant payment transaction. Typically, a consumer either enters or scans a merchant code to initiate merchant payment. In case of merchant payment, the merchant code should be unique across all the schemes. Currently, the merchant code is not unique in the way that mobile numbers or email addresses are unique. Therefore, it is recommended to prepend a prefix or suffix (FSP ID) to the merchant code so that the merchant code is unique across the FSPs. + +#### Max Size Bulk Payments + +The API supports the Bulk Payment use-case. The scheme can define the maximum number of transactions in a bulk payment. + +#### OTP Length + +The API supports One-time Password (OTP) as authentication type. A scheme can define the minimum and maximum length of OTP to be used by all FSPs. + +#### OTP Expiration Time + +An OTP’s expiration time is configured by each FSP. A scheme can recommend it to be uniform for all schemes so that users from different FSPs have a uniform user experience. + +#### Party ID Types + +The API supports account lookup system. An account lookup can be performed based on valid party ID types of a party. A scheme can choose which party ID types to support from **PartyIDType** in API Definition. + +#### Personal Identifier Types + +A scheme can choose the valid or supported personal identifier types mentioned in **PersonalIdentifierType** in API Definition. + +#### QR Code Format + +A scheme should standardize the QR code format in the following two scenarios as indicated. + +##### Payer-Initiated transaction + +Payer scans the QR code of Payee (Merchant) to initiate a Payer-Initiated Transaction. In this case, the QR code should be standardized to include the Payee information, transaction amount, transaction type and transaction note, if any. The scheme should standardize the format of QR code for Payee. + +##### Payee-Initiated Transaction + +Payee scans the QR code of Payer to initiate Payee-Initiated transaction. For example: Merchant scans the QR code of Payer to initiate a Merchant Payment. In this case, the QR code should be standardized to locate the Payer without using the account lookup system. The scheme should standardize the format of QR code; that is, FSP ID, Party ID Type and Payer ID, or only Party ID Type and Party ID. + +## API Implementation Scheme Rules + +This section describes API implementation scheme rules. + +#### API Version + +API version information must be included in all API calls as defined in _API Definition_. A scheme should recommend that all FSPs implement the same version of the API. + +#### HTTP or HTTPS + +The API supports both HTTP and HTTPS. A scheme should recommend that the communication is secured using TLS (see [Communication Security](#communication-security) section). + +#### HTTP Timeout + +FSPs and Switch should configure HTTP timeout. If FSP doesn’t get HTTP response (either **HTTP 202** or **HTTP 200**) for the **POST** or **PUT** request then FSP should timeout. Refer to the diagram in Figure 1 for the **HTTP 202** and **HTTP 200** timeouts shown in dashed lines. + +###### Figure-1 + +![Figure 1 HTTP Timeout](../assets/scheme-rules-figure-1-http-timeout.png) + +**Figure 1 – HTTP Timeout** + +#### Callback Timeouts + +The FSPs and the Switch should configure callback timeouts. The callback timeouts of the initiating FSP should be greater than the callback timeout of the Switch. A scheme should determine callback timeout for the initiating FSP and the Switch. Refer to the diagram in Figure 2 for the callback timeouts highlighted in red. + +###### Figure-2 + +![Figure 1 Callback Timeout](../assets/scheme-rules-figure-2-callback-timeout.png) + + +**Figure 2 – Callback Timeout** + +## Security and Non-Functional Requirements Scheme Rules + +This section describes the scheme rules for security, environment and other network requirements. + +#### Clock Synchronization + +It is important to synchronize clocks between FSPs and Switches. It is recommended that an NTP server or servers be used for clock synchronization. + +#### Data Field Encryption + +Data fields that need to be encrypted will be determined by national and local laws, and any standard that must be complied with. Encryption should follow _Encryption_. + +#### Digital Signing of Message + +A scheme can decide that all messages must be signed as described in _Signature_. Response messages need not to be signed. + +#### Digital Certificates + +To use the signing and encryption features detailed in _Signature_ and _Encryption_ in a scheme, FSPs and Switches must obtain digital certificates as specified by the scheme-designated _CA_ (Certificate Authority). + +#### Cryptographic Requirement + +All parties must support the encoding and encryption ciphers as specified in _Encryption_, if encryption features are to be used in the scheme. + +#### Communication Security + +A scheme should require that all HTTP communication between parties is secured using TLS[1](https://tools.ietf.org/html/rfc5246) version 1.2 or later. + +1 [https://tools.ietf.org/html/rfc5246](https://tools.ietf.org/html/rfc5246) - The Transport Layer Security (TLS) Protocol - Version 1.2 + + +### Table of Figures + +[Figure 1 – HTTP Timeout](#figure-1) + +[Figure 2 – Callback](#figure-2) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/fspiop/use-cases.md b/website/versioned_docs/v1.0.1/api/fspiop/use-cases.md new file mode 100644 index 000000000..bb076dc26 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/use-cases.md @@ -0,0 +1,1098 @@ +# Use Cases + + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| + +
    + +## Introduction + +The purpose of this document is to define a set of use cases that can be implemented using the Open API for FSP interoperability (hereafter cited as the API). The use cases referenced within this document provide an overview of transaction processing flows and business rules of each transaction step as well as relevant error conditions. + +The primary purpose of the API is to support the movement of financial transactions between one _Financial Services Provider_ (FSP) and another. + +It should be noted that the API is only responsible for message exchange between FSPs and a Switch when a cross-FSP transaction is initiated by an _End User_ in one of the FSPs. This can occur in either of two scenarios: + +- A bilateral scenario in which FSPs communicate with each other + +- A Switch based scenario in which all communication goes through a Switch + +Reconciliation, clearing and settlement after real time transactions is out of scope for the API. Additionally, account lookup is supported by the API, but it relies on the implementation in a local market in which a third party or Switch would provide such services. Therefore, the need for effective on-boarding processes and appropriate scheme rules must be considered when implementing use cases. + +
    + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### General Documents + +- _Glossary_ + +#### Logical Documents + +- _Logical Data Model_ + +- _Generic Transaction Patterns_ + +- _Use Cases_ + +#### Asynchronous REST Binding Documents + +- _API Definition_ + +- _JSON Binding Rules_ + +- _Scheme Rules_ + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- _PKI Best Practices_ + +- _Signature_ + +- _Encryption_ + +
    + +## Use Case Summaries + +The following generic transaction patterns are introduced in [Generic Transaction Patterns]() to reduce duplication of each use case description. These patterns summarize the common transaction process flows and shared function of the relevant use cases. + +- **Payer-Initiated Transaction** + - In a _Payer-Initiated Transaction_, it is the _Payer_ (that is, the payer of electronic funds) who initiates the transaction. + + The pattern should be used whenever a Payer would like to transfer funds to another party whose account is not located in the same FSP. + +- **Payee-Initiated Transaction** + + - In a _Payee-Initiated Transaction_, it is the _Payee_ (that is, the recipient of electronic funds) who initiates the transaction. + + This pattern should be used whenever a Payee would like to receive funds from another party whose account is not located in the same FSP. + +- **Payee-Initiated Transaction using OTP** + + - A _Payee-Initiated Transaction using One-Time Password (OTP)_ is like a _Payee-Initiated Transaction_, but the transaction information (including fees and taxes) and approval for the Payer is shown or entered on a Payee device instead. + + - This pattern should be used when a Payee would like to receive funds from another party whose account is not located in the same FSP, and both the transaction information (including fees and taxes) and approval is shown or entered on a Payee device instead. + +- **Bulk Transactions** + + - In a _Bulk Transaction_, it is the Payer (that is, the sender of funds) who initiates multiple transactions to multiple Payees, potentially located in different FSPs. + + - The pattern should be used whenever a Payer would like to transfer funds to multiple Payees in the same transaction. The Payees can potentially be in different FSPs. + +It is recommended to read all Generic Transaction Patterns before reading the use cases. For more information, see [Generic Transaction Patterns](). + +Each use case describes variations on and special considerations for the generic transaction pattern to which it refers. The use cases are introduced in [Table 1](#table-1) below: + +##### Table 1 + +| Use Case Name | Description | +| --- | --- | +| P2P |This use case describes the business process and business rules in which an individual End User initiates a transaction to send money to another individual End User who doesn’t belong to the same FSP as the Payer.

    This is usually a remote transaction in which Payer and Payee are not in the same location. | +| Agent-Initiated Cash-In | This use case describes the business process and business rules in which a customer requests an agent of a different FSP to cash-in (deposit funds) to their account.

    This is typically a face-to-face transaction in which the customer and the agent are in the same location. | +| Agent-Initiated Cash-Out | This use case describes the business process and business rules in which a customer requests that an agent of a different FSP to cash-out (withdraw funds) from their account.

    This is typically a face-to-face transaction in which the customer and the agent are in the same location. | +| Agent-Initiated Cash-Out
    Authorized on POS
    | This use case describes the business process and business rules in which a customer requests an agent of a different FSP to cash-out (withdraw funds) from their account. In this use case, the agent initiates the transaction through a point-of-sale (_POS_) and the customer inputs OTP on POS to authorize the transaction. Alternatively, the agent can use POS to scan a QR code generated by a customer’s mobile app to initiate the transaction. | +| Customer-Initiated Cash-Out | This use case describes the business process and business rules in which a registered customer initiates a transaction to cash-out (withdraw funds) using an agent who doesn’t belong to the customer’s FSP.

    This is typically a face-to-face transaction in which the customer and the agent are in the same location. | +| Customer-Initiated Merchant
    Payment
    | This use case describes the business process and business rules in which an individual End User initiates a purchase transaction to pay a merchant who does not belong to the same FSP as the customer.

    This is usually a face to face transaction when a customer buys goods or services at a merchant store.

    A variant of this use case is online payment, in which the online shopping system generates a QR code and displays it on a web page, and the consumer then scans the QR code by handset and completes the payment transaction. | +| Merchant-Initiated Merchant
    Payment
    | This use case describes the business process and business rules in which a merchant initiates a request for payment to the customer; the customer reviews the transaction amount in the request and confirms the request by providing authentication on their own handset. | +| Merchant-Initiated Merchant
    Payment Authorized on POS
    | This use case describes the business process and business rules in which merchant initiates a request for payment from the customer; the customer reviews the payment request on a merchant device and authorizes the payment by OTP or QR code on the merchant device. The customer authentication information is sent from _Payee FSP_ to _Payer FSP_ for authentication by Payer FSP. | +| ATM-Initiated Cash-Out | This use case describes the business process and business rules in which an ATM initiates a cash-out request from a customer account. Customer pregenerates an OTP for cash-out and uses this OTP on the ATM device to initiate ATM cash-out. The Payer FSP validates the OTP received in the ATM-Initiated Cash-Out request for authentication purposes. | +| Bulk Payments | _Bulk Payments_ is used when an organization or business is paying out funds – for example, aid or salary to multiple Payees who have accounts located in the different FSPs. The organization or business can group transactions together to make it easier for uploading and validating individual transactions in bulk before the bulk transaction is executed. It is also possible for the organization to follow up the result of the individual transactions in the bulk transaction after the bulk transaction is executed. | +| Refund | This use case describes the business flow how to refund a completed interoperability transaction. | + +**Table 1 – Use Case Summary** + +
    + +## Use Cases + +This section demonstrates ways in which the API can be used through the use cases identified in [Table 1](#table-1) – _Use Case Summary_. + +For each use case, the following is presented: +- Use Case Description +- Reference to Generic Pattern +- Actors and Roles +- Addition to Generic Transaction Pattern +- Relevant Error Conditions + +### P2P + +#### Use Case Description + +This section describes the business process and business rules for a use case in which an individual End User initiates a transaction to send money to another individual End User who doesn’t belong to the same FSP as the Payer. + +This is usually a remote transaction in which Payer and Payee are not in the same location. + +There are four steps necessary to complete a _P2P_ Transfer transaction from one FSP user to another FSP user. + +##### Step 1 + +Payer initiates a transaction to their FSP, and Payer FSP then locates Payee FSP through an API call to the Account Lookup System or by the agreed-upon _scheme_ rules. + +##### Step 2 + +Payer FSP calculates the transaction fee applied to Payer. Payer FSP sends a quote request through an API call to Payee FSP. + +##### Step 3 + +Payer FSP presents the total transaction fee and Payee name (optional) to the Payer to confirm the transaction. + +##### Step 4 + +Payer accepts the transaction and Payer FSP performs the transaction through an API call to the Switch or to Payee FSP. The transaction completes and notifications are sent to both Payer and Payee; or the Payer rejects the transaction and the transaction ends. + +
    + +### Reference to Generic Pattern + +_Payer-Initiated Transaction_ + +#### Actors and Roles + +The actors and roles for P2P are described in [Table 2](#table-2) below: + +##### Table 2 + +| Role | Map to Generic Transaction Pattern | Description | +| --- | --- | --- | +| Customer | Payer | An individual who is a registered customer of an FSP who initiates a transaction to send money to another individual. | +| Customer | Payee | The person who will receive money from Payer.

    Payee could be a registered customer of Payee FSP or, if the scheme rules allow it, an unregistered customer who will be registered during the transaction process, which is determined by the design of Payee FSP. + +**Table 2 – P2P Actors and Roles** + +#### Addition to Generic Transaction Pattern + +##### Step 2 + +The Payee FSP ID could be determined by the scheme rule without any dependence on the API. Otherwise, **Lookup Party Information** request is an option for determining in which FSP a Payee is located. + +Payer FSP will use the request **Lookup Party Information** to retrieve details of Payee from Payee FSP directly if there is no Switch between Payer FSP and Payee FSP. + +##### Steps 9 – Step 15 + +In the current version of the API, the **Calculate Quote** request to Payee FSP is mandatory even if a wholesale fee is agreed upon in the scheme. Payee FSP needs to receive transaction details from the **Calculate Quote** request to generate the condition for this transaction. + +Payer FSP can use information from response **Return Quote Information** from Payee FSP to calculate the transaction fee it will apply on Payer. The business rules for how Payer FSP calculates the transaction fee could be defined by the scheme rules; this is out of scope for the API. + +In P2P Transfer case, it is the common practice that Payer pays the entire transaction fee, and Payee is free of charge in the transaction. + +##### Step 16 + +There are several ways to push a confirmation message to Payer to authorize the transaction. For example, USSD Push Message, or SMSC notification; then Payer opens the USSD menu to query and confirm the pending transaction + +The interaction between Payer and Payer FSP is designed by each FSP, and is out-of-scope for the API. + +##### Step 19 + +The Quote ID applied in the previous step is verified in the transaction processing step. If the quote is expired, Payee FSP will reject the transaction. + +##### Step 20 + +A notification is sent to the Payee once the transaction is performed by Payee FSP. + +##### Step 28 + +Payer FSP sends notification to Payer to indicate the transaction result. + +#### Relevant Error Conditions +[Table 3](#table-3) below describes relevant errors and recommended follow-up actions for this use case. + +##### Table 3 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +|2 | Timeout | **Lookup Party Information** request timed out | Retry | +|4 | Payee is unreachable | Account Lookup System fails to locate Payee| Cancel the transaction | +|6 | Currency is not supported | The transaction currency is not supported. | Initiate a new transaction with supported currency by Payee FSP | +| 9 | Timeout | **Calculate Quote** request timed out | Retry with the same ID | +|11 | Wrong quote | Payee FSP cannot provide quote due to internal business rule validation failure or system error.

    For example, invalid account status of Payee, wrong fee configuration or database error | Cancel the transaction | +|17 | Timeout | **Perform Transfer** request timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +|19 | Transaction failed | Transaction failed at Payee FSP.
    Possible reasons:
  • Limit breach
  • Payer or Payee is blacklisted
  • Quote is expired
  • Invalid account status of Payee
  • Payee FSP internal system error

  • | Cancel the transaction | +|22 | Funds reservation timed out | Funds reservation at Payer FSP is timed out and the transaction fails at Payer FSP but succeeds at Payee FSP. | Reconcile according to the scheme rules + +**Table 3 – P2P Relevant Error Conditions** + +
    + +### Agent-Initiated Cash-In + +#### Use Case Description + +This section describes the business process and business rules for the use case in which a customer requests an agent of a different FSP to cash-in (deposit funds) to their account. This is a two-step transaction: Agent initiates a cash-in transaction from their handset or POS and then receives transaction information including possible fees. Agent can either approve or reject the transaction. Once transaction is completed, the customer gives cash to the agent. + +Agent-Initiated Cash-In is typically a face-to-face transaction in which the customer and the agent are in the same location. + +#### Reference to Generic Pattern + +_Payer-Initiated Transaction_ + +#### Actors and Roles + +The actors and roles for Agent-Initiated Cash-In are described in [Table 4](#table-4) below: + +| Role | Map to Generic Transaction Pattern | Description | +| --- | --- | --- | +|Agent | Payer | Payer is an agent (individual or organization) who will receive cash from the customer and transfer money to the customer’s account.

    Agent is a registered party with Payer FSP. | +| Customer | Payee | Customer is an individual who would like to deposit cash into their account.

    Customer is a registered individual in Payee FSP. | + +**Table 4 – Agent-Initiated Cash-In: Actors and Roles** + +#### Addition to Generic Transaction Pattern + +##### Step 1 + +Customer requests that an agent cash-in to their account. + +If a smart phone is used, the agent can scan a static QR code from the customer to capture the customer’s information and initiate the transaction. + +Optionally the agent verifies the identity of the customer. + +##### Step 12 + +This is an optional step. The customer checks cash-in transaction information and related fees on their own handset and then makes the decision to accept or reject the transaction. + +##### Step 16 + +The agent checks fees and taxes and either accepts or rejects. + +##### Step 20 + +A notification is sent to the customer after the transaction is performed by Payee FSP. + +##### Step 28 + +Payer FSP sends notification to the agent to indicate the transaction result. + +#### Relevant Error Conditions + +[Table 5](#table-5) describes relevant errors and recommended follow-up actions for this use case. + +##### Table 5 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +|2 | Timeout | **Lookup Party Information** request timed out | Retry | +|4 | Payee cannot be found | Account Lookup System fails to locate Payee | Cancel the transaction | +|6 |Currency is not supported | The transaction currency is not supported. | Initiate a new transaction with supported currency by Payee FSP | +|9 | Timeout | **Calculate Quote** request timed out | Retry with the same ID | +|15 | Wrong quote | Payee FSP cannot provide quote due to internal business rule validation failure or system error.

    For example, invalid account status of Payee, wrong fee configuration or database error | Cancel the transaction +|17 | Timeout | **Perform Transfer** request timed out | Query transfer status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +|19 |Transaction failed | Transaction failed at Payee FSP.
    Possible reasons:
  • Low balance of Payee
  • Limit breached
  • Quote is expired
  • Payer or Payee blacklisted
  • Invalid account status of Payee
  • Payee FSP internal system error

  • | Cancel the transaction | +|22 |Funds reservation timeout | Funds reservation at Payer FSP timed out and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to the scheme rules + +**Table 5 – Agent-Initiated Cash-In: Relevant Error Conditions** + +
    + +### Agent-Initiated Cash-Out + +#### Use Case Description + +This section describes the business process and business rules for the use case in which a customer requests an agent of a different FSP to cash-out (withdraw funds) from their account. This is a 2-step transaction, the agent initiates cash-out transaction request and the customer authorizes the transaction on their handset. Once transaction is completed, the agent gives cash to the customer. + +Agent-Initiated Cash-Out is a face-to-face transaction in which the customer and the agent are in the same location. + +#### Reference to Generic Pattern + +_Payee-Initiated Transaction_ + +#### Actors and Roles + +The actors and roles for Agent-Initiated Cash-Out are described in [Table 6](#table-6). + +##### Table 6 + +| Role | Map to Generic
    Transaction Pattern
    | Description | +| --- | --- | --- | +|Customer | Payer | Payer is a customer (individual or organization) who wants to withdraw cash using an agent.

    Customer is a registered party in Payer FSP. | +|Agent | Payee | Payee is an agent registered with the Payee FSP. A pre-funded wallet for the agent is maintained at Payee FSP.

    Agent is a registered party in Payee FSP. | + +**Table 6 – Agent-Initiated Cash-Out: Actors and Roles** + +#### Addition to Generic Transaction Pattern + +##### Step 1 + +The customer requests that an agent cash-out (withdraw funds) from their account. + +If a smart phone is used, the agent can scan a static QR code containing the customer’s information to capture that information and initiate the transaction. + +Optionally, the agent may verify the identity of the customer to satisfy regulatory requirements. + +##### Step 17 + +The Payer FSP shows fees and taxes to the customer. The customer indicates whether they want to proceed or not. + +##### Step 25 + +A transaction notification is sent to the agent after the transaction is performed by Payee FSP. + +##### Step 33 + +After receiving transaction notification, the agent gives the cash-out amount to the customer. + +##### Relevant Error Conditions + +[Table 7](#table-7) describes relevant errors and recommended follow-up actions for this use case. + +##### Table 7 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +| 2 | Timeout | **Lookup Party Information** request timed out | Retry | +| 3 | Payer cannot be found | Account Lookup System fails to locate the Payer | Cancel the transaction | +| 7 | Currency is not supported | The transaction currency is not supported. | Initiate a new transaction supported by Payee FSP | +| 22 | Timeout | **Perform Transfer** request timed out | Query transfer status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 24 | Transaction failed | Transaction failed at the Payee FSP.
    Possible reasons:
  • Limit Breached
  • Payer or Payee blacklisted
  • Quote is expired
  • Invalid account status of Payee
  • Payee FSP internal system error

  • | Cancel the transaction | +| 27 | Reservation is expired | Funds reservation is expired and the transaction fails at Payer FSP but succeeds at Payee FSP. | Reconcile according to scheme rules | + +**Table 7 – Agent-Initiated Cash-Out: Relevant Error Conditions** + +### Agent-Initiated Cash-Out Authorized on POS + +#### Use Case Description + +This section describes the business process and business rules for the use case in which a customer requests that an agent of a different FSP cash-out (withdraw funds) from their account. In this use case, the agent initiates the transaction through a POS, and the customer inputs a OTP on POS to authorize the transaction. Alternatively, the agent can use POS to scan a QR code generated by the mobile app of the customer to initiate the transaction. + +- Approval using OTP – A Payer can approve a transaction by first creating an OTP in their FSP. The OTP is then entered in a Payee device (usually a POS device). The OTP in the transaction request is automatically matched by the Payer FSP to either approve or reject the transaction. The OTP does not need to be encrypted as it should only be valid once during a short time period. + +- Approval using QR code – A Payer can approve a transaction by requesting a Payer FSP to generate a QR code that encodes an OTP and customer’s identifier. + +- Approval using NFC – A Payer can approve a transaction by swiping a _Near Field Communication_ (NFC) phone on a POS. The interoperability for NFC POS of one FSP to read data from NFC tag or NFC phone of another FSP should be considered if NFC technology is adopted. + +Agent-Initiated Cash-Out Authorized on POS is typically a face-to-face transaction in which the customer and the agent are in the same location. + +#### Reference to Generic Pattern + +_Payee-Initiated Transaction using OTP_ + +#### Actors and Roles + +The actors and roles for Agent-Initiated Cash-Out Authorized on POS are described in [Table 8](#table-8). + +##### Table 8 + +| Role | Map to Generic Transaction Pattern | Description | +| --- | --- | --- | +| Customer | Payer | Payer is a customer (individual or organization) who wants to withdraw cash using an agent.

    The customer is a registered party with Payer FSP.| +| Agent | Payee | Payee is an agent registered with the Payee FSP. A pre-funded wallet for the agent is maintained at Payee FSP.

    The agent is registered party with Payee FSP. | + +**Table 8 – Agent-Initiated Cash-Out Authorized on POS: Actors and Roles** + +#### Addition to Generic Transaction Pattern + +##### Step 1 + +For OTP: + +- The customer requests Payer FSP to generate an OTP. + +For QR code: + +- The customer enters cash-out amount and requests Payer FSP to generate a QR code. + +- The QR code generation should be approved by customer transaction PIN. + +##### Step 4 + +The customer requests the agent to cash-out some amount from their account. + +For OTP: + +- The agent inputs the customer’s ID and cash-out amount to initiate the transaction + +For mobile app: + +- The agent inputs cash-out amount and then scan QR code of customer via scanner POS + +For NFC: + +- The agent inputs cash-out amount and the customer taps phone on NFC POS. + +- The agent verifies identity of the customer to satisfy regulation requirements. + +##### Step 21 + +There is a risk that someone other than the owner of phone may attempt to use the phone to make a transaction at an agent store. Thus, the transaction should be approved via PIN to allow an OTP to be generated automatically. + +##### Step 25 + +The customer checks fees and taxes. If the customer agrees: + +- For OTP: The customer enters OTP on the agent phone or device. + +- For QR code/NFC: The customer confirms the payment on POS. + +If the customer disagrees: + +- For OTP: The customer doesn’t enter OTP on the agent phone or device. + +- For QR code/NFC: The customer rejects the payment on POS. + +##### Step 36 + +A notification is sent to the agent after the transaction is performed by the Payee FSP. After receiving transaction notification, the agent gives the cash-out amount to the customer. + +##### Step 44 + +The Payer FSP sends a notification of the transaction result to the customer. + +##### Relevant Error Conditions + +[Table 9](#table-9) describes relevant errors and recommended follow-up actions for this use case. + +##### Table 9 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +| 5 | Timeout | **Lookup Party Information** request timedout| Retry| +| 6 | Payer cannot be found | Account Lookup System fails to locate the Payer | Cancel the transaction | +| 8 | Transaction request timeout | **Perform Transaction Request** to Payer FSP timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 28 | OTP is expired | OTP is expired | Push another authentication request to Payee FSP
    or
    Cancel the transaction in the Payer FSP | +| 28 | Invalid OTP | OTP is unrecognized | Push another authentication request to Payee FSP
    or
    Cancel the transaction in the Payer FSP | +| 35 | Transaction failed | Transaction failed at the Payee FSP.
    Possible reasons:
  • Limit Breached
  • Payer or Payee blacklisted
  • Quote is expired
  • Invalid account status of Payee
  • Payee FSP internal system error

  • | Cancel the transaction | +| 38 | Reservation is expired | Funds reservation is expired and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to scheme rules | + +**Table 9 – Agent-Initiated Cash-Out Authorized on POS: Relevant Error Conditions** + +### Customer-Initiated Cash-Out + +#### Use Case Description + +This section describes the business process and business rules for a use case in which a registered customer initiates a transaction to withdraw cash using an agent who is in a different FSP. This is two-step business process: a customer initiates cash-out transaction on their handset and then receives transaction information including fees, which can either be rejected or accepted. + +Customer-Initiated Cash-Out usually is a face-to-face transaction in which the customer and the agent are in the same location. + +#### Reference to Generic Pattern + +_Payer-Initiated Transaction_ + +#### Actors and Roles + +The actors and roles for Customer-Initiated Cash-Out are described in [Table 10](#table-10). + +##### Table 10 + +| Role | Map to Generic Transaction Pattern | Description | +| --- | --- | --- | +| Customer | Payer | Payer is a customer (individual or organization) who wants to cash-out (withdraw funds) using an agent.

    Customer is a registered party with Payer FSP. | +| Agent | Payee | Payee is an agent registered with the Payee FSP. A pre-funded wallet for the agent is maintained at Payee FSP.

    Agent is registered party with Payee FSP. | + +**Table 10 – Customer-Initiated Cash-Out: Actors and Roles** + +#### Addition to Generic Transaction Pattern + +##### Step 1 + +The customer requests that the agent cash-out some amount from their account. + +For USSD: + +- The customer inputs cash-out amount and merchant ID to initiate the transaction. + +For mobile app: + +- If a smart phone is used, the customer can scan the static QR code of the agent to capture the agent’s information and initiate transaction. + +Optionally, the agent can verify the identity of the customer to satisfy regulatory requirements. + +##### Step 12 + +This is an optional step. Payee FSP shows fees, taxes or both to the agent. If the agent does not accept the fees or commission, they can reject the transaction. + +##### Step 16 + +Payer FSP shows fees and taxes to the customer. If the customer doesn’t want to proceed, they reject the transaction. + +##### Step 20 + +A notification is sent to the agent once the transaction is performed by Payee FSP. + +##### Step 29 + +After the customer receives transaction notification, the agent gives cash-out amount to the customer. + +#### Relevant Error Conditions + +[Table 11](#table-11) describes relevant errors and recommended follow-up actions for this use case. + +##### Table 11 + +|Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +|2 | Timeout | **Lookup Party Information** request timed out | Retry | +| 4 | Agent cannot be found | Account Lookup System fails to locate agent | Cancel the transaction | +| 6 | Currency is not supported | The transaction currency is not supported. | Initiate a new transaction with supported currency by Payee FSP | +| 9 |Timeout | **Calculate Quote** request timed out | Retry with the same ID | +| 11 | Wrong quote | Payee FSP cannot provide quote due to internal business rule validation failure or system error.

    For example, invalid account status of Payee, wrong fee configuration or database error | Cancel the transaction | +| 17 | Timeout | **Perform Transfer** request timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 19 | Transaction failed | Transaction failed at Payee FSP.
    Possible reasons:
  • Limit breached
  • Payer or Payee blacklisted
  • Quote is expired
  • Invalid account status of Payee
  • Payee FSP internal system error

  • | Cancel the transaction | +| 22 | Reservation is expired | Funds reservation is expired and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to scheme rules | + +**Table 11 – Customer-Initiated Cash-Out: Relevant Error Conditions** + +### Customer-Initiated Merchant Payment + +#### Use Case Description + +This section describes the business process and business rules for a use case in which a registered customer initiates a merchant payment transaction to pay a merchant who is in another FSP. + +This could be a face to face transaction; for example, when a customer buys goods or services at the merchant store. Another case is online payment, in which an online shopping system generates a QR code and displays on the web page, and the customer then scans the QR code on the web page and authorizes and completes the payment transaction on their handset. + +**Assumption:** Encoding/Decoding QR code is handled in each FSP and is out of scope of API. The data and its format encoded in the QR code should be defined in the scheme rules to enable QR codes to be interoperable. + +#### Reference to General Pattern + +_Payer-Initiated Transaction_ + +#### Actors and Roles + +The actors and roles for Customer-Initiated Merchant Payment are described in [Table 12](#table-12). + +##### Table 12 + +| Role | Map to Generic Transaction Pattern | Description +| --- | --- | --- | +| Customer | Payer | An individual End User of one FSP who buys goods or service from a merchant of another FSP. | +| Merchant | Payee | The business that sells goods or provide service and then receives payment from the customer. | + +**Table 12 – Customer-Initiated Merchant Payment: Actors and Roles** + +#### Addition to Generic Transaction Pattern + +##### Step 1 + +For feature phone: + +- The customer can initiate a payment transaction by inputting relevant payment information on the USSD menu, such as amount and merchant ID. + +For smart phone: + +- The customer initiates merchant payment transaction by scanning the merchant QR code. After resolving the merchant QR code, there are two scenarios: + + a) The customer inputs transaction amount in their handset to continue the transaction if the transaction amount is not encoded in the QR code. This is the case for face-to-face payment at retailer merchant store. + + b) Transaction amount has already been encoded in the QR code, and then Payer FSP has enough information to continue the transaction. This case then follows the process of the online payment case identified in [4.6.1](#461-use-case-description). + +##### Step 2 + +The merchant FSP ID could be determined by the scheme rules without depending on an Account Lookup System. Otherwise, **Lookup Party Information** request is an option to find out in which FSP the merchant is located. + +In most cases, the merchant FSP ID is captured during initiating the transaction. For example, the customer selects the merchant FSP from USSD menu, or it is already encoded in the merchant QR code. + +##### Step 9 – Step 15 + +In most cases, the customer is free of charge for the purchase transaction. **Calculate Quote** request is still necessary, because all transaction details will be sent to Payee FSP and the condition of the transfer will be generated by Payee FSP for later use (in **Perform Transfer**). + +##### Step 20 + +A notification is sent to the merchant once the transaction is performed by the Payee FSP. + +##### Step 29 + +Customer receives transaction notification and customer receives goods. + +#### Relevant Error Conditions + +[Table 13](#table-13) describes relevant errors and recommended follow-up actions for this use case. + +##### Table 13 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +| 2 | Timeout | **Lookup Party Information** request timed out | Retry | +| 4 | Merchant is unreachable | Account Lookup System fails to locate merchant | Cancel the transaction | +| 6 | Currency is not supported | The transaction currency is not supported. | Initiate a new transaction with supported currency by Payee FSP | +| 9 | Timeout | **Calculate Quote** request timed out | Retry with the same ID | +| 11 | Wrong quote | Payee FSP cannot provide quote due to internal business rule validation failure or system error.

    For example, invalid account status of Payee, wrong fee configuration or database error | Cancel the transaction | +| 17 | Timeout | **Perform Transfer** request timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period +| 19 | Transaction failed | Transaction failed at Payee FSP.
    Possible reasons:
  • Limit breached
  • Payer or Payee blacklisted
  • Quote is expired
  • Invalid account status
  • Payee FSP internal system error

  • | Cancel the transaction | +| 22 | Reservation is expired | Funds reservation is expired and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to scheme rules | + +**Table 13 – Customer-Initiated Merchant Payment: Relevant Error Conditions** + +### Merchant-Initiated Merchant Payment + +#### Use Case Description + +This use case describes a merchant payment transaction, initiated by a merchant and then authorized by the customer on their handset. + +The business process involves two parties, a merchant and a customer. The merchant initiates a _request to pay_ transaction to the customer. The customer can review the transaction details and approve or reject the transaction on their mobile device. + +Thus, it is a two-step business process in which the merchant initiates a payment transaction and the customer authorizes the transaction from their account. + +#### Reference to Generic Pattern + +_Payee-Initiated Transaction_ + +#### Actors and roles + +The actors and roles for Merchant-Initiated Merchant Payment are described in [Table 14](#table-14). + +##### Table 14 + +| Role | Map to Generic Transaction Pattern | Description | +| --- | --- | --- | +| Customer | Payer | An individual End User of one FSP who buys goods or service from a merchant of another FSP. | +| Merchant | Payee | The business who sells goods or provides services and then receives payment from the customer. | + +**Table 14 – Merchant-Initiated Merchant Payment: Actors and Roles** + +#### Addition to General Pattern + +This section describes how the use case connects to the general pattern. The description is focused on the End User as the interactions between the participating systems are described in the general pattern. + +##### Step 1 + +For feature phone: + +- The merchants can input the customers’ ID in their USSD/STK menu when initiating payment transactions. + +For smart phone: + +- To capture the customer’s ID, the merchant may use a scan device or mobile app to scan QR code generated by the customer’s mobile app. + +##### Step 10-16 + +In a merchant payment transaction, the customer is usually free-of-charge. + +##### Step 13 + +This is an optional step. Payee FSP shows the transaction details including fees to the merchant; and the merchant can accept or reject the transaction. + +##### Step 25 + +A notification is sent to the merchant after the transaction is performed by the Payee FSP. + +##### Step 33 + +Payer FSP sends a notification to the customer to indicate the transaction result. + +#### Relevant Error Conditions + +[Table 15](#table-15) below describes relevant errors and recommended follow-up actions for this use case. + +##### Table 15 + +| Step | Error Condition | Error Description | Follow Up Action | +| -- | -- | -- | -- | +| 2 | Account Lookup Timeout | **Lookup Party Information** request timed out | Retry | +| 3 | Customer cannot be found | Account Lookup System fails to locate the customer | Cancel the transaction | +| 5 | Transaction request timeout | **Perform Transaction Request** to Payer FSP timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 10 | Quote request failed | **Calculate Quote** request timed out or failed at Switch or Payee FSP | Cancel the transaction | +| 24 | Quote expired | Quote expired | Cancel the transaction | +| 27 | Reservation timeout | Funds reservation timed out at Payer FSP and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to scheme rules | + +**Table 15 – Merchant-Initiated Merchant Payment: Relevant Error Conditions** + +
    + +### Merchant-Initiated Merchant Payment Authorized on POS + +#### Use Case Description + +This use case describes a merchant payment initiated by a merchant using a device such as POS, and how to authorize a transaction with an OTP or a QR code. + +The merchant initiates a merchant payment transaction using a POS device. This device has the capability to capture the customer’s authorization on POS instead of the customer’s mobile device. The authorization information captured in POS should be sent to Payer FSP to perform the authorization. + +The business process involves two parties, Merchant and Customer. The merchant initiates a request to pay for the customer, and the customer reviews the payment request on POS and authorizes the payment by OTP or QR code on the POS itself. The customer authentication information is sent from Payee FSP to Payer FSP for authentication by Payer FSP. If authentication is successful then transaction will be posted on Payer FSP and Payee FSP. + +#### Reference to Generic Pattern + +_Payee-Initiated Transaction using OTP_ + +#### Actors and roles + +The actors and roles for Merchant-Initiated Merchant Payment Authorized on POS are described in [Table 16](#table-16) below: + +##### Table 16 + +| Role | Map to Generic Transaction | Pattern Description | +| --- | --- | --- | +| Customer | Payer | An individual End User of one FSP who buys goods or service from a merchant of another FSP. | +| Merchant | Payee | The business who sells goods or provide service and then receive payment from the customer. | + +**Table 16 – Merchant-Initiated Merchant Payment Authorized on POS: Actors and Roles** + +#### Addition to General Pattern + +This section describes how the use case connects to the general pattern. The description is focused on the end-user, because the interactions between the participating systems are described in the general pattern. + +##### Step 1-3 + +The customer can pre-authorize the transaction by generating a dynamic payment QR code on a mobile app if they have a smart phone. + +The customer can request an OTP on the USSD menu if they have a feature phone. + +##### Step 4 + +For mobile app: + +- The merchant uses a scan device such as a POS to capture the QR code and initiate the payment. + +- Both customer ID and OTP are encoded in the QR code. + +For feature phone: + +- The merchant inputs customer’s ID and amount to initiate the transaction. + +##### Step 20 + +Steps 1-3 are optional and will be used only when OTP is generated by Payer to authenticate the purchase at the merchant +device. However, it would be very rare for a customer to generate the OTP manually; instead Payer FSP would generate an OTP for the customer as described in Step 20. + +##### Step 21 + +There is a risk that someone other than the owner of phone may attempt to use the phone to make a transaction at agent store. Thus, the transaction should be approved via PIN to allow OTP to be generated automatically. + +##### Step 25 + +The customer need only confirm the transaction on POS if initiating transaction with a QR code in step 4, because OTP is encoded in the QR code and parsed in Step 4. + +##### Step 36 + +A notification is sent to the merchant once the transaction is performed by the Payee FSP. After receiving the transaction notification, the merchant gives goods to the customer. + +##### Step 44 +The Payer FSP sends a notification of the transaction result to the customer. + +#### Relevant Error Conditions + +[Table 17](#table-17) below describes relevant errors and recommended follow-up actions for this use case. + +##### Table 17 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +| 5 | Timeout | **Lookup Party Information** request timed out | Retry | +| 6 | Customer cannot be found | Account Lookup System fails to locate the customer | Cancel the transaction | +| 8 | Transaction request timeout | **Perform Transaction Request** to Payer FSP timed out | Query status and retry | +| 19 | Quote request failed | Quote failed at Switch or Payee FSP | Cancel the transaction | +| 33 | Transfer request timeout | **Perform Transfer** request to Payee FSP timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 35 | Transaction failed | Transaction failed at the Payee FSP.
    Possible reasons:
  • Limit Breached
  • Payer or Payee blacklisted
  • Quote is expired
  • Invalid account status of Payee
  • Payee FSP internal system error

  • | Cancel the transaction | +| 38 | Reservation is expired | Funds reservation timed out and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to the scheme rules | + +**Table 17 – Merchant-Initiated Merchant Payment Authorized on POS: Relevant Error Conditions** + +
    + +### ATM-Initiated Cash-Out + +#### Use Case Description + +This section describes the business flows and rules of an _ATM-Initiated Cash-Out_ use case. + +This use case involves two parties: ATM and Customer. ATM initiates a Cash-Out request from the customer account and the customer confirms the request by providing authentication (OTP) on ATM. The customer pre-generates an OTP for cash-out and uses this OTP on ATM device to initiate ATM Cash-out. The Payer FSP validates the OTP received in _ATM-Initiated Cash-Out_ request for the validity of OTP as well as for authentication. If the customer authentication via OTP is successful; then the customer’s account will be debited at Payer FSP and ATM account maintained at Payee FSP will be credited. As a result, the customer receives cash from ATM. + +#### Reference to Generic Pattern + +_Payee-Initiated Transaction using OTP_ + +#### Actors and roles + +The actors and roles for ATM Initiated Cash Out are described in [Table 18](#table-18). + +##### Table 18 + +| Role | Map to Generic Transaction | Pattern Description | +| --- | --- | --- | +| Customer | Payer | Payer is a customer who wants to withdraw cash from ATM device belonging to another FSP. | +| ATM Provider | Payee | Payee is an ATM provider who provides cash withdrawal service on ATM device to a customer belonging to another FSP. ATM would be connected to a bank network which is connected to Payee FSP. There would be a pre-funded account in Payee FSP corresponding to an ATM or ATMs, or to a Bank Switch. | + +**Table 18 – ATM-Initiated Cash-Out: Actors and Roles** + +#### Addition to General Pattern + +This section describes how the use case connects to the general pattern. The description is focused on the end-user as the interactions between the participating systems are described in the general pattern. + +##### Step 1-3 + +Steps 1 to 3 are optional; however, it is recommended that customer generate an OTP before initiating the transaction request from ATM. + +Alternatively, a customer generates a QR code for cash-out via mobile app other than OTP. + +##### Step 4 + +For mobile app: + +- ATM can scan previously-generated cash-out QR code. + +For feature phone: + +- The customer initiates withdrawal transaction by inputting their account ID and amount. + +##### Step 20 + +In _ATM-Initiated Cash-Out_, it is very rare that an OTP is automatically generated by a Payer FSP, because this will delay the transaction due to SMS delivery, and the ATM transaction will time out. Therefore, it is recommended that customer generate an OTP for ATM Cash-out as mentioned in Steps 1-3. + +##### Step 21 + +There is a risk that someone other than the owner of phone holding the handset may make a transaction at an ATM device. In this case, the transaction should be approved via PIN so that the OTP can be generated automatically. + +##### Step 25 + +If an OTP is used, the customer enters the OTP that was generated in Steps 1-3 or Step 21. + +If a QR code is used to cash-out and it is captured by an ATM when initiating the transaction in Step 4, then the customer must confirm or reject the transaction on the ATM only; inputting security credentials such as OTP or password is not necessary. + +#### Relevant Error Conditions + +[Table 19](#table-19) below describes relevant errors and recommended follow-up actions for this use case. + +##### Table 19 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +| 5 | Timeout | **Lookup Party Information** request timed out | Retry | +| 6 | Customer cannot be found | Account Lookup System fails to locate the customer | Cancel the transaction | +| 8 | Transaction request timeout | **Perform Transaction Request** timed out at Switch or Payee FSP | Query and retry | +| 14 | Quote request timeout | **Calculate Quote** request timed out | Retry | +| 15 | Quote request failed | **Calculate Quote** request fails at Switch or Payee FSP | Cancel the transaction | +| 33 | Transfer request timeout | Perform Transfer request timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 35 | Transaction request is failed | Transaction failed at the Payee FSP.
    Possible reasons:
  • Limit Breached
  • Payer or Payee blacklisted
  • Quote is expired
  • Invalid account status of merchant
  • Payee FSP internal system error

  • | Cancel the transaction and try another new transaction | +| 38 | Reservation is timeout | Funds reservation is timeout and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to the scheme rules | + +**Table 19 – ATM-Initiated Cash-Out: Relevant Error Conditions** + +
    + +### Bulk Payments + +#### Use Case Description + +This section describes a _Bulk Payments_ use case. The use case is written from the end-user perspective to give additional information to the _Generic Transaction Patterns_ document. + +Bulk Payments are used when an organization or business is paying out funds; for example, aid or salary to multiple Payees. The organization or business can group transactions together to make it easier to upload and validate individual transactions in bulk before the bulk transaction is executed. It is also possible for the organization to follow up the result of the individual transactions in the bulk transaction after the bulk transaction is executed. + +#### Reference to Generic Pattern + +_Bulk Transactions_ + +#### Actors and roles + +The actors and roles for Bulk Payments are described in [Table 20](#table-20) below: + +##### Table 20 + +| Role | Map to Generic Transaction | Pattern Description | +| --- | --- | --- | +| Payer | Payer | The Payer is a corporate, government or aid organization that is transferring money from its own account to multiple Payees. The reason can for instance be payout of monthly salary or aid disbursement.

    The Payer is a registered user with an account in the Payer FSP. | +| Payee | Payee | The Payee is, for example, an employee at a corporate or receiver of aid that is receiving a payout from the Payer.

    The Payee is a registered user with an account in one of the connected FSPs. | + +**Table 20 – Bulk Payments: Actors and Roles** + +#### Addition to General Pattern + +This section describes how the use case connects to the general pattern. The description is focused on the end-user as the interactions between the participating systems are described in the general pattern. + +##### Step 1 + +The Payer creates a bulk transaction according to the format of the Payer FSP. Each row in the bulk transaction includes information about a transfer between a Payer account and a Payee account. The information includes: + +- A unique transaction ID for the bulk so that the Payer can follow up the status of individual transactions in the bulk. + +- Identifier of the Payee + +- Amount and currency to be transferred + +The Payer will upload the bulk transaction using the interface provided by the Payer FSP. + +##### Step 12 + +The Payer is notified by the Payer FSP that the bulk is ready for review. + +The Payer will get a bulk transaction report and validate that the specified Payees have accounts and can receive funds. + +The Payer can also validate any fees that will be charged for executing the bulk transaction. Fees will be calculated per transaction in the bulk transaction. + +Before the bulk transaction is executed, the Payer must ensure that there are enough funds in the Payer account for the value of the complete bulk transaction to be completed. Depending on scheme rules the Payer FSP needs to ensure that there are enough funds prefunded to the Payee FSP to be able to complete the transactions to the Payee. + +If the Payer is satisfied after reviewing the bulk transaction, then the Payer will initiate the execution of the bulk transaction. + +If the Payer does not want to execute the bulk transaction, then the bulk transaction can be canceled. Cancellation will be +handled internally in the Payer FSP. No information regarding cancelation will be sent to the Payee FSP. + +How execution and cancelation is handled depends on the implementation in the Payer FSP. + +##### Step 21 + +The Payer can review the result of the bulk transaction execution when the Payer FSP has processed all the transactions in the uploaded bulk transaction. + +The Payer will be able to get details about the execution for each individual transaction. + +Any reprocessing that might be needed to be executed (for example, failed transactions) will be treated as a new bulk transaction in the API. + +#### Relevant Error Conditions + +Bulk Transactions have two main types of logical errors: Errors connected to the header and errors related to the transactions in the bulk transaction. + +An error related to the header will fail the complete bulk transaction. For example, if the Payer of the bulk transaction is blocked, then no transaction shall be executed. + +Errors related to an individual transaction within the bulk transaction will get a failed status and be assigned an error code. The amount of the transaction that failed will be rolled back. Other transactions in the bulk transaction will not be affected if one individual transaction fails. + +[Table 21](#table-21) below contains a description of general error cases to give an overview of the bulk transaction use case and how different error cases are handled. Detailed error codes for the operations are not included, nor are codes for communication errors and format validations errors. + +##### Table 21 + +| Step | Error Condition | Error Description | Follow Up Action | +| --- | --- | --- | --- | +| 5 | Payee not found | Account lookup fails to look up Payee at any FSP. | Payee will be excluded from any bulk transactions request and marked as failed in the bulk transaction response to the Payer | +| 8 | Payee not found | Payee FSP cannot find the Payee account | Payee FSP will mark the individual transaction in the bulk transaction as failed. | +| 15 | Not enough funds on Payer FSP account | The Payer FSP account in the | Switch has not been prefunded to cover for the complete bulk transaction. Switch would fail the complete bulk transaction as the funds for the bulk transaction cannot be reserved. | +| 16 | Not enough funds on Payer FSP account | The Payer FSP account in the Payee FSP has not been prefunded to cover for the complete bulk transaction. | Payee FSP is not able to reserve the amount for the bulk transaction.

    Payee FSP can decide to execute as many transactions as possible or to fail the complete bulk transaction. | +| 16 | Payee transfer not allowed | The Payee FSP cannot complete the transfer of funds to the Payee. This could, for example, be blocked due to an account limit. | The individual transaction will be rolled back and reported in Payer response as failed. | +| 16 | Bulk quote expired | The quote for the bulk transaction has expired | The Payee FSP will fail the complete bulk transaction requests. | + +**Table 21 – Bulk Payments: Relevant Error Conditions** + +
    + +### Refund + +This section describes how to refund a completed interoperability transaction. + +There are several refund scenarios for merchant payment transaction: + +1. The customer has entered an amount incorrectly and paid more than the invoice. + +2. The merchant is not able to deliver the goods as specified by the invoice already paid by the customer, so the merchant wants to refund money to the customer. + +3. An online merchant selling tickets (train, air or bus) provides a refund to a customer when the customer cancels the ticket. + +4. The customer has returned the goods to the merchant and the merchant wants to refund the customer. + +Additional business scenarios may require transaction reversals. For example: + +1. The customer has sent money to incorrect recipient. + +2. The customer accidently created the same transaction twice. + +It is recommended to use refund transaction to fulfill the business purpose. + +The business process will remain as reversal, but the technical implementation would require Payee FSP CCE to initiate a refund transaction. Payer FSP CCE coordinates with Payee CCE manually. If there is a Switch, then Switch administrator may help to facilitate the conversation between Payer FSP and Payee FSP. + +Note the following: + +- Refund can only be initiated by Payee of the original transaction. Alternatively, CCE of Payee FSP in the original transaction can also initiate refund from Payee account. + +- An original transaction can be refunded multiple times. + +#### Reference to Generic Pattern + +_Payer-Initiated Transaction_ + +#### Actors and roles + +The actors and roles for Bulk Payment are described in [Table 22](#table-22). + +##### Table 22 + +| Role | Map to Generic Transaction | Pattern Description | +| --- | --- | --- | --- | +| Payee | Payee | The End User who has made a wrong payment and requests a refund. | +| Payer | Payer | The End User who has received the payment in the original transaction. | + +**Table 22 – Refund: Actors and Roles** + +#### Addition to General Pattern + +This section describes how the use case connects to the general pattern. The description is focused on the end-user, because the interactions between the participating systems are described in the general pattern. + +##### Step 1 + +Payer of the original transaction can contact Payee or CCE of Payer FSP to request refund. The actual refund amount is negotiated between Payer and Payee before the refund. + +##### Step 9-15 + +Typically, the refund transaction is free-of-charge. + +##### Step 17 + +The original transaction ID should be captured in the refund transaction. + +#### Relevant Error Conditions + +[Table 23](#table-23) below describes relevant errors and recommended follow-up actions for this use case. + +##### Table 23 + +| Step | Error Condition | Error Description | Follow on Action | +| --- | --- | --- | --- | +| 2 | Timeout | **Lookup Party Information** request timed out | Retry | +| 4 | Payee cannot be found | Account Lookup System fails to locate Customer | Cancel the transaction | +| 17 | Timeout | **Perform Transfer** request timed out | Query transaction status and decide to complete or retry

    The retry policy will be defined by the scheme rules. For example, retry times and period | +| 19 | Transaction failed | Transaction failed at Payee FSP.
    Possible reasons:
  • Limit Breached
  • Quote is expired
  • Invalid account status of customer
  • Payee FSP internal system error

  • | Cancel the transaction | +| 22 | Funds reservation timeout | Funds reservation at Payer FSP timed out and the transaction fails at Payer FSP but succeeds at Payee FSP | Reconcile according to the scheme rules | + +**Table 23 – Refund: Relevant Error Conditions** + +
    + +## List of Tables + +[Table 1](#table-1) – Use Case Summary + +[Table 2](#table-2) – P2P Actors and Roles + +[Table 3](#table-3) – P2P Relevant Error Conditions + +[Table 4](#table-4) – Agent-Initiated Cash-In: Actors and Roles + +[Table 5](#table-5) – Agent-Initiated Cash-In: Relevant Error Conditions + +[Table 6](#table-6) – Agent-Initiated Cash-Out: Actors and Roles + +[Table 7](#table-7) – Agent-Initiated Cash-Out: Relevant Error Conditions + +[Table 8](#table-8) – Agent-Initiated Cash-Out Authorized on POS: Actors and Roles + +[Table 9](#table-9) – Agent-Initiated Cash-Out Authorized on POS: Relevant Error Conditions + +[Table 10](#table-10) – Customer-Initiated Cash-Out: Actors and Roles + +[Table 11](#table-11) – Customer-Initiated Cash-Out: Relevant Error Conditions + +[Table 12](#table-12) – Customer-Initiated Merchant Payment: Actors and Roles + +[Table 13](#table-13) – Customer-Initiated Merchant Payment: Relevant Error Conditions + +[Table 14](#table-14) – Merchant-Initiated Merchant Payment: Actors and Roles + +[Table 15](#table-15) – Merchant-Initiated Merchant Payment: Relevant Error Conditions + +[Table 16](#table-16) – Merchant-Initiated Merchant Payment Authorized on POS: Actors and Roles + +[Table 17](#table-17) – Merchant-Initiated Merchant Payment Authorized on POS: Relevant Error Conditions + +[Table 18](#table-18) – ATM-Initiated Cash-Out: Actors and Roles + +[Table 19](#table-19) – ATM-Initiated Cash-Out: Relevant Error Conditions + +[Table 20](#table-20) – Bulk Payments: Actors and Roles + +[Table 21](#table-21) – Bulk Payments: Relevant Error Conditions + +[Table 22](#table-22) – Refund: Actors and Roles + +[Table 23](#table-23) – Refund: Relevant Error Conditions \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/fspiop/v1.0/README.md b/website/versioned_docs/v1.0.1/api/fspiop/v1.0/README.md new file mode 100644 index 000000000..96cef71e4 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/v1.0/README.md @@ -0,0 +1,4 @@ +--- +showToc: false +--- +https://raw.githubusercontent.com/mojaloop/mojaloop-specification/master/fspiop-api/documents/v1.0-document-set/fspiop-rest-v1.0-OpenAPI-implementation.yaml \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/fspiop/v1.0/api-definition.md b/website/versioned_docs/v1.0.1/api/fspiop/v1.0/api-definition.md new file mode 100644 index 000000000..96cef71e4 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/v1.0/api-definition.md @@ -0,0 +1,4 @@ +--- +showToc: false +--- +https://raw.githubusercontent.com/mojaloop/mojaloop-specification/master/fspiop-api/documents/v1.0-document-set/fspiop-rest-v1.0-OpenAPI-implementation.yaml \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/fspiop/v1.1/api-definition.md b/website/versioned_docs/v1.0.1/api/fspiop/v1.1/api-definition.md new file mode 100644 index 000000000..1cb2bb96f --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/v1.1/api-definition.md @@ -0,0 +1,5492 @@ +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the +specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics with in angle brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature and API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.0**|2018-03-13|Initial version| +|**1.1**|2020-05-19|1. This version contains a new option for a Payee FSP to request a commit notification from the Switch. The Switch should then send out the commit notification using the new request **PATCH /transfers/**_{ID}_. The option to use commit notification replaces the previous option of using the ”Optional Additional Clearing Check”. The section describing this has been replaced with the new section ”Commit Notification”. As the **transfers** resource has been updated with the new **PATCH** request, this resource has been updated to version 1.1. As part of adding the possibility to use a commit notification, the following changes has been made:
    a. PATCH has been added as an allowed HTTP Method in Section 3.2.2. b. The call flow for **PATCH** is described in Section 3.2.3.5.
    c. Table 6 in Section 6.1.1 has been updated to include **PATCH** as a possible HTTP Method.
    d. Section 6.7.1 contains the new version of the **transfers** resource.
    e. Section 6.7.2.6 contains the process for using commit notifications
    f. Section 6.7.3.3 describes the new **PATCH /transfers**/_{ID}_ request.

    2. In addition to the changes mentioned above regarding the commit notification, the following non-API affecting changes has been made:
    a. Updated Figure 6 as it contained a copy-paste error.
    b. Added Section 6.1.2 to describe a comprehensive view of the current version for each resource.
    c. Added a section for each resource to be able to see the resource version history.
    d. Minor editorial fixes.

    3. The descriptions for two of the HTTP Header fields in Table 1 have been updated to add more specificity and context
    a. The description for the **FSPIOP-Destination** header field has been updated to indicate that it should be left empty if the destination is not known to the original sender, but in all other cases should be added by the original sender of a request.
    b. The description for the **FSPIOP-URI** header field has been updated to be more specific.

    4. The examples used in this document have been updated to use the correct interpretation of the Complex type ExtensionList which is defined in Table 84. This doesn’t imply any change as such.
    a. Listing 5 has been updated in this regard.

    5. The data model is updated to add an optional ExtensionList element to the **PartyIdInfo** complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 103 has been updated. For consistency, the data model for the **POST /participants/**_{Type}/{ID}_ and **POST /participants/**_{Type}/{ID}/{SubId}_ calls in Table 10 has been updated to include the optional ExtensionList element as well.

    6. A new Section 6.5.2.2 is added to describe the process involved in the rejection of a quote.

    7. A note is added to Section 6.7.4.1 to clarify the usage of ABORTED state in **PUT /transfers/**_{ID}_ callbacks.| +|**1.1.1**|2021-09-22|This document version only adds information about optional HTTP headers regarding tracing support in [Table 2](#table-2), see _Distributed Tracing Support for OpenAPI Interoperability_ for more information. There are no changes in any resources as part of this version.| + +## Introduction + +This document introduces and describes the _Open API_ (Application Programming Interface) _for FSP_ (Financial Service Provider) _Interoperability_ (hereafter cited as "the API"). The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP. The API does not specify any front-end services between a Payer or Payee and its own FSP; all services defined in the API are between FSPs. FSPs are connected either (a) directly to each other or (b) by a _Switch_ placed between the FSPs to route financial transactions to the correct FSP. + +The transfer of funds from a Payer to a Payee should be performed in near real-time. As soon as a financial transaction has been agreed to by both parties, it is deemed irrevocable. This means that a completed transaction cannot be reversed in the API. To reverse a transaction, a new negated refund transaction should be created from the Payee of the original transaction. + +The API is designed to be sufficiently generic to support both a wide number of use cases and extensibility of those use cases. However, it should contain sufficient detail to enable implementation in an unambiguous fashion. + +Version 1.0 of the API is designed to be used within a country or region, international remittance that requires foreign exchange is not supported. This version also contains basic support for the [Interledger Protocol](#4-interledger-protocol), which will in future versions of the API be used for supporting foreign exchange and multi-hop financial transactions. + +This document: + +- Defines an asynchronous REST binding of the logical API introduced in _Generic Transaction Patterns_. +- Adds to and builds on the information provided in [Open API for FSP Interoperability Specification](#open-api-for-fsp-interoperability-specification). + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](../logical-data-model) + +- [Generic Transaction Patterns](../generic-transaction-patterns) + +- [Use Cases](../use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](../definitions) + +- [JSON Binding Rules](../json-binding-rules) + +- [Scheme Rules](../scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](../pki-best-practices) + +- [Signature](../v1.1/signature) + +- [Encryption](../v1.1/encryption) + +#### General Documents + +- [Glossary](../glossary) + +
    + +## API Definition + +This section introduces the technology used by the API, including: + +- [General Characteristics](#general-characteristics) +- [HTTP Details](#http-details) +- [API Versioning](#api-versioning) + +### General Characteristics + +This section describes the general characteristics of the API. + +#### Architectural Style + +The API is based on the REST (REpresentational State Transfer1) architectural style. There are, however, some differences between a typical REST implementation and this one. These differences include: + +- **Fully asynchronous API** -- To be able to handle numerous concurrent long-running processes and to have a single mechanism for handling requests, all API services are asynchronous. Examples of long-running processes are: + - Financial transactions done in bulk + - A financial transaction in which user interaction is needed + +- **Decentralized** -- Services are decentralized, there is no central authority which drives a transaction. + +- **Service-oriented** -- The resources provided by the API are relatively service-oriented compared to a typical implementation of a REST-based API. + +- **Not fully stateless** -- Some state information must be kept in both client and server during the process of performing a financial transaction. + +- **Client decides common ID** -- In a typical REST implementation, in which there is a clear distinction between client and server, it is the server that generates the ID of an object when the object is created on the server. In this API, a quote or a financial transaction resides both in the Payer and Payee FSP as the services are decentralized. Therefore, there is a need for a common ID of the object. The reason for having the client decide the common ID is two-fold: + - The common ID is used in the URI of the asynchronous callback to the client. The client therefore knows which URI to listen to for a callback regarding the request. + - The client can use the common ID in an HTTP **GET** request directly if it does not receive a callback from the server (see [HTTP Details](#http-details) section for more information). + + To keep the common IDs unique, each common ID is defined as a UUID (Universally Unique IDentifier2 (UUID). To further guarantee uniqueness, it is recommended that a server should separate each client FSP's IDs by mapping the FSP ID and the object ID together. If a server still receives a non-unique common ID during an HTTP **POST** request (see [HTTP Details](#http-details) section for more details). The request should be handled as detailed in [Idempotent Services in server](#idempotent-services-in-server) section. + +#### Application-Level Protocol + +HTTP, as defined in RFC 72303, is used as the application-level protocol in the API. All communication in production environments should be secured using HTTPS (HTTP over TLS4). For more details about the use of HTTP in the API, see [HTTP Details](#http-details). + +#### URI Syntax + +The syntax of URIs follows RFC 39865 to identify resources and services provided by the API. This section introduces and notes implementation subjects specific to each syntax part. + +A generic URI has the form shown in [Listing 1](#listing-1), where the part \[_user:password@_\]_host_\[_:port_\] is the `Authority` part described in [Authority](#authority) section. +_{resource}_. + +###### Listing 1 + +``` +scheme:[//[user:password@]host[:port]][/]path[?query][#fragment] +``` + +**Listing 1 -- Generic URI format** + +##### Scheme + +In accordance with the [Application Level Protocol](#aplication-level-protocol) section, the _scheme_ (that is, the set of rules, practices and standards necessary for the functioning of payment services) will always be either **http** or **https**. + +##### Authority + +The authority part consists of an optional authentication (`User Information`) part, a mandatory host part, followed by an optional port number. + +###### User Information + +User information should in general not be used by API deployments; the security measures detailed in *API Signature* and _API_ _Encryption_ should be used instead. + +###### Host + +The host is the server's address. It can be either an IP address or a hostname. The host will (usually) differ for each deployment. + +###### Port + +The port number is optional; by default, the HTTP port is **80** and HTTPS is **443**, but other ports could also be used. Which port to use might differ from deployment to deployment. + +##### Path + +The path points to an actual API resource or service. The resources in the API are: + +- **participants** +- **parties** +- **quotes** +- **transactionRequests** +- **authorizations** +- **transfers** +- **transactions** +- **bulkQuotes** +- **bulkTransfers** + +All resources found above are also organized further in a hierarchical form, separated by one or more forward slashes (**'/'**). Resources support different services depending on the HTTP method used. All supported API resources and services, tabulated with URI and HTTP method, appear in [Table 6](#table-6). + +##### Query + +The query is an optional part of a URI; it is currently only used and supported by a few services in the API. See the API resources in [API Services](#api-services) section for more details about which services support query strings. All other services should ignore the query string part of the URI, as query strings may be added in future minor versions of the API (see [HTTP Methods](#http-methods)). + +If more than one key-value pair is used in the query string, the pairs should be separated by an ampersand symbol (**'&'**). + +[Listing 2](#listing-2) shows a URI example from the API resource **/authorization**, in which four different key-value pairs are present in the query string, separated by an ampersand symbol. + +###### Listing 2 + +``` +/authorization/3d492671-b7af-4f3f-88de-76169b1bdf88?authenticationType=OTP&retriesLeft=2&amount=102¤cy=USD +``` + +**Listing 2 -- Example URI containing several key-value pairs in the query string** + +##### Fragment + +The fragment is an optional part of a URI. It is not supported for use by any service in the API and therefore should be ignored if received. + +#### URI Normalization and Comparison + +As specified in RFC 72306, the [scheme](#scheme)) and [host](#host)) part of the URI should be considered case-insensitive. All other parts of the URI should be processed in a case-sensitive manner. + +#### Character Set + +The character set should always be assumed to be UTF-8, defined in 36297; therefore, it does not need to be sent in any of the HTTP header fields (see [HTTP Header Fields](#http-header-fields)). No character set other than UTF-8 is supported by the API. + +#### Data Exchange Format + +The API uses JSON (JavaScript Object Notation), defined in RFC 71598, as its data exchange format. JSON is an open, lightweight, human-readable and platform-independent format, well-suited for interchanging data between systems. + +
    + +### HTTP Details + +This section contains detailed information regarding the use of the application-level protocol HTTP in the API. + +#### HTTP Header Fields + +HTTP Headers are generally described in RFC 72309. The following two sections describes the HTTP header fields that should be expected and implemented in the API. + +The API supports a maximum size of 65536 bytes (64 Kilobytes) in the HTTP header. + +#### HTTP Request Header Fields + +[Table 1](#table-1) contains the HTTP request header fields that must be supported by implementers of the API. An implementation should also expect other standard and non-standard HTTP request header fields not listed here. + +###### Table 1 + +|Field|Example Values|Cardinality|Description| +|---|---|---|---| +|**Accept**|**application/vnd.interoperability.resource+json**|0..1
    Mandatory in a request from a client. Not used in a callback from the server.
    The **Accept**10 header field indicates the version of the API the client would like the server to use. See [HTTP Accept Header](#http-accept-header) for more information on requesting a specific version of the API.| +|**Content-Length**|**3495**|0..1|The **Content-Length**11 header field indicates the anticipated size of the payload body. Only sent if there is a body.
    **Note**: The API supports a maximum size of 5242880 bytes (5 Megabytes).
    | +|**Content-Type**|**application/vnd.interoperability.resource+json;version=1.0**|1|The **Content-Type**12 header indicates the specific version of the API used to send the payload body. See [Acceptable Version Requested by Client](#acceptable-version-requested-by-client) for more information.| +|**Date**|**Tue, 15 Nov 1994 08:12:31 GMT**|1|The **Date**13 header field indicates the date when the request was sent.| +|**X- Forwarded- For**|**X-Forwarded-For: 192.168.0.4, 136.225.27.13**|1..0|The **X-Forwarded-For**14 header field is an unofficially accepted standard used to indicate the originating client IP address for informational purposes, as a request might pass multiple proxies, firewalls, and so on. Multiple **X-Forwarded-For** values as in the example shown here should be expected and supported by implementers of the API.
    **Note**: An alternative to **X-Forwarded-For** is defined in RFC 723915. However, as of 2018, RFC 7239 is less-used and supported than **X-Forwarded-For**.
    | +|**FSPIOP- Source**|**FSP321**|1|The **FSPIOP-Source** header field is a non- HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing (see [Call Flow Routing](#call-flow-routing-using-fspiop-destination-and-fspiop-source) section) and signature verification (see header field **FSPIOP-Signature**).| +|**FSPIOP- Destination**|**FSP123**|0..1|The **FSPIOP-Destination** header field is a non-HTTP standard field used by the API for HTTP header-based routing of requests and responses to the destination. The field must be set by the original sender of the request if the destination is known (valid for all services except GET /parties) so that any entities between the client and the server do not need to parse the payload for routing purposes (see [Call Flow Routing](#3236-call-flow-routing-using-fspiop-destination-and-fspiop-source) section for more information regarding routing). If the destination is not known (valid for service GET /parties), the field should be left empty.| +|**FSPIOP- Encryption**||0..1|The **FSPIOP-Encryption** header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request.
    For more information, see API Encryption.
    | +|**FSPIOP- Signature**||0..1|The **FSPIOP-Signature** header field is a non-HTTP standard field used by the API for applying an end-to-end request signature.
    For more information, see API Signature.
    | +|**FSPIOP-URI**|**/parties/msisdn/123456789**|0..1|The **FSPIOP-URI** header field is a non- HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information see _API Signature_.
    In the context of the Mojaloop FSPIOP API, the value for FSPIOP-URI starts with the **_service_** in the URI value. For example, if a URL is http://stg-simulator.moja.live/payerfsp/participants/MSISDN/123456789, then the FSPIOP-URI value is “/participants/MSISDN/123456789”.| +|**FSPIOP- HTTP- Method**|**GET**|0..1|The **FSPIOP-HTTP-Method** header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information see API Signature.| + +**Table 1 -- HTTP request header fields that must be supported** + +[Table 2](#table-2) contains the HTTP request header fields that are optional to support by implementers of the API. + +###### Table 2 + +|Field|Example Values|Cardinality|Description| +|---|---|---|---| +|**traceparent**|**00-91e502e28cd723686e9940bd3f378f85-b0f903d000944947-01**|0..1|The traceparent header represents the incoming request in a tracing system in a common format. See _Distributed Tracing Support for OpenAPI Interoperability_ for more information.| +|**tracestate**|**banknrone=b0f903d0009449475**|0..1|Provides optional vendor-specific trace information, and support for multiple distributed traces. See _Distributed Tracing Support for OpenAPI Interoperability_ for more information.| + +**Table 2 -- HTTP request header fields that are optional to support** + +##### HTTP Response Header Fields + +[Table 3](#table-3) contains the HTTP response header fields that must be supported by implementers of the API. An implementation should also expect other standard and non-standard HTTP response header fields that are not listed here. + +###### Table 3 + +|Field|Example Values|Cardinality|Description| +|---|---|---|---| +|**Content-Length**|**3495**|0..1|The **Content-Length**16 header field indicates the anticipated size of the payload body. Only sent if there is a body.| +|**Content-Type**|**application/vnd.interoperability.resource+json;version=1.0**|1|The **Content-Type**17 header field indicates the specific version of the API used to send the payload body. See [Section 3.3.4.2](#3342-acceptable-version-requested-by-client) for more information.| + +**Table 3 -- HTTP response header fields** + +#### HTTP Methods + +The following HTTP methods, as defined in RFC 723118, are supported by the API: + +- **GET** -- The HTTP **GET** method is used from a client to request information about a previously-created object on a server. As all services in the API are asynchronous, the response to the **GET** method will not contain the requested object. The requested object will instead come as part of a callback using the HTTP **PUT** method. + +- **PUT** -- The HTTP **PUT** method is used as a callback to a previously sent HTTP **GET**, HTTP **POST** or HTTP **DELETE** method, sent from a server to its client. The callback will contain either: + + - Object information concerning a previously created object (HTTP **POST**) or sent information request (HTTP **GET**). + - Acknowledgement that whether an object was deleted (HTTP **DELETE**). + - Error information in case the HTTP **POST** or HTTP **GET** request failed to be processed on the server. + +- **POST** -- The HTTP **POST** method is used from a client to request an object to be created on the server. As all services in the API are asynchronous, the response to the **POST** method will not contain the created object. The created object will instead come as part of a callback using the HTTP **PUT** method. + +- **DELETE** -- The HTTP **DELETE** method is used from a client to request an object to be deleted on the server. The HTTP **DELETE** method should only be supported in a common Account Lookup System (ALS) for deleting information regarding a previously added Party (an account holder in an FSP), no other object types can be deleted. As all services in the API are asynchronous, the response to the HTTP **DELETE** method will not contain the final acknowledgement that the object was deleted or not; the final acknowledgement will come as a callback using the HTTP **PUT** method. + +- **PATCH** -- The HTTP **PATCH** method is used from a client to send a notification regarding an update of an existing object. As all services in the API are asynchronous, the response to the **POST** method will not contain the created object. This HTTP method does not result in a callback, as the **PATCH** request is used as a notification. + +
    + +#### HTTP Sequence Flow + +All the sequences and related services use an asynchronous call flow. No service supports a synchronous call flow. + +##### HTTP POST Call Flow + +[Figure 1](#figure-1) shows the normal API call flow for a request to create an object in a Peer FSP using HTTP **POST**. The service **_/service_** in the flow should be renamed to any of the services in [Table 6](#table-6) that support the HTTP **POST** method. + +###### Figure 1 + +{% uml src="assets/diagrams/sequence/figure1.plantuml" %} +{% enduml %} + +**Figure 1 -- HTTP POST call flow** + +##### HTTP GET Call Flow + +[Figure 2](#figure-2) shows the normal API call flow for a request to get information about an object in a Peer FSP using HTTP **GET**. The service **/service/**_{ID}_ in the flow should be renamed to any of the services in [Table 6](#table-6) that supports the HTTP **GET** method. + +###### Figure 2 + +{% uml src="assets/diagrams/sequence/figure2.plantuml" %} +{% enduml %} + +**Figure 2 -- HTTP GET call flow** + +##### HTTP DELETE Call Flow + +[Figure 3](#figure-3) contains the normal API call flow to delete FSP information about a Party in an ALS using HTTP **DELETE**. The service **/service/**_{ID}_ in the flow should be renamed to any of the services in [Table 6](#table-6) that supports the HTTP DELETE method. HTTP DELETE is only supported in a common ALS, which is why the figure shows the ALS entity as a server only. + +###### Figure 3 + +{% uml src="assets/diagrams/sequence/figure3.plantuml" %} +{% enduml %} + +**Figure 3 -- HTTP DELETE call flow** + +**Note:** It is also possible that requests to the ALS be routed through a Switch, or that the ALS and the Switch are the same server. + +##### HTTP PUT Call Flow** + +The HTTP **PUT** is always used as a callback to either a **POST** service request, a **GET** service request, or a **DELETE** service request. + +The call flow of a **PUT** request and response can be seen in [Figure 1](#figure-1), [Figure 2](#figure-2), and [Figure 3](#figure-3). + +##### HTTP PATCH Call Flow + +[Figure 4](#figure-4) shows an example call flow for a HTTP **PATCH**, which is used for sending a notification. First, an object is created using a **POST** service request from the Switch. The object is created in the FSP in a non-finalized state. The FSP then requests to get a notification regarding the finalized state from the Switch by sending the non-finalized state in the **PUT** callback. The Switch handles the callback and sends the notification regarding the finalized state in a **PATCH** service request. The only resource that supports updated object notification using HTTP **PATCH** is /transfers. + +###### Figure 4 + +{% uml src="assets/diagrams/sequence/figure4.plantuml" %} +{% enduml %} + +**Figure 4 -- HTTP PATCH call flow** + +**Note:** It is also possible that requests to the ALS be routed through a Switch, or that the ALS and the Switch are the same server. + +##### Call Flow Routing using FSPIOP-Destination and FSPIOP-Source + +The non-standard HTTP header fields **FSPIOP-Destination** and **FSPIOP-Source** are used for routing and message signature verification purposes (see _API Signature_ for more information regarding signature verification). [Figure 5](#figure-5) shows how the header fields are used for routing in an abstract **POST /service** call flow, where the destination (Peer) FSP is known. + +###### Figure 5 + +{% uml src="assets/diagrams/sequence/figure5.plantuml" %} +{% enduml %} + +**Figure 5 -- Using the customized HTTP header fields FSPIOP-Destination and FSPIOP-Source** + +For some services when a Switch is used, the destination FSP might be unknown. An example of this scenario is when an FSP sends a **GET /parties** to the Switch without knowing which Peer FSP that owns the Party (see [Section 6.3.2](#632-service-details) describing the scenario). **FSPIOP-Destination** will in that case be empty (or set to the Switch's ID) from the FSP, but will subsequently be set by the Switch to the correct Peer FSP. See [Figure 6](#figure-6) for an example describing the usage of **FSPIOP-Destination** and **FSPIOP-Source**. + +###### Figure 6 + +{% uml src="assets/diagrams/sequence/figure6.plantuml" %} +{% enduml %} + +**Figure 6 -- Example scenario where FSPIOP-Destination is unknown to FSP** + +
    + +#### HTTP Response Status Codes + +The API supports the HTTP response status codes19 in [Table 4](#table-4) below: + +###### Table 4 + +|Status Code|Reason|Description| +|---|---|---| +|**200**|`OK`|Standard response for a successful request. Used in the API by the client as a response on a callback to mark the completion of an asynchronous service.| +|**202**|`Accepted`|The request has been accepted for future processing at the server, but the server cannot guarantee that the outcome of the request will be successful. Used in the API to acknowledge that the server has received an asynchronous request.| +|**400**| `Bad Request`|The application cannot process the request; for example, due to malformed syntax or the payload exceeded size restrictions.| +|**401**|`Unauthorized`|The request requires authentication in order to be processed.| +|**403**|`Forbidden`|The request was denied and will be denied in the future.| +|**404**|`Not Found`|The resource specified in the URI was not found.| +|**405**|`Method Not Allowed`|An unsupported HTTP method for the request was used; see Table 6 for information on which HTTP methods are allowed in which services.| +|**406**|`Not acceptable`|The server is not capable of generating content according to the Accept headers sent in the request. Used in the API to indicate that the server does not support the version that the client is requesting.| +|**501**|`Not Implemented`|The server does not support the requested service. The client should not retry.| +|**503**|`Service Unavailable`|The server is currently unavailable to accept any new service requests. This should be a temporary state, and the client should retry within a reasonable time frame.| + + **Table 4 -- HTTP response status codes supported in the API** + +Any HTTP status codes 3*xx*20 returned by the server should not be retried and require manual investigation. + +An implementation of the API should also be capable of handling other errors not defined above as the request could potentially be routed through proxy servers. + +As all requests in the API are asynchronous, additional HTTP error codes for server errors (error codes starting with 5*xx*21 that are *not* defined in [Table 4](#table-4)) are not used by the API itself. Any error on the server during actual processing of a request will be sent as part of an error callback to the client (see [Section 9.2](#92-error-in-server-during-processing-of-request)). + +
    + +##### Error Information in HTTP Response + +In addition to the HTTP response code, all HTTP error responses (4*xx* and 5*xx* status codes) can optionally contain an **ErrorInformation** element, defined in the section on [ErrorInformation](#errorinformation). This element should be used to give more detailed information to the client if possible. + +
    + +##### Idempotent Services in Server + +All services that support HTTP **GET** must be _idempotent_; that is, the same request can be sent from a client any number of times without changing the object on the server. The server is allowed to change the state of the object; for example, a transaction state can be changed, but the FSP sending the **GET** request cannot change the state. + +All services that support HTTP **POST** must be idempotent in case the client is sending the same service ID again; that is, the server must not create a new service object if a client sends the same **POST** request again. The reason behind this is to simplify the handling of resends during error-handling in a client; however, this creates some extra requirements of the server that receives the request. An example in which the same **POST** request is sent several times can be seen [here](#client-missing-response-from-server---using-resend-of-request). + +##### Duplicate Analysis in Server on Receiving a HTTP POST Request + +When a server receives a request from a client, the server should check to determine if there is an already-existing service object with the same ID; for example, if a client has previously sent the request **POST /transfers** with the identical **transferId**. If the object already exists, the server must check to determine if the parameters of the already-created object match the parameters from the new request. + +- If the previously-created object matches the parameter from the new request, the request should be assumed to be a resend from the client. + + - If the server has not finished processing the old request and therefore has not yet sent the callback to the client, this new request can be ignored, because a callback is about to be sent to the client. + - If the server has finished processing the old request and a callback has already been sent, a new callback should be sent to the client, similar to if a HTTP **GET** request had been sent. + +- If the previously-created object does not match the parameters from the new request, an error callback should be sent to the client explaining that an object with the provided ID already exists with conflicting parameters. + +To simplify duplicate analysis, it is recommended to create and store a hash value of all incoming **POST** requests on the server, so that it is easy to compare the hash value against later incoming **POST** requests. + +
    + +### API Versioning + +The strategy of the development of the API is to maintain backwards compatibility between the API and its resources and services to the maximum extent possible; however, changes to the API should be expected by implementing parties. Versioning of the API is specific to the API resource (for example, **/participants**, **/quotes**, **/transfers**). + +There are two types of API resource versions: _Minor_ versions, which are backwards-compatible, and _major_ versions, which are backwards-incompatible. + +- Whenever a change in this document defining the characteristics of the API is updated that in some way affects an API service, the affected resource will be updated to a new major or minor version (depending on whether the changes are backwards-compatible or not). + +- Whenever a change is made to a specific service in the API, a new version of the corresponding resource will be released. + +The format of the resource version is _x_._y_ where _x_ is the major version and _y_ is the minor version. Both major and minor versions are sequentially numbered. When a new major version of a service is released, the minor version is reset to **0**. The initial version of each resource in the API is **1.0**. + +#### Changes not Affecting the API Resource Version + +Some changes will not affect the API resource version; for example, if the order of parameters within a request or callback were to be changed. + +#### Minor API Resource Version + +The following list describes the changes that are considered backwards compatible if the change affects any API service connected to a resource. API implementers should implement their client/server in such a way that the API services automatically support these changes without breaking any functionality. + +- Optional input parameters such as query strings added in a request +- Optional parameters added in a request or a callback +- Error codes added + +These types of changes affect the minor API service version. + +#### Major API Resource Versions + +The following list describes the changes that are considered backwards-incompatible if the change affects any API service connected to a resource. API implementers do _not_ need to implement their client/server in such a way that it automatically supports these changes. + +- Mandatory parameters removed or added to a request or callback +- Optional parameters changed to mandatory in a request or callback +- Parameters renamed +- Data types changed +- Business logic of API resource or connected services changed +- API resource/service URIs changed + +These types of changes affect the major API service version. Please note that the list is not comprehensive; there might be other changes as well that could affect the major API service version. + +#### Version Negotiation between Client and Server + +The API supports basic version negotiation by using HTTP content negotiation between the server and the client. A client should send the API resource version that it would like to use in the **Accept** header to the server (see [HTTP Accept Header](#http-accept-header)). If the server supports that version, it should use that version in the callback (see [Acceptable Version Requested by Client](#acceptable-version-requested-by-client)). If the server does not support the requested version, the server should reply with HTTP status 40622 including a list of supported versions (see [Non-Acceptable Version Requested by Client](#non-acceptable-version-requested-by-client)). + +#### HTTP Accept Header + +See below for an example of a simplified HTTP request which only includes an **Accept** header23. The **Accept** header should be used from a client requesting a service from a server specifying a major version of the API service. The example in [Listing 3](#listing-3) should be interpreted as "I would like to use major version 1 of the API resource, but if that version is not supported by the server then give me the latest supported version". + +###### Listing 3 + +``` +POST /service HTTP/1.1 +Accept: application/vnd.interoperability.{resource}+json;version=1, +application/vnd.interoperability.{resource}+json + +{ + ... +} +``` + +**Listing 3 -- HTTP Accept header example, requesting version 1 or the latest supported version** + +Regarding the example in [Listing 3](#listing-3): + +- The **_POST /service_** should be changed to any HTTP method and related service or resource that is supported by the API (see [Table 6](#table-6)). +- The **Accept** header field is used to indicate the API resource version the client would like to use. If several versions are supported by the client, more than one version can be requested separated by a comma (**,**) as in the example above. + - The application type is always **application/vnd.interoperability.**_{resource}_, where _{resource}_ is the actual resource (for example, **participants** or **quotes**). + - The only data exchange format currently supported is **json**. + - If a client can use any minor version of a major version, only the major version should be sent; for example, **version=1** or **version=2**. + - If a client would like to use a specific minor version, this should be indicated by using the specific _major.minor_ version; for example, **version=1.2** or **version=2.8**. The use of a specific _major.minor_ version in the request should generally be avoided, as minor versions should be backwards-compatible. + +#### Acceptable Version Requested by Client + +If the server supports the API resource version requested by the client in the Accept Headers, it should use that version in the subsequent callback. The used _major.minor_ version should always be indicated in the **Content-Type** header by the server, even if the client only requested a major version of the API. See the example in [Listing 4](#listing-4), which indicates that version 1.0 is used by the server: + +###### Listing 4 + +``` +Content-Type: application/vnd.interoperability.resource+json;version=1.0 +``` + +**Listing 4 -- Content-Type HTTP header field example** + +#### Non-Acceptable Version Requested by Client + +If the server does not support the version requested by the client in the **Accept** header, the server should reply with HTTP status 406, which indicates that the requested version is not supported. + +**Note:** There is also a possibility that the information might be sent as part of an error callback to a client instead of directly in the response; for example, when the request is routed through a Switch which does support the requested version, but the destination FSP does not support the requested version. + +Along with HTTP status 406, the supported versions should be listed as part of the error message in the extensions list, using the major version number as _key_ and minor version number as _value_. Please see error information in the example in [Listing 5](#listing-5), describing the server's supported versions. The example should be interpreted as "I do not support the resource version that you requested, but I do support versions 1.0, 2.1, and 4.2". + +###### Listing 5 + +```json +{ + "errorInformation": { + "errorCode": "3001", + "errorDescription": "The Client requested an unsupported version, see extension list for supported version(s).", + "extensionList": { + "extension": + [ + { "key": "1", "value": "0"}, + { "key": "2", "value": "1"}, + { "key": "4", "value": "2"} + ] + } + } +} +``` + +**Listing 5 -- Example error message when server does not support the requested version** + + +
    + +## Interledger Protocol + +The current version of the API includes basic support for the Interledger Protocol (ILP), by defining a concrete implementation of the Interledger Payment Request protocol24 in API Resource [/quotes](#api-resource-quotes), and API Resource, [**/transfers**](#api-resource-transfers). + +### More Information + +This document contains ILP information that is relevant to the API. For more information about the ILP protocol, see the Interledger project website25, the Interledger Whitepaper26, and the Interledger architecture specification27. + +### Introduction to Interledger + +ILP is a standard for internetworking payment networks. In the same way that the Internet Protocol (IP) establishes a set of basic standards for the transmission and addressing of data packets between different data networks, ILP establishes a set of basic standards for the addressing of financial transactions and transfer of value between accounts on different payment networks. + +ILP is not a scheme. It is a set of standards that, if implemented by multiple payment schemes, will allow those schemes to be interoperable. Therefore, implementing ILP involves adapting an existing scheme to conform to those standards. Conformance means ensuring that transfers between accounts within the scheme are done in two phases (_reserve_ and _commit_) and defining a mapping between the accounts in the scheme and the global ILP Addressing scheme. This can be done by modifying the scheme itself, or by the entities that provide ILP-conformant access to the scheme using scheme adaptors. + +The basic prerequisites for an ILP payment are the Payee ILP address (see [ILP addressing](#ilp-addressing)) and the condition (see [Conditional Transfers](#conditional-transfers)). In the current version of the API, both these prerequisites should be returned by the Payee FSP during quoting API Resource [**/quotes**](#api-resource-quotes)) of the financial transaction. + +### ILP Addressing + +A key component of the ILP standard is the ILP addressing28 scheme. It is a hierarchical scheme that defines one or more addresses for every account on a ledger. + +[Table 5](#table-5) shows some examples of ILP addresses that could be used in different scenarios, for different accounts. Note that while the structure of addresses is standardized, the content is not, except for the first segment (up to the first period (**.**)). + +###### Table 5 + +|ILP Address|Description| +|---|---| +|**g.tz.fsp1.msisdn.1234567890**|A mobile money account at **FSP1** for the user with **MSISDN 1234567890**.| +|**g.pk.fsp2.ac03396c-4dba-4743**|A mobile money account at **FSP2** identified by an opaque account id.| +|**g.us.bank1.bob**|A bank account at **Bank1** for the user **bob**.| + +**Table 5 -- ILP address examples** + +The primary purpose of an ILP addresses is to identify an account in order to route a financial transaction to that account. + +**Note:** An ILP address should not be used for identifying a counterparty in the Interoperability API. See section on [Refund](#refund) regarding how to address a Party in the API. + +It is useful to think of ILP addresses as analogous to IP addresses. They are seldom, if ever, be seen by end users but are used by the systems involved in a financial transaction to identify an account and route the ILP payment. The design of the addressing scheme means that a single account will often have many ILP addresses. The system on which the account is maintained may track these or, if they are all derived from a common prefix, may track a subset only. + +### Conditional Transfers + +ILP depends on the concept of _conditional transfers_, in which all ledgers involved in a financial transaction from the Payer to the Payee can first reserve funds out of a Payer account and then later commit them to the Payee account. The transfer from the Payer to the Payee account is conditional on the presentation of a fulfilment that satisfies the condition attached to the original transfer request. + +To support conditional transfers for ILP, a ledger must support a transfer API that attaches a condition and an expiry to the transfer. The ledger must prepare the transfer by reserving the funds from the Payer account, and then wait for one of the following events to occur: + +- The fulfilment of the condition is submitted to the ledger and the funds are committed to the Payee account. + +- The expiry timeout is reached, or the financial transaction is rejected by the Payee or Payee FSP. The transfer is then aborted and the funds that were reserved from the Payer account are returned. + +When the fulfilment of a transfer is submitted to a ledger, the ledger must ensure that the fulfilment is valid for the condition that was attached to the original transfer request. If it is valid, the transfer is committed, otherwise it is rejected, and the transfer remains in a pending state until a valid fulfilment is submitted or the transfer expires. + +ILP supports a variety of conditions for performing a conditional payment, but implementers of the API should use the SHA-256 hash of a 32-byte pre-image. The condition attached to the transfer is the SHA-256 hash and the fulfilment of that condition is the pre-image. Therefore, if the condition attached to a transfer is a SHA-256 hash, then when a fulfilment is submitted for that transaction, the ledger will validate it by calculating the SHA-256 hash of the fulfilment and ensuring that the hash is equal to the condition. + +See [Interledger Payment Request](#interledger-payment-request) for concrete information on how to generate the fulfilment and the condition. + +### ILP Packet + +The ILP Packet is the mechanism used to package end-to-end data that can be passed in a hop-by-hop service. It is included as a field in hop-by-hop service calls and should not be modified by any intermediaries. The integrity of the ILP Packet is tightly bound to the integrity of the funds transfer, as the commit trigger (the fulfilment) is generated using a hash of the ILP Packet. + +The packet has a strictly defined binary format, because it may be passed through systems that are designed for high performance and volume. These intermediary systems must read the ILP Address and the amount from the packet headers, but do not need to interpret the **data** field in the ILP Packet (see [Listing 6](#listing-6)). Since the intermediary systems should not need to interpret the **data** field, the format of the field is not strictly defined in the ILP Packet definition. It is simply defined as a variable length octet string. [Interledger Payment Request](#interledger-payment-request) contains concrete information on how the ILP Packet is populated in the API. + +The ILP Packet is the common thread that connects all the individual ledger transfers that make up an end-to-end ILP payment. The packet is parsed by the Payee of the first transfer and used to determine where to make the next transfer, and for how much. It is attached to that transfer and parsed by the Payee of the next transfer, who again determines where to make the next transfer, and for how much. This process is repeated until the Payee of the transfer is the Payee in the end-to-end financial transaction, who fulfils the condition, and the transfers are committed in sequence starting with the last and ending with the first. + +The ILP Packet format is defined in ASN.129 (Abstract Syntax Notation One), shown in [Listing 6](#listing-6). The packet is encoded using the canonical Octet Encoding Rules. + +###### Listing 6 + +``` +InterledgerProtocolPaymentMessage ::= SEQUENCE { + -- Amount which must be received at the destination amount UInt64, + -- Destination ILP Address account Address, + -- Information for recipient (transport layer information) data OCTET STRING (SIZE (0..32767)), + -- Enable ASN.1 Extensibility + extensions SEQUENCE { + ... + } +} +``` + +**Listing 6 -- The ILP Packet format in ASN.1 format** + +**Note:** The only mandatory data elements in the ILP Packet are the amount to be transferred to the account of the Payee and the ILP Address of the Payee. + +
    + +## Common API Functionality + +This section describes the common functionality used by the API, including: + +- [Quoting](#quoting) +- [Party Addressing](#party-addressing) +- [Mapping of Use Cases to Transaction Types](#mapping-of-use-cases-to-transaction-types) + +### Quoting + +Quoting is the process that determines any fees and any commission required to perform a financial transaction between two FSPs. It is always initiated by the Payer FSP to the Payee FSP, which means that the quote flows in the same way as a financial transaction. + +Two different modes for quoting between FSPs are supported in the API: _Non-disclosing of fees_ and _Disclosing of fees_. + +- _Non-Disclosing of fees_ should be used when either the Payer FSP does not want to show the Payee FSP its fee structure, or when the Payer FSP would like to have more control of the fees paid by the Payer after quoting has been performed (the latter is only applicable for _Receive amount_; see next bullet list). + +- _Disclosing of fees_ can be used for use cases in which the Payee FSP wants to subsidize the transaction in some use cases; for example, Cash-In at another FSP's agent. + +The _Non-Disclosing of fees_ mode should be the standard supported way of quoting in most schemes. _Disclosing of fees_ might be used in some schemes; for example, a scheme in which a dynamic fee structure is used and an FSP wants the ability to subsidize the Cash-In use case based on the dynamic cost. + +In addition, the Payer can decide if the amount should be _Receive amount_ or _Send amount_. + +- _Send amount_ should be interpreted as the actual amount that should be deducted from the Payer's account, including any fees. + +- _Receive amount_ should be interpreted as the amount that should be added to the Payee's account, regardless of any interoperable transaction fees. The amount excludes possible internal Payee fees added by the Payee FSP. + +The Payee FSP can choose if the actual receive amount for the Payee should be sent or not in the callback to the Payer FSP. The actual Payee receive amount should include any Payee FSP internal fees on the Payee. + +All taxes are assumed to be FSP-internal, which means that taxes are not sent as part of the API. See [Tax Information](#tax-information) for more information regarding taxes. + +**Note:** Dynamic fees implemented using a Switch, or any other intermediary, are not supported in this version of the API. + + +#### Non-Disclosing of Fees + +The fees and commission payments related to an interoperable transaction when fees are not disclosed are shown in [Figure 7](#figure-7). The fees and commission that are directly part of the API are identified by green text. The FSP internal fees, commission, and bonus payments are identified by red text. These are not part of the transaction between a Payer FSP and a Payee FSP, but the amount that the Payee will receive after any FSP internal fees can be sent for information by the Payee FSP. + +For send amount (see [Non-Disclosing Send Amount](#non-disclosing-send-amount) for more information), internal Payer FSP fees on the Payer will affect the amount that is sent from the Payer FSP. For example, if the Payer FSP has a fee of 1 USD for a 100 USD interoperable financial transaction, 99 USD is sent from the Payer FSP. For receive amount (see [Non-Disclosing Receive Amount](#non-disclosing-receive-amount) for more information), internal Payer FSP fees on the Payer will not affect the amount that is sent from the Payer FSP. Internal Payer FSP bonus or commission on the Payer should be hidden regardless of send or receive amount. + +###### Figure 7 + +![Figure 7](/assets/diagrams/images/figure7.svg) + +**Figure 7 -- Fees and commission related to interoperability when fees are not disclosed** + +See [Fee Types](#fee-types) for more information on the fee types sent in the Interoperability API. + +#### Non-Disclosing Receive Amount + +[Figure 8](#figure-8) shows an example of non-disclosing receive amount, in which the Payer would like the Payee to receive exactly 100 USD. For non-disclosing receive amount, the Payer FSP need not set the internal rating of the transaction until after the quote has been received because the Payee FSP knows what amount it will receive. + +In this example, the Payee FSP decides to give commission to the Payer FSP since funds are flowing to the Payee FSP, which will later be spent in some way; this results in a future fee income for the Payee FSP. The Payer FSP can then decide how much in fees should be taken from the Payer for cost-plus pricing. In this example, the Payer FSP would like to have 1 USD from the Payer, which means that the Payer FSP will earn 2 USD in total, as the Payer FSP will also receive 1 USD in FSP commission from the Payee FSP. + +###### Figure 8 + +{% uml src="assets/diagrams/sequence/figure8.plantuml" %} +{% enduml %} + +**Figure 8 -- Example of non-disclosing receive amount** + +###### Figure 9 + +![Figure 9](/assets/diagrams/images/figure9.svg) + +**Figure 9 -- Simplified view of money movement for non-disclosing receive amount example** + +To calculate the element **transferAmount** in the Payee FSP for a non-disclosing receive amount quote, the equation in [Listing 9](#listing-9) should be used, where _Transfer Amount_ is **transferAmount** in [Table 24](#table-24), _Quote_ _Amount_ is **amount** in [Table 23](#table-23), _Payee_ _FSP fee_ is **payeeFspFee** in [Table 24](#table-24), and Payee FSP commission is payeeFspCommission in [Table 24](#table-24). + +###### Listing 7 + +``` +Transfer amount = Quote Amount + Payee FSP Fee -- Payee FSP Commission +``` + +**Listing 7 -- Relation between transfer amount and quote amount for non-disclosing receive amount** + +#### Non-Disclosing Send Amount + +[Figure 10](#figure-10) shows an example of non-disclosing send amount, where the Payer would like to send 100 USD from the Payer's account. For non-disclosing send amount, the Payer FSP must rate (determine the internal transaction fees, commission, or both) the transaction before the quote is sent to the Payee FSP so that the Payee FSP knows how much in funds it will receive in the transaction. The actual amount withdrawn from the Payer's account is not disclosed, nor are the fees. + +In the example, the Payer FSP and the Payee FSP would like to have 1 USD each in fees so that the amount that will be received by the Payee is 98 USD. The actual amount that will be received by the Payee is in this example (not mandatory) returned in the callback to the Payer FSP, in the element **payeeReceiveAmount**. + +###### Figure 10 + +{% uml src="assets/diagrams/sequence/figure10.plantuml" %} +{% enduml %} + +**Figure 10 -- Example of non-disclosing send amount** + +###### Figure 11 + +[Figure 11](#figure-11) shows a simplified view of the movement of money for the non-disclosing send amount example. + +![Figure 11](/assets/diagrams/images/figure11.svg) + +**Figure 11 -- Simplified view of money movement for non-disclosing send amount example** + +To calculate the element **transferAmount** in the Payee FSP for a non-disclosing send amount quote, the equation in [Listing 8](#listing-8) should be used, where _Transfer Amount_ is **transferAmount** in [Table 24](#table-24), _Quote_ _Amount_ is **amount** in [Table 24](#table-24), and Payee FSP commission is **payeeFspCommission** in [Table 24](#table-24). + +###### Listing 8 + +``` +Transfer amount = Quote Amount -- Payee FSP Commission +``` + +**Listing 8 -- Relation between transfer amount and quote amount for non-disclosing send amount** + +The reason for a Payee FSP fee to be absent in the equation is that the Payer would like to send a certain amount from their account. The Payee will receive less funds instead of a fee being added on top of the amount. + +#### Disclosing of Fees + +The fees and commission payments related to an interoperable transaction when fees are disclosed can be seen in [Figure 11](#figure-11). The fees and commission that are directly related to the API are marked with green text. Internal Payee fees, bonus, and commission are marked with red text, these will have an implication on the amount that is sent by the Payer and received by the Payee. They are not part of the interoperable transaction between a Payer FSP and a Payee FSP, but the actual amount to be received by the Payee after internal Payee FSP fees have been deducted can be sent for information by the Payee FSP. + +When disclosing of fees are used, the FSP commission that the Payee FSP sends should subsidize the transaction cost for the Payer. This means that any FSP commission sent from the Payee FSP will effectively pay either a part or all of the fees that the Payer FSP has added to the transaction. If the FSP commission amount from the Payee FSP is higher than the actual transaction fees for the Payer, the excess amount should be handled as a fee paid by Payee FSP to Payer FSP. An example of excess FSP commission can be found [here](#excess-fsp-commission-example). + +###### Figure 12 + +![Figure 12](/assets/diagrams/images/figure12.svg) + +**Figure 12 -- Fees and commission related to interoperability when fees +are disclosed** + +See [Fee Types](#fee-types) for more information on the fee types sent in the Interoperability API. + +#### Disclosing Receive Amount + +[Figure 13](#figure-13) shows an example of disclosing receive amount where the Payer would like the Payee to receive exactly 100 USD. For disclosing receive amount, the Payer FSP must internally rate the transaction before the quote request is sent to the Payee FSP, because the fees are disclosed. In this example, the Payer FSP would like to have 1 USD in fees from the Payer. The Payee FSP decides to give 1 USD in commission to subsidize the transaction, so that the transaction is free for the Payer. + +###### Figure 13 + +{% uml src="assets/diagrams/sequence/figure13.plantuml" %} +{% enduml %} + +**Figure 13 -- Example of disclosing receive amount** + +[Figure 14](#figure-14) shows a simplified view of the movement of money for the disclosing receive amount example. + +###### Figure 14 + +![Figure 14](/assets/diagrams/images/figure14.svg) + +**Figure 14 -- Simplified view of money movement for disclosing receive amount example** + +To calculate the element **transferAmount** in the Payee FSP for a disclosing receive amount quote, the equation in [Listing 9](#listing-9) should be used, where _Transfer Amount_ is **transferAmount** in [Table 24](#table-24), _Quote_ _Amount_ is **amount** in [Table 24](#table-24), _Payee_ _FSP fee_ is **payeeFspFee** in [Table 24](#table-24), and Payee FSP commission is **payeeFspCommission** in [Table 24](#table-24). + +###### Listing 9 + +``` +Transfer amount = Quote Amount + Payee FSP Fee -- Payee FSP Commission +``` + +**Listing 9 -- Relation between transfer amount and quote amount for disclosing receive amount** + +#### Disclosing Send Amount + +[Figure 15](#figure-15) shows an example of disclosing send amount, where the Payer would like to send 100 USD from the Payer's account to the Payee. For disclosing send amount, the Payer FSP must rate the transaction before the quote request is sent to the Payee FSP, because the fees are disclosed. In this example, the Payer FSP and the Payee FSP would like to have 1 USD each in fees from the Payer. + +###### Figure 15 + +{% uml src="assets/diagrams/sequence/figure15.plantuml" %} +{% enduml %} + +**Figure 15 -- Example of disclosing send amount** + +###### Figure 16 + +[Figure 16](#figure-16) shows a simplified view of the movement of money for the disclosing send amount example. +![Figure 16](/assets/diagrams/images/figure16.svg) + +**Figure 16 -- Simplified view of money movement for disclosing send amount example** + +To calculate the element **transferAmount** in the Payee FSP for a disclosing send amount quote, the equation in [Listing 10](#listing-10) should be used, where _Transfer Amount_ is **transferAmount** in [Table 24](#table-24), _Quote_ _Amount_ is **amount** in [Table 24](#table-24), _Payer_ _Fee_ is **fees** in [Table 24](#table-24), and Payee FSP commission is **payeeFspCommission** in [Table 24](#table-24). + +###### Listing 10 + +``` +If (Payer Fee <= Payee FSP Commission) + Transfer amount = Quote Amount +Else + Transfer amount = Quote Amount -- (Payer Fee - Payee FSP Commission) +``` + +**Listing 10 -- Relation between transfer amount and quote amount for disclosing send amount** + +The reason for a Payee FSP fee to be absent in the equation, is that the Payer would like to send a certain amount from their account. The Payee will receive less funds instead of a fee being added on top of the amount. + +#### Excess FSP Commission Example + +[Figure 17](#figure-17) shows an example of excess FSP commission using disclosing send amount, where the Payer would like to send 100 USD from the Payer's account to the Payee. For disclosing send amount, the Payer FSP must rate the transaction before the quote request is sent to the Payee FSP, because the fees are disclosed. In this excess commission example, the Payer FSP would like to have 1 USD in fees from the Payer, and the Payee FSP gives 3 USD in FSP commission. Out of the 3 USD in FSP commission, 1 USD should cover the Payer fees, and 2 USD is for the Payer FSP to keep. + +###### Figure 17 + +{% uml src="assets/diagrams/sequence/figure17.plantuml" %} +{% enduml %} + +**Figure 17 -- Example of disclosing send amount** + +###### Figure 18 + +[Figure 18](#figure-18) shows a simplified view of the movement of money for the excess commission using disclosing send amount example. + +![Figure 18](/assets/diagrams/images/figure18.svg) + +**Figure 18 -- Simplified view of money movement for excess commission using disclosing send amount example** + +#### Fee Types + +As can be seen in [Figure 7](#figure-7) and [Figure 12](#figure-12), there are two different fee and commission types in the Quote object between the + +FSPs: + +1. **Payee FSP fee** -- A transaction fee that the Payee FSP would like to have for the handling of the transaction. + +2. **Payee FSP commission** -- A commission that the Payee FSP would like to give to the Payer FSP (non-disclosing of fees) or subsidize the transaction by paying some or all fees from the Payer FSP (disclosing of fees). In case of excess FSP commission, the excess commission should be handled as the Payee FSP pays a fee to the Payer FSP, see [here](#excess-fsp-commission-example) for an example. + +
    + +#### Quote Equations + +This section contains useful equations for quoting that have not already been mentioned. + +#### Payee Receive Amount Relation to Transfer Amount + +The amount that the Payee should receive, excluding any internal Payee FSP fees, bonus, or commission, can be calculated by the Payer FSP using the equation in [Listing 11](#listing-11), where _Transfer Amount_ is **transferAmount** in [Table 24](#table-24), _Payee_ _FSP fee_ is **payeeFspFee** in [Table 24](#table-24), and Payee FSP commission is payeeFspCommission in [Table 24](#table-24). + +###### Listing 11 + +``` +Payee Receive Amount = Transfer Amount - Payee FSP Fee + Payee FSP Commission +``` + +**Listing 11 -- Relation between transfer amount and Payee receive amount** + +The Payee receive amount including any internal Payee FSP fees can optionally be sent by the Payee FSP to the Payer FSP in the Quote callback, see element **payeeReceiveAmount** in [Table 24](#table-24). +
    + +#### Tax Information + +Tax information is not sent in the API, as all taxes are assumed to be FSP-internal. The following sections contain details pertaining to common tax types related to the API. + +##### Tax on Agent Commission + +Tax on Agent Commission is tax for an _Agent_ as a result of the Agent receiving commission as a kind of income. Either the Agent or its FSP has a relation with the tax authority, depending on how the FSP deployment is set up. As all Agent commissions are FSP-internal, no information is sent through the Interoperability API regarding Tax on Agent Commission. + +##### Tax on FSP Internal Fee + +FSPs could be taxed on FSP internal fees that they receive from the transactions; for example, Payer fees to Payer FSP or Payee fees to Payee FSP. This tax should be handled internally within the FSP and collected by the FSPs because they receive a fee. + +##### Tax on Amount (Consumption tax) + +Examples of tax on amount are VAT (Value Added Tax) and Sales Tax. These types of taxes are typically paid by a Consumer to the Merchant as part of the price of goods, services, or both. It is the Merchant who has a relationship with the tax authority, and forwards the collected taxes to the tax authority. If any VAT or Sales Tax is applicable, a Merchant should include these taxes in the requested amount from the Consumer. The received amount in the Payee FSP should then be taxed accordingly. + +##### Tax on FSP Fee + +In the API, there is a possibility for a Payee FSP to add a fee that the Payer or Payer FSP should pay to the Payee FSP. The Payee FSP should handle the tax internally as normal when receiving a fee (if local taxes apply). This means that the Payee FSP should consider the tax on the fee while rating the financial transaction as part of the quote. The tax is not sent as part of the API. + +##### Tax on FSP Commission + +In the API, there is a possibility for a Payee FSP to add a commission to either subsidize the transaction (if disclosing of fees) or incentivize the Payer FSP (if non-disclosing of fees). + +###### Non-Disclosing of Fees + +For non-disclosing of fees, all FSP commission from the Payee FSP should be understood as the Payer FSP receiving a fee from the Payee FSP. The tax on the received fee should be handled internally within the Payer FSP, similar to the way it is handled in [Tax on FSP Internal Fee](#tax-on-fsp-internal-fee). + +###### Disclosing of Fees + +If the Payee FSP commission amount is less than or equal to the amount of transaction fees originating from the Payer FSP, then the Payee FSP commission should always be understood as being used for covering fees that the Payer would otherwise need to pay. + +If the Payee FSP commission amount is higher than the fees from the Payer FSP, the excess FSP commission should be handled similarly as [Non-Disclosing of Fees](#non-disclosing-of-fees). + +
    + +#### Examples for each Use Case + +This section contains one or more examples for each use case. + +#### P2P Transfer + +A P2P Transfer is typically a receive amount, where the Payer FSP is not disclosing any fees to the Payee FSP. See [Figure 19](#figure-19) for an example. In this example, the Payer would like the Payee to receive 100 USD. The Payee FSP decides to give FSP commission to the Payer FSP, because the Payee FSP will receive funds into the system. The Payer FSP would also like to have 1 USD in fee from the Payer, so the total fee that the Payer FSP will earn is 2 USD. 99 USD is transferred from the Payer FSP to the Payee FSP after deducting the FSP commission amount of 1 USD. + +###### Figure 19 + +{% uml src="assets/diagrams/sequence/figure19.plantuml" %} +{% enduml %} + +**Figure 19 -- P2P Transfer example with receive amount** + +###### Simplified View of Money Movement + +###### Figure 20 + +See [Figure 20](#figure-20) for a highly simplified view of the movement of money for the P2P Transfer example. + +![Figure 20](/assets/diagrams/images/figure20.svg) + +**Figure 20 -- Simplified view of the movement of money for the P2P Transfer example** + +#####Agent-Initiated Cash-In (Send amount) + +[Figure 21](#figure-21) shows an example of an Agent-Initiated Cash-In where send amount is used. The fees are disclosed because the Payee (the customer) would like to know the fees in advance of accepting the Cash-In. In the example, the Payee would like to Cash-In a 100 USD bill using an Agent (the Payer) in the Payer FSP system. The Payer FSP would like to have 2 USD in fees to cover the agent commission. The Payee FSP decides to subsidize the transaction by 2 USD by giving 2 USD in FSP commission to cover the Payer FSP fees. 98 USD is transferred from the Payer FSP to the Payee FSP after deducting the FSP commission amount of 2 USD. + +###### Figure 21 + +{% uml src="assets/diagrams/sequence/figure21.plantuml" %} +{% enduml %} + +**Figure 21 -- Agent-Initiated Cash-In example with send amount** + +###### Simplified View of Money Movement + +See [Figure 22](#figure-22) for a highly simplified view of the movement of money for the Agent-initiated Cash-In example with send amount. + +###### Figure 22 + +![Figure 22](/assets/diagrams/images/figure22.svg) + +**Figure 22 -- Simplified view of the movement of money for the Agent-initiated Cash-In with send amount example** + +##### Agent-Initiated Cash-In (Receive amount) + +[Figure 23](#figure-23) shows an example of Agent-Initiated Cash-In where receive amount is used. The fees are disclosed as the Payee (the Consumer) would like to know the fees in advance of accepting the Cash-In. In the example, the Payee would like to Cash-In so that they receive 100 USD using an Agent (the Payer) in the Payer FSP system. The Payer FSP would like to have 2 USD in fees to cover the agent commission; the Payee FSP decides to subsidize the transaction by 1 USD by giving 1 USD in FSP commission to cover 50% of the Payer FSP fees. 99 USD is transferred from the Payer FSP to the Payee FSP after deducting the FSP commission amount of 1 USD. + +###### Figure 23 + +{% uml src="assets/diagrams/sequence/figure23.plantuml" %} +{% enduml %} + +**Figure 23 -- Agent-initiated Cash-In example with receive amount** + +##### Simplified View of Money Movement + +###### Figure 24 + +See [Figure 24](#figure-24) for a highly simplified view of the movement of money for the Agent-initiated Cash-In example with receive amount. + +![Figure 24](/assets/diagrams/images/figure24.svg) + +**Figure 24 -- Simplified view of the movement of money for the Agent-initiated Cash-In with receive amount example** + +##### Customer-Initiated Merchant Payment + +A Customer-Initiated Merchant Payment is typically a receive amount, where the Payer FSP is not disclosing any fees to the Payee FSP. See [Figure 25](#figure-25) for an example. In the example, the Payer would like to buy goods or services worth 100 USD from a Merchant (the Payee) in the Payee FSP system. The Payee FSP would not like to charge any fees from the Payer, but 1 USD in an internal hidden fee from the Merchant. The Payer FSP wants 1 USD in fees from the Payer. 100 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 25 + +{% uml src="assets/diagrams/sequence/figure25.plantuml" %} +{% enduml %} + +**Figure 25 -- Customer-Initiated Merchant Payment example** + +###### Simplified View of Money Movement + +See [Figure 26](#figure-26) for a highly simplified view of the movement of money for the Customer-Initiated Merchant Payment example. + +###### Figure 26 + +![Figure 26](/assets/diagrams/images/figure26.svg) + +**Figure 26 -- Simplified view of the movement of money for the Customer-Initiated Merchant Payment example** + +##### Customer-Initiated Cash-Out (Receive amount) + +A Customer-Initiated Cash-Out is typically a receive amount, where the Payer FSP is not disclosing any fees to the Payee FSP. See [Figure 27](#figure-27) for an example. In the example, the Payer would like to Cash-Out so that they will receive 100 USD in cash. The Payee FSP would like to have 2 USD in fees to cover the agent commission and the Payer FSP would like to have 1 USD in fee. 102 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 27 + +{% uml src="assets/diagrams/sequence/figure27.plantuml" %} +{% enduml %} + +**Figure 27 -- Customer-Initiated Cash-Out example (receive amount)** + +###### Simplified View of Money Movement + +See [Figure 28](#figure-28) for a highly simplified view of the movement of money for the Customer-Initiated Cash-Out with receive amount example. + +###### Figure 28 + +![Figure 28](/assets/diagrams/images/figure28.svg) + +**Figure 28 -- Simplified view of the movement of money for the Customer-Initiated Cash-Out with receive amount example** + +##### Customer-Initiated Cash-Out (Send amount) + +A Customer-Initiated Cash-Out is typically a receive amount, this +example is shown in [Customer-Initiated Cash-Out](#customer-initiated-cash-out). This section shows an example where send amount is used instead; see [Figure 29](#figure-29) for an example. In the example, the Payer would like to Cash-Out 100 USD from their account. The Payee FSP would like to have 2 USD in fees to cover the agent commission and the Payer FSP would like to have 1 USD in fee. 99 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 29 + +{% uml src="assets/diagrams/sequence/figure29.plantuml" %} +{% enduml %} + +**Figure 29 -- Customer-Initiated Cash-Out example (send amount)** + +###### Simplified View of Money Movement + +See [Figure 30](#figure-30) for a highly simplified view of the movement of money for the Customer-Initiated Cash-Out with send amount example. + +###### Figure 30 + +![Figure 30](/assets/diagrams/images/figure30.svg) + +**Figure 30 -- Simplified view of the movement of money for the Customer-Initiated Cash-Out with send amount example** + +#### Agent-Initiated Cash-Out + +An Agent-Initiated Cash-Out is typically a receive amount, in which the Payer FSP does not disclose any fees to the Payee FSP. See [Figure 31](#Figure-31) for an example. In the example, the Payer would like to Cash-Out so that they will receive 100 USD in cash. The Payee FSP would like to have 2 USD in fees to cover the agent commission and the Payer FSP would like to have 1 USD in fee. 102 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 31 + +{% uml src="assets/diagrams/sequence/figure31.plantuml" %} +{% enduml %} + +**Figure 31 -- Agent-Initiated Cash-Out example** + +######1 Simplified View of Money Movement + +See [Figure 32](#figure-32) for a highly simplified view of the movement of money for the Agent-Initiated Cash-Out example. + +###### Figure 32 + +![Figure 32](/assets/diagrams/images/figure32.svg) + +**Figure 32 -- Simplified view of the movement of money for the Agent-Initiated Cash-Out example** + +##### Merchant-Initiated Merchant Payment + +A Merchant-Initiated Merchant Payment is typically a receive amount, where the Payer FSP is not disclosing any fees to the Payee FSP. See [Figure 33](#figure-33) for an example. In the example, the Payer would like to buy goods or services worth 100 USD from a Merchant (the Payee) in the Payee FSP system. The Payee FSP does not want any fees and the Payer FSP would like to have 1 USD in fee. 100 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 33 + +{% uml src="assets/diagrams/sequence/figure33.plantuml" %} +{% enduml %} + +**Figure 33 -- Merchant-Initiated Merchant Payment example** + +###### Simplified View of Money Movement + +See [Figure 34](#figure-34) for a highly simplified view of the movement of money for the Merchant-Initiated Merchant Payment example. + +###### Figure 34 + +![Figure 34](/assets/diagrams/images/figure34.svg) + +**Figure 34 -- Simplified view of the movement of money for the Merchant-Initiated Merchant Payment example** + +##### ATM-Initiated Cash-Out + +An ATM-Initiated Cash-Out is typically a receive amount, in which the Payer FSP is not disclosing any fees to the Payee FSP. See [Figure 35](#figure-35) for an example. In the example, the Payer would like to Cash-Out so that they will receive 100 USD in cash. The Payee FSP would like to have 1 USD in fees to cover any ATM fees and the Payer FSP would like to have 1 USD in fees. 101 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 35 + +{% uml src="assets/diagrams/sequence/figure35.plantuml" %} +{% enduml %} + +**Figure 35 -- ATM-Initiated Cash-Out example** + +###### Simplified View of Money Movement + +See [Figure 36](#figure-36) for a highly simplified view of the movement of money for the ATM-Initiated Cash-Out example. + +###### Figure 36 + +![Figure 36](/assets/diagrams/images/figure36.svg) + +**Figure 36 -- Simplified view of the movement of money for the ATM-Initiated Cash-Out example** + +##### Merchant-Initiated Merchant Payment authorized on POS + +A Merchant-Initiated Merchant Payment authorized on a POS device is typically a receive amount, in which the Payer FSP does not disclose any fees to the Payee FSP. See [Figure 37](#figure-37) for an example. In the example, the Payer would like to buy goods or services worth 100 USD from a Merchant (the Payee) in the Payee FSP system. The Payee FSP decides to give 1 USD in FSP commission, and the Payer FSP decides to use the FSP commission as the transaction fee. 100 USD is transferred from the Payer FSP to the Payee FSP. + +###### Figure 37 + +{% uml src="assets/diagrams/sequence/figure37.plantuml" %} +{% enduml %} + +**Figure 37 -- Merchant-Initiated Merchant Payment authorized on POS example** + +###### Simplified View of Money Movement + +See [Figure 38](#figure-38) for a highly simplified view of the movement of money for the Merchant-Initiated Merchant Payment authorized on POS example. + +###### Figure 38 + +![Figure 38](/assets/diagrams/images/figure38.svg) + +**Figure 38 -- Simplified view of the movement of money for the +Merchant-Initiated Merchant Payment authorized on POS example** + +##### Refund + +[Figure 39](#figure-39) shows an example of a Refund transaction of the entire amount of the [Agent-Initiated Cash-In (Receive amount)](#agent-initiated-cash-in-receive-amount) example. + +###### Figure 39 + +{% uml src="assets/diagrams/sequence/figure39.plantuml" %} +{% enduml %} + +**Figure 39 -- Refund example** + +#### 5.1.6.11.1 Simplified View of Money Movement + +See [Figure 40](#figure-40) for a highly simplified view of the movement of money for the Refund example. + +###### Figure 40 + +![Figure 40](/assets/diagrams/images/figure40.svg) + +**Figure 40 -- Simplified view of the movement of money for the Refund example** + +
    + +### Party Addressing + +Both Parties in a financial transaction, (that is, the `Payer` and the `Payee`) are addressed in the API by a _Party ID Type_ (element [**PartyIdType**](#partyidtype-element)), a _Party ID_ ([**PartyIdentifier**](#partyidentifier-element)), and an optional _Party Sub ID or Type_ ([PartySubIdOrType](#partysubidortype-element)). Some Sub-Types are pre-defined in the API for personal identifiers ([PersonalIdentifierType](#personalidentifiertype-enum)); for example, for passport number or driver's license number. + +The following are basic examples of how the elements _Party ID Type_ and _Party ID_ can be used: +- To use mobile phone number **+123456789** as the counterparty in a financial transaction, set *Party ID Type* to **MSISDN** and _Party ID_ to **+123456789**. + - Example service to get FSP information: + + **GET /participants/MSISDN/+123456789** + +- To use the email **john\@doe.com** as the counterparty in a financial transaction, set _Party ID Type_ to **EMAIL**, and _Party_ _ID_ to **john\@doe.com**. + + - Example service to get FSP information: + + **GET /participants/EMAIL/john\@doe.com** + +- To use the IBAN account number **SE45 5000 0000 0583 9825 7466** as counterparty in a financial transaction, set _Party_ _ID Type_ to **IBAN**, and _Party ID_ to **SE4550000000058398257466** (should be entered without any whitespace). + + - Example service to get FSP information: + + **GET /participants/IBAN/SE4550000000058398257466** + +The following are more advanced examples of how the elements _Party ID +Type_, _Party ID_, and _Party Sub ID or Type_ can be used: + +- To use the person who has passport number **12345678** as counterparty in a financial transaction, set _Party ID Type_ to **PERSONAL\_ID**, _Party ID_ to **12345678**, and _Party Sub ID or Type_ to **PASSPORT**. + + - Example service to get FSP information: + + **GET /participants/PERSONAL\_ID/123456789/PASSPORT** + +- To use **employeeId1** working in the company **Shoe-company** as counterparty in a financial transaction, set _Party ID_ _Type_ to **BUSINESS**, _Party ID_ to **Shoe-company**, and _Party Sub ID or Type_ to **employeeId1**. + + - Example service to get FSP information: + + **GET /participants/BUSINESS/Shoe-company/employeeId1** + +**5.2.1 Restricted Characters in Party ID and Party Sub ID or Type** + +Because the _Party ID_ and the _Party Sub ID or Type_ are used as part of the URI (see [URI Syntax](#uri-syntax)), some restrictions exist on the ID: + +- Forward slash (**/**) is not allowed in the ID, as it is used by the [Path](#path), to indicate a separation of the Path. + +- Question mark (**?**) is not allowed in the ID, as it is used to indicate the [Query](#query)) part of the URI. + +
    + +### Mapping of Use Cases to Transaction Types + +This section contains information about how to map the currently supported non-bulk use cases in the API to the complex type [**TransactionType**](#transactiontype)), using the elements [TransactionScenario](#transactionscenario)), and [TransactionInitiator](#transactioninitiator)). + +For more information regarding these use cases, see _API Use Cases_. + +#### P2P Transfer + +To perform a P2P Transfer, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **TRANSFER** +- [**TransactionInitiator**](#transactioninitiator) to **PAYER** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **CONSUMER**. + +#### Agent-Initiated Cash In + +To perform an Agent-Initiated Cash In, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **DEPOSIT** +- [**TransactionInitiator**](#transactioninitiator) to **PAYER** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **AGENT**. + +#### Agent-Initiated Cash Out + +To perform an Agent-Initiated Cash Out, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **WITHDRAWAL** +- [**TransactionInitiator**](#transactioninitiator) to **PAYEE** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **AGENT** + +#### Agent-Initiated Cash Out Authorized on POS + +To perform an Agent-Initiated Cash Out on POS, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **WITHDRAWAL** +- [**TransactionInitiator**](#transactioninitiator) to **PAYEE** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **AGENT** + + +#### Customer-Initiated Cash Out + +To perform a Customer-Initiated Cash Out, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **WITHDRAWAL** +- [**TransactionInitiator**](#transactioninitiator) to **PAYER** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **CONSUMER** + +#### Customer-Initiated Merchant Payment + +To perform a Customer-Initiated Merchant Payment, set elements as +follows: + +- [**TransactionScenario**](#transactionscenario) to **PAYMENT** +- [**TransactionInitiator**](#transactioninitiator) to **PAYER** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **CONSUMER**. + +#### Merchant-Initiated Merchant Payment + +To perform a Merchant-Initiated Merchant Payment, set elements as +follows: + +- [**TransactionScenario**](#transactionscenario) to **PAYMENT** +- [**TransactionInitiator**](#transactioninitiator) to **PAYEE** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **BUSINESS** + +#### Merchant-Initiated Merchant Payment Authorized on POS + +To perform a Merchant-Initiated Merchant Payment, set elements as +follows: + +- [**TransactionScenario**](#transactionscenario) to **PAYMENT** +- [**TransactionInitiator**](#transactioninitiator) to **PAYEE** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **DEVICE** + +#### ATM-Initiated Cash Out + +To perform an ATM-Initiated Cash Out, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **WITHDRAWAL** +- [**TransactionInitiator**](#transactioninitiator) to **PAYEE** +- [**TransactionInitiatorType**](#transactioninitiatortype) to **DEVICE** + +#### Refund + +To perform a Refund, set elements as follows: + +- [**TransactionScenario**](#transactionscenario) to **REFUND** +- [**TransactionInitiator**](#transactioninitiator) to **PAYER** +- [**TransactionInitiatorType**](#transactioninitiatortype) depends on the initiator of the Refund. + +Additionally, the [Refund](#refund) complex type must be populated with the transaction ID of the original transaction that is to be refunded. + +
    + +## API Services + +This section introduces and details all services that the API supports for each resource and HTTP method. Each API resource and service is also mapped to a logical API resource and service described in [Generic Transaction Patterns](../generic-transaction-patterns). + + +### High Level API Services + +On a high level, the API can be used to perform the following actions: + +- **Lookup Participant Information** -- Find out in which FSP the counterparty in a financial transaction is located. + + - Use the services provided by the API resource **/participants**. + +- **Lookup Party Information** -- Get information about the counterparty in a financial transaction. + + - Use the services provided by the API resource **/parties**. + +- **Perform Transaction Request** -- Request that a Payer transfer electronic funds to the Payee, at the request of the Payee. The Payer can approve or reject the request from the Payee. An approval of the request will initiate the actual financial transaction. + + - Use the services provided by the API resource **/transactionRequests**. + +- **Calculate Quote** -- Calculate all parts of a transaction that will influence the transaction amount; that is, fees and FSP commission. + + - Use the services provided by the API resource **/quotes** for a single transaction quote; that is, one Payer to one Payee. + - Use the services provided by the API resource **/bulkQuotes** for a bulk transaction quote; that is, one Payer to multiple Payees. + +- **Perform Authorization** -- Request the Payer to enter the applicable credentials when they have initiated the transaction from a POS, ATM, or similar device in the Payee FSP system. + + - Use the services provided by the API resource **/authorizations**. + +- **Perform Transfer** -- Perform the actual financial transaction by transferring the electronic funds from the Payer to the Payee, possibly through intermediary ledgers. + + - Use the services provided by the API resource **/transfers** for single transaction; that is, one Payer to one Payee. + - Use the services provided by the API resource **/bulkTransfers** for bulk transaction; that is, one Payer to multiple Payees. + +- **Retrieve Transaction Information** -- Get information related to the financial transaction; for example, a possible created token on successful financial transaction. + + - Use the services provided by the API resource **/transactions**. + + +#### Supported API services + +[Table 6](#table-6) includes high-level descriptions of the services that the API provides. For more detailed information, see the sections that follow. + +###### Table 6 + +|URI|HTTP method GET|HTTP method PUT|HTTP method POST|HTTP method DELETE|HTTP method PATCH| +|---|---|---|---|---|---| +|**/participants**|Not supported|Not supported|Request that an ALS create FSP information regarding the parties provided in the body or, if the information already exists, request that the ALS update it|Not supported|Not Supported| +|**/participants/**_{ID}_|Not supported|Callback to inform a Peer FSP about a previously-created list of parties.|Not supported|Not Supported|Not Supported| +|**/participants/**_{Type}_/_{ID}_ Alternative: **/participants/**_{Type}_/_{ID}_/_{SubId}_|Get FSP information regarding a Party from either a Peer FSP or an ALS.|Callback to inform a Peer FSP about the requested or created FSP information.|Request an ALS to create FSP information regarding a Party or, if the information already exists, request that the ALS update it|Request that an ALS delete FSP information regarding a Party.|Not Supported| +|**/parties/**_{Type}_/_{ID}_ Alternative: **/parties/**_{Type}_/_{ID}_/_{SubId}_|Get information regarding a Party from a Peer FSP.|Callback to inform a Peer FSP about the requested information about the Party.|Not supported|Not support|Not Supported| +|**/transactionRequests**|Not supported|Not supported|Request a Peer FSP to ask a Payer for approval to transfer funds to a Payee. The Payer can either reject or approve the request.|Not supported|Not Supported| +|**/transactionRequests/**_{ID}_|Get information about a previously-sent transaction request.|Callback to inform a Peer FSP about a previously-sent transaction request.|Not supported|Not supported|Not Supported| +|**/quotes**|Not supported|Not supported|Request that a Peer FSP create a new quote for performing a transaction.|Not supported|Not Supported| +|**/quotes/**_{ID}_|Get information about a previously-requested quote.|Callback to inform a Peer FSP about a previously- requested quote.|Not supported|Not supported|Not Supported| +|**/authorizations/**_{ID}_|Get authorization for a transaction from the Payer whom is interacting with the Payee FSP system.|Callback to inform Payer FSP regarding authorization information.|Not supported|Not supported|Not Supported| +|**/transfers**|Not supported|Not supported|Request a Peer FSP to perform the transfer of funds related to a transaction.|Not supported|Not Supported| +|**/transfers/**_{ID}_|Get information about a previously-performed transfer.|Callback to inform a Peer FSP about a previously-performed transfer.|Not supported|Not supported|Commit notification to Payee FSP| +|**/transactions/**_{ID}_|Get information about a previously-performed transaction.|Callback to inform a Peer FSP about a previously-performed transaction.|Not supported|Not supported|Not Supported| +|**/bulkQuotes**|Not supported|Not supported|Request that a Peer FSP create a new quote for performing a bulk transaction.|Not supported|Not Supported| +|**/bulkQuotes/**_{ID}_|Get information about a previously-requested bulk transaction quote.|Callback to inform a Peer FSP about a previously-requested bulk transaction quote.|Not supported|Not supported|Not Supported| +|**/bulkTransfers**|Not supported|Not supported|Request that a Peer FSP create a bulk transfer.|Not supported|Not Supported| +|**/bulkTransfers/**_{ID}_|Get information about a previously-sent bulk transfer.|Callback to inform a Peer FSP about a previously-sent bulk transfer.|Not supported|Not supported|Not supported| + +**Table 6 – API-supported services** + +#### Current Resource Versions + +[Table 7](#table-7) contains the version for each resource that this document version describes. + +###### Table 7 + +|Resource|Current Version|Last Updated| +|---|---|---| +|/participants|1.1|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/parties|1.1|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/transactionRequests|1.1|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/quotes|1.1|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/authorizations|1.0|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/transfers|1.1|Added possible commit notification using PATCH /transfers/``. The process of using commit notifications is described in Section 6.7.2.6. The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/transactions|1.0|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/bulkQuotes|1.1|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| +|/bulkTransfers|1.1|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| + +**Table 7 – Current resource versions** + +
    + +### API Resource /participants + +This section defines the logical API resource **Participants**, described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-participants). + +The services provided by the resource **/participants** are primarily used for determining in which FSP a counterparty in a financial transaction is located. Depending on the scheme, the services should be supported, at a minimum, by either the individual FSPs or a common service. + +If a common service (for example, an ALS) is supported in the scheme, the services provided by the resource **/participants** can also be used by the FSPs for adding and deleting information in that system. + +#### Resource Version History + +[Table 8](#table-8) contains a description of each different version of the **/participants** resource. + +###### Table 8 + +|Version|Date|Description| +|---|---|---| +|1.0|2018-03-13|Initial version| +|1.1|2020-05-19|The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated. +For consistency, the data model for the **POST /participants/**_{Type}/{ID}_ and **POST /participants/**_{Type}/{ID}/{SubId}_ calls in Table 10 has been updated to include the optional ExtensionList element as well.| + +**Table 8 – Version history for resource /participants** + +#### Service Details + +Different models are used for account lookup, depending on whether an ALS exists. The following sections describe each model in turn. + +#### No Common Account Lookup System + +[Figure 41](#figure-41) shows how an account lookup can be performed if there is no common ALS in a scheme. The process is to ask the other FSPs (in sequence) if they "own" the Party with the provided identity and type pair until the Party can be found. + +If this model is used, all FSPs should support being both client and server of the different HTTP **GET** services under the **/participants** resource. The HTTP **POST** or HTTP **DELETE** services under the **/participants** resource should not be used, as the FSPs are directly used for retrieving the information (instead of a common ALS). + +###### Figure 41 + +{% uml src="assets/diagrams/sequence/figure41.plantuml" %} +{% enduml %} + +**Figure 41 -- How to use the services provided by /participants if there is no common Account Lookup System** + +#### Common Account Lookup System + +[Figure 42](#figure-42) shows how an account lookup can be performed if there is a common ALS in a scheme. The process is to ask the common Account Lookup service which FSP owns the Party with the provided identity. The common service is depicted as "Account Lookup" in the flows; this service could either be implemented by the switch or as a separate service, depending on the setup in the market. + +The FSPs do not need to support the server side of the different HTTP **GET** services under the **/participants** resource; the server side of the service should be handled by the ALS. Instead, the FSPs (clients) should provide FSP information regarding its accounts and account holders (parties) to the ALS (server) using the HTTP **POST** (to create or update FSP information, see [POST /participants](#post-participants) and [POST /participants/_{Type}_/_{ID}_](#post-participants-type-id)) and HTTP **DELETE** (to delete existing FSP information, see [DELETE /participants/_{Type}_/_{ID}_](#delete-participantstypeid)) methods. + +###### Figure 42 + +{% uml src="assets/diagrams/sequence/figure42.plantuml" %} +{% enduml %} + +**Figure 42 -- How to use the services provided by /participants if there is a common Account Lookup System** + +#### Requests + +This section describes the services that can be requested by a client on the resource **/participants**. + +##### GET /participants/_{Type}_/_{ID}_ + +Alternative URI: **GET /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_ + +Logical API service: [Lookup Participant Information](../generic-transaction-patterns#lookup-participant-information) + +The HTTP request **GET /participants/**_{Type}_**/**_{ID}_ (or **GET /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_) is used to find out in which FSP the requested Party, defined by _{Type}_, _{ID}_ and optionally _{SubId}_, is located (for example, **GET** **/participants/MSISDN/123456789**, or **GET /participants/BUSINESS/shoecompany/employee1**). See [Refund](#refund) for more information regarding addressing of a Party. + +This HTTP request should support a query string (see [URI Syntax](#uri-syntax) for more information regarding URI syntax) for filtering of currency. To use filtering of currency, the HTTP request **GET /participants/**_{Type}_**/**_{ID}_**?currency=**_XYZ_ should be used, where _XYZ_ is the requested currency. + +Callback and data model information for **GET /participants/**_{Type}_**/**_{ID}_ (alternative **GET /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_): + +- Callback - [**PUT /participants/**_{Type}_/_{ID}_](#put-participants-type-id) +- Error Callback - [**PUT /participants/**_{Type}_/_{ID}_**/error**](#put-participants-type-iderror) +- Data Model -- Empty body + +##### POST /participants + +Alternative URI: N/A + +Logical API service: [Create Bulk Participant Information](../generic-transaction-patterns#create-bulk-participant-information) + +The HTTP request **POST /participants** is used to create information on the server regarding the provided list of identities. This request should be used for bulk creation of FSP information for more than one Party. The optional currency parameter should indicate that each provided Party supports the currency. + +Callback and data model information for **POST /participants**: + +- Callback -- [**PUT /participants/**_{ID}_](#put-participants-type-id) +- Error Callback -- [**PUT /participants/**_{ID}_ **/error**](#put-participants-type-iderror) +- Data Model -- See [Table 9](#table-9) + +###### Table 9 + +|Name|Cardinality|Type|Description| +|---|---|---|---| +|**requestId**|1|CorrelationId|The ID of the request, decided by the client. Used for identification of the callback from the server.| +|**partyList**|1..10000|PartyIdInfo|List of PartyIdInfo elements that the client would like to update or create FSP information about.| +|**currency**|0..1|Currency|Indicate that the provided Currency is supported by each PartyIdInfo in the list.| + +**Table 9 - POST /participants data model** + +##### POST /participants/_{Type}_/_{ID}_ + +Alternative URI: **POST /participants/**_{Type}_/_{ID}_/_{SubId}_ + +Logical API service: [Create Participant Information](../generic-transaction-patterns#create-participant-information) + +The HTTP request **POST /participants/**_{Type}_**/**_{ID}_ (or **POST /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_) is used to create information on the server regarding the provided identity, defined by _{Type}_, _{ID}_, and optionally _{SubId}_ (for example, **POST** **/participants/MSISDN/123456789** or **POST /participants/BUSINESS/shoecompany/employee1**). See [Refund](#refund) for more information regarding addressing of a Party. + +Callback and data model information for **POST /participants**/_{Type}_**/**_{ID}_ (alternative **POST** **/participants/**_{Type}_**/**_{ID}_**/**_{SubId}_): + +- Callback -- [**PUT /participants/**_{Type}_**/**_{ID}_](#put-participants-type-id) +- Error Callback -- [**PUT /participants/**_{Type}_**/**_{ID}_**/error**](#put-participants-type-iderror) +- Data Model -- See [Table 10](#table-10) + +###### Table 10 + +|Name|Cardinality|Type|Description| +|---|---|---|---| +|**fspId**|1|FspId|FSP Identifier that the Party belongs to.| +|**currency**|0..1|Currency|Indicate that the provided Currency is supported by the Party.| +|**extensionList**| 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 10 -- POST /participants/_{Type}_/_{ID}_ (alternative POST /participants/_{Type}_/_{ID}_/_{SubId}_) data model** + +##### DELETE /participants/_{Type}_/_{ID}_ + +Alternative URI: **DELETE /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_ + +Logical API service: [Delete Participant Information](../generic-transaction-patterns#delete-participant-information) + +The HTTP request **DELETE /participants/**_{Type}_**/**_{ID}_ (or **DELETE /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_) is used to delete information on the server regarding the provided identity, defined by _{Type}_ and _{ID}_) (for example, **DELETE** **/participants/MSISDN/123456789**), and optionally _{SubId}_. See [Refund](#refund) for more information regarding addressing of a Party. + +This HTTP request should support a query string (see [URI Syntax](#uri-syntax) for more information regarding URI syntax) to delete FSP information regarding a specific currency only. To delete a specific currency only, the HTTP request **DELETE** **/participants/**_{Type}_**/**_{ID}_**?currency**_=XYZ_ should be used, where _XYZ_ is the requested currency. + +**Note:** The ALS should verify that it is the Party's current FSP that is deleting the FSP information. + +Callback and data model information for **DELETE /participants/**_{Type}_**/**_{ID}_ (alternative **GET** **/participants/**_{Type}_**/**_{ID}_**/**_{SubId}_): + +- Callback -- [**PUT /participants/**_{Type}_**/**_{ID}_](#put-participants-type-id) + +- Error Callback -- [**PUT /participants/**_{Type}_**/**_{ID}_**/error**](#put-participants-type-iderror) + +- Data Model -- Empty body + +
    + +#### Callbacks + +This section describes the callbacks used by the server for services provided by the resource **/participants**. + +##### PUT /participants/_{Type}_/_{ID}_ + +Alternative URI: **PUT /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_ + +Logical API service: [Return Participant Information](../generic-transaction-patterns#return-participant-information) + +The callback **PUT /participants/**_{Type}_**/**_{ID}_ (or **PUT /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_) is used to inform the client of a successful result of the lookup, creation, or deletion of the FSP information related to the Party. If the FSP information is deleted, the **fspId** element should be empty; otherwise the element should include the FSP information for the Party. + +See [Table 11](#table-11) for data model. + +###### Table 11 + +|Name|Cardinality|Type|Description| +|---|---|---|---| +|**fspId**|0..1|FspId|FSP Identifier that the Party belongs to.| + +**Table 11 -- PUT /participants/_{Type}_/_{ID}_ (alternative PUT /participants/_{Type}_/_{ID}_/_{SubId}_) data model** + +##### PUT /participants/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Bulk Participant Information](../generic-transaction-patterns#return-bulk-participant-information) + +The callback **PUT /participants/**_{ID}_ is used to inform the client of the result of the creation of the provided list of identities. + +See [Table 12](#table-12) for data model. + +###### Table 12 + +|Name|Cardinality|Type|Description| +|---|---|---|---| +|**partyList**|1..10000|PartyResults|List of PartyResult elements that were either created or failed to be created.| +|**currency**|0..1|Currency|Indicate that the provided Currency was set to be supported by each successfully added PartyIdInfo.| + +**Table 12 -- PUT /participants/_{ID}_ data model** + +####Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/participants**. + +##### PUT /participants/_{Type}_/_{ID}_/error + +Alternative URI: **PUT /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_**/error** + +Logical API service: [Return Participant Information Error](../generic-transaction-patterns#return-participant-information-error) + +If the server is unable to find, create or delete the associated FSP of the provided identity, or another processing error occurred, the error callback **PUT /participants/**_{Type}_**/**_{ID}_**/error** (or **PUT /participants/**_{Type}_**/**_{ID}_**/**_{SubId}_**/error**) is used. See [Table 13](#table-13) for data model. + +###### Table 13 + +|Name|Cardinality|Type|Description| +|---|---|---|---| +|**errorInformation**|1|ErrorInformation|Error code, category description.| + +**Table 13 -- PUT /participants/_{Type}_/_{ID}_/error (alternative PUT /participants/_{Type}_/_{ID}_/_{SubId}_/error) data model** + +##### PUT /participants/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Return Bulk Participant Information Error](../generic-transaction-patterns#return-bulk-participant-information-error) + +If there is an error during FSP information creation on the server, the error callback **PUT /participants/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the **requestId** (see [Table 9](#table-9)) that was used for the creation of the participant information. See [Table 14](#table-14) for data model. + +###### Table 14 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **error Information** | 1 | ErrorInformation | Error code, category description. | + +**Table 14 -- PUT /participants/_{ID}_/error data model** + +#### States + +There are no states defined for the **/participants** resource; either the server has FSP information regarding the requested identity or it does not. + +
    + +### API Resource /parties + +This section defines the logical API resource **Parties,** described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-parties). + +The services provided by the resource **/parties** is used for finding out information regarding a Party in a Peer FSP. + +#### Resource Version History + +[Table 15](#table-15) contains a description of each different version of the **/parties** resource. + +###### Table 15 + +|Version|Date|Description| +|---|---|---| +|1.0|2018-03-13|Initial version| +|1.1|2020-05-19|The data model is updated to add an optional ExtensioinList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| + +**Table 15 – Version history for resource /parties** + +#### Service Details + +[Figure 43](#figure-43) contains an example process for the [**/parties**](../generic-transaction-patterns#api-resource-parties) resource. Alternative deployments could also exist; for example, a deployment in which the Switch and the ALS are in the same server, or one in which the User's FSP asks FSP 1 directly for information regarding the Party. + +###### Figure 43 + +{% uml src="assets/diagrams/sequence/figure43.plantuml" %} +{% enduml %} + +**Figure 43 -- Example process for /parties resource** + +
    + +#### Requests + +This section describes the services that can be requested by a client in the API on the resource **/parties**. + +##### GET /parties/_{Type}_/_{ID}_ + +Alternative URI: **GET /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_ + +Logical API service: [Lookup Party Information](../generic-transaction-patterns#lookup-party-information) + +The HTTP request **GET /parties/**_{Type}_**/**_{ID}_ (or **GET /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_) is used to lookup information regarding the requested Party, defined by _{Type}_, _{ID}_ and optionally _{SubId}_ (for example, **GET /parties/MSISDN/123456789**, or **GET** **/parties/BUSINESS/shoecompany/employee1**). See [Refund](#refund) for more information regarding addressing of a Party. + +Callback and data model information for **GET /parties/**_{Type}_**/**_{ID}_ (alternative **GET /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_): + +- Callback - [**PUT /parties/**_{Type}_**/**_{ID}_](#put-partiestypeid) +- Error Callback - [**PUT /parties/**_{Type}_**/**_{ID}_**/error**](#put-partiestypeiderror) +- Data Model -- Empty body + +
    + +#### Callbacks + +This section describes the callbacks that are used by the server for services provided by the resource **/parties**. + +##### PUT /parties/_{Type}_/_{ID}_ + +Alternative URI: **PUT /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_ + +Logical API service: [Return Party Information](../generic-transaction-patterns#return-party-information) + +The callback **PUT /parties/**_{Type}_**/**_{ID}_ (or **PUT /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_) is used to inform the client of a successful result of the Party information lookup. See [Table 16](#table-16) for data model. + +###### Table 16 + +| **Name** | **Cardinal** | **Type** | **Description** | +| --- | --- | --- | --- | +| **party** | 1 | Party | Information regarding the requested Party. | + +**Table 16 -- PUT /parties/_{Type}_/_{ID}_ (alternative PUT /parties/_{Type}_/_{ID}_/_{SubId}_) data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/parties**. + +#### PUT /parties/_{Type}_/_{ID}_/error + +Alternative URI: **PUT /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_**/error** + +Logical API service: [Return Party Information Error](../generic-transaction-patterns#return-party-information-error) + +If the server is unable to find Party information of the provided identity, or another processing error occurred, the error callback **PUT /parties/**_{Type}_**/**_{ID}_**/error** (or **PUT /parties/**_{Type}_**/**_{ID}_**/**_{SubId}_**/error**) is used. See [Table 17](#table-17) for data model. + +###### Table 17 + +| **Name** | **Cardinality** | **Type** | **Description** | +|---|---|---|---| +| **errorInformation** | 1 | ErrorInformation | Error code, category description. | + +**Table 17 -- PUT /parties/_{Type}_/_{ID}_/error (alternative PUT /parties/_{Type}_/_{ID}_/_{SubId}_/error) data model** + +#### States + +There are no states defined for the **/parties** resource; either an FSP has information regarding the requested identity or it does not. + +
    + +### API Resource /transactionRequests + +This section defines the logical API resource **Transaction Requests**, described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-transaction-requests). + +The primary service that the API resource **/transactionRequests** enables is for a Payee to request a Payer to transfer electronic funds to the Payee. The Payer can either approve or reject the request from the Payee. The decision by the Payer could be made programmatically if: + +- The Payee is trusted (that is, the Payer has pre-approved the Payee in the Payer FSP), or + +- An authorization value - that is, a _one-time password_ (_OTP_) is correctly validated using the API Resource **/authorizations**, see [Section 6.6](#66-api-resource-authorizations). + +Alternatively, the Payer could make the decision manually. + +#### Resource Version History + +[Table 18](#table-18) contains a description of each different version of the **/transactionRequests** resource. + +###### Table 18 + +|Version|Date|Description| +|---|---|---| +|1.0|2018-03-13|Initial version| +|1.1|2020-05-19|The data model is updated to add an optional ExtensioinList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| + +**Table 18 – Version history for resource /transactionRequests** + +#### Service Details + +[Figure 44](#figure-44) shows how the request transaction process works, using the **/transactionRequests** resource. The approval or rejection is not shown in the figure. A rejection is a callback **PUT /transactionRequests/**_{ID}_ with a **REJECTED** state, similar to the callback in the figure with the **RECEIVED** state, as described in [Section 6.4.2.1](#6421-payer-rejected-transaction-request). An approval by the Payer is not sent as a callback; instead a quote and transfer are sent containing a reference to the transaction request. + +###### Figure 44 + +{% uml src="assets/diagrams/sequence/figure44.plantuml" %} +{% enduml %} +**Figure 44 -- How to use the /transactionRequests service** + +##### Payer Rejected Transaction Request + +[Figure 45](#figure-45) shows the process by which a transaction request is rejected. Possible reasons for rejection include: + +- The Payer rejected the request manually. +- An automatic limit was exceeded. +- The Payer entered an OTP incorrectly more than the allowed number of times. + +###### Figure 45 + +{% uml src="assets/diagrams/sequence/figure45.plantuml" %} +{% enduml %} +**Figure 45 -- Example process in which a transaction request is rejected** + +#### Requests + +This section describes the services that a client can request on the resource **/transactionRequests**. + +##### GET /transactionRequests/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Retrieve Transaction Request Information](../generic-transaction-patterns#retrieve-transaction-request-information) + +The HTTP request **GET /transactionRequests/**_{ID}_ is used to get information regarding a previously-created or requested transaction request. The _{ID}_ in the URI should contain the **transactionRequestId** (see [Table 15](#table-15)) that was used for the creation of the transaction request. + +Callback and data model information for **GET /transactionRequests/**_{ID}_: + +- Callback - [**PUT /transactionRequests/**_{ID}_](#put-transactionrequestsid) +- Error Callback - [**PUT /transactionRequests/**_{ID}_**/error**](#put-transactionrequestsiderror) +- Data Model -- Empty body + +##### POST /transactionRequests + +Alternative URI: N/A + +Logical API service: [Perform Transaction Request](../generic-transaction-patterns#perform-transaction-request) + +The HTTP request **POST /transactionRequests** is used to request the creation of a transaction request for the provided financial transaction on the server. + +Callback and data model information for **POST /transactionRequests**: + +- Callback - [**PUT /transactionRequests/**_{ID}_](#put-transactionrequestsid) +- Error Callback - [**PUT /transactionRequests/**_{ID}_**/error**](#put-transactionrequestsiderror) +- Data Model -- See [Table 19](#table-19) + +###### Table 19 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **transactionRequestId** | 1 | CorrelationId | Common ID between the FSPs for the transaction request object, decided by the Payee FSP. The ID should be reused for resends of the same transaction request. A new ID should be generated for each new transaction request. | +| **payee** | 1 | Party | Information about the Payee in the proposed financial transaction. | +| **payer** | 1 | PartyInfo | Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction. | +| **amount** | 1 | Money | Requested amount to be transferred from the Payer to Payee. | +| **transactionType** | 1 | TransactionType | Type of transaction. | +| **note** | 0..1 | Note | Reason for the transaction request, intended to the Payer. | +| **geoCode** | 0..1 | GeoCode | Longitude and Latitude of the initiating Party. Can be used to detect fraud. | +| **authenticationType** | 0.11 | AuthenticationType | OTP or QR Code, otherwise empty. | +| **expiration** | 0..1 | DateTime | Can be set to get a quick failure in case the peer FSP takes too long to respond. Also, it may be beneficial for Consumer, Agent, Merchant to know that their request has a time limit. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 19 -- POST /transactionRequests data model** + +####Callbacks + +This section describes the callbacks that are used by the server under the resource **/transactionRequests**. + +##### PUT /transactionRequests/_{ID}_ + +Alternative URI: N/A + +Logical API service: **Return Transaction Request Information** + +The callback **PUT /transactionRequests/**_{ID}_ is used to inform the client of a requested or created transaction request. The _{ID}_ in the URI should contain the **transactionRequestId** (see [Table 19](#table-19)) that was used for the creation of the transaction request, or the _{ID}_ that was used in the [**GET /transactionRequests/**_{ID}_](#get-transactionrequestsid). See [Table 20](#table-20) for data model. + +###### Table 20 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **transactionId** | 0..1 | CorrelationId | Identifies a related transaction (if a transaction has been created). | +| **transactionRequestState** | 1 | TransactionRequestState | State of the transaction request. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 20 -- PUT /transactionRequests/_{ID}_ data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/transactionRequests**. + +##### PUT /transactionRequests/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Return Transaction Request Information Error](../generic-transaction-patterns#return-transaction-request-information-error) + +If the server is unable to find or create a transaction request, or another processing error occurs, the error callback **PUT** **/transactionRequests/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the **transactionRequestId** (see [Table 19](#table-19)) that was used for the creation of the transaction request, or the _{ID}_ that was used in the [**GET /transactionRequests/**_{ID}_](#get-transactionrequestsid). See [Table 21](#table-21) for data model. + +###### Table 21 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | ---| --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description. | + +**Table 21 -- PUT /transactionRequests/_{ID}_/error data model** + +#### 6.4.6 States + +The possible states of a transaction request can be seen in [Figure 46](#figure-46). + +**Note:** A server does not need to keep transaction request objects that have been rejected in their database. This means that a client should expect that an error callback could be received for a rejected transaction request. + +###### Figure 46 + +![Figure 46](/assets/diagrams/images/figure46.svg) + +**Figure 46 -- Possible states of a transaction request** + +
    + +### API Resource /quotes + +This section defines the logical API resource **Quotes**, described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-quotes). + +The main service provided by the API resource **/quotes** is calculation of possible fees and FSP commission involved in performing an interoperable financial transaction. Both the Payer and Payee FSP should calculate their part of the quote to be able to get a total view of all the fees and FSP commission involved in the transaction. + +A quote is irrevocable; it cannot be changed after it has been created. However, it can expire (all quotes are valid only until they reach expiration). + +**Note:** A quote is not a guarantee that the financial transaction will succeed. The transaction can still fail later in the process. A quote only guarantees that the fees and FSP commission involved in performing the specified financial transaction are applicable until the quote expires. + +For more information see [Quoting](#quoting). + +#### Resource Version History + +[Table 22](#table-22) contains a description of each different version of the **/quotes** resource. + +###### Table 22 + +|Version|Date|Description| +|---|---|---| +|1.0|2018-03-13|Initial version| +|1.1|2020-05-19|The data model is updated to add an optional ExtensioinList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| + +**Table 22 – Version history for resource /quotes** + +#### Service Details + +[Figure 47](#figure-47) contains an example process for the API resource **/quotes**. The example shows a Payer Initiated Transaction, but it could also be initiated by the Payee, using the API Resource [**/transactionRequests**](#api-resource-transactionrequests). The lookup process is in that case performed by the Payee FSP instead. + +###### Figure 47 + +{% uml src="assets/diagrams/sequence/figure47.plantuml" %} +{% enduml %} + +**Figure 47 -- Example process for resource /quotes** + +#### Quote Expiry Details + +The quote request from the Payer FSP can contain an expiry of the quote, if the Payer FSP would like to indicate when it is no longer useful for the Payee FSP to return a quote. For example, the transaction itself might otherwise time out, or if its quote might time out. + +The Payee FSP should set an expiry of the quote in the callback to indicate when the quote is no longer valid for use by the Payer FSP. + +#### Rejection of Quote + +The Payee FSP can reject a quote request from the Payer FSP by sending the error callback **PUT /quotes/**_{ID}_/**error** instead of the callback **PUT /quotes/**_{ID}_. +Depending on which generic transaction pattern (see Section 8 for more information) that is used, the Payer FSP can reject a quote using one of the following processes: + +- If the transaction is initiated by the Payer (see Section 8.1), the Payer FSP should not inform the Payee FSP regarding the rejection. The created quote at the Payee FSP should have an expiry time, at which time it is automatically deleted. +- If the transaction is initiated by the Payee (see Section 8.2 and 8.3), the Payer FSP should inform the Payee FSP regarding the rejection using the callback **PUT /transactionRequests/**_{ID}_ with a rejected state. The process is described in more detail in Section 6.4.2.1. + +#### Interledger Payment Request + +As part of supporting Interledger and the concrete implementation of the Interledger Payment Request (see [Interledgeer Protocol](#interledger-protocol)), the Payee FSP must: + +- Determine the ILP Address (see [ILP Addressing](#ILP-addressing) for more information) of the Payee and the amount that the Payee will receive. Note that since the **amount** element in the ILP Packet is defined as an UInt64, which is an Integer value, the amount should be multiplied with the currency's exponent (for example, USD's exponent is 2, which means the amount should be multiplied by 102, and JPY's exponent is 0, which means the amount should be multiplied by 100). Both the ILP Address and the amount should be populated in the ILP Packet (see [ILP Packet](#ilp-packet) for more information). + +- Populate the **data** element in the ILP Packet by the [Transaction](#transaction) data model. +- Generate the fulfilment and the condition (see [Conditional Transfers](#conditional-transfers) for more information). Populate the **condition** element in the [PUT /quotes/**_{ID}_](#put-quotes-id)). [Table 19](#table-19) shows data model with the generated condition. + +The fulfilment is a temporary secret that is generated for each financial transaction by the Payee FSP and used as the trigger to commit the transfers that make up an ILP payment. + +The Payee FSP uses a local secret to generate a SHA-256 HMAC of the ILP Packet. The same secret may be used for all financial transactions or the Payee FSP may store a different secret per Payee or based on another segmentation. + +The choice and cardinality of the local secret is an implementation decision that may be driven by scheme rules. The only requirement is that the Payee FSP can determine which secret that was used when the ILP Packet is received back later as part of an incoming transfer (see [API Resource Transfers](#api-resource-transfers)). + +The fulfilment and condition are generated in accordance with the algorithm defined in [Listing 12](#listing-12). Once the Payee FSP has derived the condition, the fulfilment can be discarded as it can be regenerated later. + +###### Listing 12 + +Generation of the fulfilment and condition + +**Inputs:** + +- Local secret (32-byte binary string) +- ILP Packet + +**Algorithm:** + +1. Let the fulfilment be the result of executing the HMAC SHA-256 algorithm on the ILP Packet using the local secret as the key. + +2. Let the condition be the result of executing the SHA-256 hash algorithm on the fulfilment. + +**Outputs:** + +- Fulfilment (32-byte binary string) +- Condition (32-byte binary string) + +**Listing 12 -- Algorithm to generate the fulfilment and the condition** + +#### Requests + +This section describes the services that can be requested by a client in the API on the resource **/quotes**. + +##### GET /quotes/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Retrieve Quote Information](../generic-transaction-patterns#retrieve-quote-information) + +The HTTP request **GET /quotes/**_{ID}_ is used to get information regarding a previously-created or requested quote. The _{ID}_ in the URI should contain the **quoteId** (see [Table 23](#table-23)) that was used for the creation of the quote. + +Callback and data model information for **GET /quotes/**_{ID}_: + +- Callback -- [**PUT /quotes/**_{ID}_](#put-quotes-id) +- Error Callback -- [**PUT /quotes/**_{ID}_**/_error_**](#put-quotes-iderror) +- Data Model -- Empty body + +##### POST /quotes + +Alternative URI: N/A + +Logical API service: [Calculate Quote Information](../generic-transaction-patterns#calculate-quote-information) + +The HTTP request **POST /quotes** is used to request the creation of a quote for the provided financial transaction on the server. + +Callback and data model information for **POST /quotes**: + +- Callback -- [**PUT /quotes/**_{ID}_](#put-quotes-id) +- Error Callback -- [**PUT /quotes/**_{ID}_**/error**](#put-quotes-iderror) +- Data Model -- See [Table 23](#table-23) + +###### Table 23 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **quoteId** | 1 | CorrelationId | Common ID between the FSPs for the quote object, decided by the Payer FSP. The ID should be reused for resends of the same quote for a transaction. A new ID should be generated for each new quote for a transaction. | +| **transactionId** | 1 | CorrelationId | Common ID (decided by the Payer FSP) between the FSPs for the future transaction object. The actual transaction will be created as part of a successful transfer process. The ID should be reused for resends of the same quote for a transaction. A new ID should be generated for each new quote for a transaction. | +| **transactionRequestId** | 0..1 | CorrelationId | Identifies an optional previously-sent transaction request. | +| **payee** | 1 | Party | Information about the Payee in the proposed financial transaction. | +| **payer** | 1 | Party | Information about the Payer in the proposed financial transaction. | +| **amountType** | 1 | AmountType |**SEND** for send amount, **RECEIVE** for receive amount. | +| **amount** | 1 | Money | Depending on **amountType**:
    If **SEND**: The amount the Payer would like to send; that is, the amount that should be withdrawn from the Payer account including any fees. The amount is updated by each participating entity in the transaction.
    If **RECEIVE**: The amount the Payee should receive; that is, the amount that should be sent to the receiver exclusive any fees. The amount is not updated by any of the participating entities.
    | +| **fees** | 0..1 | Money | Fees in the transaction.
  • The fees element should be empty if fees should be non-disclosed.
  • The fees element should be non-empty if fee should be disclosed.
  • | +| **transactionType** | 1 | TransactionType | Type of transaction for which the quote is requested. | +| **geoCode** | 0..1 | GeoCode | Longitude and Latitude of the initiating Party. Can be used to detect fraud. | +| **note** | 0..1 | Note | A memo that will be attached to the transaction. | +| **expiration** | 0..1 | DateTime | Expiration is optional. It can be set to get a quick failure in case the peer FSP takes too long to respond. Also, it may be beneficial for Consumer, Agent, and Merchant to know that their request has a time limit. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 23 -- POST /quotes data model** + +#### Callbacks + +This section describes the callbacks that are used by the server under the resource **/quotes**. + +#### PUT /quotes/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Quote Information](../generic-transaction-patterns#return-quote-information) + +The callback **PUT /quotes/**_{ID}_ is used to inform the client of a requested or created quote. The _{ID}_ in the URI should contain the **quoteId** (see [Table 23](#table-23)) that was used for the creation of the quote, or the _{ID}_ that was used in the [**GET /quotes/**_{ID}_](#get-quotesid). See [Table 24](#table-24) for data model. + +###### Table 24 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **transferAmount** | 1 | Money | The amount of Money that the Payer FSP should transfer to the Payee FSP. | +| **payeeReceiveAmount** | 0..1 | Money | The amount of Money that the Payee should receive in the end-to-end transaction. Optional as the Payee FSP might not want to disclose any optional Payee fees. | +| **payeeFspFee** | 0..1 | Money | Payee FSP’s part of the transaction fee. | +| **payeeFspCommission** | 0..1 | Money | Transaction commission from the Payee FSP. | +| **expiration** | 1 | DateTime | Date and time until when the quotation is valid and can be honored when used in the subsequent transaction. | +| **geoCode** | 0..1 | GeoCode | Longitude and Latitude of the Payee. Can be used to detect fraud. | +| **ilpPacket** | 1 | IlpPacket | The ILP Packet that must be attached to the transfer by the Payer. | +| **condition** | 1 | IlpCondition | The condition that must be attached to the transfer by the Payer. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment | + +**Table 24 -- PUT /quotes/_{ID}_ data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server +under the resource **/quotes**. + +##### PUT /quotes/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Return Quote Information Error](../generic-transaction-patterns#return-quote-information-error) + +If the server is unable to find or create a quote, or some other processing error occurs, the error callback **PUT** **/quotes/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the **quoteId** (see [Table 23](#table-23)) that was used for the creation of the quote, or the _{ID}_ that was used in the [**GET /quotes/**_{ID}_](#get-quotesid). See [Table 25](#table-25) for data model. + +###### Table 25 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description.| + +**Table 25 -- PUT /quotes/_{ID}_/error data model** + +#### States + +###### Figure 48 + +[Figure 48](#figure-48) contains the UML (Unified Modeling Language) state machine for the possible states of a quote object. + +**Note:** A server does not need to keep quote objects that have been either rejected or expired in their database. This means that a client should expect that an error callback could be received for an expired or rejected quote. + +![Figure 48](/assets/diagrams/images/figure48.svg) + +**Figure 48 -- Possible states of a quote** + +
    + +### API Resource /authorizations + +This section defines the logical API resource **Authorizations**, described in [Generic Transaction Patterns](../gerneric-transaction-patterns#api-resource-authorizations). + +The API resource **/authorizations** is used to request the Payer to enter the applicable credentials in the Payee FSP system for approving the financial transaction, when the Payer has initiated the transaction from a POS, ATM, or similar, in the Payee FSP system and would like to authorize by an OTP. + +#### Resource Version History + +[Table 26](#table-26) contains a description of each different version of the **/authorizations** resource. + +###### Table 26 + +|Version|Date|Description| +|---|---|---| +|1.0|2018-03-13|Initial version| + +**Table 26 – Version history for resource /authorizations** + +#### Service Details + +[Figure 49](#figure-49) contains an example process for the API resource **/authorizations.** The Payee FSP first sends a [transaction request](#api-resource-transactionrequests)) that is authorized using OTP. The Payer FSP then performs the quoting process (see [API Resource Quotes](#api-resource-quotes)) before an authorization request is sent to the Payee FSP system for the Payer to approve by entering the OTP. If the OTP is correct, the transfer process should be initiated (see [API Resource Transfers](#api-resource-transfers)). + +###### Figure 49 + +{% uml src="assets/diagrams/sequence/figure49.plantuml" %} +{% enduml %} + +**Figure 49 -- Example process for resource /authorizations** + +#### Resend Authorization Value + +If the notification containing the authorization value fails to reach the Payer, the Payer can choose to request a resend of the authorization value if the POS, ATM, or similar device supports such a request. See [Figure 50](#figure-50) for an example of a process where the Payer requests that the OTP be resent. + +###### Figure 50 + +{% uml src="assets/diagrams/sequence/figure50.plantuml" %} +{% enduml %} + +**Figure 50 -- Payer requests resend of authorization value (OTP)** + +##### Retry Authorization Value + +The Payer FSP must decide the number of times a Payer can retry the authorization value in the POS, ATM, or similar device. This will be set in the **retriesLeft** query string (see [URI Syntax](#uri-syntax) for more information regarding URI syntax) of the [**GET** **/authorizations/**_{ID}_](#get-authorizationsid) service for more information. If the Payer FSP sends retriesLeft=1, this means that it is the Payer's last try of the authorization value. See [Figure 51](#figure-51) for an example process where the Payer enters the incorrect OTP, and the **retriesLeft** value is subsequently decreased. + +###### Figure 51 + +{% uml src="assets/diagrams/sequence/figure51.plantuml" %} +{% enduml %} + +**Figure 51 -- Payer enters incorrect authorization value (OTP)** + +##### Failed OTP authorization + +If the user fails to enter the correct OTP within the number of allowed retries, the process described in [Payer Rejected Transaction Request](#payer-rejected-transaction-request) is performed. + +#### Requests + +This section describes the services that can be requested by a client in the API on the resource **/authorizations**. + +##### GET /authorizations/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Perform Authorization](../generic-transaction-patterns#perform-authorization) + +The HTTP request **GET /authorizations/**_{ID}_ is used to request the Payer to enter the applicable credentials in the Payee FSP system. The _{ID}_ in the URI should contain the **transactionRequestID** (see [Table 15](#table-15)), received from the [**POST** **/transactionRequests**](#post-transactionrequests)) service earlier in the process. + +This request requires a query string (see [URI Syntax](#uri-syntax) for more information regarding URI syntax) to be included in the URI, with the following key-value pairs: + +- **authenticationType=**_{Type}_, where _{Type}_ value is a valid authentication type from the enumeration [AuthenticationType](#authenticationtype). +- **retriesLeft=**_{NrOfRetries}_, where _{NrOfRetries}_ is the number of retries left before the financial transaction is rejected. _{NrOfRetries}_ must be expressed in the form of the data type [Integer](#integer)). **retriesLeft=1** means that this is the last retry before the financial transaction is rejected. +- **amount=**_{Amount}_, where _{Amount}_ is the transaction amount that will be withdrawn from the Payer's account. _{Amount}_ must be expressed in the form of the data type [Amount](#amount). +- **currency=**_{Currency}_, where _{Currency}_ is the transaction currency for the amount that will be withdrawn from the Payer's account. The _{Currency}_ value must be expressed in the form of the enumeration [CurrencyCode](#currencycode)). + +An example URI containing all the required key-value pairs in the query string is the following: + +**GET /authorization/3d492671-b7af-4f3f-88de-76169b1bdf88?authenticationType=OTP&retriesLeft=2&amount=102¤cy=USD** + +Callback and data model information for **GET /authorization/**_{ID}_: + +- Callback - [**PUT /authorizations/**_{ID}_](#6641-put-authorizationsid) +- Error Callback - [**PUT /authorizations/**_{ID}_**/error**](#6651-put-authorizationsiderror) +- Data Model -- Empty body + +#### 6.6.4 Callbacks + +This section describes the callbacks that are used by the server under the resource **/authorizations**. + +#### 6.6.4.1 PUT /authorizations/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Authorization Result](../generic-transaction-patterns#return-authorization-result) + +The callback **PUT /authorizations/** _{ID}_ is used to inform the client of the result of a previously-requested authorization. The _{ID}_ in the URI should contain the _{ID}_ that was used in the [**GET /authorizations/**_{ID}_](#get-authorizationsid). **See** [Table 27](#table-27) **for** data model. + +###### Table 27 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **authenticationInfo** | 0..1 | AuthenticationInfo | OTP or QR Code if entered, otherwise empty. | +| **responseType** | 1 | AuthorizationResponse | Enum containing response information; if the customer entered the authentication value, rejected the transaction, or requested a resend of the authentication value. | + +**Table 27 – PUT /authorizations/{ID} data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/authorizations**. + +#### PUT /authorizations/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Return Authorization Error](../generic-transaction-patterns#return-authorization-error) + +If the server is unable to find the transaction request, or another processing error occurs, the error callback **PUT** **/authorizations/**_{ID}_ **/error** is used. The _{ID}_ in the URI should contain the _{ID}_ that was used in the [**GET /authorizations/**_{ID}_](#get-authorizationsid). **See** [Table 28](#table-28) **for** data model. + +###### Table 28 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description | + +**Table 28 -- PUT /authorizations/_{ID}_/error data model** + +#### States + +There are no states defined for the **/authorizations** resource. + +
    + +### API Resource /transfers + +This section defines the logical API resource **Transfers**, described in [Generic Transaction Patterns](../generic-transation-patterns#api-resource-transfers). + +The services provided by the API resource **/transfers** are used for performing the hop-by-hop ILP transfer or transfers, and to perform the end-to-end financial transaction by sending the transaction details from the Payer FSP to the Payee FSP. The transaction details are sent as part of the transfer data model in the ILP Packet. + +The Interledger protocol assumes that the setup of a financial transaction is achieved using an end-to-end protocol, but that an ILP transfer is implemented on the back of hop-by-hop protocols between FSPs connected to a common ledger. In the current version of the API, the API Resource **/quotes** performs the setup of the financial transaction. Before a transfer can be performed, the quote must be performed to setup the financial transaction. See [API Resource Quotes](#api-resource-quotes) for more information. + +An ILP transfer is exchanged between two account holders on either side of a common ledger. It is usually expressed in the form of a request to execute a transfer on the common ledger and a notification to the recipient of the transfer that the transfer has been reserved in their favor, including a condition that must be fulfilled to commit the transfer. + +When the Payee FSP presents the fulfilment to the common ledger, the transfer is committed in the common ledger. At the same time, the Payer FSP is notified that the transfer has been committed along with the fulfilment. + +#### Resource Version History + +Table 29 contains a description of each different version of the **/transfers** resource. + +| Version | Date | Description| +| ---- | ---- | ---- | +| **1.0** | 2018-03-13 | Initial version | +| **1.1** | 2020-05-19 | The resource is updated to support commit notifications using HTTP Method **PATCH**. The new request **PATCH /transfers/{ID}** is described in Section 6.7.3.3. The process of using commit notifications is described in Section 6.7.2.6.

    The data model is updated to add an optional ExtensionList element to the PartyIdInfo complex type based on the Change Request: [https://github.com/mojaloop/mojaloop-specification/issues/30](https://github.com/mojaloop/mojaloop-specification/issues/30). Following this, the data model as specified in Table 93 has been updated.| + +**Table 29 –- Version history for resource /transfers** + +#### Service Details + +This section provides details regarding hop-by-hop transfers and end-to-end financial transactions. + +#### Process + +[Figure 52](#figure-52) shows how the transaction process works using the **POST /transfers** service. + +###### Figure 52 + +{% uml src="assets/diagrams/sequence/figure52.plantuml" %} +{% enduml %} + +**Figure 52 -- How to use the POST /transfers service** + +#### Transaction Irrevocability + +The API is designed to support irrevocable financial transactions only; this means that a financial transaction cannot be changed, cancelled, or reversed after it has been created. This is to simplify and reduce costs for FSPs using the API. A large percentage of the operating costs of a typical financial system is due to reversals of transactions. + +As soon as a Payer FSP sends a financial transaction to a Payee FSP (that is, using **POST /transfers** including the end-to-end financial transaction), the transaction is irrevocable from the perspective of the Payer FSP. The transaction could still be rejected in the Payee FSP, but the Payer FSP can no longer reject or change the transaction. An exception to this would be if the transfer's expiry time is exceeded before the Payee FSP responds (see [Expired Quote](#expired-quote) and [Client Receiving Expired Transfer](#client-receiving-expired-transfer) for more information). As soon as the financial transaction has been accepted by the Payee FSP, the transaction is irrevocable for all parties. + +#### Expired Quote + +If a server receives a transaction that is using an expired quote, the server should reject the transfer or transaction. + +#### Timeout and Expiry + +The Payer FSP must always set a transfer expiry time to allow for use cases in which a swift completion or failure is needed. If the use case does not require a swift completion, a longer expiry time can be set. If the Payee FSP fails to respond before the expiry time, the transaction is cancelled in the Payer FSP. The Payer FSP should still expect a callback from the Payee FSP. + +Short expiry times are often required in retail scenarios, in which a customer may be standing in front of a merchant; both parties need to know if the transaction was successful before the goods or services are given to the customer. + +In [Figure 52](#figure-52), an expiry has been set to 30 seconds from the current time in the request from the Payer FSP, and to 20 seconds from the same time in the request from the Switch to the Payee FSP. This strategy of using shorter timeouts for each entity in the chain from Payer FSP to Payee FSP should always be used to allow for extra communication time. + +**Note:** It is possible that a successful callback might be received in the Payer FSP after the expiry time; for example, due to congestion in the network. The Payer FSP should allow for some extra time after the actual expiry time before cancelling the financial transaction in the system. If a successful callback is received after the financial transaction has been cancelled, the transaction should be marked for reconciliation and handled separately in a reconciliation process. + +#### Client Receiving Expired Transfer + +[Figure 53](#figure-53) shows an example of a possible error scenario connected to expiry and timeouts. For some reason, the callback from the Payee FSP takes longer time to send than the expiry time in the optional Switch. This leads to the Switch cancelling the reserved transfer, and an error callback for the transfer is sent to the Payer FSP. Now the Payer FSP and the Payee FSP have two different views of the result of the financial transaction; the transaction should be marked for reconciliation. + +###### Figure 53 + +{% uml src="assets/diagrams/sequence/figure53.plantuml" %} +{% enduml %} + +**Figure 53 -- Client receiving an expired transfer** + +To limit these kinds of error scenarios, the clients (Payer FSP and optional Switch in [Figure 52](#figure-52)) participating in the ILP transfer should allow some extra time after actual expiry time during which the callback from the server can be received. The client(s) should also query the server after expiry, but before the end of the extra time, if any callback from the server has been lost due to communication failure. Reconciliation could still be necessary though, even with extra time allowed and querying the server for the transaction. + +#### Commit Notification + +As an alternative option to avoid the error scenario described in [Client Receiving Expired Transfer](#client-receiving-expired-transfer) for use cases where it is complicated to perform a refund, a Payee FSP can (if the scheme allows it) reserve the transfer and then wait for a subsequent commit notification from the Switch. To request a commit notification instead of committing directly is a business decision made by the Payee FSP (if the scheme allows it), based on the context of the transaction. For example, a Cash Out or a Merchant Payment transaction can be understood as a higher-risk transaction, because it is not possible to reverse a transaction if the customer is no longer present; a P2P Transfer can be understood as lower risk because it is easier to reverse by refunding the transaction to the customer. +To request a commit notification from the Switch, the Payee FSP must mark the transfer state (see Section 6.7.6) as reserved instead of committed in the **PUT /transfers/**_{ID}_ callback. Based on the transfer state, the Switch should then perform the following: + +- If the transfer is committed, the Switch should not send a commit notification as the Payee FSP has already accepted the risk that the transfer in some rare cases might fail. This is the default way of committing, shown in [Process](#process). +- If the transfer is reserved, the Switch must send a commit notification to the Payee FSP when the transfer is completed (committed or aborted). + +The commit notification is sent in the request **PATCH /transfers/**_{ID}_ from the Switch to the Payee FSP. If the Payee FSP does not get a commit notification from the Switch within a reasonable time, the Payee FSP should resend the **PUT /transfers/**_{ID}_ callback to the Switch. The Payee FSP needs to receive the commit notification from the Switch before committing the transfer, or accept the risk that the transfer in the Switch might have failed. The Payee FSP is not allowed to rollback the transfer without receiving an aborted state (see Section 6.7.6) from the Switch, as the Payee FSP has sent the fulfilment (which is the commit trigger) to the Switch. +[Figure 54](#figure-54) shows an example where a commit notification is requested by the Payee FSP. In this example the commit was successful in the Switch. + +###### Figure 54 + +{% uml src="assets/diagrams/sequence/figure54.plantuml" %} +{% enduml %} + +**Figure 54 -- Commit notification where commit of transfer was successful in Switch** + +[Figure 55](#figure-55) shows an example in which the commit in the Switch failed due to some reason, for example the expiry time had expired in the Switch due to network issues. This is the same example as in [Figure 53](#figure-53), but where no reconciliation is needed as the Payee FSP receives a commit notification before performing the actual transfer to the Payee. + +###### Figure 55 + +{% uml src="assets/diagrams/sequence/figure55.plantuml" %} +{% enduml %} + +**Figure 55 -- Commit notification where commit of transfer in Switch failed** + +#### Refunds + +Instead of supporting reversals, the API supports refunds. To refund a transaction using the API, a new transaction should be created by the Payee of the original transaction. The new transaction should revers the original transaction (either the full amount or a partial amount); for example, if customer X sent 100 USD to merchant Y in the original transaction, a new transaction where merchant Y sends 100 USD to customer X should be created. There is a specific transaction type to indicate a refund transaction; for example, if the quote of the transaction should be handled differently than any other type of transaction. The original transaction ID should be sent as part of the new transaction for informational and reconciliation purposes. + +#### Interledger Payment Request + +As part of supporting Interledger and the concrete implementation of the Interledger Payment Request (see [Interledger Protocol](#interledger-protocol)), the Payer FSP must attach the ILP Packet, the condition, and an expiry to the transfer. The condition and the ILP Packet are the same as those sent by the Payee FSP in the callback of the quote; see [Interledger Payment Request](#interledger-payment-request) section for more information. + +The end-to-end ILP payment is a chain of one or more conditional transfers that all depend on the same condition. The condition is provided by the Payer FSP when it initiates the transfer to the next ledger. + +The receiver of that transfer parses the ILP Packet to get the Payee ILP Address and routes the ILP payment by performing another transfer on the next ledger, attaching the same ILP Packet and condition and a new expiry that is less than the expiry of the incoming transfer. + +When the Payee FSP receives the final incoming transfer to the Payee account, it extracts the ILP Packet and performs the following steps: + +1. Validates that the Payee ILP Address in the ILP Packet corresponds to the Payee account that is the destination of the transfer. +2. Validates that the amount in the ILP Packet is the same as the amount of the transfer and directs the local ledger to perform a reservation of the final transfer to the Payee account (less any hidden receiver fees, see [Quoting](#quoting)). +3. If the reservation is successful, the Payee FSP generates the fulfilment using the same algorithm that was used when generating the condition sent in the callback of the quote (see [Interledger Payment Request](#interledger-payment-request)). +4. The fulfilment is submitted to the Payee FSP ledger to instruct the ledger to commit the reservation in favor of the Payee. The ledger will validate that the SHA-256 hash of the fulfilment matches the condition attached to the transfer. If it does, it commits the reservation of the transfer. If not, it rejects the transfer and the Payee FSP rejects the payment and cancels the previously-performed reservation. + +The fulfilment is then passed back to the Payer FSP through the same ledgers in the callback of the transfer. As funds are committed on each ledger after a successful validation of the fulfilment, the entity that initiated the transfer will be notified that the funds it reserved have been committed and the fulfilment will be shared as part of that notification message. + +The final transfer to be committed is the transfer on the Payer FSP's ledger where the reservation is committed from their account. At this point the Payer FSP notifies the Payer of the successful financial transaction. + +#### Requests + +This section describes the services that can be requested by a client in the API on the resource **/transfers**. + +##### GET /transfers/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Authorization Result](../generic-transaction-patterns#return-authorization-result) + +The HTTP request **GET /transfers/**_{ID}_ is used to get information regarding a previously-created or requested transfer. The _{ID}_ in the URI should contain the **transferId** (see [Table 23](#table-23)) that was used for the creation of the transfer. + +Callback and data model information for **GET /transfer/**_{ID}_: + +- Callback -- [**PUT /transfers/**_{ID}_](#put-transfersid) +- Error Callback -- [**PUT /transfers/**_{ID}_**/error**](#put-transfersiderror) +- Data Model -- Empty body + +##### POST /transfers + +Alternative URI: N/A + +Logical API service: [Perform Transfer](../generic-transaction-patterns#perform-transfer) + +The HTTP request **POST /transfers** is used to request the creation of a transfer for the next ledger, and a financial transaction for the Payee FSP. + +Callback and data model information for **POST /transfers**: + +- Callback -- [**PUT /transfers/**_{ID}_](#put-transfersid) +- Error Callback -- [**PUT /transfers/**_{ID}_**/error**](#put-transfersiderror) +- Data Model -- See [Table 30](#table-30) + +###### Table 30 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **transferId** | 1| CorrelationId | The common ID between the FSPs and the optional Switch for the transfer object, decided by the Payer FSP. The ID should be reused for resends of the same transfer. A new ID should be generated for each new transfer. | +| **payeeFsp** | 1 | FspId | Payee FSP in the proposed financial transaction. | +| **payerFsp** | 1 | FspId | Payer FSP in the proposed financial transaction. | +| **amount** | 1 | Money | The transfer amount to be sent. | +| **ilpPacket** | 1 | IlpPacket | The ILP Packet containing the amount delivered to the Payee and the ILP Address of the Payee and any other end-to-end data. | +| **condition** | 1 | IlpCondition | The condition that must be fulfilled to commit the transfer. | +| **expiration** | 1 | DateTime | Expiration can be set to get a quick failure expiration of the transfer. The transfer should be rolled back if no fulfilment is delivered before this time. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 30 – POST /transfers data model** + +##### PATCH /transfers/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Commit Notiifcation](../generic-transaction-patterns#commit-notification) + +The HTTP request **PATCH /transfers/**_{ID}_ is used by a Switch to update the state of an earlier reserved transfer, if the Payee FSP has requested a commit notification when the Switch has completed processing of the transfer. The _{ID}_ in the URI should contain the transferId (see Table 30) that was used for the creation of the transfer. Please note that this request does not generate a callback. See Table 31 for data model. + +###### Table 31 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **completedTimestamp** | 1| DateTime | Time and date when the transaction was completed | +| **transferState** | 1 | TransferState | State of the transfer | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 31 –- PATCH /transfers/_{ID}_ data model** + +#### Callbacks + +This section describes the callbacks that are used by the server under the resource **/transfers**. + +##### PUT /transfers/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Transfer Information](../generic-transaction-patterns#return-transfer-information) + +The callback **PUT /transfers/**_{ID}_ is used to inform the client of a requested or created transfer. The _{ID}_ in the URI should contain the **transferId** (see [Table 30](#table-30)) that was used for the creation of the transfer, or the _{ID}_ that was used in the [**GET** **/transfers/**_{ID}_](#6731-get-transfersid). **See** [Table 32](#table-32) **for** data model. + +**Note**: For **PUT /transfers/**_{ID}_ callbacks, the state ABORTED is not a valid enumeration option as **transferState** in Table 32. If a transfer is to be rejected, then the FSP making the callback should use an error callback, i.e., a callback on the /error endpoint. At the same time, it should be noted that a **transferState** value ‘ABORTED’ is valid for a callback to a **GET /transfers/**_{ID}_ call. + +###### Table 32 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **fulfilment** | 0..1 | IlpFulfilment | Fulfilment of the condition specified with the transaction. Mandatory if transfer has completed successfully. | +| **completedTimestamp** | 0..1 | DateTime | Time and date when the transaction was completed | +| **transferState** | 1 | TransferState | State of the transfer | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment | + +**Table 32 -- PUT /transfers/_{ID}_ data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/transfers**. + +##### PUT /transfers/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Return Transfer Information Error](../generic-transaction-patterns#return-transfer-information-error) + +If the server is unable to find or create a transfer, or another processing error occurs, the error callback **PUT** + +**/transfers/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the **transferId** (see [Table 30](#table-30)) that was used for the creation of the transfer, or the _{ID}_ that was used in the [**GET /transfers/**_{ID}_](#6731-get-transfersid). See [Table 33](#table-33) for data model. + +###### Table 33 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description. | + +**Table 33 -- PUT /transfers/_{ID}_/error data model** + +**6.7.6 States** + +###### Figure 56 + +The possible states of a transfer can be seen in [Figure 56](#figure-56). + +![Figure 56](/assets/diagrams/images/figure56.svg) + +**Figure 56 -- Possible states of a transfer** + +
    + + +### API Resource /transactions + +This section defines the logical API resource **Transactions**, described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-transactions). + +The services provided by the API resource **/transactions** are used for getting information about the performed end-to-end financial transaction; for example, to get information about a possible token that was created as part of the transaction. + +The actual financial transaction is performed using the services provided by the API Resource [**/transfers**](#67-api-resource-transfers), which includes the end-to-end financial transaction between the Payer FSP and the Payee FSP. + +#### Resource Version History + +[Table 34](#table-34) contains a description of each different version of the **/transactions** resource. + +###### Table 34 + +|Version|Date|Description| +|---|---|---| +|1.0|2018-03-13|Initial version| + +**Table 34 – Version history for resource /transactions** + +#### Service Details + +[Figure 57](#figure-57) shows an example for the transaction process. The actual transaction will be performed as part of the transfer process. The service **GET /transactions/**_{TransactionID}_ can then be used to get more information about the financial transaction that was performed as part of the transfer process. + +###### Figure 57 + +{% uml src="assets/diagrams/sequence/figure57.plantuml" %} +{% enduml %} + +**Figure 57 -- Example transaction process** + +#### Requests + +This section describes the services that can be requested by a client on the resource **/transactions**. + +##### GET /transactions/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Retrieve Transaction Information](../generic-transaction-patterns#retrieve-transaction-information) + +The HTTP request **GET /transactions/**_{ID}_ is used to get transaction information regarding a previously-created financial transaction. The _{ID}_ in the URI should contain the **transactionId** that was used for the creation of the quote (see [Table 23](#table-23)), as the transaction is created as part of another process (the transfer process, see [API Resource Transfers](#api-resource-transfers)). + +Callback and data model information for **GET /transactions/**_{ID}_: + +- Callback -- [**PUT /transactions/**_{ID}_](#put-transactionsid) +- Error Callback -- [**PUT /transactions/**_{ID}_**/error**](#put-transactionsiderror) +- Data Model -- Empty body + +#### Callbacks + +This section describes the callbacks that are used by the server under the resource **/transactions**. + +##### PUT /transactions/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Transaction Information](../generic-transaction-patterns#return-transaction-information) + +The callback **PUT /transactions/**_{ID}_ is used to inform the client of a requested transaction. The _{ID}_ in the URI should contain the _{ID}_ that was used in the [**GET /transactions/**_{ID}_](#get-transactionsid). See [Table 35](#table-35) for data model. + +###### Table 35 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **completedTimestamp** | 0..1 | DateTime | Time and date when the transaction was completed. | +| **transactionState** | 1 | TransactionState | State of the transaction. | +| **code** | 0..1 | Code | Optional redemption information provided to Payer after transaction has been completed. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 35 -- PUT /transactions/_{ID}_ data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/transactions**. + +##### PUT /transactions/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Return Transaction Information Error](../generic-transaction-patterns#retrieve-transaction-information-error) + +If the server is unable to find or create a transaction, or another processing error occurs, the error callback **PUT** **/transactions/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the _{ID}_ that was used in the [**GET /transactions/**_{ID}_](#get-transactionsid). See [Table 36](#table-36) for data model. + +###### Table 36 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description. | + +**Table 36 -- PUT /transactions/_{ID}_/error data model** + +#### States + +###### Figure 58 + +The possible states of a transaction can be seen in [Figure 58](#figure-58). + +**Note:** For reconciliation purposes, a server must keep transaction objects that have been rejected in its database for a scheme-agreed time period. This means that a client should expect a proper callback about a transaction (if it has been received by the server) when requesting information regarding the same. + +![Figure 58](/assets/diagrams/images/figure58.svg) + +**Figure 58 -- Possible states of a transaction** + +
    + +### API Resource /bulkQuotes + +This section defines the logical API resource **Bulk Quotes**, described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-bulk-quotes). + +The services provided by the API resource **/bulkQuotes** service are used for requesting the creation of a bulk quote; that is, a quote for more than one financial transaction. For more information regarding a single quote for a transaction, see API Resource [/quotes](#api-resource-quotes). + +A created bulk quote object contains a quote for each individual transaction in the bulk in a Peer FSP. A bulk quote is irrevocable; it cannot be changed after it has been created However, it can expire (all bulk quotes are valid only until they reach expiration). + +**Note:** A bulk quote is not a guarantee that the financial transaction will succeed. The bulk transaction can still fail later in the process. A bulk quote only guarantees that the fees and FSP commission involved in performing the specified financial transaction are applicable until the bulk quote expires. + +#### Resource Version History + +Table 37 contains a description of each different version of the **/bulkQuotes** resource. + +| Version | Date | Description| +| ---- | ---- | ---- | +| **1.0** | 2018-03-13 | Initial version | +| **1.1** | 2020-05-19 | The data model is updated to add an optional ExtensioinList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| + +**Table 37 –- Version history for resource /bulkQuotes** + +#### Service Details + +[Figure 59](#figure-59) shows how the bulk quotes process works, using the **POST /bulkQuotes** service. When receiving the bulk of transactions from the Payer, the Payer FSP should: + +1. Lookup the FSP in which each Payee is; for example, using the API Resource [/participants](#api-resource-participants). + +2. Divide the bulk based on Payee FSP. The service **POST /bulkQuotes** is then used for each Payee FSP to get the bulk quotes from each Payee FSP. Each quote result will contain the ILP Packet and condition (see [ILP Packet](#ilp-packet) and [Conditional Transfers](#conditional-transfers)) needed to perform each transfer in the bulk transfer (see API Resource [/bulkTransfers](#api-resource-bulktransfers)), which will perform the actual financial transaction from the Payer to each Payee. + +###### Figure 59 + +{% uml src="assets/diagrams/sequence/figure59.plantuml" %} +{% enduml %} + +**Figure 59 -- Example bulk quote process** + +#### Requests + +This section describes the services that can be requested by a client in the API on the resource **/bulkQuotes**. + +##### GET /bulkQuotes/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Retrieve Bulk Quote Information](../generic-transaction-patterns#retrieve-bulk-quote-information) + +The HTTP request **GET /bulkQuotes/**_{ID}_ is used to get information regarding a previously-created or requested bulk quote. + +The _{ID}_ in the URI should contain the **bulkQuoteId** (see [Table 38](#table-38)) that was used for the creation of the bulk quote. + +Callback and data model information for **GET /bulkQuotes/**_{ID}_: + +- Callback -- [PUT /bulkQuotes/**_{ID}_](#put-bulkquotesid) +- Error Callback -- [PUT /bulkQuotes/**_{ID}_**/error**](#put-bulkquotesiderror) +- Data Model -- Empty body + +##### POST /bulkQuotes + +Alternative URI: N/A + +Logical API service: **Calculate Bulk Quote** + +The HTTP request **POST /bulkQuotes** is used to request the creation of a bulk quote for the provided financial transactions on the server. + +Callback and data model information for **POST /bulkQuotes**: + +- Callback -- [**PUT /bulkQuotes/**_{ID}_](#6941-put-bulkquotesid) +- Error Callback -- [**PUT /bulkQuotes/**_{ID}_**/error**](#6951-put-bulkquotesiderror) +- Data Model -- See [Table 38](#table-38) + +###### Table 38 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **bulkQuoteId** | 1 | CorrelationId | Common ID between the FSPs for the bulk quote object, decided by the Payer FSP. The ID should be reused for resends of the same bulk quote. A new ID should be generated for each new bulk quote. | +| **payer** | 1 | Party | Information about the Payer in the proposed financial transaction. | +| **geoCode** | 0..1 | GeoCode | Longitude and Latitude of the initiating Party. Can be used to detect fraud. | +| **expiration** | 0..1 | DateTime | Expiration is optional to let the Payee FSP know when a quote no longer needs to be returned. | +| **individualQuotes** | 1..1000 | IndividualQuote | List of quotes elements. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 38 -- POST /bulkQuotes data model** + +#### Callbacks + +This section describes the callbacks that are used by the server under the resource **/bulkQuotes**. + +##### PUT /bulkQuotes/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Return Bulk Quote Information](../generic-transaction-patterns#return-bulk-quote-information) + +The callback **PUT /bulkQuotes/**_{ID}_ is used to inform the client of a requested or created bulk quote. The _{ID}_ in the URI should contain the **bulkQuoteId** (see [Table 38](#table-38)) that was used for the creation of the bulk quote, or the _{ID}_ that was used in the [**GET /bulkQuotes/**_{ID}_](#6931-get-bulkquotesid). See [Table 39](#table-39) for data model. + +###### Table 39 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **individualQuoteResults** | 0..1000 | IndividualQuoteResult | Fees for each individual transaction, if any of them are charged per transaction. | +| **expiration** | 1 | DateTime | Date and time until when the quotation is valid and can be honored when used in the subsequent transaction request. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 39 -- PUT /bulkQuotes/_{ID}_ data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/bulkQuotes**. + +##### PUT /bulkQuotes/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Retrieve Bulk Quote Information Error](../generic-transaction-patterns#retrieve-bulk-quote-information-error) + +If the server is unable to find or create a bulk quote, or another processing error occurs, the error callback **PUT** **/bulkQuotes/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the **bulkQuoteId** (see [Table 38](#table-38)) that was used for the creation of the bulk quote, or the _{ID}_ that was used in the [**GET /bulkQuotes/**_{ID}_](#6931-get-bulkquotesid). See [Table 40](#table-40) for data model. + +###### Table 40 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description. | + +**Table 40 -- PUT /bulkQuotes/_{ID}_/error data model** + +#### States + +###### Figure 60 + +The possible states of a bulk quote can be seen in [Figure 60](#figure-60). + +**Note:** A server does not need to keep bulk quote objects that have been either rejected or expired in their database. This means that a client should expect that an error callback could be received for a rejected or expired bulk quote. + +![Figure 60](/assets/diagrams/images/figure60.svg) + +**Figure 60 -- Possible states of a bulk quote** + +
    + +### API Resource /bulkTransfers + +This section defines the logical API resource **Bulk Transfers**, described in [Generic Transaction Patterns](../generic-transaction-patterns#api-resource-bulk-transfers). + +The services provided by the API resource **/bulkTransfers** are used for requesting the creation of a bulk transfer or for retrieving information about a previously-requested bulk transfer. For more information about a single transfer, see API Resource [/transfers](#api-resource-transfers). Before a bulk transfer can be requested, a bulk quote needs to be performed. See API Resource [/bulkQuotes](#api-resource-bulkquotes), for more information. + +A bulk transfer is irrevocable; it cannot be changed, cancelled, or reversed after it has been sent from the Payer FSP. + +#### Resource Version History + +Table 41 contains a description of each different version of the **/bulkTransfers** resource. + +| Version | Date | Description| +| ---- | ---- | ---- | +| **1.0** | 2018-03-13 | Initial version | +| **1.1** | 2020-05-19 | The data model is updated to add an optional ExtensioinList element to the PartyIdInfo complex type based on the Change Request: https://github.com/mojaloop/mojaloop-specification/issues/30. Following this, the data model as specified in Table 93 has been updated.| + +**Table 41 –- Version history for resource /bulkTransfers** + +#### Service Details + +[Figure 61](#figure-61) shows how the bulk transfer process works, using the **POST /bulkTransfers** service. When receiving the bulk transactions from the Payer, the Payer FSP should perform the following: + +1. Lookup the FSP in which each Payee is; for example, using the API Resource **/participants**, [Section 6.2](#62-api-resource-participants). +2. Perform the bulk quote process using the API Resource **/bulkQuotes**, [Section 6.9](#69-api-resource-bulkquotes). The bulk quote callback should contain the required ILP Packets and conditions needed to perform each transfer. +3. Perform bulk transfer process in [Figure 61](#figure-61) using **POST /bulkTransfers**. This performs each hop-to-hop transfer and the end-to-end financial transaction. For more information regarding hop-to-hop transfers vs end-to-end financial transactions, see [Section 6.7](#67-api-resource-transfers). + +###### Figure 61 + +{% uml src="assets/diagrams/sequence/figure61.plantuml" %} +{% enduml %} + +**Figure 61 -- Example bulk transfer process** + +#### Requests + +This section describes the services that can a client can request on the resource **/bulkTransfers**. + +##### GET /bulkTransfers/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Retrieve Bulk Transfer Information](../generic-transaction-patterns#retrieve-bulk-transfer-information) + +The HTTP request **GET /bulkTransfers/**_{ID}_ is used to get information regarding a previously-created or requested bulk transfer. The _{ID}_ in the URI should contain the **bulkTransferId** (see [Table 42](#table-42)) that was used for the creation of the bulk transfer. + +Callback and data model information for **GET /bulkTransfers/**_{ID}_: + +- Callback -- [PUT /bulkTransfers/_{ID}_](#put-bulktransfersid) +- Error Callback -- [PUT /bulkTransfers/_{ID}_/error](#put-bulktransfersiderror) +- Data Model -- Empty body + +##### POST /bulkTransfers + +Alternative URI: N/A + +Logical API service: [Perform Bulk Transfer](../generic-transaction-patterns#perform-bulk-transfer) + +The HTTP request **POST /bulkTransfers** is used to request the creation of a bulk transfer on the server. + +- Callback - [PUT /bulkTransfers/_{ID}_](#put-bulktransfersid) +- Error Callback - [PUT /bulkTransfers/_{ID}_/error](#put-bulktransfersiderror) +- Data Model -- See [Table 42](#table-42) + +###### Table 42 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **bulkTransferId** | 1 | CorrelationId | Common ID between the FSPs and the optional Switch for the bulk transfer object, decided by the Payer FSP. The ID should be reused for resends of the same bulk transfer. A new ID should be generated for each new bulk transfer. | +| **bulkQuoteId** | 1 | CorrelationId | ID of the related bulk quote | +| **payeeFsp** | 1 | FspId | Payee FSP identifier. | +| **payerFsp** | 1 | FspId | Payer FSP identifier. | +| **individualTransfers** | 1..1000 | IndividualTransfer | List of IndividualTransfer elements. | +| **expiration** | 1 | DateTime | Expiration time of the transfers. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 42 -- POST /bulkTransfers data model** + +#### Callbacks + +This section describes the callbacks that are used by the server under the resource **/bulkTransfers**. + +##### PUT /bulkTransfers/_{ID}_ + +Alternative URI: N/A + +Logical API service: [Retrieve Bulk Transfer Information](../generic-transaction-patterns#retrieve-bulk-transfer-information) + +The callback **PUT /bulkTransfers/**_{ID}_ is used to inform the client of a requested or created bulk transfer. The _{ID}_ in the URI should contain the **bulkTransferId** (see [Table 42](#table-42)) that was used for the creation of the bulk transfer ([POST /bulkTransfers](#post-bulktransfers)), or the _{ID}_ that was used in the [GET /bulkTransfers/_{ID}_](#get-bulktransfersid). See [Table 43](#table-43) for data model. + +###### Table 43 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **completedTimestamp** | 0..1 | DateTime | Time and date when the bulk transaction was completed. | +| **individualTransferResults** | 0..1000 | **Error! Reference source not found.** | List of **Error! Reference source not found.** elements. | +| **bulkTransferState** | 1 | BulkTransferState | The state of the bulk transfer. | +| **extensionList** | 0..1 | ExtensionList | Optional extension, specific to deployment. | + +**Table 43 -- PUT /bulkTransfers/_{ID}_ data model** + +#### Error Callbacks + +This section describes the error callbacks that are used by the server under the resource **/bulkTransfers**. + +##### PUT /bulkTransfers/_{ID}_/error + +Alternative URI: N/A + +Logical API service: [Retrieve Bulk Transfer Information Eerror](../generic-transaction-patterns#retrieve-bulk-transfer-information-error) + +If the server is unable to find or create a bulk transfer, or another processing error occurs, the error callback **PUT** **/bulkTransfers/**_{ID}_**/error** is used. The _{ID}_ in the URI should contain the **bulkTransferId** (see [Table 42](#table-42)) that was used for the creation of the bulk transfer ([POST /bulkTransfers](#post-bulktransfers)), or the _{ID}_ that was used in the [GET /bulkTransfers/_{ID}_](#get-bulktransfersid). See [Table 44](#table-44) for data model. + +###### Table 44 + +| **Name** | **Cardinality** | **Type** | **Description** | +| --- | --- | --- | --- | +| **errorInformation** | 1 | ErrorInformation | Error code, category description. | + +**Table 44 -- PUT /bulkTransfers/_{ID}_/error data model** + +#### States + +###### Figure 62 + +The possible states of a bulk transfer can be seen in [Figure 62](#figure-62). + +**Note:** A server must keep bulk transfer objects that have been rejected in their database during a market agreed time-period for reconciliation purposes. This means that a client should expect a proper callback about a bulk transfer (if it has been received by the server) when requesting information regarding the same. + +![Figure 62](/assets/diagrams/images/figure62.svg) + +**Figure 62 -- Possible states of a bulk transfer** + +
    + +## API Supporting Data Models + +This section provides information about additional supporting data models used by the API. + +### Format Introduction + +This section introduces formats used for element data types used by the API. + +All element data types have both a minimum and maximum length. These lengths are indicated by one of the following: + +- A minimum and maximum length +- An exact length +- A regular expression limiting the element such that only a specific length or lengths can be used. + +#### Minimum and Maximum Length + +If a minimum and maximum length is used, this will be indicated after the data type in parentheses: First the minimum value (inclusive value), followed by two period characters (..), and then the maximum value (inclusive value). + +Examples: + +- `String(1..32)` – A String that is minimum one character and maximum 32 characters long. +- `Integer(3..10)` - An Integerr that is minimum 3 digits, but maximum 10 digits long. + +#### Exact Length + +If an exact length is used, this will be indicated after the data type in parentheses containing only one exact value. Other lengths are not allowed. + +Examples: + +- `String(3)` – A String that is exactly three characters long. +- `Integer(4)` – An Integer that is exactly four digits long. + +#### Regular Expressions + +Some element data types are restricted using regular expressions. The regular expressions in this document use the standard for syntax and character classes established by the programming language Perl[30](https://perldoc.perl.org/perlre.html#Regular-Expressions). + +### Element Data Type Formats + +This section defines element data types used by the API. + + + +#### String + +The API data type `String` is a normal JSON String[31](https://tools.ietf.org/html/rfc7159#section-7), limited by a minimum and maximum number of characters. + +##### Example Format I + +`String(1..32)` – A String that is minimum *1* character and maximum *32* characters long. + +An example of `String(1..32)` appears below: + +- _This String is 28 characters_ + +##### Example Format II + +`String(1..128)` – A String that is minimum *1* character and maximum *128* characters long. + +An example of `String(32..128)` appears below: + +- _This String is longer than 32 characters, but less than 128_ + +
    + +#### Enum + +The API data type `Enum` is a restricted list of allowed JSON [String](#string)) values; an enumeration of values. Other values than the ones defined in the list are not allowed. + +##### Example Format + +`Enum of String(1..32)` – A String that is minimum one character and maximum 32 characters long and restricted by the allowed list of values. The description of the element contains a link to the enumeration. + +
    + +#### UndefinedEnum + +The API data type **UndefinedEnum** is a JSON String consisting of 1 to 32 uppercase characters including an underscore character (**\_**). + +##### Regular Expression + +The regular expression for restricting the **UndefinedEnum** type appears in [Listing 13](#listing-13). + +###### Listing 13 + +``` +^[A-Z_]{1,32}$ +``` + +**Listing 13 -- Regular expression for data type UndefinedEnum** + +
    + +#### Name + +The API data type `Name` is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. + +##### Regular Expression + +The regular expression for restricting the `Name` type appears in [Listing 14](#listing-14) below. The restriction does not allow a string consisting of whitespace only, all Unicode32 characters are allowed, as well as the period (**.**), apostrophe (**'**), dash (**-**), comma (**,**) and space characters ( ). The maximum number of characters in the **Name** is 128. + +**Note:** In some programming languages, Unicode support needs to be specifically enabled. As an example, if Java is used the flag `UNICODE_CHARACTER_CLASS` needs to be enabled to allow Unicode characters. + +###### Listing 14 + +``` +^(?!\s*$)[\w .,'-]{1,128}$ +``` + +**Listing 14 -- Regular expression for data type Name** + +
    + +#### Integer + +The API data type `Integer` is a JSON String consisting of digits only. Negative numbers and leading zeroes are not allowed. The data type is always limited by a number of digits. + +##### 7.2.5.1 Regular Expression + +The regular expression for restricting an `Integer` appears in [Listing 15](#listing-15). + +###### Listing 15 + +``` +^[1-9]\d*$ +``` + +**Listing 15 -- Regular expression for data type Integer** + + +##### Example Format + +`Integer(1..6)` – An `Integer` that is at minimum one digit long, maximum six digits. + +An example of `Integer(1..6)` appears below: + +- _123456_ + +
    + +#### OtpValue + +The API data type `OtpValue` is a JSON String of three to 10 characters, consisting of digits only. Negative numbers are not allowed. One or more leading zeros are allowed. + +##### Regular Expression + +The regular expression for restricting the `OtpValue` type appears in [Listing 16](#listing-16). + +###### Listing 16 + +``` +^\d{3,10}$ +``` + +**Listing 16 -- Regular expression for data type OtpValue** + +
    + +#### BopCode + +The API data type `BopCode` is a JSON String of three characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. + +##### Regular Expression + +The regular expression for restricting the `BopCode` type appears in [Listing 17](#listing-17). + +###### Listing 17 + +``` +^[1-9]\d{2}$ +``` + +**Listing 17 -- Regular expression for data type BopCode** + +
    + +#### ErrorCode + +The API data type `ErrorCode` is a JSON String of four characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. + +##### Regular Expression + +The regular expression for restricting the `ErrorCode` type appears in [Listing 18](#listing-18). + +###### Listing 18 + +``` +^[1-9]\d{3}$ +``` + +**Listing 18 -- Regular expression for data type ErrorCode** + +
    + +#### TokenCode + +The API data type `TokenCode` is a JSON String between four and 32 characters. It can consist of either digits, uppercase characters from **A** to **Z**, lowercase characters from **a** to **z**, or a combination of the three. + +##### 7.2.9.1 Regular Expression + +The regular expression for restricting the `TokenCode` appears in [Listing 19](#listing-19). + +###### Listing 19 + +``` +^[0-9a-zA-Z]{4,32}$ +``` + +**Listing 19 -- Regular expression for data type TokenCode** + +
    + +#### MerchantClassificationCode + +The API data type `MerchantClassificationCode` is a JSON String consisting of one to four digits. + +##### 7.2.10.1 Regular Expression + +The regular expression for restricting the `MerchantClassificationCode` type appears in [Listing 20](#listing-20). + +###### Listing 20 + +``` +^[\d]{1,4}$ +``` + +**Listing 20 -- Regular expression for data type MerchantClassificationCode** + +
    + +#### Latitude + +The API data type `Latitude` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### 7.2.11.1 Regular Expression + +The regular expression for restricting the `Latitude` type appears in [Listing 21](#listing-21). + +###### Listing 21 + +``` +^(\+|-)?(?:90(?:(?:\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\.[0-9]{1,6})?))$ +``` + +**Listing 21 -- Regular expression for data type Latitude** + +
    + +#### Longitude + +The API data type `Longitude` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### 7.2.12.1 Regular Expression + +The regular expression for restricting the `Longitude` type appears in [Listing 22](#listing-22). + +###### Listing 22 + +``` +^(\+|-)?(?:180(?:(?:\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.[0-9]{1,6})?))$ +``` + +**Listing 22 -- Regular expression for data type Longitude** + +
    + +#### Amount + +The API data type `Amount` is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting the `Amount` type appears in [Listing 23](#listing-23). This pattern does not allow any trailing zeroes at all, but allows an amount without a minor currency unit. It also only allows four digits in the minor currency unit; a negative value is not allowed. Using more than 18 digits in the major currency unit is not allowed. + +###### Listing 23 + +``` +^([0]|([1-9][0-9]{0,17}))([.][0-9]{0,3}[1-9])?$ +``` + +**Listing 23 -- Regular expression for data type Amount** + +##### Example Values + +See [Table 45](#table-45) for validation results for some example **Amount** values using the [regular expression](#regular-expression-6). + +###### Table 45 + +| **Value** | **Validation result** | +| --- | --- | +| **5** | Accepted | +| **5.0** | Rejected | +| **5.** | Rejected | +| **5.00** | Rejected | +| **5.5** | Accepted | +| **5.50** | Rejected | +| **5.5555** | Accepted | +| **5.55555** | Rejected | +| **555555555555555555** | Accepted | +| **5555555555555555555** | Rejected | +| **-5.5** | Rejected | +| **0.5** | Accepted | +| **.5** | Rejected | +| **00.5** | Rejected | +| **0** | Accepted | + +**Table 45 -- Example results for different values for Amount type** + +
    + +#### DateTime + +The API data type `DateTime` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### 7.2.14.1 Regular Expression + +The regular expression for restricting the `DateTime` type appears in [Listing 24](#listing-24). The format is according to ISO 860133, expressed in a combined date, time and time zone format. A more readable version of the format is + +_yyyy_**-**_MM_**-**_dd_**T**_HH_**:**_mm_**:**_ss_**.**_SSS_[**-**_HH_**:**_MM_] + +###### Listing 24 + +``` +^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468\][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:(\.\d{3}))(?:Z|[+-][01]\d:[0-5]\d)$ +``` + +**Listing 24 -- Regular expression for data type DateTime** + +##### Examples + +Two examples of the `DateTime` type appear below: + +**2016-05-24T08:38:08.699-04:00** + +**2016-05-24T08:38:08.699Z** (where **Z** indicates Zulu time zone, which is the same as UTC). + +
    + +#### Date + +The API data type `Date` is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. + +##### Regular Expression + +The regular expression for restricting the **Date** type appears in [Listing 25](#listing-25). This format, as specified in ISO 8601, contains a date only. A more readable version of the format is _yyyy_**-**_MM_**-**_dd_. + +###### Listing 25 + +``` +^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$ +``` + +**Listing 25 -- Regular expression for data type Date** + +##### Examples + +Two examples of the `Date` type appear below: + +- _1982-05-23_ + +- _1987-08-05_ + +
    + +#### UUID + +The API data type `UUID` (Universally Unique Identifier) is a JSON String in canonical format, conforming to RFC 412234, that is restricted by a regular expression for interoperability reasons. A UUID is always 36 characters long, 32 hexadecimal symbols and four dashes ('**-**'). + +##### 7.2.16.1 Regular Expression + +The regular expression for restricting the `UUID` type appears in [Listing 26](#listing-26). + +###### Listing 26 + +``` +^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ +``` + +**Listing 26 -- Regular expression for data type UUID** + +##### Example + +An example of a `UUID` type appears below: + +- _a8323bc6-c228-4df2-ae82-e5a997baf898_ + +
    + +#### BinaryString + +The API data type `BinaryString` is a JSON String. The string is a base64url35 encoding of a string of raw bytes, where a padding (character '**=**') is added at the end of the data if needed to ensure that the string is a multiple of four characters. The length restriction indicates the allowed number of characters. + +##### Regular Expression + +The regular expression for restricting the `BinaryString` type appears in [Listing 27](#listing-27). + +###### Listing 27 + +``` +^[A-Za-z0-9-_]+[=]{0,2}$ +``` + +**Listing 27 -- Regular expression for data type BinaryString** + +##### Example Format + +`BinaryString(32)` –32 bytes of data base64url encoded. + +An example of a `BinaryString(32..256)` appears below. Note that a padding character, `'='` has been added to ensure that the string is a multiple of four characters. + +- _QmlsbCAmIE1lbGluZGEgR2F0ZXMgRm91bmRhdGlvbiE=_ + +
    + +#### BinaryString32 + +The API data type `BinaryString32` is a fixed size version of the API data type `BinaryString` defined [here](#binarystring), where the raw underlying data is always of 32 bytes. The data type **BinaryString32** should not use a padding character as the size of the underlying data is fixed. + +##### Regular Expression + +The regular expression for restricting the `BinaryString32` type appears in [Listing 28](#listing-28). + +###### Listing 28 + +``` +^[A-Za-z0-9-_]{43}$ +``` + +**Listing 28 -- Regular expression for data type BinaryString32** + +##### Example Format +`BinaryString(32)` – 32 bytes of data base64url encoded. + +An example of a `BinaryString32` appears below. Note that this is the same binary data as the example shown in the [Example Format](#example-format-4) of the `BinaryString` type, but due to the underlying data being fixed size, the padding character `'='` is excluded. + +``` +QmlsbCAmIE1lbGluZGEgR2F0ZXMgRm91bmRhdGlvbiE +``` + +
    + +### Element Definitions + +This section defines elements types used by the API. + +#### AmountType element + +[Table 46](#table-46) below contains the data model for the element `AmountType`. + +###### Table 46 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **AmountType** | 1 | [Enum](#enum) of [String(1..32)](#string) | This element contains the amount type. See [AmountType](#amounttype-enum) enumeration for more information on allowed values. | + +**Table 46 – Element AmountType** + +
    + +#### AuthenticationType element + +[Table 47](#table-47) below contains the data model for the element `AuthenticationType`. + +###### Table 47 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Authentication** | 1 | [Enum](#enum) of [String(1..32)](#string) | This element contains the authentication type. See [AuthenticationType](#authenticationtype-enum) enumeration for possible enumeration values. | + +**Table 47 – Element AuthenticationType** + +
    + +#### AuthenticationValue element + +[Table 48](#table-48) below contains the data model for the element `AuthenticationValue`. + +###### Table 48 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **AuthenticationValue** | 1 | Depends on [AuthenticationType](#authenticationtype-element).

    If `OTP`: type is [Integer(1..6)](#integer). For example:**123456**

    OtpValue
    If `QRCODE`: type is [String(1..64)](#string) | This element contains the authentication value. The format depends on the authentication type used in the [AuthenticationInfo](#authenticationinfo) complex type. | + +**Table 48 – Element AuthenticationValue** + +
    + +#### AuthorizationResponse element + +[Table 49](#table-49) below contains the data model for the element `AuthorizationResponse`. + +###### Table 49 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **AuthorizationResponse** | 1 | [Enum](#enum) of [String(1..32)](#string) | This element contains the authorization response. See [AuthorizationResponse](#authorizationresponse-enum) enumeration for possible enumeration values. | + +**Table 49 – Element AuthorizationResponse** + +
    + +#### BalanceOfPayments element + +[Table 50](#table-50) below contains the data model for the element `BalanceOfPayment`. + +###### Table 50 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **BalanceOfPayments** | 1 | [BopCode](#bopcode) | The possible values and meaning are defined in [https://www.imf.org/external/np/sta/bopcode/](https://www.imf.org/external/np/sta/bopcode/) | + +**Table 50 – Element BalanceOfPayments** + +
    + +#### BulkTransferState element + +[Table 51](#table-51) below contains the data model for the element `BulkTransferState`. + +###### Table 51 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **BulkTransferState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [BulkTransferState](#bulktransferstate-enum) enumeration for information on allowed values| + +**Table 51 – Element BulkTransferState** + +
    + +#### Code element + +[Table 52](#table-52) below contains the data model for the element `Code`. + +###### Table 52 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Code** | 1 | [TokenCode](#tokencode) | Any code/token returned by the Payee FSP. | + +**Table 52 – Element Code** + +
    + +#### CorrelationId element + +[Table 53](#table-53) below contains the data model for the element `CorrelationId`. + +###### Table 53 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **CorrelationId** | 1 |[UUID](#uuid) | Identifier that correlates all messages of the same sequence. | + + +**Table 53 – Element CorrelationId** + +
    + +#### Currency element + +[Table 54](#table-54) below contains the data model for the element `Currency`. + +###### Table 54 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Currency** | 1 | [Enum](#enum) of [String(3)](#string) | See [Currency](#currencycode-enum) enumeration for information on allowed values | + +**Table 54 – Element Currency** + +
    + +#### DateOfBirth element + +[Table 55](#table-55) below contains the data model for the element `DateOfBirth`. + +###### Table 55 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **DateOfBirth** | 1 | Examples

    Two examples of the [DateTime](#datetime) type appear below:

    2016-05-24T08:38:08.699-04:00

    2016-05-24T08:38:08.699Z (where Z indicates Zulu time zone, which is the same as UTC).

    Date

    | Date of Birth of the Party.| + +**Table 55 – Element DateOfBirth** + +
    + +#### ErrorCode element + +[Table 56](#table-56) below contains the data model for the element `ErrorCode`. + +###### Table 56 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ErrorCode** | 1 | [ErrorCode](#errorcode) | Four digit error code, see section on [Error Codes](#error-codes) for more information. | + +**Table 56 – Element ErrorCode** + +
    + +#### ErrorDescription element + +[Table 57](#table-57] below contains the data model for the element `ErrorDescription`. + +###### Table 57 + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ErrorDescription** | 1 | [String(1..128)](#string) | Error description string. | + +**Table 57 – Element ErrorDescription** + +
    + +#### ExtensionKey element + +[Table 58](#table-58) below contains the data model for the element `ExtensionKey`. + +###### Table 58 + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ExtensionKey** | 1 | [String(1..32)](#string) | The extension key. | + +**Table 58 – Element ExtensionKey** + +
    + +#### ExtensionValue element + +[Table 59](#table-59) below contains the data model for the element `ExtensionValue`. + +###### Table 59 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **ExtensionValue** | 1 | [String(1..128)](#string) | The extension value. | + +**Table 59 – Element ExtensionValue** + +
    + +#### FirstName element +[Table 60](#table-60) below contains the data model for the element `FirstName`. + +###### Table 60 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **FirstName** | 1 | [Name](#name) | First name of the Party | + +**Table 60 – Element FirstName** + +
    + +#### FspId element + +[Table 61](#table-61) below contains the data model for the element `FspId`. + +###### Table 61 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **FspId** | 1 | [String(1..32)](#string)| The FSP identifier. | + +**Table 61 – Element FspId** + +
    + +#### IlpCondition element + +[Table 62](#table-62) below contains the data model for the element `IlpCondition`. + +###### Table 62 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **IlpCondition** | 1 | [BinaryString32](#binarystring32) | The condition that must be attached to the transfer by the Payer. | + +**Table 62 – Element IlpCondition** + +
    + +#### IlpFulfilment element + +[Table 63](#table-63) below contains the data model for the element `IlpFulfilment`. + +###### Table 63 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **IlpFulfilment** | 1 | [BinaryString32](#binarystring32) | The fulfilment that must be attached to the transfer by the Payee. | + +**Table 63 – Element IlpFulfilment** + +
    + +#### IlpPacket element + +[Table 64](#table-64) below cntains the data model for the element `IlpPacket`. + +###### Table 64 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **IlpPacket** | 1 | Example

    An example of a [UUID](#uuid) type appears below:

    a8323bc6-c228-4df2-ae82-e5a997baf898

    [BinaryString(1..32768)](#binarystring)

    | Information for recipient (transport layer information). | + +**Table 64 – Element IlpPacket** + +
    + +#### LastName element + +[Table 65](#table-65) below contains the data model for the element `LastName`. + +###### Table 65 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **LastName** | 1 | [Name](#name) | Last name of the Party (ISO 20022 definition). | + +**Table 65 – Element LastName** + +
    + +#### MerchantClassificationCode element + +[Table 66](#table-66) below contains the data model for the element `MerchantClassificationCode`. + +###### Table 66 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **MerchantClassificationCode** | 1 | [MerchantClassificationCode](#merchantclassificationcode) | A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, and so on. | + +**Table 66 – Element MerchantClassificationCode** + +
    + +#### MiddleName element + +[Table 67](#table-67) below contains the data model for the element `MiddleName`. + +###### Table 67 + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **MiddleName** | 1 | [Name](#name) | Middle name of the Party (ISO 20022 definition). | + +**Table 67 – Element MiddleName** + +
    + +#### Note element + +[Table 68](#table-68) below contains the data model for the element `Note`. + +###### Table 68 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **Note** | 1 | [String(1..128)](#string) | Memo assigned to transaction. | + +**Table 68 – Element Note** + +
    + + +#### PartyIdentifier element + +[Table 69](#table-69) below contains the data model for the element `PartyIdentifier`. + +###### Table 69 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartyIdentifier** | 1 | [String(1..128)](#string) | Identifier of the Party.| + +**Table 69 – Element PartyIdentifier** + +
    + +#### PartyIdType element + +[Table 70](#table-70) below contains the data model for the element `PartyIdType`. + +###### Table 70 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartyIdType** | 1 | Enum of [String(1..32)](#string) | See [PartyIdType](#partyidtype-enum) enumeration for more information on allowed values. | + +**Table 70 – Element PartyIdType** + +
    + +#### PartyName element + +[Table 71](#table-71) below contains the data model for the element `PartyName`. + +###### Table 71 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartyName** | 1 | `Name` | Name of the Party. Could be a real name or a nickname. | + +**Table 71 – Element PartyName** + +
    + +#### PartySubIdOrType element + +[Table 72](#table-72) below contains the data model for the element `PartySubIdOrType`. + +###### Table 72 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **PartySubIdOrType** | 1 | [String(1..128)](#string) | Either a sub-identifier of a [PartyIdentifier](#partyidentifier-element), or a sub-type of the [PartyIdType](#partyidtype-element), normally a `PersonalIdentifierType`. | + +**Table 72 – Element PartySubIdOrType** + +
    + +#### RefundReason element + +[Table 73](#table-73) below contains the data model for the element `RefundReason`. + +###### Table 73 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **RefundReason** | 1 | [String(1..128)](#string) | Reason for the refund. | + +**Table 73 – Element RefundReason** + +
    + +#### TransactionInitiator element + +[Table 74](#table-74) below contains the data model for the element `TransactionInitiator`. + +###### Table 74 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionInitiator** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionInitiator](#transactioninitiator-enum) enumeration for more information on allowed values. | + +**Table 74 – Element TransactionInitiator** + +
    + +#### TransactionInitiatorType element + +[Table 75](#table-75) below contains the data model for the element `TransactionInitiatorType`. + +###### Table 75 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionInitiatorType** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionInitiatorType](#transactioninitiatortype-enum) enumeration for more information on allowed values. | + +**Table 75 – Element TransactionInitiatorType** + +
    + +#### TransactionRequestState element + +[Table 76](#table-76) below contains the data model for the element `TransactionRequestState`. + +###### Table 76 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionRequestState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionRequestState](#transactionrequeststate-enum) enumeration for more information on allowed values. | + + +**Table 76 – Element TransactionRequestState** + +
    + +#### TransactionScenario element + +[Table 77](#table-77) below contains the data model for the element `TransactionScenario`. + +###### Table 77 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionScenario** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionScenario](#transactionscenario-enum) enumeration for more information on allowed values. | + +**Table 77 – Element TransactionScenario** + +
    + +#### TransactionState element + +[Table 78](#table-78) below contains the data model for the element `TransactionState`. + +###### Table 78 + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransactionState](#transactionstate-enum) enumeration for more information on allowed values. | + +**Table 78 – Element TransactionState** + +
    + + +#### TransactionSubScenario element + +[Table 79](#table-79) below contains the data model for the element `TransactionSubScenario`. + +###### Table 79 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionSubScenario** | 1 | [UndefinedEnum](#undefinedenum) | Possible sub-scenario, defined locally within the scheme.| + +**Table 79 – Element TransactionSubScenario** + +
    + +#### TransferState element + +[Table 80](#table-80) below contains the data model for the element `TransferState`. + +###### Table 80 + +|Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| **TransactionState** | 1 | [Enum](#enum) of [String(1..32)](#string) | See [TransferState](#transferstate-enum) enumeration for more information on allowed values. | + +**Table 80 – Element TransferState** + + +
    + + +### Complex Types + +This section describes complex types used by the API. + +#### AuthenticationInfo + +[Table 81](#table-81) contains the data model for the complex type `AuthenticationInfo`. + +###### Table 81 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **authentication** | 1 | `AuthenticationType` | Type of authentication. | +| **authenticationValue** | 1 | `AuthenticationValue` | Authentication value. | + +**Table 81 -- Complex type AuthenticationInfo** + +
    + +#### ErrorInformation + +[Table 82](#table-82) contains the data model for the complex type `ErrorInformation`. + +###### Table 82 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **errorCode** | 1 | `Errorcode` | Specific error number. | +| **errorDescription** | 1 | `ErrorDescription` | Error description string. | +| **extensionList** | 1 | `ExtensionList` | Optional list of extensions, specific to deployment. | + +**Table 82 -- Complex type ErrorInformation** + +
    + +#### Extension + +[Table 83](#table-83) contains the data model for the complex type `Extension`. + +###### Table 83 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **key** | 1 | `ExtensionKey` | Extension key. | +| **value** | 1 | `ExtensionValue` | Extension value. | + +**Table 83 -- Complex type Extension** + +
    + +#### ExtensionList + +[Table 84](#table-84) contains the data model for the complex type `ExtensionList`. + +###### Table 84 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **extension** | 1..16 | `Extension` | Number of Extension elements. | + +**Table 84 -- Complex type ExtensionList** + +
    + +#### IndividualQuote + +[Table 85](#table-85) contains the data model for the complex type `IndividualQuote`. + +###### Table 85 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **quoteId** | 1 | `CorrelationId` | Identifies quote message. | +| **transactionId** | 1 | `CorrelationId` | Identifies transaction message. | +| **payee** | 1 | `Party` | Information about the Payee in the proposed financial transaction. | +| **amountType** | 1 | `AmountType` | **SEND** for sendAmount, **RECEIVE** for receiveAmount. | +| **amount** | 1 | `Money` | Depending on **amountType**:
    If **SEND**: The amount the Payer would like to send; that is, the amount that should be withdrawn from the Payer account including any fees. The amount is updated by each participating entity in the transaction.
    If **RECEIVE**: The amount the Payee should receive; that is, the amount that should be sent to the receiver exclusive any fees. The amount is not updated by any of the participating entities. | +| **fees** | 0..1 | `Money` | Fees in the transaction.
    • The fees element should be empty if fees should be non-disclosed.
    • The fees element should be non-empty if fees should be disclosed.
    +| **transactionType** | 1 | `TransactionType` | Type of transaction that the quote is requested for. | +| **note** | 0..1 | Note | Memo that will be attached to the transaction.| +| **extensionList** | 0..1 | `ExtensionList` | Optional extension, specific to deployment. | + +**Table 85 -- Complex type IndividualQuote** + +
    + +#### IndividualQuoteResult + +[Table 86](#table-86) contains the data model for the complex type `IndividualQuoteResult`. + +###### Table 86 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **quoteId** | 1 | `CorrelationId` | Identifies the quote message. | +| **payee** | 0..1 | `Party` | Information about the Payee in the proposed financial transaction. | +| **transferAmount** | 0..1 | `Money` | The amount of Money that the Payer FSP should transfer to the Payee FSP. | +| **payeeReceiveAmount** | 0..1 | `Money` | Amount that the Payee should receive in the end-to-end transaction. Optional as the Payee FSP might not want to disclose any optional Payee fees. | +| **payeeFspFee** | 0..1 | `Money` | Payee FSP’s part of the transaction fee. | +| **payeeFspCommission** | 0..1 | `Money` | Transaction commission from the Payee FSP. | +| **ilpPacket** | 0..1 | `IlpPacket` | ILP Packet that must be attached to the transfer by the Payer. | +| **condition** | 0..1 | `IlpCondition` | Condition that must be attached to the transfer by the Payer. | +| **errorInformation** | 0..1 | `ErrorInformation` | Error code, category description.
    **Note: payee, transferAmount, payeeReceiveAmount, payeeFspFee, payeeFspCommission, ilpPacket,** and **condition** should not be set if **errorInformation** is set.
    +| **extensionList** | 0..1 | `ExtensionList` | Optional extension, specific to deployment | + +**Table 86 -- Complex type IndividualQuoteResult** + +
    + +#### IndividualTransfer + +[Table 87](#table-87) contains the data model for the complex type `IndividualTransfer`. + +###### Table 87 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **transferId** | 1 | `CorrelationId` | Identifies messages related to the same **/transfers** sequence. | +| **transferAmount** | 1 | `Money` | Transaction amount to be sent. | +| **ilpPacket** | 1 | `IlpPacket` | ILP Packet containing the amount delivered to the Payee and the ILP Address of the Payee and any other end-to-end data. | +| **condition** | 1 | `IlpCondition` | Condition that must be fulfilled to commit the transfer. | +| **extensionList** | 0..1 | `ExtensionList` | Optional extension, specific to deployment. | + +**Table 87 -- Complex type IndividualTransfer** + +
    + +#### IndividualTransferResult + +[Table 88](#table-88) contains the data model for the complex type `IndividualTransferResult`. + +###### Table 88 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **transferId** | 1 | `CorrelationId` | Identifies messages related to the same /transfers sequence. | +| **fulfilment** | 0..1 | `IlpFulfilment` | Fulfilment of the condition specified with the transaction.
    **Note:** Either **fulfilment** or **errorInformation** should be set, not both. | +| **errorInformation** | 0..1 | `ErrorInformation` | If transfer is REJECTED, error information may be provided.
    **Note:** Either **fulfilment** or **errorInformation** should be set, not both.| +| **extensionList** | 0..1 | `ExtensionList` | Optional extension, specific to deployment.| + +**Table 88 -- Complex type IndividualTransferResult** + +
    + +#### GeoCode + +[Table 89](#table-89) contains the data model for the complex type `GeoCode`. + +###### Table 89 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **latitude** | 1 | `Latitude` | Latitude of the Party. | +| **longitude** | 1 | `Longitude` | Longitude of the Party. | + +**Table 89 -- Complex type GeoCode** + +
    + +#### Money + +[Table 90](#table-90) contains the data model for the complex type `Money`. + +###### Table 90 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **currency** | 1 | `Currency` | Currency of the amount. | +| **amount** | 1 | `Amount` | Amount of money. | + +**Table 90 -- Complex type Money** + +
    + +#### Party + +[Table 91](#table-91) contains the data model for the complex type `Party`. + +###### Table 91 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **partyIdInfo** | 1 | `PartyIdInfo` | Party Id type, id, sub ID or type, and FSP Id. | +| **merchantClassificationCode** | 0..1 | `MerchantClassificationCode` | Used in the context of Payee Information, where the Payee happens to be a merchant accepting merchant payments. | +| **name** | 0..1 | `PartyName` | Display name of the Party, could be a real name or a nick name. | +| **personalInfo** | 0..1 | `PartyPersonalInfo` | Personal information used to verify identity of Party such as first, middle, last name and date of birth. | + +**Table 91 -- Complex type Party** + +
    + +#### PartyComplexName + +[Table 92](#table-92) contains the data model for the complex type `PartyComplexName`. + +###### Table 92 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **firstName** | 0..1 | `FirstName` | Party's first name. | +| **middleName** | 0..1 | `MiddleName` | Party's middle name. | +| **lastName** | 0..1 | `LastName` | Party's last name. | + +**Table 92 -- Complex type PartyComplexName** + +
    + +#### PartyIdInfo + +[Table 93](#table-93) contains the data model for the complex type `PartyIdInfo`. + +###### Table 93 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **partyIdType** | 1 | `PartyIdType` | Type of the identifier. | +| **partyIdentifier** | 1 | `PartyIdentifier` | An identifier for the Party. | +| **partySubIdOrType** | 0..1 | `PartySubIdOrType` | A sub-identifier or sub-type for the Party. | +| **fspId** | 0..1 | `FspId` | FSP ID (if know) | +| **extensionList** | 0..1 | `ExtensionList` | Optional extension, specific to deployment. | + +**Table 93 -- Complex type PartyIdInfo** + +
    + +#### PartyPersonalInfo + +[Table 94](#table-94) contains the data model for the complex type `PartyPersonalInfo`. + +###### Table 94 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **complexName** | 0..1 | `PartyComplexName` | First, middle and last name for the Party. | +| **dateOfBirth** | 0..1 | `DateOfBirth` | Date of birth for the Party. | + +**Table 94 -- Complex type PartyPersonalInfo** + +
    + +#### PartyResult + +[Table 95](#table-95) contains the data model for the complex type `PartyResult`. + +###### Table 95 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **partyId** | 1 | `PartyIdInfo` | Party Id type, id, sub ID or type, and FSP Id. | +| **errorInformation** | 0..1 | `ErrorInformation` | If the Party failed to be added, error information should be provided. Otherwise, this parameter should be empty to indicate success. | + +**Table 95 -- Complex type PartyResult** + +
    + +#### Refund + +[Table 96](#table-96) contains the data model for the complex type `Refund`. + +###### Table 96 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **originalTransactionId** | 1 | `CorrelationId` | Reference to the original transaction ID that is requested to be refunded. | +| **refundReason** | 0..1 | `RefundReason` | Free text indicating the reason for the refund. | + +**Table 96 -- Complex type Refund** + +
    + +#### Transaction + +[Table 97](#table-97) contains the data model for the complex type Transaction. The Transaction type is used to carry end-to-end data between the Payer FSP and the Payee FSP in the ILP Packet, see [IlpPacket](#ilp-packet). Both the **transactionId** and the **quoteId** in the data model is decided by the Payer FSP in the [POST /quotes](#post-quotes), see [Table 23](#table-23). + +###### Table 97 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **transactionId** | 1 | `CorrelationId` | ID of the transaction, the ID is decided by the Payer FSP during the creation of the quote. | +| **quoteId** | 1 | `CorrelationId` | ID of the quote, the ID is decided by the Payer FSP during the creation of the quote. | +| **payee** | 1 | `Party` | Information about the Payee in the proposed financial transaction. | +| **payer** | 1 | `Party` | Information about the Payer in the proposed financial transaction. | +| **amount** | 1 | `Money` | Transaction amount to be sent. | +| **transactionType** | 1 | `TransactionType` | Type of the transaction. | +| **note** | 0..1 | `Note` | Memo associated to the transaction, intended to the Payee. | +| **extensionList** | 0..1 | `ExtensionList` | Optional extension, specific to deployment. | + +**Table 97 -- Complex type Transaction** + +
    + +#### TransactionType + +[Table 98](#table-98) contains the data model for the complex type `TransactionType`. + +###### Table 98 + +| **Name** | **Cardinality** | **Format** | **Description** | +| --- | --- | --- | --- | +| **scenario** | 1 | `TransactionScenario` | Deposit, withdrawal, refund, ... | +| **subScenario** | 0..1 | `TransactionSubScenario` | Possible sub-scenario, defined locally within the scheme. | +| **initiator** | 1 | `TransactionInitiator` | Who is initiating the transaction: Payer or Payee | +| **initiatorType** | 1 | `TransactionInitiatorType` | Consumer, agent, business, ... | +| **refundInfo** | 0..1 | `Refund` | Extra information specific to a refund scenario. Should only be populated if scenario is REFUND. | +| **balanceOfPayments** | 0..1 | `BalanceOfPayments` | Balance of Payments code. | + +**Table 98 -- Complex type TransactionType** + +
    + +### Enumerations + +This section contains the enumerations that are used by the API. + +#### AmountType enum + +[Table 99](#table-99) contains the allowed values for the enumeration `AmountType`. + +###### Table 99 + +| **Name** | **Description** | +| --- | --- | +| **SEND** | Amount the Payer would like to send; that is, the amount that should be withdrawn from the Payer account including any fees. | +| **RECEIVE** | Amount the Payer would like the Payee to receive; that is, the amount that should be sent to the receiver exclusive fees. | + +**Table 99 -- Enumeration AmountType** + +
    + +#### AuthenticationType enum + +[Table 100](#table-100) contains the allowed values for the enumeration `AuthenticationType`. + +###### Table 100 + +| **Name** | **Description** | +| --- | --- | +| **OTP** | One-time password generated by the Payer FSP. | +| **QRCODE** | QR code used as One Time Password. | + +**Table 100 -- Enumeration AuthenticationType** + +
    + +#### AuthorizationResponse enum + +[Table 101](#table-101) contains the allowed values for the enumeration `AuthorizationResponse`. + +###### Table 101 + +| **Name** | **Description** | +| --- | --- | +| **ENTERED** | Consumer entered the authentication value. | +| **REJECTED** | Consumer rejected the transaction. | +| **RESEND** | Consumer requested to resend the authentication value. | + +**Table 101 -- Enumeration AuthorizationResponse** + +
    + +#### BulkTransferState enum + +[Table 102](#table-102) contains the allowed values for the enumeration `BulkTransferState`. + +###### Table 102 + +| **Name** | **Description** | +| --- | --- | +| **RECEIVED** | Payee FSP has received the bulk transfer from the Payer FSP. | +| **PENDING** | Payee FSP has validated the bulk transfer. | +| **ACCEPTED** | Payee FSP has accepted the bulk transfer for processing. | +| **PROCESSING** | Payee FSP has started to transfer fund to the Payees. | +| **COMPLETED** | Payee FSP has completed transfer of funds to the Payees. | +| **REJECTED** | Payee FSP has rejected processing the bulk transfer. | + +**Table 102 -- Enumeration BulkTransferState** + +
    + +#### CurrencyCode enum + +The currency codes defined in ISO 421736 as three-letter alphabetic codes are used as the standard naming representation for currencies. The currency codes from ISO 4217 are not shown in this document, implementers are instead encouraged to use the information provided by the ISO 4217 standard directly. + +
    + +#### PartyIdType enum + +[Table 103](#Table-103) contains the allowed values for the enumeration `PartyIdType`. + +###### Table 103 + +| **Name** | **Description** | +| --- | --- | +| **MSISDN** | An MSISDN (Mobile Station International Subscriber Directory Number; that is, a phone number) is used in reference to a Party. The MSISDN identifier should be in international format according to the ITU-T E.16437 standard. Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix. | +| **EMAIL** | An email is used in reference to a Party. The format of the email should be according to the informational RFC 369638. | +| **PERSONAL_ID** | A personal identifier is used in reference to a participant. Examples of personal identification are passport number, birth certificate number, and national registration number. The identifier number is added in the [PartyIdentifier](#partyidentifier-element) element. The personal identifier type is added in the [PartySubIdOrType](#partysubidortype-element) element. | +| **BUSINESS** | A specific Business (for example, an organization or a company) is used in reference to a participant. The BUSINESS identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the [PartySubIdOrType](#partysubidortype-element) element should be used. | +| **DEVICE** | A specific device (for example, POS or ATM) ID connected to a specific business or organization is used in reference to a Party. For referencing a specific device under a specific business or organization, use the [PartySubIdOrType](#partysubidortype-element) element. | +| **ACCOUNT_ID** | A bank account number or FSP account ID should be used in reference to a participant. The ACCOUNT_ID identifier can be in any format, as formats can greatly differ depending on country and FSP. +| **IBAN** | A bank account number or FSP account ID is used in reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without whitespace. | +| **ALIAS** | An alias is used in reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias is a username in the FSP system. The ALIAS identifier can be in any format. It is also possible to use the [PartySubIdOrType](#partysubidortype-element) element for identifying an account under an Alias defined by the [PartyIdentifier](#partyidentifier-element). | + +**Table 103 -- Enumeration PartyIdType** + +
    + +#### PersonalIdentifierType enum + +[Table 104](#table-104) contains the allowed values for the enumeration `PersonalIdentifierType`. + +###### Table 104 + +| **Name** | **Description** | +| --- | --- | +| **PASSPORT** | A passport number is used in reference to a Party. | +| **NATIONAL_REGISTRATION** | A national registration number is used in reference to a Party. | +| **DRIVING_LICENSE** | A driving license is used in reference to a Party. | +| **ALIEN_REGISTRATION** | An alien registration number is used in reference to a Party. | +| **NATIONAL_ID_CARD** | A national ID card number is used in reference to a Party. | +| **EMPLOYER_ID** | A tax identification number is used in reference to a Party. | +| **TAX_ID_NUMBER** | A tax identification number is used in reference to a Party. | +| **SENIOR_CITIZENS_CARD** | A senior citizens card number is used in reference to a Party. | +| **MARRIAGE_CERTIFICATE** | A marriage certificate number is used in reference to a Party. | +| **HEALTH_CARD** | A health card number is used in reference to a Party. | +| **VOTERS_ID** | A voter’s identification number is used in reference to a Party. | +| **UNITED_NATIONS** | An UN (United Nations) number is used in reference to a Party. | +| **OTHER_ID** | Any other type of identification type number is used in reference to a Party. | + +**Table 104 -- Enumeration PersonalIdentifierType** + +
    + +#### TransactionInitiator + +[Table 105](#table-105) describes valid values for the enumeration `TransactionInitiator`. + +###### Table 105 + +| **Name** | **Description** | +| --- | --- | +| **PAYER** | Sender of funds is initiating the transaction. The account to send from is either owned by the Payer or is connected to the Payer in some way. | +| **PAYEE** | Recipient of the funds is initiating the transaction by sending a transaction request. The Payer must approve the transaction, either automatically by a pre-generated OTP or by pre-approval of the Payee, or manually by approving on their own Device. | + +**Table 105 -- Enumeration TransactionInitiator** + +
    + +#### TransactionInitiatorType + +[Table 106](#table-106) contains the allowed values for the enumeration `TransactionInitiatorType`. + +###### Table 106 + +| **Name** | **Description** | +| --- | --- | +| **CONSUMER ** | Consumer is the initiator of the transaction. | +| **AGENT** | Agent is the initiator of the transaction. | +| **BUSINESS** | Business is the initiator of the transaction. | +| **DEVICE** | Device is the initiator of the transaction. | + +**Table 106 -- Enumeration TransactionInitiatorType** + +
    + +#### TransactionRequestState + +[Table 107](#table-107) contains the allowed values for the enumeration `TransactionRequestState`. + +###### Table 107 + +| **Name** | **Description** | +| --- | --- | +| **RECEIVED** | Payer FSP has received the transaction from the Payee FSP. | +| **PENDING** | Payer FSP has sent the transaction request to the Payer. | +| **ACCEPTED** | Payer has approved the transaction. | +| **REJECTED** | Payer has rejected the transaction. | + +**Table 107 -- Enumeration TransactionRequestState** + +
    + +#### TransactionScenario + +[Table 108](#table-108) contains the allowed values for the enumeration `TransactionScenario`. + +###### Table 108 + +| **Name** | **Description** | +| --- | --- | +| **DEPOSIT** | Used for performing a Cash-In (deposit) transaction. In a normal scenario, electronic funds are transferred from a Business account to a Consumer account, and physical cash is given from the Consumer to the Business User. | +| **WITHDRAWAL** | Used for performing a Cash-Out (withdrawal) transaction. In a normal scenario, electronic funds are transferred from a Consumer’s account to a Business account, and physical cash is given from the Business User to the Consumer. | +| **TRANSFER** | Used for performing a P2P (Peer to Peer, or Consumer to Consumer) transaction. | +| **PAYMENT** | Usually used for performing a transaction from a Consumer to a Merchant or Organization, but could also be for a B2B (Business to Business) payment. The transaction could be online for a purchase in an Internet store, in a physical store where both the Consumer and Business User are present, a bill payment, a donation, and so on. | +| **REFUND** | Used for performing a refund of transaction. | + +**Table 108 -- Enumeration TransactionScenario** + +
    + +#### TransactionState + +[Table 109](#table-109) contains the allowed values for the enumeration `TransactionState`. + +###### Table 109 + +| **Name** | **Description** | +| --- | --- | +| **RECEIVED** | Payee FSP has received the transaction from the Payer FSP. | +| **PENDING** | Payee FSP has validated the transaction. | +| **COMPLETED** | Payee FSP has successfully performed the transaction. | +| **REJECTED** | Payee FSP has failed to perform the transaction. | + +**Table 109 -- Enumeration TransactionState** + +
    + +#### TransferState + +[Table 110](#table-110) contains the allowed values for the enumeration `TransferState`. + +###### Table 110 + +| **Name** | **Description** | +| --- | --- | +| **RECEIVED** | Next ledger has received the transfer. | +| **RESERVED** | Next ledger has reserved the transfer. | +| **COMMITTED** | Next ledger has successfully performed the transfer. | +| **ABORTED** | Next ledger has aborted the transfer due a rejection or failure to perform the transfer. | + +**Table 110 -- Enumeration TransferState** + +
    + +### Error Codes + +###### Figure 63 + +Each error code in the API is a four-digit number, for example, **1234**, where the first number (**1** in the example) represents the high-level error category, the second number (**2** in the example) represents the low-level error category, and the last two numbers (**34** in the example) represents the specific error. [Figure 63](#figure-63) shows the structure of an error code. The following sections contain information about defined error codes for each high-level error category. + +![Figure 63](/assets/diagrams/images/figure63.svg) + +**Figure 63 -- Error code structure** + +Each defined high- and low-level category combination contains a generic error (_x_**0**_xx_), which can be used if there is no specific error, or if the server would not like to return information which is considered private. + +All specific errors below _xx_**40**; that is, _xx_**00** to _xx_**39**, are reserved for future use by the API. All specific errors above and including _xx_**40** can be used for scheme-specific errors. If a client receives an unknown scheme-specific error, the unknown scheme-specific error should be interpreted as a generic error for the high- and low-level category combination instead (_xx_**00**). + +#### Communication Errors -- 1_xxx_ + +All possible communication or network errors that could arise that cannot be represented by an HTTP status code should use the high-level error code **1** (error codes **1**_xxx_). Because all services in the API are asynchronous, these error codes should generally be used by a Switch in the Callback to the client FSP if the Peer FSP cannot be reached, or when a callback is not received from the Peer FSP within an agreed timeout. + +Low level categories defined under Communication Errors: + +- **Generic Communication Error** -- **10**_xx_ + +See [Table 111](#table-111) for all communication errors defined in the API. + +###### Table 111 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **1000** | Communication error | Generic communication error. | X | X | X | X | X | X | X | X | X | +| **1001** | Destination communication error | Destination of the request failed to be reached. This usually indicates that a Peer FSP failed to respond from an intermediate entity. | X | X | X | X | X | X | X | X | X | + +**Table 111 -- Communication errors -- 1_xxx_** + +#### Server Errors -- 2_xxx_ + +All possible errors occurring on the server in which it failed to fulfil an apparently valid request from the client should use the high-level error code **2** (error codes **2**_xxx_). These error codes should indicate that the server is aware that it has encountered an error or is otherwise incapable of performing the requested service. + +Low-level categories defined under server errors: + +- **Generic server error** -- **20**_xx_ + +See [Table 112](#Table-112) for server errors defined in the API. + +###### Table 112 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **2000** | Generic server error | Generic server error to be used in order not to disclose information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **2001** | Internal server error | Generic unexpected exception. This usually indicates a bug or unhandled error case. | X | X | X | X | X | X | X | X | X | +| **2002** | Not implemented | Service requested is not supported by the server. | X | X | X | X | X | X | X | X | X | +| **2003** | Service currently unavailable | Service requested is currently unavailable on the server. This could be because maintenance is taking place, or because of a temporary failure. | X | X | X | X | X | X | X | X | X | +| **2004** | Server timed out | Timeout has occurred, meaning the next Party in the chain did not send a callback in time. This could be because a timeout is set too low or because something took longer than expected. | X | X | X | X | X | X | X | X | X | +| **2005** | Server busy | Server is rejecting requests due to overloading. Try again later. | X | X | X | X | X | X | X | X | X | + +**Table 112 -- Server errors -- 2_xxx_** + +#### Client Errors -- 3_xxx_ + +All possible errors occurring on the server in which the server reports that the client has sent one or more erroneous parameters should use the high-level error code **3** (error codes **3**_xxx_). These error codes should indicate that the server could not perform the service according to the request from the client. The server should provide an explanation why the service could not be performed. + +Low level categories defined under client Errors: + +- **Generic Client Error** -- **30**_xx_ + + - See [Table 113](#table-113) for generic client errors defined in the API. + +- **Validation Error** -- **31**_xx_ + + - See [Table 114](#table-114) the validation errors defined in the API. + +- **Identifier Error** -- **32**_xx_ + + - See [Table 115](#table-115) for identifier errors defined in the API. + +- **Expired Error** -- **33**_xx_ + + - See [Table 116](#table-116) for expired errors defined in the API. + +###### Table 113 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **3000** | Generic client error | Generic client error, used in order not to disclose information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **3001** | Unacceptable version requested | Client requested to use a protocol version which is not supported by the server. | X | X | X | X | X | X | X | X | X | +| **3002** | Unknown URI | Provided URI was unknown to the server. | X | X | X | X | X | X | X | X | X | +| **3003** | Add Party information error | Error occurred while adding or updating information regarding a Party. | X | X | X | X | X | X | X | X | X | + +**Table 113 -- Generic client errors -- 30_xx_** + +###### Table 114 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **3100** | Generic validation error | Generic validation error to be used in order not to disclose information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **3101** | Malformed syntax | Format of the parameter is not valid. For example, amount set to **5.ABC**. The error description field should specify which information element is erroneous. | X | X | X | X | X | X | X | X | X | +| **3102** | Missing mandatory element | Mandatory element in the data model was missing. | X | X | X | X | X | X | X | X | X | +| **3103** | Too many elements | Number of elements of an array exceeds the maximum number allowed. | X | X | X | X | X | X | X | X | X | +| **3104** | Too large payload | Size of the payload exceeds the maximum size. | X | X | X | X | X | X | X | X | X | +| **3105** | Invalid signature | Some parameters have changed in the message, making the signature invalid. This may indicate that the message may have been modified maliciously. | X | X | X | X | X | X | X | X | X | +| **3106** | Modified request | Request with the same ID has previously been processed in which the parameters are not the same. ||| X | X | X | X | X | X | X | +| **3107** | Missing mandatory extension parameter | Scheme-mandatory extension parameter was missing. ||| X | X | X | X | X | X | X | + +**Table 114 -- Validation errors -- 31_xx_** + +###### Table 115 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **3200** | Generic ID not found | Generic ID error provided by the client. | X | X | X | X | X | X | X | X | X | +| **3201** | Destination FSP Error | Destination FSP does not exist or cannot be found. | X | X | X | X | X | X | X | X | X | +| **3202** | Payer FSP ID not found |Provided Payer FSP ID not found. |||||| X ||| X | +| **3203** | Payee FSP ID not found |Provided Payee FSP ID not found. |||||| X ||| X | +| **3204** | Party not found |Party with the provided identifier, identifier type, and optional sub id or type was not found. | X | X | X | X |||||| +| **3205** | Quote ID not found |Provided Quote ID was not found on the server. |||| X || X |||| +| **3206** | Transaction request ID not found |Provided Transaction Request ID was not found on the server. ||| X ||| X |||| +| **3207** | Transaction ID not found |Provided Transaction ID was not found on the server. ||||||| X ||| +| **3208** | Transfer ID not found |Provided Transfer ID was not found on the server. |||||| X |||| +| **3209** | Bulk quote ID not found |Provided Bulk Quote ID was not found on the server. |||||||| X | X | +| **3210** | Bulk transfer ID not found |Provided Bulk Transfer ID was not found on the server. ||||||||| X | + +**Table 115 -- Identifier errors -- 32_xx_** + +###### Table 116 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **3300** | Generic expired error | Generic expired object error, to be used in order not to disclose information that may be considered private. | X | X | X | X | X | X | X | X | X | +| **3301** | Transaction request expired | Client requested to use a transaction request that has already expired. |||| X |||||| +| **3302** | Quote expired | Client requested to use a quote that has already expired. ||||| X | X ||| X | +| **3303** | Transfer expired | Client requested to use a transfer that has already expired. | X | X | X | X | X | X | X | X | X | + +**Table 116 -- Expired errors -- 33_xx_** + +#### Payer Errors -- 4_xxx_ + +All errors occurring on the server for which the Payer or the Payer FSP is the cause of the error should use the high-level error code **4** (error codes **4**_xxx_). These error codes indicate that there was no error on the server or in the request from the client, but the request failed for a reason related to the Payer or the Payer FSP. The server should provide an explanation why the service could not be performed. + +Low level categories defined under Payer Errors: + +- **Generic Payer Error** -- **40**_xx_ + +- **Payer Rejection Error** -- **41**_xx_ + +- **Payer Limit Error** -- **42**_xx_ + +- **Payer Permission Error** -- **43**_xx_ + +- **Payer Blocked Error** -- **44**_xx_ + +See [Table 117](#table-117) for Payer errors defined in the API. + +###### Table 117 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **4000** | Generic Payer error | Generic error related to the Payer or Payer FSP. Used for protecting information that may be considered private. ||| X | X | X | X | X | X | X | +| **4001** | Payer FSP insufficient liquidity | Payer FSP has insufficient liquidity to perform the transfer. |||||| X |||| +| **4100** | Generic Payer rejection | Payer or Payer FSP rejected the request. ||| X | X | X | X | X | X | X | +| **4101** | Payer rejected transaction request | Payer rejected the transaction request from the Payee. ||| X ||||||| +| **4102** | Payer FSP unsupported transaction type |Payer FSP does not support or rejected the requested transaction type ||| X ||||||| +| **4103** | Payer unsupported currency | Payer does not have an account which supports the requested currency. ||| X ||||||| +| **4200** | Payer limit error | Generic limit error, for example, the Payer is making more payments per day or per month than they are allowed to, or is making a payment which is larger than the allowed maximum per transaction. ||| X | X || X || X | X | +| **4300** | Payer permission error | Generic permission error, the Payer or Payer FSP does not have the access rights to perform the service. ||| X | X | X | X | X | X | X | +| **4400** | Generic Payer blocked error | Generic Payer blocked error; the Payer is blocked or has failed regulatory screenings. ||| X | X | X | X | X | X | X | + +**Table 117 -- Payer errors -- 4_xxx_** + +#### Payee Errors -- 5_xxx_ + +All errors occurring on the server for which the Payee or the Payee FSP is the cause of an error use the high-level error code **5** (error codes **5**_xxx_). These error codes indicate that there was no error on the server or in the request from the client, but the request failed for a reason related to the Payee or the Payee FSP. The server should provide an explanation why the service could not be performed. + +Low level categories defined under Payee Errors: + +- **Generic Payee Error** -- **50**_xx_ + +- **Payee Rejection Error** -- **51**_xx_ + +- **Payee Limit Error** -- **52**_xx_ + +- **Payee Permission Error** -- **53**_xx_ + +- **Payee Blocked Error** -- **54**_xx_ + +See [Table 118](#table-118) for all Payee errors defined in the API. + +###### Table 118 + +| **Error Code** | **Name** | **Description** | /participants | /parties | /transactionRequests | /quotes | /authorizations | /transfers | /transactions | /bulkQuotes | /bulkTransfers | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **5000** | Generic Payee error | Generic error due to the Payer or Payer FSP, to be used in order not to disclose information that may be considered private. ||| X | X | X | X | X | X | X | +| **5001** | Payee FSP insufficient liquidity | Payee FSP has insufficient liquidity to perform the transfer. |||||| X |||| +| **5100** | Generic Payee rejection | Payee or Payee FSP rejected the request. ||| X | X | X | X | X | X | X | +| **5101** | Payee rejected quote | Payee does not want to proceed with the financial transaction after receiving a quote. |||| X |||| X || +| **5102** | Payee FSP unsupported transaction type | Payee FSP does not support or has rejected the requested transaction type |||| X ||||| X | +| **5103** | Payee FSP rejected quote | Payee FSP does not want to proceed with the financial transaction after receiving a quote. |||| X |||| X || +| **5104** | Payee rejected transaction | Payee rejected the financial transaction. |||||| X ||| X | +| **5105** | Payee FSP rejected transaction | Payee FSP rejected the financial transaction. |||||| X ||| X | +| **5106** | Payee unsupported currency | Payee does not have an account that supports the requested currency. |||| X || X || X | X | +| **5200** | Payee limit error | Generic limit error, for example, the Payee is receiving more payments per day or per month than they are allowed to, or is receiving a payment that is larger than the allowed maximum per transaction. ||| X | X || X || X | X | +| **5300** |Payee permission error | Generic permission error, the Payee or Payee FSP does not have the access rights to perform the service. ||| X | X | X | X | X | X | X | +| **5400** | Generic Payee blocked error | Generic Payee Blocked error, the Payee is blocked or has failed regulatory screenings. ||| X | X | X | X | X | X | X | + +**Table 118 -- Payee errors -- 5_xxx_** + + +## Generic Transaction Patterns Binding + +This section provides information about how the logical transaction patterns from [Generic Transaction Patterns](../generic-transaction-patterns) are used in the asynchronous REST binding of the API. Much of the information is provided by way of sequence diagrams. For more information regarding the steps in these diagrams, see [Generic Transaction Patterns](../generic-transaction-patterns). + +### Payer Initiated Transaction + +The `Payer Initiated Transaction` pattern is introduced in [Generic Transaction Patterns](../generic-transaction-patterns#payer-initiated-transaction). On a high-level, the pattern should be used whenever a Payer would like to transfer funds to another Party whom is not located in the same FSP as the Payer. [Figure 64](#figure-64) shows the sequence diagram for a `Payer Initiated Transaction` using the asynchronous REST binding of the logical version. The process for each number in the sequence diagram is described in [Generic Transaction Patterns](../generic-transaction-patterns#payer-initiated-transaction). + +###### Figure 64 + +{% uml src="assets/diagrams/sequence/figure64.plantuml" %} +{% enduml %} + +**Figure 64 -- Payer Initiated Transaction pattern using the asynchronous REST binding** + +### Payee Initiated Transaction + +The `Payee Initiated Transaction` pattern is introduced in [Generic Transaction Patterns](../generic-transaction-patterns#payer-initiated-transaction). On a high-level, the pattern should be used whenever a Payee would like to request that Payer transfer funds to a Payee. The Payer and the Payee are assumed to be in different FSPs, and the approval of the transaction is performed in the Payer FSP. If the transaction information and approval occur on a Payee device instead, use the related Payee Initiated Transaction using OTP](#payee-initiated-transaction-using-otp) instead. [Figure 65](#figure-65) shows the sequence diagram for a `Payee Initiated Transaction` using the asynchronous REST binding of the logical version. The process for each number in the sequence diagram is described in [Generic Transaction Patterns](../generic-transaction-patterns#payee-initiated-transaction). + +###### Figure 65 + +{% uml src="assets/diagrams/sequence/figure65.plantuml" %} +{% enduml %} + +**Figure 65 -- Payee Initiated Transaction pattern using the asynchronous REST binding** + +### Payee Initiated Transaction using OTP + +The `Payee Initiated Transaction using OTP` pattern is introduced in [Generic Transaction Patterns](../generic-transaction-patterns#payee-initiated-transaction-using-otp). On a high-level, this pattern is like the [Payee Initiated Transaction](#payee-initiated-transaction); however, in this pattern the transaction information and approval for the Payer is shown and entered on a Payee device instead. As in other transaction patterns, the Payer and the Payee are assumed to be in different FSPs. [Figure 66](#figure-66) shows the sequence diagram for a `Payee Initiated Transaction using OTP` using the asynchronous REST binding of the logical version. The process for each number in the sequence diagram is described in [Generic Transaction Patterns](../generic-transaction-patterns#payee-initiated-transaction-using-otp). + +###### Figure 66 + +{% uml src="assets/diagrams/sequence/figure66.plantuml" %} +{% enduml %} + +**Figure 66 -- Payee Initiated Transaction using OTP pattern using the asynchronous REST binding** + +### Bulk Transactions + +The `Bulk Transactions` pattern is introduced in [Generic Transaction Patterns](../generic-transaction-patterns#bulk-transactions). On a high-level, the pattern is used whenever a Payer would like to transfer funds to multiple Payees using one single transaction. The Payees can be in different FSPs. [Figure 67](#figure-67) shows the sequence diagram for a `Bulk Transactions` using the asynchronous REST binding of the logical version. The process for each number in the sequence diagram is described in [Generic Transaction Patterns](../generic-transaction-patterns#bulk-transactions). + +###### Figure 67 + +{% uml src="assets/diagrams/sequence/figure67.plantuml" %} +{% enduml %} + +**Figure 67 -- Bulk Transactions pattern using the asynchronous REST binding** + +
    + +## API Error Handling + +This section describes how to handle missing responses or callbacks, as well as how to handle errors in a server during processing of a request. + +### Erroneous Request + +If a server receives an erroneous service request that can be handled immediately (for example, malformed syntax or resource not found), a valid HTTP client error code (starting with **4_xx_**39) should be returned to the client in the response. The HTTP error codes defined in the API appear in [Table 4](#table-4). The HTTP response may also contain an [**ErrorInformation**](#errorinformation) element for the purpose of describing the error in more detail (for more information, see [Error Information in HTTP Response](#error-information-in-http-response)). + +
    + +### Error in Server During Processing of Request + +[Figure 68](#figure-68) shows an example of how to handle an error on a server during processing. + +###### Figure 68 + +{% uml src="assets/diagrams/sequence/figure68.plantuml" %} +{% enduml %} + +**Figure 68 -- Error on server during processing of request** + +#### Internal Processing Steps + +The following list describes the steps in the sequence (see [Figure 68](#figure-68)). + +1. The client would like the server to create a new service object and thus uses a **POST** request. + +2. The server receives the request. It immediately sends an **accepted** response to the client, and then tries to create the object based on the service request. A processing error occurs, and the request cannot be handled as requested. The server sends the callback **_PUT_ /**_{resource}_**/**_{ID}_**/error** including an error code ([Error Codes](#error-codes)) and error description to notify the client of the error. + +3. The client receives the error callback and immediately responds with **OK**. The client then handles the error. + +4. The server receives the **OK** response and the process is completed. + +
    + +### Client Handling on Error Callback + +The following sections explain how a client handles error callbacks from a server. + +#### API Resource /participants + +The typical error from the **/participants** service is that the requested Party could not be found. The client could either try another server, or notify the end user that the requested Party could not be found. + +#### API Resource /parties + +The typical error from the **/parties** service is that the requested Party could not be found. The client could either try another server, or notify the end user that information regarding the requested Party could not be found. + +#### API Resource /quotes + +The typical error from the **/quotes** service is that a quote could not be calculated for the requested transaction. The client should notify the end user that the requested transaction could not be performed. + +#### API Resource /transactionRequests + +The typical error from the **/transactionRequests** service is that the Payer rejected the transaction or that an automatic validation failed. The client should notify the Payee that the transaction request failed. + +#### API Resource /authorizations + +The typical error from the **/authorizations** service is that the transaction request could not be found. The client should notify the Payer that the transaction request has been cancelled. + +#### API Resource /transfers + +The typical error from the **/transfers** service is that either the hop-to-hop transfer process or the end-to-end financial transaction failed. For example, a limit breach was discovered, or the Payee could not be found. The client (the Payer FSP) should in any error case cancel the reservation for the financial transaction that was performed before requesting the transaction to be performed on the server (the Payee FSP). See [Figure 69](#figure-69) for an example including a financial Switch between the FSPs. + +###### Figure 69 + +{% uml src="assets/diagrams/sequence/figure69.plantuml" %} +{% enduml %} + +**Figure 69 -- Handling of error callback from POST /transfers** + +##### Internal Processing Steps + +The following list provides a detailed description of all the steps in the sequence (see [Figure 69](#figure-69)). + +1. The transfer is reserved from the Payer's account to either a combined Switch account or a Payee FSP account, depending on setup. After the transfer has been successfully reserved, the request [POST /transfers](#post-transfers) is used on the Switch. The transfer is now irrevocable from the Payer FSP. The Payer FSP then waits for an **accepted** response from the Switch. + +2. The Switch receives the request [POST /transfers](#post-transfers) and immediately sends an **accepted** response to the Payer FSP. The Switch then performs all applicable internal transfer validations. If the validations are successful, a transfer is reserved from a Payer FSP account to a Payee FSP account. After the transfer has been successfully reserved, the request [POST /transfers](#post-transfers) is used on the Payee FSP. The transfer is now irrevocable from the Switch. The Switch then waits for an **accepted** response from the Payee FSP. + +3. The Payee FSP receives the [POST /transfers](#post-transfers) and immediately sends an **accepted** response to the Switch. The Payee FSP then performs all applicable internal transaction validations. The validation is assumed to fail at this point, for example, due to a limit breach. The error callback [PUT /transfers/_{ID}_/error](#put-transfers-id-error) is used on the Switch to inform the Payer FSP about the error. The Payee FSP then waits for an **OK** response from the Switch to complete the transfer process. + +4. The Switch receives the error callback [PUT /transfers/_{ID}_/error](#put-transfers-id-error) and immediately responds with an **OK** response. The Switch then cancels the earlier reserved transfer, as it has received an error callback. The Switch will then use the callback [PUT /transfers/_{ID}_/error](#put-transfers-id-error) to the Payer FSP, using the same parameters, and wait for an **OK** response to complete the transfer process. + +5. The Payer FSP receives the callback [PUT /transfers/_{ID}_/error](#put-transfers-id-error) and immediately responds with an **OK** response. The Payer FSP then cancels the earlier reserved transfer because it has received an error callback. + +#### API Resource /transactions + +The normal error case from the **/transactions** service is that the transaction could not be found in the Peer FSP. + +#### API Resource /bulkQuotes + +The typical error from the **/bulkQuotes** service is that a quote could not be calculated for the requested transaction. The client should notify the end user that the requested transaction could not be performed. + +#### API Resource /bulkTransfers + +The typical error case from the **/bulkTransfers** service is that the bulk transaction was not accepted; for example, due to a validation error. The client (the Payer FSP) should in any error case cancel the reservation for the financial transaction that was performed before requesting that the transaction be performed on the server (the Payee FSP). See [Figure 70](#figure-70) for an example including a financial Switch between the FSPs. + +###### Figure 70 + +{% uml src="assets/diagrams/sequence/figure70.plantuml" %} +{% enduml %} + +**Figure 70 -- Handling of error callback from API Service /bulkTransfers** + +##### Internal Processing Steps + +The following list describes the steps in the sequence (see [Figure 70](#figure-70)). + +1. Each individual transfer in the bulk transfer is reserved from the Payer's account to either a combined Switch account or a Payee FSP account, depending on setup. After each transfer has been successfully reserved, the request [POST /bulkTransfers](#post-bulktransfers) is used on the Switch. The bulk transfer is now irrevocable from the Payer FSP. The Payer FSP then waits for an **accepted** response from the Switch. + +2. The Switch receives the request [POST /bulkTransfers](#post-bulktransfers) and immediately sends an **accepted** response to the Payer FSP. The Switch then performs all applicable internal transfer validations. If the validations are successful, each individual transfer is reserved from a Payer FSP account to a Payee FSP account. After the transfers have been successfully reserved, the request [POST /bulkTransfers](#post-bulktransfers) is used on the Payee FSP. The bulk transfer is now irrevocable from the Switch. The Switch then waits for an **accepted** response from the Payee FSP. + +3. The Payee FSP receives [POST /bulkTransfers](#post-bulktransfers) and immediately sends an **accepted** response to the Switch. The Payee FSP then performs all applicable internal bulk transfer validations. The validation is assumed to fail due to some reason; for example, a validation failure that prevents the entire bulk transfer from being performed. The error callback [PUT /bulkTransfers/_{ID}_/error](#put-bulktransfers-id-error) is used on the Switch to inform the Payer FSP about the error. The Payee FSP then waits for an **OK** response from the Switch to complete the bulk transfer process. + +4. The Switch receives the error callback [PUT /bulkTransfers/_{ID}_/error](#put-bulktransfers-id-error) and immediately responds with an **OK** response. The Switch then cancels all the previous reserved transfers, because it has received an error callback. The Switch then uses the callback [PUT /bulkTransfers/_{ID}_/error](#put-bulktransfers-id-error) to the Payer FSP, using the same parameters, and waits for an **OK** response to complete the bulk transfer process. + +5. The Payer FSP receives the callback [PUT /bulkTransfers/_{ID}_/error](#put-bulktransfers-id-error) and immediately responds with an **OK** response. The Payer FSP then cancels all the earlier reserved transfers, as it has received an error callback. + +
    + +### Client Missing Response from Server - Using Resend of Request + +[Figure 71](#figure-71) shows an example UML (Unified Modeling Language) sequence diagram in which a client (FSP or Switch) performs error handling when the client misses a response from a server (Switch or Peer FSP) pertaining to a service request, using resend of the same service request. + +###### Figure 71 + +{% uml src="assets/diagrams/sequence/figure71.plantuml" %} +{% enduml %} + +**Figure 71 -- Error handling from client using resend of request** + +#### Internal Processing Steps + +The following list provides a detailed description of all the steps in the sequence (see [Figure 71](#figure-71)). + +1. The client would like the server to create a new service object. The HTTP request is lost somewhere on the way to the server. + +2. The client notes that no response has been received from the server within a specified timeout. The client resends the service request. + +3. The server receives the resent request. It immediately sends an **accepted** response to the client, and then creates the object in accordance with the service request. + +4. The **accepted** HTTP response from the server is lost on the way to the client, and the client notes that no response has been received from the server within a specified timeout. The client resends the service request. + +5. The server receives the resent request. It immediately sends an **accepted** response to the client, and then notes that the service request is the same as in [Step 3](#figure-70). As the service request is a resend, the server should not create a new object based on the service request. The server sends a callback to notify the client about the object created in [Step 3](#figure-70). + +6. The client receives the callback regarding the created object. The client sends an **OK** HTTP response to the server to complete the process. + +7. The server receives the **OK** HTTP response from the client, completing the process. + +
    + +### Server Missing Response from Client + +A server using the API is not responsible for making sure that a callback is properly delivered to a client. However, it is considered good practice to retry if the server does not receive an **OK** response from the client. + +#### Client Missing Callback - Using GET request + +[Figure 72](#figure-72) is a UML sequence diagram showing how a client (Switch or Peer FSP) would perform error handling in case of no callback from a client (FSP or Switch) within a reasonable time. + +###### Figure 72 + +{% uml src="assets/diagrams/sequence/figure72.plantuml" %} +{% enduml %} + +**Figure 72 -- Error handling from client using GET request** + +#### Internal Processing Steps + +The following list provides a detailed description of all the steps in the sequence (see [Figure 71](#figure-71)). + +1. The client would like the server to create a new service object; a service request is sent. + +2. The server receives the service request. It immediately sends an **accepted** response to the client, and then creates the object based on the service request. The object creation is a long running process; for example, a bulk transfer consisting of numerous financial transactions. + +3. The server notes that no callback has been received from the client within a reasonable time. The client uses a **GET** service request with the ID that was provided in the original service request. + +4. The server receives the **GET** service request. The server sends an accepted HTTP response to the client to notify that the request will be handled. + +5. The client receives the **accepted** HTTP response and waits for the callback, which arrives sometime later; the client sends an **OK** HTTP response and the process is completed. + +6. The server sends the callback to the client containing the requested information, and an **OK** HTTP response is received from the client, which completes the process. + +
    + +## End-to-End Example + +This section contains an end-to-end example in which an account holder is provisioned, and then a P2P Transfer from a Payer located in one FSP to a Payee located in another FSP is performed. The example includes both HTTP requests and responses, HTTP headers, and data models in JSON, but without additional security features of using JWS (see [_Signature_](./signature.md)) and field level encryption using JWE (see [_Encryption_](./encryption.md)). + +### Example Setup + +This section explains the setup of the example. + +#### Nodes + +###### Figure 73 + +The nodes in the end-to-end example in this section are simplified by having only two FSPs, where one FSP is a bank (identifier **BankNrOne**) and the other FSP is a mobile money operator (identifier **MobileMoney**), and one Switch (identifier **Switch**). The Switch also acts as the Account Lookup System (ALS) in this simplified setup (see [Figure 73](#figure-73)). + +![Figure 73](/assets/diagrams/images/figure73.svg) + +**Figure 73 -- Nodes in end-to-end example** + +#### Account Holders + +The account holders in the example are: + +- One account holder in the FSP **BankNrOne** named Mats Hagman. Mats Hagman has a bank account with IBAN number **SE4550000000058398257466**. The currency of the account is USD. + +- One account holder in the FSP **MobileMoney** named Henrik Karlsson. Henrik Karlsson has a mobile money account that is identified by his phone number **123456789**. The currency of the account is USD. + +#### Scenario + +The scenario in the example is that Mats Hagman in FSP **BankNrOne** wants to transfer 100 USD to Henrik Karlsson in the FSP **MobileMoney**. Before Henrik Karlsson can be found by FSP **BankNrOne**, Henrik's FSP **MobileMoney** should provide information to the Switch specifying in which FSP Henrik Karlsson can be found in. The end-to-end flow including all used services can be found in [Other Notes](#other-notes). + +#### Other Notes + +The JSON messages used in the examples are formatted with color coding, indentations, and line breaks for very long lines to simplify the read of the examples. + +Both FSPs are assumed to have a pre-funded Switch account in their respective FSPs. + +### End-to-End Flow + +[Figure 74](#figure-74) shows the end-to-end flow of the entire example, from provisioning of FSP information to the actual transaction. + +###### Figure 74 + +{% uml src="assets/diagrams/sequence/figure74.plantuml" %} +{% enduml %} + +**Figure 74 -- End-to-end flow, from provision of account holder FSP information to a successful transaction** + +### Provision Account Holder + +Before the Payee Henrik Karlsson can be found by the Payer FSP **BankNrOne**, Henrik Karlsson should be provisioned to the ALS, which is also the Switch in this simplified example, by Henrik's FSP (**MobileMoney**). This is performed through either one of the services [**POST /participants**](#6232-post-participants) (bulk version) or [POST /participants/_{Type}_/_{ID}_](#post-participants-type-id) (single version). As the Payee in this example is only one (Henrik Karlsson), the single [POST /participants/_{Type}_/_{ID}_](#post-participants-type-id) version is used by FSP **MobileMoney**. The provision could happen anytime, for example when Henrik Karlsson signed up for the financial account, or when the FSP **MobileMoney** connected to the Switch for the first time. + +#### FSP MobileMoney Provisions Henrik Karlsson: Step 1 in End-to-End Flow + +[Listing 29](#listing-29) shows the HTTP request where the FSP **MobileMoney** provisions FSP information for account holder Henrik Karlsson, identified by **MSISDN** and **123456789** (see [Party Addressing](#party-addressing) for more information). The JSON element **fspId** is set to the FSP identifier (MobileMoney), and JSON element **currency** is set to the currency of the account (USD). + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, +and [POST /participants/_{Type}_/_{ID}_](#post-participants-type-id) for more information about the service ). **More** information regarding routing of requests using **FSPIOP-Destination** and **FSPIOP-Source** can be found in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). Information about API version negotiation can be found in [Version Negotiation between Client and Server](#version-negotiation-between-client-and-server). + +###### Listing 29 + +``` +POST /participants/MSISDN/123456789 HTTP/1.1 +Accept: application/vnd.interoperability.participants+json;version=1 +Content-Length: 50 +Content-Type: +application/vnd.interoperability.participants+json;version=1.0 +Date: Tue, 14 Nov 2017 08:12:31 GMT +FSPIOP-Source: MobileMoney +FSPIOP-Destination: Switch +{ + "fspId": "MobileMoney", + "currency": "USD" +} +``` + +**Listing 29 -- Provision FSP information for account holder Henrik Karlsson** + +[Listing 30](#listing-30) shows the synchronous HTTP response where the Switch immediately (after basic verification of for example required headers) acknowledges the HTTP request in [Listing 29](#listing-29). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 30 + +``` +HTTP/1.1 202 Accepted +Content-Type: +application/vnd.interoperability.participants+json;version=1.0 +``` + +**Listing 30 -- Synchronous response on provision request** + +
    + +#### Switch Handles Provision: Step 2 in End-to-End Flow + +When the Switch has received the HTTP request in [Listing 29](#listing-29) and sent the synchronous response in [Listing 30](#listing-30), the Switch should verify the body of the request in [Listing 29](#listing-29). An example verification is to check that the **fspId** element is the same as the **FSPIOP-Source** , as it should be the FSP of the account holder who provisions the information. A scheme could also have restrictions on which currencies are allowed, which means that the Switch should then check that the currency in the **currency** element is allowed. + +After the Switch has verified the request correctly, the information that the account holder identified by **MSISDN** and **123456789** is located in FSP **MobileMoney** should be stored in the Switch's database. + +
    + +#### Switch Sends Successful Callback: Step 3 in End-to-End Flow + +When the Switch has successfully stored the information that the account holder identified by **MSISDN** and **123456789** is located in FSP **MobileMoney**, the Switch must send a callback using the service [PUT /participants/_{Type}_/_{ID}_](#put-participants-type-id) to notify the FSP **MobileMoney** about the outcome of the request in [Listing 29](#listing-29). [Listing 31](#listing-31) shows the HTTP request for the callback. + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request. In the callback, the **Accept** header should not be used as this is a callback to an earlier requested service. The HTTP headers **FSPIOP-Destination** and **FSPIOP-Source** are now inverted compared to the HTTP request in [Listing 29](#listing-29), as detailed in the section on [PUT /participants/_{Type}_/_{ID}_](#put-participants-type-id). + +###### Listing 31 + +``` +PUT /participants/MSISDN/123456789 HTTP/1.1 +Content-Length: 50 +Content-Type: +Date: Tue, 14 Nov 2017 08:12:32 GMT +FSPIOP-Source: MobileMoney +FSPIOP-Destination: Switch +{ + "fspId": "MobileMoney", + "currency": "USD" +} +``` + +**Listing 31 -- Callback for the earlier requested provision service** + +[Listing 32](#listing-32) shows the synchronous HTTP response where the FSP **MobileMoney** immediately (after basic verification of for example required headers) acknowledges the completion of the process, after receiving the callback in [Listing 31](#listing-31). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 32 + +``` +HTTP/1.1 200 OK +Content-Type: +application/vnd.interoperability.participants+json;version=1.0 +``` + +**Listing 32 -- Synchronous response for the callback** + +
    + +### P2P Transfer + +As the intended Payee Henrik Karlsson is now known by the Switch (which is also the ALS) as detailed in [Provision Account Holder](#provision-account-holder), Mats Hagman can now initiate and approve the use case P2P Transfer from his bank to Henrik Karlsson. + +#### Initiate Use Case: Step 4 in End-to-End Flow + +Mats Hagman knows that Henrik Karlsson has phone number **123456789**, so he inputs that number on his device as recipient and 100 USD as amount. The actual communication between Mats' device and his bank **BankNrOne** is out of scope for this API. + +
    + +#### Request Party Information from Switch: Step 5 in End-to-End Flow + +In Step 5 in the end-to-end flow, **BankNrOne** receives the request from Mats Hagman that he would like the phone number 123456789 to receive 100 USD. **BankNrOne** performs an internal search to see if 123456789 exists within the bank, but fails to find the account internally. **BankNrOne** then uses the service [GET /parties/_{Type}_/_{ID}_](#get-parties-type-id) in the Switch to see if the Switch knows anything about the account. + +[Listing 33](#listing-33) shows the HTTP request where the FSP **BankNrOne** asks the Switch for Party information regarding the account identified by **MSISDN** and **123456789**. + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, and [GET /parties/_{Type}_/_{ID}_](#get-parties-type-id) for more information about the service. **More** information regarding routing of requests using **FSPIOP-Destination** and **FSPIOP-Source** can be found in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). In this request, the FSP **BankNrOne** does not know in which FSP the other account holder resides. Thus, the **FSPIOP-Destination** is not present. Information about API version negotiation can be found in [Version Negotiation between Client and Server](#version-negotiation-between-client-and-server). + +###### Listing 33 + +``` +GET /parties/MSISDN/123456789 HTTP/1.1 +Accept: application/vnd.interoperability.parties+json;version=1 +Content-Type: application/vnd.interoperability.parties+json;version=1.0 +Date: Tue, 15 Nov 2017 10:13:37 GMT +FSPIOP-Source: BankNrOne +``` + +**Listing 33 -- Get Party information for account identified by MSISDN and 123456789 from FSP BankNrOne** + +[Listing 34](#listing-34) shows the synchronous HTTP response where the Switch immediately (after basic verification of for example required headers) acknowledges the HTTP request in [Listing 33](#listing-33). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 34 + +``` +HTTP/1.1 202 Accepted +Content-Type: application/vnd.interoperability.parties+json;version=1.0 +``` + +**Listing 34 -- Synchronous response on the request for Party information** + +#### Request Party Information from FSP: Step 6 in End-to-End Flow + +When the Switch has received the HTTP request in [Listing 33](#listing-33) and sent the synchronous response in [Listing 34](#listing-34), the Switch can proceed with checking its database if it has information regarding in which FSP the account holder identified by **MSISDN** and **123456789** is located. As that information was provisioned as detailed in [Provisoin Account Holder](#provision-account-holder), the Switch knows that the account is in FSP **MobileMoney**. Therefore, the Switch sends the HTTP request in [Listing 35](#listing-35). + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, and [GET /parties/_{Type}_/_{ID}_](#get-parties-type-id) for more information about the service. **More** information regarding routing of requests using **FSPIOP-Destination** and **FSPIOP-Source** can be found in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source); in this request the Switch has added the header **FSPIOP-Destination** because the Switch knew to where the request should be routed. Information about API version negotiation can be found in [Version Negotiation between Client and Server](#version-negotiation-between-client-and-server). + + + +###### Listing 35 + +``` +GET /parties/MSISDN/123456789 HTTP/1.1 +Accept: application/vnd.interoperability.parties+json;version=1 +Content-Type: application/vnd.interoperability.parties+json;version=1.0 +Date: Tue, 15 Nov 2017 10:13:38 GMT +FSPIOP-Source: BankNrOne +FSPIOP-Destination: MobileMoney +``` + +**Listing 35 -- Get Party information for account identified by MSISDN and 123456789 from Switch** + +[Listing 36](#listing-36) shows the synchronous HTTP response where the FSP **MobileMoney** immediately (after basic verification of for example required headers) acknowledges the HTTP request in [Listing 35](#listing-35). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 36 + +``` +HTTP/1.1 202 Accepted +Content-Type: application/vnd.interoperability.parties+json;version=1.0 +``` + +**Listing 36 -- Synchronous response on request for Party information** + +
    + +#### Lookup Party Information in FSP MobileMoney: Step 7 in End-to-End Flow + +When the FSP **MobileMoney** has received the HTTP request in [Listing 35](#listing-35) and sent the synchronous response in [Listing 36](#listing-36), the FSP **MobileMoney** can proceed with checking its database for more information regarding the account identified by **MSISDN** and **123456789**. As the account exists and is owned by Henrik Karlsson, the FSP **MobileMoney** sends the callback in [Listing 37](#listing-37). The FSP **MobileMoney** does not want to share some details, for example birth date, with the other FSP (**BankNrOne**), so some optional elements are not sent. + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, +and [PUT /participants/_{Type}_/_{ID}_](#put-participants-type-id) for more information about the callback. **In** the callback, the **Accept** header should not be sent. The HTTP headers **FSPIOP-Destination** and **FSPIOP-Source** are now inverted compared to the HTTP request in [Listing 35](#listing-35), as detailed in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). + +###### Listing 37 + +```` +PUT /parties/MSISDN/123456789 HTTP/1.1 +Content-Type: application/vnd.interoperability.parties+json;version=1.0 +Content-Length: 347 +Date: Tue, 15 Nov 2017 10:13:39 GMT +FSPIOP-Source: MobileMoney +FSPIOP-Destination: BankNrOne +{ + "party": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "123456789", + "fspId": "MobileMoney" + }, + "personalInfo": { + "complexName": { + "firstName": "Henrik", + "lastName": "Karlsson" + } + } + } +} +```` + +**Listing 37 -- Callback to the request for Party information** + +[Listing 38](#listing-38) shows the synchronous HTTP response where the Switch immediately (after basic verification of for example required headers) acknowledges the completion of the process, after receiving the callback in [Listing 37](#listing-37). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 38 + +``` +HTTP/1.1 200 OK +Content-Type: application/vnd.interoperability.parties+json;version=1.0 +``` + +**Listing 38 -- Synchronous response for the Party information callback** + +
    + +#### Send Callback to FSP BankNrOne: Step 8 in End-to-End Flow + +When the Switch has received the callback in [Listing 37](#listing-37) and sent the synchronous response in [Listing 38](#listing-38), it should relay the exact same callback as in [Listing 37](#listing-37) to the FSP **BankNrOne**, and **BankNrOne** should then respond synchronously with the exact same response as in [Listing 38](#listing-38). + +The HTTP request and response are not repeated in this section, as they are the same as in the last section, but sent from the Switch to **BankNrOne** (HTTP request in [Listing 37](#listing-37)) and from **BankNrOne** to the Switch (HTTP response in [Listing 38](#listing-38)) instead. + +
    + +#### Send Quote Request from FSP BankNrOne: Step 9 in End-to-End Flow + +After receiving Party information in the callback [PUT /parties/_{Type}_/_{ID}_](#put-parties-type-id), the FSP **BankNrOne** now knows that the account identified by **MSISDN** and **123456789** exists and that it is in the FSP **MobileMoney**. It also knows the name of the account holder. Depending on implementation, the name of the intended Payee (Henrik Karlsson) could be shown to Mats Hagman already in this step before sending the quote. In this example, a quote request is sent before showing the name and any fees. + +The FSP **BankNrOne** sends the HTTP request in [Listing 39](#listing-39) to request the quote. **BankNrOne** does not want to disclose its fees (see [Quoting](#quoting) for more information about quoting), which means that it does not include the **fees** element in the request. The **amountType** element is set to RECEIVE as Mats wants Henrik to receive 100 USD. The **transactionType** is set according to [Mapping of Use Cases to Transaction Types](#mapping-of-use-cases-to-transaction-types). Information about Mats is sent in the **payer** element. **BankNrOne** has also generated two UUIDs for the quote ID (7c23e80c-d078-4077-8263-2c047876fcf6) and the transaction ID (85feac2f-39b2-491b-817e-4a03203d4f14). These IDs must be unique, as described in [Architectural Style](#architectural-style). + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, and [Section 6.5.3.2](#6532-post-quotes) for more information about the service [POST /quotes](#6532-post-quotes). **More** information regarding routing of requests using **FSPIOP-Destination** and **FSPIOP-Source** can be found in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). Information about API version negotiation can be found in [Version Negotiation between Client and Server](#version-negotiation-between-client-and-server). + +###### Listing 39 + +```` +POST /quotes HTTP/1.1 +Accept: application/vnd.interoperability.quotes+json;version=1 +Content-Type: application/vnd.interoperability.quotes+json;version=1.0 +Content-Length: 975 +Date: Tue, 15 Nov 2017 10:13:40 GMT +FSPIOP-Source: BankNrOne +FSPIOP-Destination: MobileMoney +{ + "quoteId": "7c23e80c-d078-4077-8263-2c047876fcf6", + "transactionId": "85feac2f-39b2-491b-817e-4a03203d4f14", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "123456789", + "fspId": "MobileMoney" + } + }, + "payer": { + "personalInfo": { + "complexName": { + "firstName": "Mats", + "lastName": "Hagman" + } + }, + "partyIdInfo": { + "partyIdType": "IBAN", + "partyIdentifier": "SE4550000000058398257466", + "fspId": "BankNrOne" + } + }, + "amountType": "RECEIVE", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "note": "From Mats", + "expiration": "2017-11-15T22:17:28.985-01:00" +} +```` + +**Listing 39 -- Request quote for transaction of 100 USD** + +[Listing 40](#listing-40) shows the synchronous HTTP response where the Switch immediately (after basic verification of for example required headers) acknowledges the HTTP request in [Listing 39](#listing-39). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 40 + +``` +HTTP/1.1 202 Accepted +Content-Type: application/vnd.interoperability.quotes+json;version=1.0 +``` + +**Listing 40 -- Synchronous response on quote request** + +#### Send Quote Request from Switch: Step 10 in End-to-End Flow** + +When the Switch has received the quote request in [Listing 39](#listing-39) and sent the synchronous response in [Listing 40](#listing-40), it should relay the same request as in [Listing 39](#listing-39) to the FSP **MobileMoney**, and **MobileMoney** should then respond synchronously with the same response as in [Listing 40](#listing-40). + +The HTTP request and response are not repeated in this section, as they are the same as in the last section, but sent from the Switch to **MobileMoney** (HTTP request in [Listing 39](#listing-39)) and from **MobileMoney** to the Switch (HTTP response in [Listing 40](#listing-40)) instead. + +
    + +#### Determine fees and FSP commission in FSP MobileMoney: Step 11 in End-to-End Flow + +When the FSP **MobileMoney** has received the HTTP request in [Listing 39](#listing-40) and sent the synchronous response in [Listing 40](#listing-40), the FSP **MobileMoney** should validate the request and then proceed to determine the applicable fees and/or FSP commission for performing the transaction in the quote request. + +In this example, the FSP **MobileMoney** decides to give 1 USD in FSP commission as the FSP **MobileMoney** will receive money, which should later generate more income for the FSP (future possible fees). Since the Payee Henrik Karlsson should receive 100 USD and the FSP commission is determined to 1 USD, the FSP **BankNrOne** only needs to transfer 99 USD to the FSP **MobileMoney** (see [Non Disclosing Receive Amount](#non-disclosing-receive-amount) for the equation). The 99 USD is entered in the transferAmount element in the callback, which is the amount that should later be transferred between the FSPs. + +To send the callback, the FSP **MobileMoney** then needs to create an ILP Packet (see [ILP Packet](#ilp-packet) for more information) that is base64url-encoded, as the **ilpPacket** element in the [PUT /quotes/_{ID}_](#put-quotes-id) callback is defined as a [BinaryString](#binarystring). How to populate the ILP Packet is explained in [Interledger Payment Request](#interledger-payment-request). Henrik's ILP address in the FSP **MobileMoney** has been set to **g.se.mobilemoney.msisdn.123456789** (see [ILP Addressing](#ilp-addressing) for more information about ILP addressing). As the transfer amount is 99 USD and the currency USD's exponent is 2, the amount to be populated in the ILP Packet is 9900 (99 \* 10\^2 = 9900). The remaining element in the ILP Packet is the **data** element. As described in [Interledger Payment Request](#interledger-payment-request), this element should contain the Transaction data model (see [Transaction](#transaction)). With the information from the quote request, the Transaction in this example becomes as shown in [Listing 41](#listing-41). Base64url-encoding the entire ILP Packet with the **amount**, **account**, and the **data** element then results in the **ilpPacket** element in the [PUT /quotes/_{ID}_](#put-quotes-id) callback. + +When the ILP Packet has been created, the fulfilment and the condition can be generated as defined in the algorithm in [Listing 12](#listing-12). Using a generated example secret shown in [Listing 42](#listing-42) (shown as base64url-encoded), the fulfilment becomes as in [Listing 43](#listing-43) (shown as base64url-encoded) after executing the HMAC SHA-256 algorithm on the ILP Packet using the generated secret as key. The FSP **MobileMoney** is assumed to save the fulfilment in the database, so that it does not have to be regenerated later. The condition is then the result of executing the SHA-256 hash algorithm on the fulfilment, which becomes as in [Listing 44](#listing-44) (shown as base64url-encoded). + +The complete callback to the quote request becomes as shown in [Listing 45](#listing-45). + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, and [PUT /quotes/_{ID}_](#put-quotes-id) for more information about the callback. **The** _{ID}_ in the URI should be taken from the quote ID in the quote request, which in the example is 7c23e80c-d078-4077-8263-2c047876fcf6. In the callback, the **Accept** header should not be sent. The HTTP headers **FSPIOP-Destination** and **FSPIOP-Source** are now inverted compared to the HTTP request in [Listing 39](#listing-39), as detailed in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). + +###### Listing 41 + +``` +{ + "transactionId": "85feac2f-39b2-491b-817e-4a03203d4f14", + "quoteId": "7c23e80c-d078-4077-8263-2c047876fcf6", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "123456789", + "fspId": "MobileMoney" + }, + "personalInfo": { + "complexName": { + "firstName": "Henrik", + "lastName": "Karlsson" + } + } + }, + "payer": { + "personalInfo": { + "complexName": { + "firstName": "Mats", + "lastName": "Hagman" + } + }, + "partyIdInfo": { + "partyIdType": "IBAN", + "partyIdentifier": "SE4550000000058398257466", + "fspId": "BankNrOne" + } + }, + "amount": { + "amount": "99", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "note": "From Mats" +} +``` + +**Listing 41 -- The Transaction JSON object** + +###### Listing 42 + +``` +JdtBrN2tskq9fuFr6Kg6kdy8RANoZv6BqR9nSk3rUbY +``` + +**Listing 42 -- Generated secret, encoded in base64url** + +###### Listing 43 + +``` +mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s +``` + +**Listing 43 -- Calculated fulfilment from the ILP Packet and secret, encoded in base64url** + +###### Listing 44 + +``` +fH9pAYDQbmoZLPbvv3CSW2RfjU4jvM4ApG\_fqGnR7Xs +``` + +**Listing 44 -- Calculated condition from the fulfilment, encoded in base64url** + +###### Listing 45 + +``` +PUT /quotes/7c23e80c-d078-4077-8263-2c047876fcf6 HTTP/1.1 +Content-Type: application/vnd.interoperability.quotes+json;version=1.0 +Content-Length: 1802 +Date: Tue, 15 Nov 2017 10:13:41 GMT +FSPIOP-Source: MobileMoney +FSPIOP-Destination: BankNrOne +{ + "transferAmount": { + "amount": "99", + "currency": "USD" + }, + "payeeReceiveAmount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2017-11-15T14:17:09.663+01:00", + "ilpPacket": "AQAAAAAAACasIWcuc2UubW9iaWxlbW9uZXkubXNpc2RuLjEyMzQ1Njc4OY- +IEIXsNCiAgICAidHJhbnNhY3Rpb25JZCI6ICI4NWZlY- +WMyZi0zOWIyLTQ5MWItODE3ZS00YTAzMjAzZDRmMTQiLA0KICAgICJxdW90ZUlkIjogIjdjMjNlOD- +BjLWQwNzgtNDA3Ny04MjYzLTJjMDQ3ODc2ZmNmNiIsDQogICAgInBheWVlIjogew0KICAgICAgI- +CAicGFydHlJZEluZm8iOiB7DQogICAgICAgICAgICAicGFydHlJZFR5cGUiOiAiTVNJU0ROIiwNCiAgI- +CAgICAgICAgICJwYXJ0eUlkZW50aWZpZXIiOiAiMTIzNDU2Nzg5IiwNCiAgICAgICAgI- +CAgICJmc3BJZCI6ICJNb2JpbGVNb25leSINCiAgICAgICAgfSwNCiAgICAgI- +CAgInBlcnNvbmFsSW5mbyI6IHsNCiAgICAgICAgICAgICJjb21wbGV4TmFtZSI6IHsNCiAgICAgICAgI- +CAgICAgICAiZmlyc3ROYW1lIjogIkhlbnJpayIsDQogICAgICAgICAgICAgICAgImxhc3ROYW1lIjogIk- +thcmxzc29uIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfSwNCiAgICAicGF5ZXIi- +OiB7DQogICAgICAgICJwZXJzb25hbEluZm8iOiB7DQogICAgICAgICAgICAiY29tcGxleE5hbWUi- +OiB7DQogICAgICAgICAgICAgICAgImZpcnN0TmFtZSI6ICJNYXRzIiwNCiAgICAgICAgICAgICAgI- +CAibGFzdE5hbWUiOiAiSGFnbWFuIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9LA0KICAgICAgI- +CAicGFydHlJZEluZm8iOiB7DQogICAgICAgICAgICAicGFydHlJZFR5cGUiOiAiSUJBTiIsDQogICAgI- +CAgICAgICAicGFydHlJZGVudGlmaWVyI- +jogIlNFNDU1MDAwMDAwMDA1ODM5ODI1NzQ2NiIsDQogICAgICAgICAgICAiZnNwSWQiOiAiQmFua05yT25 +lIg0KICAgICAgICB9DQogICAgfSwNCiAgICAiYW1vdW50Ijogew0KICAgICAgICAiYW1vdW50IjogIjEw- +MCIsDQogICAgICAgICJjdXJyZW5jeSI6ICJVU0QiDQogICAgfSwNCiAgICAidHJhbnNhY3Rpb25UeXBlI- +jogew0KICAgICAgICAic2NlbmFyaW8iOiAiVFJBTlNGRVIiLA0KICAgICAgICAiaW5pdGlhdG9yI- +jogIlBBWUVSIiwNCiAgICAgICAgImluaXRpYXRvclR5cGUiOiAiQ09OU1VNRVIiDQogICAgfSwNCiAgI- +CAibm90ZSI6ICJGcm9tIE1hdHMiDQp9DQo\u003d\u003d", + "condition": "fH9pAYDQbmoZLPbvv3CSW2RfjU4jvM4ApG_fqGnR7Xs" +} +``` + +**Listing 45 -- Quote callback** + +**Note:** The element **ilpPacket** in [Listing 45](#listing-45) should be on a single line in a real implementation; it is shown with line breaks in this example in order to show the entire value. + +[Listing 46](#listing-46) shows the synchronous HTTP response where the Switch immediately (after basic verification of for example required headers) acknowledges the completion of the process, after receiving the callback in [Listing 45](#listing-45). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 46 + +``` +HTTP/1.1 200 OK +Content-Type: application/vnd.interoperability.quotes+json;version=1.0 +``` + +**Listing 46 -- Synchronous response on the quote callback** + +#### Send Callback to FSP BankNrOne: Step 12 in End-to-End Flow + +When the Switch has received the quote callback in [Listing 45](#listing-45) and sent the synchronous response in [Listing 46](#listing-46), it should relay the exact same callback as in [Listing 45](#listing-45) to the FSP **BankNrOne**, and **BankNrOne** should then respond synchronously with the exact same response as in [Listing 46](#listing-46). + +The HTTP request and response are not repeated in this section, as they are the same as in the last section, but sent from the Switch to **BankNrOne** (HTTP request in [Listing 45](#listing-45)) and from **BankNrOne** to the Switch (HTTP response in [Listing 46](#listing-46)) instead. + +
    + +#### Determine fees in FSP BankNrOne: Step 13 in End-to-End Flow + +When the FSP **BankNrOne** has received the quote callback in [Listing 45](#listing-45) and sent the synchronous response in [Listing 46](#listing-46), the FSP **BankNrOne** can proceed with determining the fees for the Payer Mats Hagman. In this example, the fee for the Payer is set to 0 USD, but the FSP commission from the FSP **MobileMoney** is kept as an income for the FSP **BankNrOne**. This means that for the Payee Henrik Karlsson to receive 100 USD, the Payer Mats Hagman must transfer 100 USD from his account. 99 USD will then be transferred between the FSPs **BankNrOne** and **MobileMoney**. + +The FSP **BankNrOne** then notifies Mats Hagman that the transaction to transfer 100 USD to Henrik Karlsson will cost 0 USD in fees. How Mats Hagman is notified is out of scope of this API. + +
    + +#### Payer Accepts Transaction: Step 14 in End-to-End Flow + +In this example, Mats Hagman accepts to perform the transaction. How the acceptance is sent is outside the scope of this API. + +#### Send Transfer Request from FSP BankNrOne: Step 15 in End-to-End Flow + +When Mats Hagman has accepted the transaction, FSP **BankNrOne** reserves the internal transfers needed to perform the transaction. This means that 100 USD will be reserved from Mats Hagman's account, where 1 USD will end up as income for the FSP and 99 USD will be transferred to the prefunded Switch account. After the reservations are successfully performed, the FSP **BankNrOne** sends a [POST /transfers](#post-transfers) to the Switch as in [Listing 47](#listing-47). The same ilpPacket and condition elements are sent as was received in the quote callback and the **amount** is the same as the received **transferAmount**, see [Listing 45](#listing-45). + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, and [Post Transfers](#post-transfers) for more information about the service [POST /transfers](#post-transfers).**More** information regarding routing of requests using **FSPIOP-Destination** and **FSPIOP-Source** can be found in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). Information about API version negotiation can be found in [Version Negotiation between Client and Server](#version-negotiation-between-client-and-server). + +###### Listing 47 + +``` +POST /transfers HTTP/1.1 +Accept: application/vnd.interoperability.transfers+json;version=1 +Content-Type: application/vnd.interoperability.transfers+json;version=1.0 +Content-Length: 1820 +Date: Tue, 15 Nov 2017 10:14:01 +FSPIOP-Source: BankNrOne +FSPIOP-Destination: MobileMoney +{ + "transferId":"11436b17-c690-4a30-8505-42a2c4eafb9d", + "payerFsp":"BankNrOne", + "payeeFsp": "MobileMoney", + "amount": { + "amount": "99", + "currency": "USD" + }, + "expiration": "2017-11-15T11:17:01.663+01:00", + "ilpPacket": "AQAAAAAAACasIWcuc2UubW9iaWxlbW9uZXkubXNpc2RuLjEyMzQ1Njc4OY- +IEIXsNCiAgICAidHJhbnNhY3Rpb25JZCI6ICI4NWZlY- +WMyZi0zOWIyLTQ5MWItODE3ZS00YTAzMjAzZDRmMTQiLA0KICAgICJxdW90ZUlkIjogIjdjMjNlOD- +BjLWQwNzgtNDA3Ny04MjYzLTJjMDQ3ODc2ZmNmNiIsDQogICAgInBheWVlIjogew0KICAgICAgI- +CAicGFydHlJZEluZm8iOiB7DQogICAgICAgICAgICAicGFydHlJZFR5cGUiOiAiTVNJU0ROIiwNCiAgI- +CAgICAgICAgICJwYXJ0eUlkZW50aWZpZXIiOiAiMTIzNDU2Nzg5IiwNCiAgICAgICAgI- +CAgICJmc3BJZCI6ICJNb2JpbGVNb25leSINCiAgICAgICAgfSwNCiAgICAgI- +CAgInBlcnNvbmFsSW5mbyI6IHsNCiAgICAgICAgICAgICJjb21wbGV4TmFtZSI6IHsNCiAgICAgICAgI- +CAgICAgICAiZmlyc3ROYW1lIjogIkhlbnJpayIsDQogICAgICAgICAgICAgICAgImxhc3ROYW1lIjogIk- +thcmxzc29uIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfSwNCiAgICAicGF5ZXIi- +OiB7DQogICAgICAgICJwZXJzb25hbEluZm8iOiB7DQogICAgICAgICAgICAiY29tcGxleE5hbWUi- +OiB7DQogICAgICAgICAgICAgICAgImZpcnN0TmFtZSI6ICJNYXRzIiwNCiAgICAgICAgICAgICAgI- +CAibGFzdE5hbWUiOiAiSGFnbWFuIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9LA0KICAgICAgI- +CAicGFydHlJZEluZm8iOiB7DQogICAgICAgICAgICAicGFydHlJZFR5cGUiOiAiSUJBTiIsDQogICAgI- CAgICAgICAicGFydHlJZGVudGlmaWVyI- +jogIlNFNDU1MDAwMDAwMDA1ODM5ODI1NzQ2NiIsDQogICAgICAgICAgICAiZnNwSWQiOiAiQmFua05yT25 lIg0KICAgICAgICB9DQogICAgfSwNCiAgICAiYW1vdW50Ijogew0KICAgICAgICAiYW1vdW50IjogIjEw- +MCIsDQogICAgICAgICJjdXJyZW5jeSI6ICJVU0QiDQogICAgfSwNCiAgICAidHJhbnNhY3Rpb25UeXBlI- +jogew0KICAgICAgICAic2NlbmFyaW8iOiAiVFJBTlNGRVIiLA0KICAgICAgICAiaW5pdGlhdG9yI- +jogIlBBWUVSIiwNCiAgICAgICAgImluaXRpYXRvclR5cGUiOiAiQ09OU1VNRVIiDQogICAgfSwNCiAgI- +CAibm90ZSI6ICJGcm9tIE1hdHMiDQp9DQo\u003d\u003d", +"condition": "fH9pAYDQbmoZLPbvv3CSW2RfjU4jvM4ApG_fqGnR7Xs" +} +``` + +**Listing 47 -- Request to transfer from FSP BankNrOne to FSP MobileMoney** + +**Note:** The element **ilpPacket** in [Listing 47](#listing-47) should be on a single line in a real implementation, it is shown with line breaks in this example for being able to show the entire value. + +[Listing 48](#listing-48) shows the synchronous HTTP response where the Switch immediately (after basic verification of for example required headers) acknowledges the HTTP request in [Listing 47](#listing-47). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 48 + +``` +HTTP/1.1 202 Accepted +Content-Type: application/vnd.interoperability.transfers+json;version=1.0 +``` + +**Listing 48 -- Synchronous response on transfer request** + +
    + +#### Send Transfer Request from Switch: Step 16 in End-to-End Flow + +When the Switch has received the transfer request in [Listing 47](#listing-47) and sent the synchronous response in [Listing 48](#listing-48), it should reserve the transfer from **BankNrOne**'s account in the Switch to **MobileMoney**'s account in the Switch. After the reservation is successful, the Switch relays nearly the same request as in [Listing 47](#listing-47) to the FSP **MobileMoney**; expect that the **expiration** element should be decreased as mentioned in [Timeout and Expiry](#timeout-and-expiry). [Listing 49](#listing-49) shows the HTTP request with the **expiration** decreased by 30 seconds compared to [Listing 47](#listing-47). The FSP **MobileMoney** should then respond synchronously with the same response as in [Listing 48](#listing-48). + +###### Listing 49 + +``` +POST /transfers HTTP/1.1 +Accept: application/vnd.interoperability.transfers+json;version=1 +Content-Type: application/vnd.interoperability.transfers+json;version=1.0 +Content-Length: 1820 +Date: Tue, 15 Nov 2017 10:14:01 GMT +FSPIOP-Source: BankNrOne +FSPIOP-Destination: MobileMoney +{ + "transferId":"11436b17-c690-4a30-8505-42a2c4eafb9d", + "payerFsp":"BankNrOne", + "payeeFsp": "MobileMoney", + "amount": { + "amount": "99", + "currency": "USD" + }, + "expiration": "2017-11-15T11:16:31.663+01:00", + "ilpPacket": "AQAAAAAAACasIWcuc2UubW9iaWxlbW9uZXkubXNpc2RuLjEyMzQ1Njc4OY- +IEIXsNCiAgICAidHJhbnNhY3Rpb25JZCI6ICI4NWZlY- +WMyZi0zOWIyLTQ5MWItODE3ZS00YTAzMjAzZDRmMTQiLA0KICAgICJxdW90ZUlkIjogIjdjMjNlOD- +BjLWQwNzgtNDA3Ny04MjYzLTJjMDQ3ODc2ZmNmNiIsDQogICAgInBheWVlIjogew0KICAgICAgI- +CAicGFydHlJZEluZm8iOiB7DQogICAgICAgICAgICAicGFydHlJZFR5cGUiOiAiTVNJU0ROIiwNCiAgI- +CAgICAgICAgICJwYXJ0eUlkZW50aWZpZXIiOiAiMTIzNDU2Nzg5IiwNCiAgICAgICAgI- +CAgICJmc3BJZCI6ICJNb2JpbGVNb25leSINCiAgICAgICAgfSwNCiAgICAgI- +CAgInBlcnNvbmFsSW5mbyI6IHsNCiAgICAgICAgICAgICJjb21wbGV4TmFtZSI6IHsNCiAgICAgICAgI- +CAgICAgICAiZmlyc3ROYW1lIjogIkhlbnJpayIsDQogICAgICAgICAgICAgICAgImxhc3ROYW1lIjogIk- +thcmxzc29uIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfSwNCiAgICAicGF5ZXIi- +OiB7DQogICAgICAgICJwZXJzb25hbEluZm8iOiB7DQogICAgICAgICAgICAiY29tcGxleE5hbWUi- +OiB7DQogICAgICAgICAgICAgICAgImZpcnN0TmFtZSI6ICJNYXRzIiwNCiAgICAgICAgICAgICAgI- +CAibGFzdE5hbWUiOiAiSGFnbWFuIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9LA0KICAgICAgI- +CAicGFydHlJZEluZm8iOiB7DQogICAgICAgICAgICAicGFydHlJZFR5cGUiOiAiSUJBTiIsDQogICAgI- +CAgICAgICAicGFydHlJZGVudGlmaWVyI- +jogIlNFNDU1MDAwMDAwMDA1ODM5ODI1NzQ2NiIsDQogICAgICAgICAgICAiZnNwSWQiOiAiQmFua05yT25 +lIg0KICAgICAgICB9DQogICAgfSwNCiAgICAiYW1vdW50Ijogew0KICAgICAgICAiYW1vdW50IjogIjEw- +MCIsDQogICAgICAgICJjdXJyZW5jeSI6ICJVU0QiDQogICAgfSwNCiAgICAidHJhbnNhY3Rpb25UeXBlI- +jogew0KICAgICAgICAic2NlbmFyaW8iOiAiVFJBTlNGRVIiLA0KICAgICAgICAiaW5pdGlhdG9yI- +jogIlBBWUVSIiwNCiAgICAgICAgImluaXRpYXRvclR5cGUiOiAiQ09OU1VNRVIiDQogICAgfSwNCiAgI- +CAibm90ZSI6ICJGcm9tIE1hdHMiDQp9DQo\u003d\u003d", +"condition": "fH9pAYDQbmoZLPbvv3CSW2RfjU4jvM4ApG_fqGnR7Xs" +} +``` + +**Listing 49 -- Request to transfer from FSP BankNrOne to FSP MobileMoney with decreased expiration** + +**Note:** The element **ilpPacket** in [Listing 49](#listing-49) should be on a single line in a real implementation; it is shown with line breaks in this example in order to show the entire value. + +
    + +#### Perform Transfer in FSP MobileMoney: Step 17 in End-to-End Flow + +When the FSP **MobileMoney** has received the transfer request in [Listing 47](#listing-47), it should perform the transfer as detailed in the earlier quote request, this means that 100 USD should be transferred to Henrik Karlsson's account, where 99 USD is from the prefunded Switch account and 1 USD is from an FSP commission account. + +As proof of performing the transaction, the FSP **MobileMoney** then retrieves the stored fulfilment [(Listing 43](#listing-43)) from the database (stored in [Determine Fees and FSP commission in FSP MobileMoney](#determine-fees-and-fsp-commission-in-fsp-mobilemoney-step-11-in-end-to-end-flow)) and enters that in the **fulfilment** element in the callback [PUT /transfers/_{ID}_](#put-transfersid). The **transferState** is set to COMMITTED and the **completedTimestamp** is set to when the transaction was completed; see [Listing 50](#listing-50) for the complete HTTP request. + +At the same time, a notification is sent to the Payee Henrik Karlsson to +say that he has received 100 USD from Mats Hagman. + +How the notification is sent is out of scope for this API. + +See [Table 1](#table-1) for the required HTTP headers in a HTTP request, and [PUT /transfers/_{ID}_](#put-transfersid) for more information about the callback. **The** _{ID}_ in the URI should be taken from the transfer ID in the transfer request, which in the example is 11436b17-c690-4a30-8505-42a2c4eafb9d. In the callback, the **Accept** header should not be sent. The HTTP headers **FSPIOP-Destination** and **FSPIOP-Source** are now inverted compared to the HTTP request in [Listing 47](#listing-47), as detailed in [Call Flow Routing using FSPIOP Destination and FSPIOP Source](#call-flow-routing-using-fspiop-destination-and-fspiop-source). + +###### Listing 50 + +``` +PUT /transfers/11436b17-c690-4a30-8505-42a2c4eafb9d HTTP/1.1 +Content-Type: application/vnd.interoperability.transfers+json;version=1.0 +Content-Length: 166 +Date: Tue, 15 Nov 2017 10:14:02 GMT +FSPIOP-Source: MobileMoney +FSPIOP-Destination: BankNrOne +{ + "fulfilment": "mhPUT9ZAwd-BXLfeSd7-YPh46rBWRNBiTCSWjpku90s", + "completedTimestamp": "2017-11-16T04:15:35.513+01:00", + "transferState": "COMMITTED" +} +``` + +**Listing 50 -- Callback for the transfer request** + +[Listing 51](#listing-51) shows the synchronous HTTP response in which the Switch immediately (after basic verification of for example required headers) acknowledges the completion of the process, after receiving the callback in [Listing 50](#listing-50). + +See [Table 3](#table-3) for the required HTTP headers in a HTTP response. + +###### Listing 51 + +``` +HTTP/1.1 200 OK +Content-Type: application/vnd.interoperability.transfers+json;version=1.0 +``` + +**Listing 51 -- Synchronous response on the transfers callback** + +
    + +#### Payee Receives Transaction Notification: Step 18 in End-to-End Flow + +The Payee Henrik Karlsson receives the transaction notification, and is thereby informed of the successful transaction. + +
    + +#### Perform Transfer in Switch: Step 19 in End-to-End Flow + +When the Switch has received the transfer callback in [Listing 50](#listing-50) and sent the synchronous response in [Listing 51](#listing-51), it should validate the fulfilment, perform the earlier reserved transfer and relay the exact same callback as in [Listing 50](#listing-50) to the FSP **BankNrOne**, and **BankNrOne** should then respond synchronously with the same response as in [Listing 51](#listing-51). + +The validation of the fulfilment is done by calculating the SHA-256 hash of the fulfilment and ensuring that the hash is equal to the condition from the transfer request. + +The HTTP request and response are not repeated in this section, as they are the same as in the last section, but sent from the Switch to **BankNrOne** (HTTP request in [Listing 50](#listing-51)) and from **BankNrOne** to the Switch (HTTP response in [Listing 51](#listing-51)) instead. + +
    + +#### Perform Transfer in FSP BankNrOne: Step 20 in End-to-End Flow + +When the FSP **BankNrOne** has received the transfer callback in [Listing 50](#listing-50) and sent the synchronous response in [Listing 51](#listing-51), the FSP **BankNrOne** should validate the fulfilment (see [Section 10.4.16](#10416-perform-transfer-in-switch----step-19-in-end-to-end-flow)) and then perform the earlier reserved transfer. + +After the reserved transfer has been performed, the Payer Mats Hagman should be notified of the successful transaction. How the notification is sent is outside the scope of this API. + +#### Payer Receives Transaction Notification: Step 21 in End-to-End Flow + +The Payer Mats Hagman receives the transaction notification and is thereby informed of the successful transaction. + + + + + +1 [http://www.ics.uci.edu/\~fielding/pubs/dissertation/rest\_arch\_style.htm](http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) -- Representational State Transfer (REST) + +2 [https://tools.ietf.org/html/rfc4122](https://tools.ietf.org/html/rfc4122) -- A Universally Unique IDentifier (UUID) URN Namespace + +3 [https://tools.ietf.org/html/rfc7230](https://tools.ietf.org/html/rfc7230) -- Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing + +4 [https://tools.ietf.org/html/rfc5246](https://tools.ietf.org/html/rfc5246) -- The Transport Layer Security (TLS) Protocol - Version 1.2 + +5 [https://tools.ietf.org/html/rfc3986](https://tools.ietf.org/html/rfc3986) -- Uniform Resource Identifier (URI): Generic Syntax + +6 [https://tools.ietf.org/html/rfc7230\#section-2.7.3](https://tools.ietf.org/html/rfc7230#section-2.7.3) -- Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing - http and https URI Normalization and Comparison + +7 [https://tools.ietf.org/html/rfc3629](https://tools.ietf.org/html/rfc3629) -- UTF-8, a transformation format of ISO 10646 + +8 [https://tools.ietf.org/html/rfc7159](https://tools.ietf.org/html/rfc7159) -- The JavaScript Object Notation (JSON) Data Interchange Format + +9 [https://tools.ietf.org/html/rfc7230\#section-3.2](https://tools.ietf.org/html/rfc7230#section-3.2) -- Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing - Header Fields + +10 [https://tools.ietf.org/html/rfc7231\#section-5.3.2](https://tools.ietf.org/html/rfc7231#section-5.3.2) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Accept + +11 [https://tools.ietf.org/html/rfc7230\#section-3.3.2](https://tools.ietf.org/html/rfc7230#section-3.3.2) -- Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing -- Content-Length + +12 [https://tools.ietf.org/html/rfc7231\#section-3.1.1.5](https://tools.ietf.org/html/rfc7231#section-3.1.1.5) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content -- Content-Type + +13 [https://tools.ietf.org/html/rfc7231\#section-7.1.1.2](https://tools.ietf.org/html/rfc7231#section-7.1.1.2) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content -- Date + +14 [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) -- X-Forwarded-For + +15 [https://tools.ietf.org/html/rfc7239](https://tools.ietf.org/html/rfc7239) -- Forwarded HTTP Extension + +16 [https://tools.ietf.org/html/rfc7230\#section-3.3.2](https://tools.ietf.org/html/rfc7230#section-3.3.2) -- Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing -- Content-Length + +17 [https://tools.ietf.org/html/rfc7231\#section-3.1.1.5](https://tools.ietf.org/html/rfc7231#section-3.1.1.5) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content -- Content-Type + +18 [https://tools.ietf.org/html/rfc7231\#section-4](https://tools.ietf.org/html/rfc7231#section-4) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Request Methods + +19 [https://tools.ietf.org/html/rfc7231\#section-6](https://tools.ietf.org/html/rfc7231#section-6) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Response Status Codes + +20 [https://tools.ietf.org/html/rfc7231\#section-6.4](https://tools.ietf.org/html/rfc7231#section-6.4) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Redirection 3xx + +21 [https://tools.ietf.org/html/rfc7231\#section-6.6](https://tools.ietf.org/html/rfc7231#section-6.6) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Server Error 5xx + +22 [https://tools.ietf.org/html/rfc7231\#section-6.5.6](https://tools.ietf.org/html/rfc7231#section-6.5.6) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - 406 Not Acceptable + +23 [https://tools.ietf.org/html/rfc7231\#section-5.3.2](https://tools.ietf.org/html/rfc7231#section-5.3.2) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Accept + +24 [https://interledger.org/rfcs/0011-interledger-payment-request/](https://interledger.org/rfcs/0011-interledger-payment-request/) -- Interledger Payment Request (IPR) + +25 [https://interledger.org/](https://interledger.org/) -- Interledger + +26 [https://interledger.org/interledger.pdf](https://interledger.org/interledger.pdf) -- A Protocol for Interledger Payments + +27 [https://interledger.org/rfcs/0001-interledger-architecture/](https://interledger.org/rfcs/0001-interledger-architecture/) -- Interledger Architecture + +28 [https://interledger.org/rfcs/0015-ilp-addresses/](https://interledger.org/rfcs/0015-ilp-addresses/) -- ILP Addresses + +29 [https://www.itu.int/rec/dologin\_pub.asp?lang=e&id=T-REC-X.696-201508-I!!PDF-E&type=items](https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-X.696-201508-I!!PDF-E&type=items) -- Information technology -- ASN.1 encoding rules: Specification of Octet Encoding Rules (OER) + +30 [https://perldoc.perl.org/perlre.html\#Regular-Expressions](https://perldoc.perl.org/perlre.html#Regular-Expressions) -- perlre - Perl regular expressions + +31 [https://tools.ietf.org/html/rfc7159\#section-7](https://tools.ietf.org/html/rfc7159#section-7) -- The JavaScript Object Notation (JSON) Data Interchange Format - Strings + +32 [http://www.unicode.org/](http://www.unicode.org/) -- The Unicode Consortium + +33 [https://www.iso.org/iso-8601-date-and-time-format.html](https://www.iso.org/iso-8601-date-and-time-format.html) -- Date and time format - ISO 8601 + +34 [https://tools.ietf.org/html/rfc4122](https://tools.ietf.org/html/rfc4122) -- A Universally Unique IDentifier (UUID) URN Namespace + +35 [https://tools.ietf.org/html/rfc4648\#section-5](https://tools.ietf.org/html/rfc4648#section-5) -- The Base16, Base32, and Base64 Data Encodings - Base 64 Encoding with URL and Filename Safe Alphabet + +36 [https://www.iso.org/iso-4217-currency-codes.html](https://www.iso.org/iso-4217-currency-codes.html) -- Currency codes - ISO 4217 + +37 [https://www.itu.int/rec/T-REC-E.164/en](https://www.itu.int/rec/T-REC-E.164/en) -- E.164 : The international public telecommunication numbering plan + +38 [https://tools.ietf.org/html/rfc3696](https://tools.ietf.org/html/rfc3696) -- Application Techniques for Checking and Transformation of Names + +39 [https://tools.ietf.org/html/rfc7231\#section-6.5](https://tools.ietf.org/html/rfc7231#section-6.5) -- Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Client Error 4xx \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/fspiop/v1.1/encryption.md b/website/versioned_docs/v1.0.1/api/fspiop/v1.1/encryption.md new file mode 100644 index 000000000..cc20c46b3 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/v1.1/encryption.md @@ -0,0 +1,635 @@ +# Encryption + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +The following conventions are used in this document to identify the specified types of information + +| **Type of Information** | **Convention** | **Example** | +| :--- | :--- | :--- | +| **Elements of the API, such as resources** | Boldface | **/authorization** | +| **Variables** | Italics within curly brackets | _{ID}_ | +| **Glossary terms** | Italics on first occurrence; defined in _Glossary_ | The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP. | +| **Library documents** | Italics | User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead. | + +### Document Version Information + +| **Version** | **Date** | **Change Description** | +| :--- | :--- | :--- | +|**1.1**|2020-05-19|This version contains these changes: 1. ExstensionList elements in Section 4 have been updated based on the issue [Interpretation of the Data Model for the ExtensionList element](https://github.com/mojaloop/mojaloop-specification/issues/51), to fix the data model of the extensionList Object.| +| **1.0** | 2018-03-13 | Initial version | + +
    + +## Introduction + +This document details security methods to be implemented for Open API (Application Programming Interface) for FSP (Financial Service Provider) Interoperability (hereafter cited as "the API") to ensure confidentiality of API messages between an API client and the API +server. + +In information security, _confidentiality_ means that information is not made available or disclosed to unauthorized individuals, entities, or processes (excerpt from ISO27000[The ISO 27000 Directory](http://www.27000.org)). For the API, confidentiality means that some sensitive fields in the payload of an API message cannot be accessed or identified in an unauthorized or undetected manner by the intermediaries involved in the API communication. That is, if some fields of an API message are encrypted by the API client, then only the expected API recipient can decrypt those fields. + +JSON Web Encryption (JWE, defined in RFC 7516[JSON Web Encryption (JWE)](https://tools.ietf.org/html/rfc7516)) must be applied to the API to provide end to end message confidentiality. When an API client sends an HTTP request (such as an API request or callback message) to a counterparty, the API client can determine whether there are sensitive fields in the API message to be protected according to the regulation or local schema. If there is a field to be protected, then the API client uses JWE to encrypt the value of that field. Subsequently, the cipher text of that field will be transmitted to the counterparty. + +To support encryption for multiple fields of an API message, JWE is extended in this document to adapt to the requirements of the API. + +
    + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](./logical-data-model) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./api-definition) + +- [JSON Binding Rules](../json-binding-rules) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](./v1.1/signature) + +- [Encryption](#) + +#### General Documents + +- [Glossary](./glossary) + +
    + +## API Encryption Definition + +This section introduces the technology used by API encryption, including: + +- Data exchange format for the encrypted fields of an API message. + +- Mechanism for encrypting and decrypting fields. + +### Encryption Data Model + +The API uses the customized HTTP header parameter **FSPIOP-Encryption** to represent the encrypted fields of an API message; its value is a JSON object serialization. The data model of this parameter is described in [Table 1](#table-1), [Table 2](#table-2) and [Table 3](#table-3). + +**Note**: If **FSPIOP-Encryption** is present in an API message, then it must also be protected by the API signature. That means **FSPIOP-Encryption** must be included in the JWS Protected Header of the signature. + +###### Table 1 + +| **Name** | **Cardinality** | **Type** | **Description** | +| :--- | :---: | :--- | :--- | +| **encryptedFields** | 1 | EncryptedFields | Information about the encrypted fields of an API message | +**Table 1 -- Data model of HTTP Header Field FSPIOP-Encryption** + +###### Table 2 + +| **Name** | **Cardinality** | **Type** | **Description** | +| :--- | :---: | :--- | :--- | +| **encryptedField** | 1..* | EncryptedField | Information about the encrypted field of an API message | +**Table 2 -- Data model of complex type EncryptedFields** + +###### Table 3 + +| **Name** | **Cardinality** | **Type** | **Description** | +| :--- | :---: | :--- | :--- | +|**fieldName** | 1 | String(1..512) | This element identifies the field to be encrypted in the payload of an API message.
    Because the API payload is a JSON Object serialization string, the field name must be able to identify the exact element path in the JSON Object. A single period ('**.**') character is used to separate the elements in an element path. For example, **payer.personalInfo.dateOfBirth** is a valid value for this element for the API request **POST /quotes**.
    | +| **encryptedKey** | 1 | String(1..512) | Encrypted Content Encryption Key (CEK) value. Its value is encoded by BASE64URL(JWE Encrypted Key).
    If there are multiple fields of the API message to be encrypted, we recommend that the same JWE Encrypted Key be used to simplify the implementation; however, this is a decision to be made by each FSP internally based on their implementation.
    | +|**protectedHeader** | 1 | String(1..1024) | This element identifies the Header Parameters that are applied to JWE to encrypt the specified field. Its value is encoded by BASE64URL(UTF8(JWE Protected Header)).
    For example, if the JWE Protected Header applied to the encryption is ```{"alg":"RSA-OAEP- 256","enc":"A256GCM"}```, then the value is ```eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ```.
    | +| **initializationVector** | 1 | String(1..128) | Initialization Vector value used when encrypting the plaintext. Its value is encoded by BASE64URL(JWE Initialization Vector). | +| **authenticationTag** | 1 | String(1..128) | Authentication Tag value resulting from authenticated encryption of the plaintext with Additional Authenticated Data. Its value is encoded by BASE64URL(JWE Authentication Tag) | +**Table 3 -- Data model of complex type EncryptedField** + +### Encrypt Fields of API Message + +This section describes the encryption process for message fields. The order of the steps is not significant in cases where there are no dependencies between the inputs and outputs of the steps. + +1. Determine the algorithm used to determine the CEK value (this is the algorithm recorded in the **alg** (algorithm) Header Parameter of the resulting JWE). Because the CEK should be encrypted with the public key of the API recipient, in the API the available algorithms to protect the CEK can only be **RSA-OAEP-256**. +2. If there are multiple fields to be encrypted in the API message, then perform Steps 3-15 for each field. +3. Generate a random CEK. The FSP can generate the value using either its own application or using the JWE implementation employed. +4. Encrypt the CEK with the algorithm determined by the JWE header parameter **alg**. +5. Compute the encoded key value BASE64URL(JWE Encrypted Key). +6. Generate a random JWE Initialization Vector of the correct size for the content encryption algorithm (if required for the algorithm); otherwise, let the JWE Initialization Vector be the empty octet sequence. +7. Compute the encoded Initialization Vector value BASE64URL(JWE Initialization Vector). +8. If a **zip** parameter was included, compress the plaintext using the specified compression algorithm and let *M* be the octet sequence representing the compressed plain text; otherwise, let _M_ be the octet sequence representing the plain text. +9. Create the JSON object or objects containing the desired set of header parameters, which together comprise the JWE Protected Header. Besides the parameter **alg**, the parameter **enc** must be included in the JWE Protected Header. The available values for the parameter **enc** in the API can only be: **A128GC**_M_, **A192GC**_M_, **A256GC**_M_. **A256GC**_M_ is recommended. +10. Compute the Encoded Protected Header value BASE64URL(UTF8(JWE Protected Header)). +11. Let the Additional Authenticated Data encryption parameter be ASCII(Encoded Protected Header). +12. Encrypt *M* using the CEK, the JWE Initialization Vector, and the Additional Authenticated Data value using the specified content encryption algorithm to create the JWE Cipher text value and the JWE Authentication Tag (which is the Authentication Tag output from the encryption operation). +13. Compute the encoded cipher text value BASE64URL(JWE Cipher Text). +14. Compute the encoded Authentication Tag value BASE64URL(JWE Authentication Tag). +15. Compute the **encryptedField** element (see Table 3) for the HTTP header parameter **FSPIOP-Encryption**. +16. Compute the value for the HTTP Header parameter **FSPIOP-Encryption** as described in [FSPIOP API](/fspiop) documentation. The value for this **FSPIOP-Encryption** is JSON Object Serialization string. + +**Note**: If JWE is used to encrypt some fields of the payload, then the API client should: + +1. Encrypt the desired fields. + +2. Replace those fields' value with the encoded cipher text in the payload. + +3. Sign the payload. + +### Decrypt Fields of API Message + +If the HTTP Header parameter **FSPIOP-Encryption** (which is also protected by the API signature) is present, then the API message recipient should decrypt the encrypted fields of the API message after the API signature is validated successfully. The message decryption process is the reverse of the encryption process. The order of the steps is not significant in cases where there are no dependencies between the inputs and outputs of the steps. If there are multiple fields being encrypted, then all fields must be decrypted successfully; otherwise it indicates the API message is invalid. + +1. Parse the HTTP Header parameter **FSPIOP-Encryption** to get encrypted fields' information, including field name, JWE Protected Header, JWE Encrypted Key, JWE Initialization Vector, and JWE Authentication Tag for each field. If there are multiple fields being encrypted, then perform Steps 2-9 for each encrypted field. +2. Get the cipher text of the encrypted field by parsing the payload with the specified field path. The value of the specified field is already encoded with BASE64URL. +3. Verify that the octet sequence resulting from decoding the encoded JWE Protected Header is a UTF-8-encoded representation of a valid JSON object conforming to JSON Data Interchange Format (defined in RFC 7159[The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc7159)); let the JWE Protected Header be this JSON object. +4. Verify that the parameters in the JWE Protected Header understand and can process all fields that are required to support the JWE specification; for example, the algorithm being used. +5. Determine that the algorithm specified by the **alg** (algorithm) Header Parameter matches the algorithm of the public / private key of the API recipient. +6. Decrypt the JWE Encrypted Key with the private key of the API recipient to get the JWE CEK. +7. Let the Additional Authenticated Data encryption parameter be ASCII(Encoded Protected Header). +8. Decrypt the JWE Cipher Text using the CEK, the JWE Initialization Vector, the Additional Authenticated Data value, and the JWE Authentication Tag (which is the Authentication Tag input to the calculation) using the specified content encryption algorithm, returning the decrypted plaintext and validating the JWE Authentication Tag in the manner specified for the algorithm. If the JWE Authentication Tag is incorrect, then reject the input without any decryption. +9. If a **zip** parameter was included, then the API recipient should decompress the decrypted plaintext using the specified compression algorithm. + +## API Encryption/Decryption Examples + +This section uses a typical quote process to explain how the API encryption and decryption are implemented using JWE. As the algorithm of public / private key of the API recipient can only be RSA, the RSA key used for this example is represented in JSON Web Key (JWK, defined in RFC 7517[JSON Web Key(JWK)](https://tools.ietf.org/html/rfc7517)) format below (with line breaks and indentation within values for display purposes only): + +```json +{ + "kty": "RSA", + "n": "oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E- + BVvxkeDNjbC4he8rUWcJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9Le + wND8MW2Krf3Spsk_ZkoFnilakGygTwpZ3uesH- + PFABNIUYpOiN15dsQRkgr0vEhxN92i2asbOenSZeyaxziK72UwxrrKoExv6kc5tw + XTq4h-QChLOln0_mtUZwfsRaMStPs6mS6XrgxnxbWhojf663tuEQueGC- + FCMfra36C9knDFGzKsNa7LZK2djYgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm- + L5StowjzGy-_bq6Gw", + "e": "AQAB", + "d": "kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4- + WY5NWV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD93D + t62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghkqDp0Vqj3 + kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vlt3UVe4WO3JkJOz + lpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K- + VFs3VSndVTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ", + "p": "1r52Xk46c-LsfB5P442p7atdPUrxQSy4mti_tZI3Mgf2EuFVbUoDBvaRQ- + SWxkbk- + moEzL7JXroSBjSrK3YIQgYdMgyAEPTPjXv_hI2_1eTSPVZfzL0lffNn03IXqWF5M + DFuoUYE0hzb2vhrlN_rKrbfDIwUbTrjjgieRbwC6Cl0", + "q": + "wLb35x7hmQWZsWJmB_vle87ihgZ19S8lBEROLIsZG4ayZVe9Hi9gDVCOBmUDdaD + YVTSNx_8Fyw1YYa9XGrGnDew00J28cRUoeBB_jKI1oma0Orv1T9aXIWxKwd4gvxF + ImOWr3QRL9KEBRzk2RatUBnmDZJTIAfwTs0g68UZHvtc", + "dp": "ZK- + YwE7diUh0qR1tR7w8WHtolDx3MZ_OTowiFvgfeQ3SiresXjm9gZ5KLhMXvo-uz- + KUJWDxS5pFQ_M0evdo1dKiRTjVw_x4NyqyXPM5nULPkcpU827rnpZzAJKpdhWAgq + rXGKAECQH0Xt4taznjnd_zVpAmZZq60WPMBMfKcuE", + "dq": + "Dq0gfgJ1DdFGXiLvQEZnuKEN0UUmsJBxkjydc3j4ZYdBiMRAy86x0vHCjywcMlY + Yg4yoC4YZa9hNVcsjqA3FeiL19rk8g6Qn29Tt0cj8qqyFpz9vNDBUfCAiJVeESOj + JDZPYHdHY8v1b-o-Z2X5tvLx-TCekf7oxyeKDUqKWjis", + "qi": "VIMpMYbPf47dT1w_zDUXfPimsSegnMOA1zTaX7aGk_8urY6R8- + ZW1FxU7AlWAyLWybqq6t16VFd7hQd0y6flUK4SlOydB61gwanOsXGOAOv82cHq0E + 3eL4HrtZkUuKvnPrMnsUUFlfUdybVzxyjz9JF_XyaY14ardLSjf4L_FNY" +} +``` + +### Encryption Example + +The following message text is an example of POST /quotes without encryption sent by Payer FSP to a Payee FSP. + +```json +POST /quotes HTTP/1.1 +FSPIOP-Destination:5678 +Accept:application/vnd.interoperability.quotes+json;version=1.0 +Content-Length:975 +Date:Tue, 23 May 2017 21:12:31 GMT +FSPIOP-Source:1234 +Content-Type:application/vnd.interoperability.quotes+json;version=1.0 +``` + +```json +{ + "payee": { + "partyIdInfo": { "partyIdType": "MSISDN", "partyIdentifier": "15295558888", + "fspId": "5678" } }, + "amountType": "RECEIVE", + "transactionType": { "scenario": "TRANSFER", "initiator": "PAYER", + "subScenario": "P2P Transfer across MM systems", "initiatorType": "CONSUMER" }, + "note": "this is a sample for POST /quotes", + "amount": { "amount": "150","currency": "USD" }, + "fees": { "amount": "1.5", "currency": "USD" }, + "extensionList": { + "extension": [ + { "value": "value1", "key": "key1"}, + { "value": "value2", "key": "key2"}, + { "value": "value3", "key": "key3" } + ] + }, + "geoCode": { "latitude": "57.323889", "longitude": "125.520001" + }, + "expiration": "2017-05-24T08:40:00.000-04:00", + "payer": { + "personalInfo": { + "complexName": { "firstName": "Bill", "middleName": "Ben", "LastName": "Lee" + }, "dateOfBirth": "1986-02-14" }, + "partyIdInfo": { "partyIdType": "MSISDN", + "partySubIdOrType": "RegisteredCustomer", "partyIdentifier": "16135551212", + "fspId": "1234" + }, "name": "Bill Lee" + }, "quoteId": "59e331fa-345f-4554-aac8-fcd8833f7d50", + "transactionId": "36629a51-393a-4e3c-b347-c2cb57e1e1fc" +} +``` + +In this case, the Payer FSP would like to encrypt two fields of the API message: **payer** and **payee.partyIdInfo.partyIdentifier**. + +#### Encrypt the Required Fields + +Because there are two fields to be encrypted, the Payer FSP needs to encrypt the two fields one-by-one. + +##### Encrypt "payer" + +The Payer FSP performs the following steps to encrypt the field **payer** in the **POST /quotes** API message. + +1. Determine the algorithm used to determine the CEK value. In this case, assuming it is **RSA-OAEP-256**. +2. Generate a 256-bit random CEK. In this case, its value is (using JSON Array notation): + +``` +191 100 167 60 2 248 21 136 172 39 145 120 102 7 73 31 166 66 114 199 219 157 104 162 7 253 10 105 33 136 57 167 +``` + +3. Encrypt the CEK with the Payee FSP's public key shown in JSON Web +Key format in [API Encryption/Decryption Examples](#api-encryptiondecryption-examples). In this case, the encrypted value is (using JSON Array notation): + +``` +22 210 45 47 153 95 183 79 84 26 194 42 27 152 50 195 163 18 235 121 140 120 224 129 180 120 21 0 46 196 21 114 251 148 127 75 198 42 87 250 186 98 15 136 249 131 224 73 111 108 159 140 107 156 80 30 133 77 86 26 28 13 66 83 248 229 132 77 203 113 229 24 208 155 81 172 9 164 25 126 206 217 25 206 30 218 38 190 128 196 250 233 34 47 86 91 157 140 87 240 29 119 126 136 168 10 87 246 213 23 104 114 215 134 71 87 46 55 131 174 15 193 194 90 194 208 212 15 24 33 143 38 253 125 121 175 220 202 106 95 127 129 192 2 72 137 14 40 147 207 166 239 161 248 159 203 52 223 103 129 54 83 85 199 211 228 56 82 83 135 166 103 42 76 191 146 80 40 192 123 42 18 31 113 25 198 24 58 87 149 47 182 144 86 182 137 253 103 214 34 192 76 254 64 14 114 97 194 28 60 75 164 131 170 210 231 168 205 181 78 79 136 82 115 218 174 5 48 158 162 230 229 164 85 26 135 15 164 206 36 182 131 115 224 207 12 178 234 145 6 181 140 243 41 8 151 +``` + +4. Compute the encoded key value BASE64URL(JWE Encrypted Key). In this case, its value is: + +``` +FtItL5lft09UGsIqG5gyw6MS63mMeOCBtHgVAC7EFXL7lH9LxipX-rpiD4j5g-BJb2yfjGucUB6 FTVYaHA1CU_jlhE3LceUY0JtRrAmkGX7O2RnOHtomvoDE-ukiL1ZbnYxX8B13foioClf21Rdoct eGR1cuN4OuD8HCWsLQ1A8YIY8m_X15r9zKal9_gcACSIkOKJPPpu-h-J_LNN9ngTZTVcfT5DhSU 4emZypMv5JQKMB7KhIfcRnGGDpXlS-2kFa2if1n1iLATP5ADnJhwhw8S6SDqtLnqM21Tk-IUnPa rgUwnqLm5aRVGocPpM4ktoNz4M8MsuqRBrWM8ykIlw +``` + +5. Generate a random JWE Initialization Vector of the correct size for the content encryption algorithm. In this case, its value is (using JSON Array notation): + +``` +101 98 192 15 167 157 93 152 54 145 173 236 83 4 6 243 +``` + +6. Compute the encoded Initialization Vector value BASE64URL(JWE Initialization Vector). In this case, its value is: + +``` +ZWLAD6edXZg2ka3sUwQG8w +``` + +7. Get the plaintext of the field **payer** of the API message as the payload to be encrypted. In this case, its value is: + +```json +{ + "personalInfo": { + "dateOfBirth": "1986-02-14", "complexName": { + "middleName": "Ben", "lastName": "Lee", "firstName": "Bill" } }, + "name": "Bill Lee", + "partyIdInfo": { "fspId": "1234", "partyIdType": "MSISDN", + "partySubIdOrType": "RegisteredCustomer", "partyIdentifier": "16135551212" + } +} +``` + +8. Create the JSON object or objects containing the desired set of header parameters, which together comprise the JWE Protected Header. In this case, its value is: + +```json +{"alg":"RSA-OAEP-256","enc":"A256GCM"} +``` + +9. Compute the Encoded Protected Header value BASE64URL(UTF8(JWE Protected Header)). In this case, its value is: + +``` +eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0 +``` + +10. Let the Additional Authenticated Data encryption parameter be ASCII(Base64URL(JWE Protected Header)). +11. Encrypt the plain text using the CEK, the JWE Initialization Vector, and the Additional Authenticated Data value using the specified content encryption algorithm to create the JWE Cipher text value and the JWE Authentication Tag (which is the Authentication Tag output from the encryption operation). +12. Compute the encoded cipher text value BASE64URL(JWE Cipher Text). In this case its value is: + +``` +BfXbxoyXcWCzL3DwG7B2P5UswlP8MPXerIkKbRR3vDLuN7lfa33puj7VICFeqG1fAlxrXgs_Nvk ZkE4WlqGNlQ_nBS1xYknxjh7hkPVb-V-Z9ZEvLdcaHlGJrH5oEvR7RIB8TOHgVHP1brlrEptB4- 4ejXXv80cbknRJtDl_mmjaU_Na4irGrWhA3ZhXZM1aM7wtquJLIk-1ZNLadGnGPygl21sEITF8h fPzbk7Djs45nBc5izWcoskCCNvLDU6PqOEhWe3y6GdsDiqFPB1OeZRq06ZBEfKZzAAJ0u3KZqoO BAEVHVvt41D3ejVimTVQJs1dVL2HacvuJyVW6YugwFotZbg +``` + +13. Compute the encoded Authentication Tag value BASE64URL(JWE Authentication Tag). In this case its value is: + +``` +9GaZEDZD9wmzqVGCI-FDgQ +``` + +##### Encrypt payee.partyIdInfo.partyIdentifier + +1. Determine the algorithm used to determine the CEK value. In this case, assuming it is **RSA-OAEP-256**. +2. Generate a 256-bit random CEK. In this case, the same CEK defined in [Encryption Data Model](#encryption-data-model) is used., Its value is (using JSON Array notation): + +``` +191 100 167 60 2 248 21 136 172 39 145 120 102 7 73 31 166 66 114 199 219 157 104 162 7 253 10 105 33 136 57 167 +``` + +3. Encrypt the CEK with the Payee FSP's public key represented in JSON Web Key format in [API Encryption/Decryption Examples](#api-encryptiondecryption-examples). In this case, its value is (using JSON Array notation): + +``` +149 174 138 153 221 70 241 229 93 27 56 185 185 210 242 238 81 187 207 88 40 43 24 7 245 121 94 73 151 150 249 19 15 158 11 97 80 99 194 60 143 138 168 211 202 210 52 19 128 211 156 179 101 248 95 163 23 166 217 222 14 12 163 206 242 182 170 211 119 22 84 107 3 97 153 207 240 211 82 113 100 254 39 62 224 183 250 176 156 63 198 73 245 187 239 16 136 127 120 130 146 236 29 47 255 116 223 240 39 224 94 165 102 120 242 9 182 84 138 109 205 55 242 20 186 91 140 49 198 244 250 58 123 3 63 22 51 59 5 183 112 17 160 238 34 217 11 109 79 246 174 221 138 118 82 21 15 239 72 185 77 20 178 20 192 89 45 68 140 190 251 233 82 123 33 49 191 135 49 21 25 42 253 171 211 151 7 238 142 206 201 140 206 6 129 23 173 56 153 159 31 39 52 119 102 147 197 213 230 97 113 71 168 184 6 57 183 109 173 233 206 110 112 202 179 74 56 153 184 122 114 234 151 28 15 131 79 192 80 145 130 170 188 82 92 61 121 90 63 148 37 110 20 132 49 131 +``` + +**Note**: Although the same CEK is used for the two fields **payer** and **payee.partyIdInfo.partyIdentifier**, the encrypted CEK values may be different from each other because of the use of a random number when encrypting the CEK by JWE implementations (for example, jose4j, nimbus-jose-jwt, and so on). This depends on how the JWE is implemented in each FSP system. +4. Compute the encoded key value BASE64URL(JWE Encrypted Key). In this case, its value is: + +``` +la6Kmd1G8eVdGzi5udLy7lG7z1goKxgH9XleSZeW-RMPngthUGPCPI-KqNPK0jQTgNOcs2X4X6M XptneDgyjzvK2qtN3FlRrA2GZz_DTUnFk_ic-4Lf6sJw_xkn1u--niH94gpLsHS__dN_wJ-BepW Z48gm2VIptzTfyFLpbjDHG9Po6ewM_FjM7BbdwEaDuItkLbU_2rt2KdlIVD-9IuU0UshTAWS1Ej L776VJ7ITG_hzEVGSr9q9OXB-6OzsmMzgaBF604mZ8fJzR3ZpPF1eZhcUeouAY5t22t6c5ucMqz SjiZuHpy6pccD4NPwFCRgqq8Ulw9eVo_lCVuFIQxgw +``` + +5. Generate a random JWE Initialization Vector of the correct size for the content encryption algorithm. In this case, its value is (using JSON Array notation): + +``` +86 250 136 87 147 231 201 138 65 75 164 215 147 100 136 195 +``` + +6. Compute the encoded Initialization Vector value BASE64URL(JWE Initialization Vector). In this case, its value is: + +``` +VvqIV5PnyYpBS6TXk2SIww +``` + +7. Get the plain text of the field **payee.partyIdInfo.partyIdentifier** of the API message as the payload to be encrypted. In this case, its value is + +``` +15295558888 +``` + +8. Create the JSON object or objects containing the desired set of Header Parameters, which together comprise the JWE Protected Header. In this case, its value is: + +```json +{"alg":"RSA-OAEP-256","enc":"A256GCM"} +``` + +9. Compute the Encoded Protected Header value BASE64URL(UTF8(JWE Protected Header)). In this case, its value is: + +``` +eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0 +``` + +10. Let the Additional Authenticated Data encryption parameter be ASCII(Encoded Protected Header). +11. Encrypt the plain text using the CEK, the JWE Initialization Vector, and the Additional Authenticated Data value using the specified content encryption algorithm to create the JWE Cipher text value and the JWE Authentication Tag (which is the Authentication Tag output from the encryption operation). +12. Compute the encoded cipher text value BASE64URL(JWE Cipher Text). In this case its value is: + +``` +WBQN5nLDGK26EiM +``` + +13. Compute the encoded Authentication Tag value BASE64URL(JWE Authentication Tag). In this case its value is: + +``` +6jQVo7kmZq3jMNXfavxoXQ +``` + +#### Producing FSPIOP-Encryption + +Using the given data model of the header **FSPIOP-Encryption**, get the header's value as shown below (line break and indentation are only for display purpose): + +```json +{ + "encryptedFields": + [ + { + "initializationVector":"ZWLAD6edXZg2ka3sUwQG8w", + "fieldName":"payer", + "encryptedKey":"FtItL5lft09UGsIqG5gyw6MS63mMeOCBtHgVAC7EFXL7lH9LxipX-rpiD4j5g- + BJb2yfjGucUB6FTVYaHA1CU_jlhE3LceUY0JtRrAmkGX7O2RnOHtomvoDE- + ukiL1ZbnYxX8B13foioClf21RdocteGR1cuN4OuD8HCWsLQ1A8YIY8m_X15r9zKal9_gcAC- + SIkOKJPPpu-h-J_LNN9ngTZTVcfT5DhSU4emZypMv5JQKMB7KhIfcRnGGDpXlS- + 2kFa2if1n1iLATP5ADnJhwhw8S6SDqtLnqM21Tk-IUnPargUwnqLm5aRVGo- + cPpM4ktoNz4M8MsuqRBrWM8ykIlw", + "authenticationTag":"9GaZEDZD9wmzqVGCI-FDgQ", + "protectedHeader":"eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0" + }, + { + "initializationVector":"VvqIV5PnyYpBS6TXk2SIww", + "fieldName":"payee.partyIdInfo.partyIdentifier", + "encryptedKey":"la6Kmd1G8eVdGzi5udLy7lG7z1goKxgH9XleSZeW-RMPngthUGPCPI- + KqNPK0jQTgNOcs2X4X6MXptneDgyjzvK2qtN3FlRrA2GZz_DTUnFk_ic-4Lf6sJw_xkn1u-- + niH94gpLsHS__dN_wJ-BepWZ48gm2VIptzTfyFLpbjDHG9Po6ewM_FjM7BbdwEa- + DuItkLbU_2rt2KdlIVD-9IuU0UshTAWS1EjL776VJ7ITG_hzEVGSr9q9OXB- + 6OzsmMzgaBF604mZ8fJzR3ZpPF1eZhcUeouAY5t22t6c5ucMqzS- + jiZuHpy6pccD4NPwFCRgqq8Ulw9eVo_lCVuFIQxgw", + "authenticationTag":"6jQVo7kmZq3jMNXfavxoXQ", + "protectedHeader":"eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0" + } + ] +} +``` + +#### Re-produce API message with encryption + +Using the cipher text of the encrypted field to replace the plain text of the corresponding field of the API message (the string with, **light grey** background in the message text below), add parameter **FSPIOP-Encryption** (the string with **light grey** background in the message text below) into the HTTP header of the API message. + +**Note**: The **FSPIOP-Encryption** parameter should be included in the JWS Protected Header for the signature of the API message, and the HTTP body of the API message below should be the JWS Payload for the signature. The signature process is out-of- scope for this document. + +```json +POST /quotes HTTP/1.1 +Accept:application/vnd.interoperability.quotes+json;version=1.0 +Content-Type:application/vnd.interoperability.quotes+json;version=1.0 +Date:Tue, 23 May 2017 21:12:31 GMT +FSPIOP-Source:1234 +FSPIOP-Destination:5678 +Content-Length:1068 +FSPIOP-Encryption: {"encryptedFields":{ + "initializationVector":"ZWLAD6edXZg2ka3sUwQG8w", + "fieldName":"payer", + "encryptedKey":"FtItL5lft09UGsIqG5gyw6MS63mMeOCBtHgVAC7EFXL7lH9LxipX- +rpiD4j5g-BJb2yfjGucUB6FTVYaHA1CU_jlhE3LceUY0JtRrAmkGX7O2RnOHtomvoDE- +ukiL1ZbnYxX8B13foioClf21RdocteGR1cuN4OuD8HCWsLQ1A8YIY8m_X15r9zKal9_gcACSIkOKJPPpu- +h-J_LNN9ngTZTVcfT5DhSU4emZypMv5JQKMB7KhIfcRnGGDpXlS- +2kFa2if1n1iLATP5ADnJhwhw8S6SDqtLnqM21Tk- +IUnPargUwnqLm5aRVGocPpM4ktoNz4M8MsuqRBrWM8ykIlw", + "authenticationTag":"9GaZEDZD9wmzqVGCI-FDgQ", + "protectedHeader":"eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0" + }, { + "initializationVector":"VvqIV5PnyYpBS6TXk2SIww", + "fieldName":"payee.partyIdInfo.partyIdentifier", + "encryptedKey":"la6Kmd1G8eVdGzi5udLy7lG7z1goKxgH9XleSZeW-RMPngthUGPCPI- +KqNPK0jQTgNOcs2X4X6MXptneDgyjzvK2qtN3FlRrA2GZz_DTUnFk_ic-4Lf6sJw_xkn1u-- +niH94gpLsHS__dN_wJ- +BepWZ48gm2VIptzTfyFLpbjDHG9Po6ewM_FjM7BbdwEaDuItkLbU_2rt2KdlIVD- +9IuU0UshTAWS1EjL776VJ7ITG_hzEVGSr9q9OXB- +6OzsmMzgaBF604mZ8fJzR3ZpPF1eZhcUeouAY5t22t6c5ucMqzSjiZuHpy6pccD4NPwFCRgqq8Ulw9eVo_lCVuFIQxgw", + "authenticationTag":"6jQVo7kmZq3jMNXfavxoXQ", + "protectedHeader":"eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0" + } + ] +} +{"amount":{"amount":"150","currency":"USD"},"transactionType":{"scenario":"TRANSFER","initiator":"PAYER","subScenario":"P2P Transfer across MM systems","initiatorType":"CONSUMER"},"transactionId":"36629a51-393a-4e3c-b347-c2cb57e1e1fc","quoteId":"59e331fa-345f-4554-aac8-fcd8833f7d50","payer":"BfXbcoyXcWCzL3DwG7B2P5UswlP8MPXerIkKbRR3vDLuN7lfa33puj7VICFeqG1fAlxrXgs_NvkZkE4WlqGNlQ_nBS1xYknxjh7hkPVb-B-Z9ZEvLdcaHlGJrH5oEvR7RIB8TOHgVHP1brlrEptB4-4ejXXv80cbknRJtDl_mmjaU_Na4irGrWhA3ZhXZM1aM7wtquJLIk-1ZNLadGnGPygl21sEITF8hfPzbk7Djs45nBc5izWcoskCCNvLDU6PqOEhWe3y6GdsDiqFPB10eZRq06ZBEfKZzAAJ0u3KZqoOBAEVHVvt41D3ejVimTVQJs1dVL2HacvuJyVW6ugwFotZbg","expiration":"2017-05-24T08:40:00.000-04:00","payee":{"partyIdInfo":{"fspId":"5678","partyIdType":"MSISDN","partyIdentifier":"WBQN5nLDGK26EiM"}},"fees":{"amount":"1.5","currency":"USD"},"extensionList":{"extension":[{"value":"value1","key":"key1"},{"value":"value2","key":"key2"},{"value":"value3","key":"key3"}]},"note":"this is a sample for POST/quotes","geoCode":{"longitude":"125.520001","latitude":"57.323889"},"amountType":"RECEIVE"} +``` + +### Decryption Example + +In this example, the Payee FSP receives the POST /quotes API message from Payer FSP. The message is described in [Encryption Data Model](#encryption-data-model). If the Payee FSP detects that the HTTP header parameter **FSPIOP-Encryption** is present in the message, then the Payee FSP knows that some fields were encrypted by the Payer FSP. The Payee FSP then performs the following steps to decrypt the encrypted fields.] + +#### Parse FSPIOP-Encryption + +The Payee FSP verifies that the value of **FSPIOP-Encryption** is a UTF-8-encoded representation of a valid JSON object conforming to RFC 7159. The FSP then parses the HTTP Header parameter **FSPIOP-Encryption** to get encrypted fields information, including field name, JWE Protected Header, JWE Encrypted Key, JWE Initialization Vector, and JWE Authentication Tag for each field. + +#### Decrypt the Encrypted Fields + +In this case, the Payee FSP gets two fields **payer** and **payee.partyIdInfo.partyIdentifier** from the HTTP header **FSPIOP- Encryption**. Then the Payee FSP decrypts the two fields one-by-one. + +##### Decrypt payer + +The Payer FSP performs the following steps to decrypt the field **payer** in the **POST /quotes** API message. + +1. Get the encoded BASE64RUL(JWE Protected Header) from the parsed **FSPIOP-Encryption** for the field **payer**. In this case its value is: + +``` +eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0 +``` + +2. Decode the encoded JWE Protected Header. In this case its value is: + +```json +{"alg":"RSA-OAEP-256","enc":"A256GCM" +``` + +3. Check that the decoded value of JWE Protected Header is a UTF-8-encoded representation of a completely valid JSON object conforming to JSON Data Interchange Format (RFC 7159), and that the parameters in the JWE Protected Header can process all fields that are required to support the JWE specification. +4. Get the encoded BASE64URL(JWE Encrypted Key). In this case its value is: + +``` +FtItL5lft09UGsIqG5gyw6MS63mMeOCBtHgVAC7EFXL7lH9LxipX-rpiD4j5g-BJb2yfjGucUB6 FTVYaHA1CU_jlhE3LceUY0JtRrAmkGX7O2RnOHtomvoDE-ukiL1ZbnYxX8B13foioClf21Rdoct eGR1cuN4OuD8HCWsLQ1A8YIY8m_X15r9zKal9_gcACSIkOKJPPpu-h-J_LNN9ngTZTVcfT5DhSU 4emZypMv5JQKMB7KhIfcRnGGDpXlS-2kFa2if1n1iLATP5ADnJhwhw8S6SDqtLnqM21Tk-IUnPa rgUwnqLm5aRVGocPpM4ktoNz4M8MsuqRBrWM8ykIlw] +``` + +5. Decode the encoded JWE Encrypted Key. In this case its value is as follows (using JSON Array notation): + +``` +[22 210 45 47 153 95 183 79 84 26 194 42 27 152 50 195 163 18 235 121 140 120 224 129 180 120 21 0 46 196 21 114 251 148 127 75 198 42 87 250 186 98 15 136 249 131 224 73 111 108 159 140 107 156 80 30 133 77 86 26 28 13 66 83 248 229 132 77 203 113 229 24 208 155 81 172 9 164 25 126 206 217 25 206 30 218 38 190 128 196 250 233 34 47 86 91 157 140 87 240 29 119 126 136 168 10 87 246 213 23 104 114 215 134 71 87 46 55 131 174 15 193 194 90 194 208 212 15 24 33 143 38 253 125 121 175 220 202 106 95 127 129 192 2 72 137 14 40 147 207 166 239 161 248 159 203 52 223 103 129 54 83 85 199 211 228 56 82 83 135 166 103 42 76 191 146 80 40 192 123 42 18 31 113 25 198 24 58 87 149 47 182 144 86 182 137 253 103 214 34 192 76 254 64 14 114 97 194 28 60 75 164 131 170 210 231 168 205 181 78 79 136 82 115 218 174 5 48 158 162 230 229 164 85 26 135 15 164 206 36 182 131 115 224 207 12 178 234 145 6 181 140 243 41 8 151] +``` + +6. Decrypt the JWE Encrypted Key using the specified algorithm **RSA-OAEP-256** with the Payee FSP's private key to get the CEK. In this case the decrypted CEK is (using JSON Array notat ion): + +``` +[191 100 167 60 2 248 21 136 172 39 145 120 102 7 73 31 166 66 114 199 219 157 104 162 7 253 10 105 33 136 57 167] +``` + +7. Get the encoded BASE64URL(JWE Initialization Vector). Its value is: + +``` +ZWLAD6edXZg2ka3sUwQG8w +``` + +8. Decode the encoded JWE Initialization Vector. In this case, its value is (using JSON Array notation): + +``` +[101 98 192 15 167 157 93 152 54 145 173 236 83 4 6 243] +``` + +9. Get the value of the field **payer** from the API message as the encoded BASE64URL(JWE Cipher Text) to be decrypted. In this case, its value is + +``` +BfXbxoyXcWCzL3DwG7B2P5UswlP8MPXerIkKbRR3vDLuN7lfa33puj7VICFeqG1fAlxrXgs\_Nvk ZkE4WlqGNlQ\_nBS1xYknxjh7hkPVb-V-Z9ZEvLdcaHlGJrH5oEvR7RIB8TOHgVHP1brlrEptB4- 4ejXXv80cbknRJtDl\_mmjaU\_Na4irGrWhA3ZhXZM1aM7wtquJLIk-1ZNLadGnGPygl21sEITF8h fPzbk7Djs45nBc5izWcoskCCNvLDU6PqOEhWe3y6GdsDiqFPB1OeZRq06ZBEfKZzAAJ0u3KZqoO BAEVHVvt41D3ejVimTVQJs1dVL2HacvuJyVW6YugwFotZbg +``` + +10. Get the encoded Authentication Tag value BASE64URL(JWE Authentication Tag). In this case its value is: + +``` +9GaZEDZD9wmzqVGCI-FDgQ +``` + +11. Decrypt the cipher text using the CEK, the JWE Initialization Vector, and the Additional Authenticated Data value using the specified content encryption algorithm to decrypt the JWE Cipher text. In this case, the plain text is + +```json +{ + "personalInfo": { + "dateOfBirth": "1986-02-14", + "complexName": { "middleName": "Ben", "lastName": "Lee", + "firstName": "Bill" } }, + "name": "Bill Lee", + "partyIdInfo": { + "fspId": "1234", "partyIdType": "MSISDN", + "partySubIdOrType": "RegisteredCustomer", "partyIdentifier": + "16135551212" + } +} +``` + +12. Verify that the plaintext is a UTF-8-encoded representation of a completely valid JSON object conforming to RFC 7159, and the content matches the data mode definition for the **payer**. + +##### Decrypt payee.partyIdInfo.partyIdentifier + +The Payer FSP performs the following steps to decrypt the field **payee.partyIdInfo.partyIdentifier** in the **POST /quotes** API message. + +1. Get the encoded BASE64RUL(JWE Protected Header) from the parsed **FSPIOP-Encryption** for the field **payee.partyIdInfo.partyIdentifier**. In this case its value is: + +``` +eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0 +``` + +2. Decode the encoded JWE Protected Header. In this case its value is: + +```json +{"alg":"RSA-OAEP-256","enc":"A256GCM"} +``` + +3. Verify that the decoded value of JWE Protected Header is a UTF-8-encoded representation of a completely valid JSON object conforming to RFC 7159, and that the parameters in the JWE Protected Header understand and can process all fields that are required to support the JWE specification. +4. Get the encoded BASE64URL(JWE Encrypted Key). In this case its value is: + +``` +la6Kmd1G8eVdGzi5udLy7lG7z1goKxgH9XleSZeW-RMPngthUGPCPI-KqNPK0jQTgNOcs2X4X6M XptneDgyjzvK2qtN3FlRrA2GZz_DTUnFk_ic-4Lf6sJw_xkn1u--niH94gpLsHS__dN_wJ-BepW Z48gm2VIptzTfyFLpbjDHG9Po6ewM_FjM7BbdwEaDuItkLbU_2rt2KdlIVD-9IuU0UshTAWS1Ej L776VJ7ITG_hzEVGSr9q9OXB-6OzsmMzgaBF604mZ8fJzR3ZpPF1eZhcUeouAY5t22t6c5ucMqz SjiZuHpy6pccD4NPwFCRgqq8Ulw9eVo_lCVuFIQxgw +``` + +5. Decode the encoded JWE Encrypted Key. In this case its value is (using JSON Array notation): + +``` +[149 174 138 153 221 70 241 229 93 27 56 185 185 210 242 238 81 187 207 88 40 43 24 7 245 121 94 73 151 150 249 19 15 158 11 97 80 99 194 60 143 138 168 211 202 210 52 19 128 211 156 179 101 248 95 163 23 166 217 222 14 12 163 206 242 182 170 211 119 22 84 107 3 97 153 207 240 211 82 113 100 254 39 62 224 183 250 176 156 63 198 73 245 187 239 167 136 127 120 130 146 236 29 47 255 116 223 240 39 224 94 165 102 120 242 9 182 84 138 109 205 55 242 20 186 91 140 49 198 244 250 58 123 3 63 22 51 59 5 183 112 17 160 238 34 217 11 109 79 246 174 221 138 118 82 21 15 239 72 185 77 20 178 20 192 89 45 68 140 190 251 233 82 123 33 49 191 135 49 21 25 42 253 171 211 151 7 238 142 206 201 140 206 6 129 23 173 56 153 159 31 39 52 119 102 147 197 213 230 97 113 71 168 184 6 57 183 109 173 233 206 110 112 202 179 74 56 153 184 122 114 234 151 28 15 131 79 192 80 145 130 170 188 82 92 61 121 90 63 148 37 110 20 132 49 131] +``` + +6. Decrypt the JWE Encrypted Key using the specified algorithm **RSA-OAEP-256** with the Payee FSP's private key to get the CEK. In this case the decrypted CEK is (using JSON Array notation): + +``` +[191 100 167 60 2 248 21 136 172 39 145 120 102 7 73 31 166 66 114 199 219 157 104 162 7 253 10 105 33 136 57 167] +``` + +7. Get the encoded BASE64URL(JWE Initialization Vector). Its value is: + +``` +VvqIV5PnyYpBS6TXk2SIww +``` + +8. Decode the encoded JWE Initialization Vector. In this case, its value is (using JSON Array notation): + +``` +[86 250 136 87 147 231 201 138 65 75 164 215 147 100 136 195] +``` + +9. Get the value of the field **payee.partyIdInfo.partyIdentifier** from the API message as the encoded BASE64URL(JWE Cipher Text) to be decrypted. In this case, its value is: + +``` +WBQN5nLDGK26EiM +``` + +10. Get the encoded Authentication Tag value BASE64URL(JWE Authentication Tag). In this case its value is: + +``` +6jQVo7kmZq3jMNXfavxoXQ +``` + +11. Decrypt the cipher text using the CEK, the JWE Initialization Vector, and the Additional Authenticated Data value using the specified content encryption algorithm to decrypt the JWE Cipher text. In this case, the plain text is + +``` +15295558888 +``` + +12. Verify that the plain text is a valid **partyIdentifier** value. + +
    + +## Table of Tables +- [Table 1 -- Data model of HTTP Header Field FSPIOP-Encryption](#table-1) +- [Table 2 -- Data model of complex type EncryptedFields](#table-2) +- [Table 3 -- Data model of complex type EncryptedField](#table-3) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/fspiop/v1.1/signature.md b/website/versioned_docs/v1.0.1/api/fspiop/v1.1/signature.md new file mode 100644 index 000000000..42f8f32ed --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/fspiop/v1.1/signature.md @@ -0,0 +1,423 @@ +# Signature + +## Preface + +This section contains information about how to use this document. + +### Conventions Used in This Document + +This document uses the notational conventions for BASE64URL(OCTETS), UTF8(STRING), ASCII(STRING), and || defined in RFC 7515[1](https://tools.ietf.org/html/rfc7515#section-1.1). + +The following conventions are used in this document to identify the specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics within curly brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature_ and _API Encryption_ should be used instead.| + +### Document Version Information + +|Version|Date|Change Description| +|---|---|---| +|**1.1**|2020-05-19|This version contains the below changes: 1. Sections 3.1, 3.2 and 3.3 have been updated based on ”Solution Proposal 12 - Clarify usage of FSPIOP-Destination”. 2. ExtensionList elements in Section 4 have been updated based on the issue [Interpretation of the Data Model for the ExtensionList element](https://github.com/mojaloop/mojaloop-specification/issues/51), to fix the data model of the extensionList Object.| +|**1.0**|2018-03-13|Initial version| + +
    + +## Introduction + +This document details the security methods to be implemented for Open API for FSP Interoperability (hereafter cited as the API) to ensure _integrity_ and _non-repudiation_ between the API client and the API server. + +In information security, _data integrity_ means maintaining and assuring the accuracy and completeness of data over its entire life-cycle. For the API, data integrity means that an API message cannot be modified in an unauthorized or undetected manner by parties involved in the API communication. + +In legal terms, _non-repudiation_ means that a person intends to fulfill their obligations to a contract. It also means that one party in a transaction cannot deny having received the transaction, nor can the other party deny having sent the transaction. For the API, non-repudiation means that an API client cannot deny having sent an API message to a counterparty. JSON Web Signature (JWS), as defined in RFC 7515[2](https://tools.ietf.org/html/rfc7515), must be applied to the API to provide message integrity and non-repudiation for either component fields of an API payload or the full API payload. Whenever an API client sends an API message to a counterparty, the API client should sign the message using its private key. After the counterparty receives the API message, the counterparty must validate the signature with the API client’s public key. Only the HTTP request message of an API message need to be signed, any HTTP response message of the APIs SHALL NOT be signed. + +**Note:** The corresponding public key should either be shared in advance with the counterparty or retrieved by the counterparty (for example, the local scheme Certificate Authority). + +Because intermediary fees are not supported in the current version of the API, intermediaries involved in API message-transit may not modify the API message payload. Thus, the signature at full payload level is used to protect the integrity of the full payload of an API message from end-to-end. Regardless of how many intermediaries there are in transit, the original payload cannot be modified by the intermediaries. The final recipient of the API message must validate the signature generated by the original API client based on the message payload received. + +**Note:** Whether the signature needs to be validated by the intermediaries in transit is determined by the internal implementation of each intermediary or the local schema. + +**Note:** In a future version of the API, intermediary fees may be supported; at that time, signature-at-field-level may also be supported. However, both features are out-of-scope for the current version of the API. + +
    + +### Open API for FSP Interoperability Specification + +The Open API for FSP Interoperability Specification includes the following documents. + +#### Logical Documents + +- [Logical Data Model](./logical-data-model) + +- [Generic Transaction Patterns](./generic-transaction-patterns) + +- [Use Cases](./use-cases) + +#### Asynchronous REST Binding Documents + +- [API Definition](./definitions) + +- [JSON Binding Rules](./json-binding-rules) + +- [Scheme Rules](./scheme-rules) + +#### Data Integrity, Confidentiality, and Non-Repudiation + +- [PKI Best Practices](./pki-best-practices) + +- [Signature](#) + +- [Encryption](./v1.1/encryption) + +#### General Documents + +- [Glossary](../glossary) + +
    + +## API Signature Definition + +This section introduces the technology used by the API signature, including the data exchange format for the signature of an API message and the mechanism used to generate and verify a signature. + + +### Signature Data Model + +The API uses a customized HTTP header parameter **FSPIOP-Signature** to represent the signature that is produced by the initiating API client for the API message. The data model for this parameter is described in [Table 1](#table-1). + +**Note:** Currently the API does not support intermediaries in an API message; only the message-initiator can sign a message. If this is required in the future, there will be new customized HTTP header parameter, but this is out-of-scope for the current version of the API. + +###### Table 1 + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| protectedHeader | 1 | String(1..32768) |
    This element indicates the HTTP header parameters that are protected by the signature. Its value must be BASE64URL(UTF8(JWS Protected Header)).

    According to JWS specification, the **alg** header parameter must be present to identify the cryptographic algorithm used to secure the JWS.

    A customized parameter **FSPIOP-URI** that represents the URI path and query parameters of HTTP request message of the APIs must be present.

    A customized parameter **FSPIOP-HTTP-Method** that holds the HTTP method used in the HTTP message must be present.

    A customized parameter **FSPIOP-Source** that represents the system which sent the API request must be present.

    The customized HTTP header parameter **FSPIOP-Destination** is mandatory in protectedHeader if the destination FSP is known by the message-initiator. Otherwise this header must not be protected as it can be changed by intermediate systems. See API Definition for more information regarding which services that the header FSPIOP-Destination is optional for.
    | +| signature | 1 | String(1..512) | This element indicates the signature. Its value is part of JWS serialization; that is, BASE64URL(JWS Signature). | +**Table 1 – Data model of HTTP header field FSPIOP-Signature** + +### Generating a Signature + +To create the signature for an API message, the following steps are performed. The order of the steps is not significant in cases where there are no dependencies between the inputs and outputs of the steps. + +1. Create the content to be used as the JWS Payload. Because the signature is currently at full payload level, the full HTTP body of the API message is the JWS Payload. + +2. Compute the encoded payload value BASE64URL(JWS Payload). + +3. Create the JSON object or objects containing the desired JWS Protected Header. + + A. The **alg** JWS Protected Header parameter must be present. In the API, the available algorithms for the signature are **RS256, RS384, RS512**. A key of size 2048 bits or larger must be used with these algorithms. + + B. Other parameters registered in the IANA JSON _Web Signature and Encryption Header Parameters_[3](https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-header-parameters) are optional. + + C. The customized parameter **FSPIOP-URI** must be included in JWS Protected Header to protect the URI path and query parameters of the APIs. + + D. The customized parameter **FSPIOP-HTTP-Method** must be included in JWS Protected Header to protect the HTTP request operation method. + + E. The parameter **FSPIOP-Source** must be present, and its value comes from the corresponding HTTP header parameter **FSPIOP-Source**. + + F. The parameter **FSPIOP-Destination** must be present if the destination FSP is known by the message-initiator, and its value must then be the same as the HTTP header parameter **FSPIOP-Destination**. + + G. Other HTTP Header parameters of the APIs are recommended to be included in JWS Protected Header, but they are optional in this JWS Protected Header. + +4. Compute the encoded header value BASE64URL(UTF8(JWS Protected Header)). + +5. Compute the JWS Signature according to the JWS specification using the output of Step 2 and Step 4. + +6. Compute the encoded signature value BASE64URL(JWS Signature). + +7. Compute the value for the HTTP header parameter **FSPIOP-Signature** as described in the [Signature Data Model](#signature-data-model) section. The value for this **FSPIOP-Signature** is a JSON Object Serialization string. + +**Note:** If JSON Web Encryption (JWE) is used to encrypt some fields of the payload (for more information, see Encryption), then the API client should first encrypt the desired fields, then replace the plain text of those fields with the encoded cipher text in the payload, and then finally sign the payload. + +### Validating Signature + +When validating the signature of an API request, the following steps are performed. The order of the steps is not significant in cases where there are no dependencies between the inputs and outputs of the steps. If any of the listed steps fails, then the signature cannot be validated. + +1. Parse the HTTP header parameter **FSPIOP-Signature** to get the components **protectedHeader** and **signature**. + +2. Use BASE64URL to decode the encoded representation of the JWS Protected Header. Verify that the resulting octet sequence is a UTF-8-encoded representation of a completely valid JSON object conforming to JSON Data Interchange Format, defined in RFC 7159[4](https://tools.ietf.org/html/rfc7159). + +3. Verify the parameters in the JWS Protected Header. + + a) The parameter **alg** must be present and its value must be one of **RS256, RS384, RS512**. + + b) Other parameters registered in the IANA JSON _Web Signature and Encryption Header Parameters_ are optional. + + c) The parameter **FSPIOP-URI** must be present and Its value must be the same as the input URL value of the request. + + d) The parameter **FSPIOP-HTTP-Method** must be present and its value must be same as the operation method of the request. + + e) The parameter **FSPIOP-Source** must be present, and its value must be the same as the corresponding HTTP header parameter **FSPIOP-Source**. + + f) If the parameter **FSPIOP-Destination** is present in the JWS Protected Header, then its value must be same as the corresponding HTTP header parameter **FSPIOP-Destination**. + + g) If there are other HTTP header parameters present in JWS Protected Header, then their values must be validated with the corresponding HTTP header values. + +4. Compute the encoded payload value BASE64URL(JWS Payload). Because the current signature is at full payload level, the full HTTP body of the API message is the JWS Payload. + +5. Validate the JWS Signature against the JWS Signing Input ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload)) in the manner defined for the algorithm being used, which must be accurately represented by the value of the **alg** (algorithm) Header Parameter. + +6. Record whether the validation succeeded. + +
    + +## API Signature Examples + +This section uses a typical quote process to explain how the API signature is implemented using JWS. The FSPs in the API can verify that their internal implementation for API signature is correct using the following case. + +The case in this section uses RS256 as the signature algorithm. The RSA key used for the signature example is represented in JSON Web Key (JWK), defined in RFC 7517[5](https://tools.ietf.org/html/rfc7517), format below (with line breaks and indentation within values for display purposes only): + +```json +{ + "kty": "RSA", + "n": "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddxHmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMsD1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSHSXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ", + "e": "AQAB", + "d": "Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97IjlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYTCBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLhBOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ", + "p": "4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdiYrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPGBY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc", + "q": "uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxaewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc", + "dp": "BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3QCLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0", + "dq": "h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-kyNlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU", + "qi": "IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2oy26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLUW0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U" +} +``` + +### Generating a Sample Signature + +The following message text is an example of `POST /quotes` without a signature sent by Payer FSP to a counterparty (line breaks and indentation within values for display purposes only). + +```json +POST /quotes HTTP/1.1 +Accept:application/vnd.interoperability.quotes+json;version=1.0 +FSPIOP-Source:1234 +FSPIOP-Destination:5678 +Content-Length:975 +Date:Tue, 23 May 2017 21:12:31 GMT +Content-Type:application/vnd.interoperability.quotes+json;version=1.0 +{ + "amount": { "amount": "150", "currency": "USD" },"transactionType": { + "scenario": "TRANSFER", "initiator": "PAYER","subScenario": "P2P Transfer across MM systems","initiatorType": "CONSUMER" + }, + "transactionId": "36629a51-393a-4e3c-b347-c2cb57e1e1fc","quoteId": "59e331fa-345f-4554-aac8-fcd8833f7d50","expiration": "2017-05-24T08:40:00.000-04:00", + "payer": { + "personalInfo": { + "dateOfBirth": "1986-02-14", + "complexName": { "middleName": "Ben", + "LastName": "Lee", "firstName": "Bill" } }, + "name": "Bill Lee", + "partyIdInfo": { "fspId": "1234", "partyIdType": "MSISDN", + "partySubIdOrType": "RegisteredCustomer","partyIdentifier": "16135551212" } + }, + "payee": { + "partyIdInfo": { "fspId": "5678", + "partyIdType": "MSISDN", + "partyIdentifier": "15295558888" } + }, + "fees": { "amount": "1.5", "currency": "USD" }, + "extensionList": { + "extension": [ + { "value": "value1", "key": "key1" }, + { "value": "value2", "key": "key2" }, + { "value": "value3", "key": "key3" } + ] + }, + "note": "this is a sample for POST /quotes", + "geoCode": { + "longitude": "125.520001", "latitude": "57.323889" }, + "amountType": "RECEIVE" +} +``` + +#### Computing Signature Input + +According to JWS specification, the signature input is BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload). + +Assuming the HTTP header parameters **Date** and **FSPIOP-Destination** are protected by the signature, and the algorithm RS256 is used to sign the message, the JWS Protected Header in this case is as follows (line breaks and indentation within values for display purposes only): + +```json +{ + "alg":"RS256", + "FSPIOP-Destination":"5678", + "FSPIOP-URI":"/quotes", + "FSPIOP-HTTP-Method":"POST", + "Date":"Tue, 23 May 2017 21:12:31 GMT", + "FSPIOP-Source":"1234" +} +``` + +Encoding this JWS Protected Header as BASE64URL(UTF8(JWS Protected Header)) gives this value: + +``` +eyJhbGciOiJSUzI1NiIsIkZTUElPUC1EZXN0aW5hdGlvbiI6IjU2NzgiLCJGU1BJT1AtVVJJIjoiL3F1b3RlcyIsIkZTUElPUC1IVFRQLU1ldGhvZCI6IlBPU1QiLCJEYXRlIjoiVHVlLCAyMyBNYXkgMjAxNyAyMToxMjozMSBHTVQiLCJGU1BJT1AtU291cmNlIjoiMTIzNCJ9 +``` + +In this case, JWS Payload is the HTTP Body described in [Generating A Signature](#generating-a-signature) section. Encoding this JWS Payload as BASE64URL(JWS Payload) gives this value: + +``` +eyJwYXllZSI6eyJwYXJ0eUlkSW5mbyI6eyJwYXJ0eUlkVHlwZSI6Ik1TSVNETiIsInBhcnR5SWRlbnRpZmllciI6IjE1Mjk1NTU4ODg4IiwiZnNwSWQiOiI1Njc4In19LCJhbW91bnRUeXBlIjoiUkVDRUlWRSIsInRyYW5zYWN0aW9uVHlwZSI6eyJzY2VuYXJpbyI6IlRSQU5TRkVSIiwiaW5pdGlhdG9yIjoiUEFZRVIiLCJzdWJTY2VuYXJpbyI6IlAyUCBUcmFuc2ZlciBhY3Jvc3MgTU0gc3lzdGVtcyIsImluaXRpYXRvclR5cGUiOiJDT05TVU1FUiJ9LCJub3RlIjoidGhpcyBpcyBhIHNhbXBsZSBmb3IgUE9TVCAvcXVvdGVzIiwiYW1vdW50Ijp7ImFtb3VudCI6IjE1MCIsImN1cnJlbmN5IjoiVVNEIn0sImZlZXMiOnsiYW1vdW50IjoiMS41IiwiY3VycmVuY3kiOiJVU0QifSwiZXh0ZW5zaW9uTGlzdCI6W3sidmFsdWUiOiJ2YWx1ZTEiLCJrZXkiOiJrZXkxIn0seyJ2YWx1ZSI6InZhbHVlMiIsImtleSI6ImtleTIifSx7InZhbHVlIjoidmFsdWUzIiwia2V5Ijoia2V5MyJ9XSwiZ2VvQ29kZSI6eyJsYXRpdHVkZSI6IjU3LjMyMzg4OSIsImxvbmdpdHVkZSI6IjEyNS41MjAwMDEifSwiZXhwaXJhdGlvbiI6IjIwMTctMDUtMjRUMDg6NDA6MDAuMDAwLTA0OjAwIiwicGF5ZXIiOnsicGVyc29uYWxJbmZvIjp7ImNvbXBsZXhOYW1lIjp7ImZpcnN0TmFtZSI6IkJpbGwiLCJtaWRkbGVOYW1lIjoiQmVuIiwiTGFzdE5hbWUiOiJMZWUifSwiZGF0ZU9mQmlydGgiOiIxOTg2LTAyLTE0In0sInBhcnR5SWRJbmZvIjp7InBhcnR5SWRUeXBlIjoiTVNJU0ROIiwicGFydHlTdWJJZE9yVHlwZSI6IlJlZ2lzdGVyZWRDdXN0b21lciIsInBhcnR5SWRlbnRpZmllciI6IjE2MTM1NTUxMjEyIiwiZnNwSWQiOiIxMjM0In0sIm5hbWUiOiJCaWxsIExlZSJ9LCJxdW90ZUlkIjoiNTllMzMxZmEtMzQ1Zi00NTU0LWFhYzgtZmNkODgzM2Y3ZDUwIiwidHJhbnNhY3Rpb25JZCI6IjM2NjI5YTUxLTM5M2EtNGUzYy1iMzQ3LWMyY2I1N2UxZTFmYyJ9 +``` + +#### Producing Signature + +Use the given RSA Private Key, the JWS Protected Header and the JWS Payload to generate the signature, then encoding the signature as BASE64URL(JWS Signature) produces this value: + +``` +dz2ntyS0_rDyA0pLeWluG--tBcYYrlvG99ffkXcEB-dz2ntyS0_rDyA0pLeWluG--tBcYYrlvG99ffkXcEB-uve5Qzvzyn0ZUi82J7h17RsdfHPuTnbEGvCeU9Y4Bg0nIZHGL4icswaaO09T5hPPYKBTzVQeHkokLmL4dXpHdr1ggSEpu3WEU3nfgOFGGAdOq355i1iGuDbhqm_lSfVHaqdVCEhkJ2Y_r2glO2QpdZrcbvsBV39derj_PlfISBBGjdh0dIPxnFIVcZuPHiq9Ha2MslrBHfqwFfNeU_xhErBd2PywkDQJbKOlfqdkmFC9bS8Ofx0O6Mg7qdFGw-QkseJTfp0HMbH1d9e6H0cocY8xfuDNGaZpOJhxiYtiPLg +``` + +#### Re-produce API Request with Signature + +As described in the [Signature Data Model](#signature-data-model) section, the API signature is represented by a customized HTTP header parameter **FSPIOP-Signature**; thus the API request with the signature in this case is the following message text (line breaks and indentation within values for display purposes only). + +```json +POST /quotes HTTP/1.1 +FSPIOP-Destination:5678 +Accept:application/vnd.interoperability.quotes+json;version=1.0 +Content-Length:975 +Date:Tue, 23 May 2017 21:12:31 GMT +FSPIOP-Source:1234 +Content-Type:application/vnd.interoperability.quotes+json;version=1.0 +FSPIOP-Signature: {"signature": "dz2ntyS0_rDyA0pLeWluG--tBcYYrlvG99ffkXcEBuve5Qzvzyn0ZUi82J7h17RsdfHPuTnbEGvCeU9Y4Bg0nIZHGL4icswaaO09T5hPPYKBTzVQeHkokLmL4dXpHdr1ggSEpu3WEU3nfgOFGGAdOq355i1iGuDbhqm_lSfVHaqdVCEhkJ2Y_r2glO2QpdZrcbvsBV39derj_PlfISBBGjdh0dIPxnFIVcZuPHiq9Ha2MslrBHfqwFfNeU_xhErBd2PywkDQJbKOlfqdkmFC9bS8Ofx0O6Mg7qdFGwQkseJTfp0HMbH1d9e6H0cocY8xfuDNGaZpOJhxiYtiPLg", "protectedHeader": "eyJhbGciOiJSUzI1NiIsIkZTUElPUC1EZXN0aW5hdGlvbiI6IjU2NzgiLCJGU1BJT1AtVVJJIjoiL3F1b3RlcyIsIkZTUElPUC1IVFRQLU1ldGhvZCI6IlBPU1QiLCJEYXRlIjoiVHVlLCAyMyBNYXkgMjAxNyAyMToxMjozMSBHTVQiLCJGU1BJT1AtU291cmNlIjoiMTIzNCJ9" +} +{ + "amount": { "amount": "150", "currency": "USD" }, + "transactionType": { + "scenario": "TRANSFER", "initiator": "PAYER", + "subScenario": "P2P Transfer across MM systems", + "initiatorType": "CONSUMER" }, + "transactionId": "36629a51-393a-4e3c-b347-c2cb57e1e1fc", + "quoteId": "59e331fa-345f-4554-aac8-fcd8833f7d50", + "expiration": "2017-05-24T08:40:00.000-04:00", + "payer": { + "personalInfo": { "dateOfBirth": "1986-02-14", + "complexName": { "middleName": "Ben", + "LastName": "Lee", "firstName": "Bill" } }, + "name": "Bill Lee", + "partyIdInfo": { "fspId": "1234", "partyIdType": "MSISDN", + "partySubIdOrType": "RegisteredCustomer", + "partyIdentifier": "16135551212" } }, + "payee": { "partyIdInfo": { "fspId": "5678", + "partyIdType": "MSISDN", + "partyIdentifier": "15295558888" } }, + "fees": { "amount": "1.5", "currency": "USD" }, + "extensionList": { + "extension": [ + { "value": "value1", "key": "key1" }, + { "value": "value2", "key": "key2" }, + { "value": "value3", "key": "key3" } + ] + }, + "note": "this is a sample for POST /quotes", + "geoCode": { "longitude": "125.520001", "latitude": "57.323889" }, + "amountType": "RECEIVE" +} +``` + +### Validating the Signature + +After the Payee FSP receives the `POST /quotes` API message from Payer FSP, the Payee FSP must validate the signature signed by the Payer FSP. + +#### Parse FSPIOP-Signature + +1. Parse the HTTP header parameter **FSPIOP-Signature** to get the components **protectedHeader** and signature. In this case, the value of **protectedHeader** is: + +``` +eyJhbGciOiJSUzI1NiIsIkZTUElPUC1EZXN0aW5hdGlvbiI6IjU2NzgiLCJGU1BJT1AtVVJJIjo +iL3F1b3RlcyIsIkZTUElPUC1IVFRQLU1ldGhvZCI6IlBPU1QiLCJEYXRlIjoiVHVlLCAyMyBNYX +kgMjAxNyAyMToxMjozMSBHTVQiLCJGU1BJT1AtU291cmNlIjoiMTIzNCJ9 +``` + +2. Use BASE64URL to decode the encoded representation of the JWS Protected Header. Verify that the resulting octet sequence is a UTF-8-encoded representation of a completely valid JSON object conforming to JSON Data Interchange Format, defined in RFC7159. In this case, the decoded JSON object is: + +```json +{ + "alg":"RS256", + "FSPIOP-Destination":"5678", + "FSPIOP-URI":"/quotes", + "FSPIOP-HTTP-Method":"POST", + "Date":"Tue, 23 May 2017 21:12:31 GMT", + "FSPIOP-Source":"1234" +} +``` + +3. Verify that the **alg** parameter is valid for the API. That means it must be in the list of **RS256, RS384, RS512**. In this case, the value of **alg** is **RS256**, which is valid. + +4. Verify that the value of the parameter **FSPIOP-URI** is same as the input URL of this API message. + +5. Verify that the value of the parameter **FSPIOP-HTTP-Method** is same as the HTTP method of this API message. + +6. Verify that the value of the HTTP header parameter **FSPIOP-Source** is the same as the corresponding value listed in this JWS Protected Header. + +7. Verify that the values for the HTTP header parameter **FSPIOP-Destination** are the same as the corresponding values stated in this JWS Protected Header. + +8. Verify the other protected HTTP header parameters. In this case, the **Date** parameter is protected by JWS Protected Header. If the parameters **Date** in the HTTP header of this API message and **Date** in the JWS Protected Header are equal, then the validation is successful. Both **Date** parameters in the example should be the following value: + +``` +"Tue, 23 May 2017 21:12:31 GMT" +``` + +The validation is passed. + +#### Verify JWS Signature + +1. In this case, the JWS Payload is the full HTTP body of the API message, that is (line breaks and indentation within values for display purposes only): + +```json +{ + "amount": { "amount": "150", "currency": "USD" }, + "transactionType": { "scenario": "TRANSFER", "initiator": "PAYER", + "subScenario": "P2P Transfer across MM systems", + "initiatorType": "CONSUMER" + }, + "transactionId": "36629a51-393a-4e3c-b347-c2cb57e1e1fc", + "quoteId": "59e331fa-345f-4554-aac8-fcd8833f7d50", + "expiration": "2017-05-24T08:40:00.000-04:00", + "payer": { + "personalInfo": { "dateOfBirth": "1986-02-14", + "complexName": { "middleName": "Ben", + "LastName": "Lee", "firstName": "Bill" } }, + "name": "Bill Lee", + "partyIdInfo": { "fspId": "1234", + "partyIdType": "MSISDN", + "partySubIdOrType": "RegisteredCustomer", + "partyIdentifier": "16135551212" } }, + "payee": { + "partyIdInfo": { "fspId": "5678", + "partyIdType": "MSISDN", + "partyIdentifier": "15295558888" } }, + "fees": { "amount": "1.5", "currency": "USD" }, + "extensionList": { + "extension": [ + { "value": "value1", "key": "key1" }, + { "value": "value2", "key": "key2" }, + { "value": "value3", "key": "key3" } + ] + }, + "note": "this is a sample for POST /quotes", + "geoCode": { "longitude": "125.520001", "latitude": "57.323889" }, + "amountType": "RECEIVE" +} + ``` + +2. Compute the encoded payload value BASE64URL(JWS Payload). Get the encoded value as: + +``` +eyJwYXllZSI6eyJwYXJ0eUlkSW5mbyI6eyJwYXJ0eUlkVHlwZSI6Ik1TSVNETiIsInBhcnR5SWRlbnRpZmllciI6IjE1Mjk1NTU4ODg4IiwiZnNwSWQiOiI1Njc4In19LCJhbW91bnRUeXBlIjoiUkVDRUlWRSIsInRyYW5zYWN0aW9uVHlwZSI6eyJzY2VuYXJpbyI6IlRSQU5TRkVSIiwiaW5pdGlhdG9yIjoiUEFZRVIiLCJzdWJTY2VuYXJpbyI6IlAyUCBUcmFuc2ZlciBhY3Jvc3MgTU0gc3lzdGVtcyIsImluaXRpYXRvclR5cGUiOiJDT05TVU1FUiJ9LCJub3RlIjoidGhpcyBpcyBhIHNhbXBsZSBmb3IgUE9TVCAvcXVvdGVzIiwiYW1vdW50Ijp7ImFtb3VudCI6IjE1MCIsImN1cnJlbmN5IjoiVVNEIn0sImZlZXMiOnsiYW1vdW50IjoiMS41IiwiY3VycmVuY3kiOiJVU0QifSwiZXh0ZW5zaW9uTGlzdCI6W3sidmFsdWUiOiJ2YWx1ZTEiLCJrZXkiOiJrZXkxIn0seyJ2YWx1ZSI6InZhbHVlMiIsImtleSI6ImtleTIifSx7InZhbHVlIjoidmFsdWUzIiwia2V5Ijoia2V5MyJ9XSwiZ2VvQ29kZSI6eyJsYXRpdHVkZSI6IjU3LjMyMzg4OSIsImxvbmdpdHVkZSI6IjEyNS41MjAwMDEifSwiZXhwaXJhdGlvbiI6IjIwMTctMDUtMjRUMDg6NDA6MDAuMDAwLTA0OjAwIiwicGF5ZXIiOnsicGVyc29uYWxJbmZvIjp7ImNvbXBsZXhOYW1lIjp7ImZpcnN0TmFtZSI6IkJpbGwiLCJtaWRkbGVOYW1lIjoiQmVuIiwiTGFzdE5hbWUiOiJMZWUifSwiZGF0ZU9mQmlydGgiOiIxOTg2LTAyLTE0In0sInBhcnR5SWRJbmZvIjp7InBhcnR5SWRUeXBlIjoiTVNJU0ROIiwicGFydHlTdWJJZE9yVHlwZSI6IlJlZ2lzdGVyZWRDdXN0b21lciIsInBhcnR5SWRlbnRpZmllciI6IjE2MTM1NTUxMjEyIiwiZnNwSWQiOiIxMjM0In0sIm5hbWUiOiJCaWxsIExlZSJ9LCJxdW90ZUlkIjoiNTllMzMxZmEtMzQ1Zi00NTU0LWFhYzgtZmNkODgzM2Y3ZDUwIiwidHJhbnNhY3Rpb25JZCI6IjM2NjI5YTUxLTM5M2EtNGUzYy1iMzQ3LWMyY2I1N2UxZTFmYyJ9 +``` + +3. Validate the JWS Signature against the JWS Signing Input (that is, the JWS Protected Header, JWS Payload) with the specified algorithm **RS256** (specified in the JWS Protected Header), and the public key. Record whether the validation succeeded or not. + +
    + +## References + +1 [https://tools.ietf.org/html/rfc7515#section-1.1](https://tools.ietf.org/html/rfc7515#section-1.1) – JSON Web Signature (JWS) - Notational Conventions + +2 [https://tools.ietf.org/html/rfc7515](https://tools.ietf.org/html/rfc7515) - JSON Web Signature (JWS) + +3 [https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-header-parameters](https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-header-parameters) - JSON Web Signature and Encryption Header Parameters + +4 [https://tools.ietf.org/html/rfc7159](https://tools.ietf.org/html/rfc7159) - The JavaScript Object Notation (JSON) Data Interchange Format + +5 [https://tools.ietf.org/html/rfc7517](https://tools.ietf.org/html/rfc7517) - JSON Web Key (JWK) diff --git a/website/versioned_docs/v1.0.1/api/settlement/README.md b/website/versioned_docs/v1.0.1/api/settlement/README.md new file mode 100644 index 000000000..6ee179c40 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/settlement/README.md @@ -0,0 +1,4 @@ +--- +showToc: false +--- +https://raw.githubusercontent.com/mojaloop/central-settlement/master/src/interface/swagger.json \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/README.md b/website/versioned_docs/v1.0.1/api/thirdparty/README.md new file mode 100644 index 000000000..0a05cd1e1 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/README.md @@ -0,0 +1,41 @@ +# Third Party API + +The Third Party API is an API for non-fund-holding participants to interact over a centralized Mojaloop hub. +Specifically, this API allows Payment Initiation Service Providers (PISPs) to act as a proxy in initiating +payments, while allowing for the strong authentication of users. + +## Terms + +The following terms are commonly used across the Third Party API Documentation + +| **Term** | **Alternative and Related Terms** | **Definition** | **Source** | +| --- | --- | --- | --- | +| **Payment Initiation Service Provider** | PISP, 3rd Party Payment Initiator (3PPI) | Regulated entities like retail banks or third parties, that allow customers to make payments without accessing bank accounts or cards | [PSD2](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32015L2366&qid=1633311418487) | +| **FSP** | Provider, Financial Service Provider (FSP), Payment Service Provider, Digital Financial Services Provider (DFSP) | The entity that provides a digital financial service to an end user (either a consumer, a business, or a government.) In a closed-loop payment system, the Payment System Operator is also the provider. In an open-loop payment system, the providers are the banks or non-banks which participate in that system. | [ITU-T](https://www.itu.int/dms_pub/itu-t/opb/tut/T-TUT-ECOPO-2018-PDF-E.pdf) | +| **User** | End User | An end user that is shared between a PISP and DFSP. Mostly used in the context of a real human being, but this could also be a machine user, or a business for example | +| **Consent** | Account Link | A representation of an agreement between the DFSP, PISP and User | | +| **Auth-Service** | | A service run by the Mojaloop Hub that is responsible for verifying and storing Consents, and verifying transaction request signatures | | + +## API Definitions + +The Third Party API is defined across the following OpenAPI 3.0 files: + +- [Third Party API - PISP](https://github.com/mojaloop/mojaloop-specification/blob/master/thirdparty-api/thirdparty-pisp-v1.0.yaml) +- [Third Party API - DFSP](https://github.com/mojaloop/mojaloop-specification/blob/master/thirdparty-api/thirdparty-dfsp-v1.0.yaml) + +The implementation of these APIs will depend on the role of the participant. PISPs should implement the [Third Party API - PISP](https://github.com/mojaloop/mojaloop-specification/blob/master/thirdparty-api/thirdparty-pisp-v1.0.yaml) +interface in order to request and manage Account Linking operations, and initiate Third Party Transaction Requests. + +DFSPs who wish to support Account Linking operations, and be able to respond to and verify Third Party Transaction Requests should +implement the [Third Party API - DFSP](https://github.com/mojaloop/mojaloop-specification/blob/master/thirdparty-api/thirdparty-dfsp-v1.0.yaml). + +## Transaction Patterns + +The interactions and examples of how a DFSP and PISP will interact with the Third Party API can be found in the following Transaction Patterns Documents: + +1. [Linking](./transaction-patterns-linking.md) describes how an account link and credential can be established between a DFSP and a PISP +2. [Transfer](./transaction-patterns-transfer.md) describes how a PISP can initate a payment from a DFSP's account using the account link + +## Data Models + +The [Data Models Document](./data-models.md) describes in detail the Data Models used in the Third Party API diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/_sync_docs.sh b/website/versioned_docs/v1.0.1/api/thirdparty/_sync_docs.sh new file mode 100644 index 000000000..fd92ad483 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/_sync_docs.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +## +# Synchronises the definition docs from their disparate locations into one place. +# +# The API Spec for the Third Party API is managed by the api-snippets project +## + +set -eu + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +GIT_URL="https://github.com/mojaloop/api-snippets.git" +BRANCH='master' +CLONE_DIR='/tmp/api-snippets' + +rm -rf ${CLONE_DIR} + +git clone -b ${BRANCH} ${GIT_URL} ${CLONE_DIR} + +# API definition, grab from mojaloop/pisp-project +cp ${CLONE_DIR}/thirdparty/openapi3/thirdparty-dfsp-api.yaml ${DIR}/thirdparty-dfsp-v1.0.yaml +cp ${CLONE_DIR}/thirdparty/openapi3/thirdparty-pisp-api.yaml ${DIR}/thirdparty-pisp-v1.0.yaml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/README.md b/website/versioned_docs/v1.0.1/api/thirdparty/assets/README.md new file mode 100644 index 000000000..8ef0a6124 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/README.md @@ -0,0 +1,15 @@ +# thirdparty-api/assets + +Supporting Assets for the Third Party API Specification + + +## Rebuild all Puml -> svg + +For consistent rending of sequence diagrams, we build the .puml sources to .svgs using the following script + +```bash +./_build_plantuml_all.sh +``` + +This also ensures that the sequence diagrams are easily readable inline in markdown documents. + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/_build_plantuml_all.sh b/website/versioned_docs/v1.0.1/api/thirdparty/assets/_build_plantuml_all.sh new file mode 100644 index 000000000..06435f49d --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/_build_plantuml_all.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PUML_PORT=9999 +export PUML_BASE_URL=http://localhost:${PUML_PORT} + +## +# searches through repo for plantuml sources +# and exports them using `node-plantuml` +## + +trap ctrl_c INT +function ctrl_c() { + echo "exit early - stopping docker" + docker stop puml-local + exit 1 +} + +# run the docker puml server +docker run -d --rm \ + --name puml-local \ + -p ${PUML_PORT}:8080 \ + plantuml/plantuml-server:jetty-v1.2020.21 + +# Wait for docker to be up +sleep 2 + +for i in $(find ${DIR}/diagrams -name '*.puml'); do + echo "rendering .puml -> .svg for diagram diagram: $i" + ${DIR}/_render_svg.mjs $i $(echo $i | sed 's/puml/svg/g') +done + +docker stop puml-local diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/_build_plantuml_diff.sh b/website/versioned_docs/v1.0.1/api/thirdparty/assets/_build_plantuml_diff.sh new file mode 100644 index 000000000..c54d72603 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/_build_plantuml_diff.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PUML_PORT=9999 +export PUML_BASE_URL=http://localhost:${PUML_PORT} + +## +# searches through repo for plantuml sources +# and exports them using `node-plantuml` +## + +trap ctrl_c INT +function ctrl_c() { + echo "exit early - stopping docker" + docker stop puml-local + exit 1 +} + +# run the docker puml server +docker run -d --rm \ + --name puml-local \ + -p ${PUML_PORT}:8080 \ + plantuml/plantuml-server:jetty-v1.2020.21 + +# Wait for docker to be up +sleep 2 + +for i in $(git diff --staged --name-only `find ${DIR}/../docs -name '*.puml'`); do + echo "rendering .puml -> .svg for diagram diagram: $i" + ${DIR}/_render_svg.mjs $i $(echo $i | sed 's/puml/svg/g') +done + + +git add ./ + +docker stop puml-local diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/_render_svg.js b/website/versioned_docs/v1.0.1/api/thirdparty/assets/_render_svg.js new file mode 100644 index 000000000..02ef94920 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/_render_svg.js @@ -0,0 +1,64 @@ +#!/usr/bin/env node + + +/** + * Uses plantuml server to render a puml to svg + */ + +const fs = require('fs') +const path = require('path') +const util = require('util') +const got = require('got') +const SVGO = require('svgo') +const plantumlEncoder = require('plantuml-encoder') + +const rendererBaseUrl = process.env.PUML_BASE_URL || 'http://www.plantuml.com/plantuml' + +svgo = new SVGO({ + js2svg: { pretty: true, indent: 2 }, + plugins: [ + { removeComments: true }, + ] +}); + +async function main() { + let [_, _script, inputPath, outputPath] = process.argv + + if (!inputPath) { + console.log("usage: ./_render_svg.mjs []") + process.exit(1) + } + + // If not specified, replace .puml or .plantuml with `.svg` + if (!outputPath) { + outputPath = inputPath.replace('.puml', '.svg') + .replace('.plantuml', '.svg') + } + + const rawPumlContents = fs.readFileSync(inputPath) + const encoded = plantumlEncoder.encode(rawPumlContents.toString()) + const url = path.join(rendererBaseUrl, 'svg', encoded) + let result + try { + result = await got.get(url) + } catch (err) { + console.log('http request failed to render puml with error', err.message) + if (err.message.indexOf('Response code 403') > -1) { + console.log('Note: sometimes the public puml renderer fails when the input diagrams are too large. Try running your own renderer server with docker.') + } + + if (err.message.indexOf('Response code 400') > -1) { + console.log('This could be due to bad syntax in the puml diagram. Url is:') + console.log(url) + } + + process.exit(1) + } + + // Strip comments and prettify svg + // This makes sure that our .svg files are deterministic and diffable + const formatted = await svgo.optimize(result.body) + fs.writeFileSync(outputPath, formatted.data) +} + +main() diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/0-pre-linking.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/0-pre-linking.puml new file mode 100644 index 000000000..b07cf9129 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/0-pre-linking.puml @@ -0,0 +1,49 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Pre-linking + +box "Mobile device" + participant App +end box + +box "PISP" + participant PISP +end box + +box "Mojaloop" + participant Switch +end box + +autonumber 1 "PRE-#" +activate App +App -> PISP ++: What DFSPs are available to link with? + + +PISP -> Switch ++: ""GET /services/THIRD_PARTY_DFSP""\n""FSPIOP-Source: pispa""\n""FSPIOP-Destination: switch"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> PISP ++: ""PUT /services/THIRD_PARTY_DFSP""\n""FSPIOP-Source: switch""\n""FSPIOP-Destination: pispa""\n\ + ""{""\n\ + "" "serviceProviders": ["" \n\ + "" "dfspa", "dfspb""" \n\ + "" ]"" \n\ + ""}"" +PISP --> Switch: ""200 OK"" + +PISP --> App --: We have dfspa and dfspb\n + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/0-pre-linking.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/0-pre-linking.svg new file mode 100644 index 000000000..c7ee47f89 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/0-pre-linking.svg @@ -0,0 +1,107 @@ + + + PISP Linking: Pre-linking + + + + Mobile device + + + + PISP + + + + Mojaloop + + + + + + App + + + + PISP + + + + Switch + + + + + PRE-1 + + + What DFSPs are available to link with? + + + + PRE-2 + + + GET /services/THIRD_PARTY_DFSP + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: switch + + + + + PRE-3 + + + 202 Accepted + + + + PRE-4 + + + PUT /services/THIRD_PARTY_DFSP + + + FSPIOP-Source: switch + + + FSPIOP-Destination: pispa + + + { + + + "serviceProviders": [ + + + "dfspa", "dfspb + + + " + + + ] + + + } + + + + + PRE-5 + + + 200 OK + + + + + PRE-6 + + + We have dfspa and dfspb + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/1-discovery.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/1-discovery.puml new file mode 100644 index 000000000..c719fb2af --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/1-discovery.puml @@ -0,0 +1,85 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + + +title PISP Linking: Discovery + +box "Mobile device" + participant App +end box + +box "PISP" + participant PISP +end box + +box "Mojaloop" + participant Switch +end box + +participant DFSP + +autonumber 1 "DISC-#" +activate PISP + +... + +note over App, DFSP + The user will be prompted in the PISP App for the unique ID they use with their DFSP, and the type of identifier they use. This could be a an account ALIAS, MSISDN, email address, etc. +end note + +... + +PISP -> Switch ++: ""GET /accounts/username1234""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""GET /accounts/username1234""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> Switch ++: ""PUT /accounts/username1234""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""[""\n\ + "" { accountNickname: "Chequing Account", id: "dfspa.username.1234", currency: "ZAR" },""\n\ + "" { accountNickname: "Everyday Spend", id: "dfspa.username.5678", currency: "USD" }""\n\ + ""]"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /accounts/username1234""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""[""\n\ + "" { accountNickname: "Chequing Account", id: "dfspa.username.1234", currency: "ZAR" },""\n\ + "" { accountNickname: "Everyday Spend", id: "dfspa.username.5678", currency: "USD" }""\n\ + ""]"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +... + +note over App, DFSP + The PISP can now present a list of possible accounts to the user for pairing. +end note + +... + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/1-discovery.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/1-discovery.svg new file mode 100644 index 000000000..68f6c49c0 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/1-discovery.svg @@ -0,0 +1,194 @@ + + + PISP Linking: Discovery + + + + Mobile device + + + + PISP + + + + Mojaloop + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + App + + + + PISP + + + + Switch + + + + DFSP + + + + + + + + + + The user will be prompted in the PISP App for the unique ID they use with their DFSP, and the type of identifier they use. This could be a an account ALIAS, MSISDN, email address, etc. + + + + DISC-1 + + + GET /accounts/username1234 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + + + DISC-2 + + + 202 Accepted + + + + DISC-3 + + + GET /accounts/username1234 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + + + DISC-4 + + + 202 Accepted + + + + DISC-5 + + + PUT /accounts/username1234 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + [ + + + { accountNickname: "Chequing Account", id: "dfspa.username.1234", currency: "ZAR" }, + + + { accountNickname: "Everyday Spend", id: "dfspa.username.5678", currency: "USD" } + + + ] + + + + + DISC-6 + + + 200 OK + + + + DISC-7 + + + PUT /accounts/username1234 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + [ + + + { accountNickname: "Chequing Account", id: "dfspa.username.1234", currency: "ZAR" }, + + + { accountNickname: "Everyday Spend", id: "dfspa.username.5678", currency: "USD" } + + + ] + + + + + DISC-8 + + + 200 OK + + + + + The PISP can now present a list of possible accounts to the user for pairing. + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.puml new file mode 100644 index 000000000..8d52071bc --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.puml @@ -0,0 +1,119 @@ +@startuml + + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Request consent (OTP) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant DFSP + +autonumber 1 "REQ-#" + +activate PISP + +... + +note over PISP, DFSP + The user initiated some sort of account linking by choosing the appropriate DFSP from a screen inside the PISP application. +end note + +... + +PISP -> Switch ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234", ""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Verify the consentRequest validity + + +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ +"" {""\n\ + "" authChannels: [ "OTP" ], ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" + +note over PISP, DFSP + Here, the DFSP sends an OTP directly to the user (e.g., via SMS). +end note + +deactivate DFSP + +Switch -> PISP: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ +""{""\n\ + "" authChannels: [ "OTP" ], ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch + +note over PISP, DFSP + At this point, the PISP knows that the OTP authChannel is in use and the PISP App should prompt the user to provide the OTP. +end note + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.svg new file mode 100644 index 000000000..ad65ece6b --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.svg @@ -0,0 +1,294 @@ + + + PISP Linking: Request consent (OTP) + + + + Mojaloop + + + + + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + + + + + + The user initiated some sort of account linking by choosing the appropriate DFSP from a screen inside the PISP application. + + + + REQ-1 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "Web", "OTP" ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-2 + + + 202 Accepted + + + + REQ-3 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "Web", "OTP" ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-4 + + + 202 Accepted + + + + REQ-5 + + + Verify the consentRequest validity + + + + REQ-6 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + authChannels: [ "OTP" ], + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-7 + + + 200 OK + + + + + Here, the DFSP sends an OTP directly to the user (e.g., via SMS). + + + + REQ-8 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + authChannels: [ "OTP" ], + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-9 + + + 200 OK + + + + + At this point, the PISP knows that the OTP authChannel is in use and the PISP App should prompt the user to provide the OTP. + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/2-request-consent-web.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/2-request-consent-web.puml new file mode 100644 index 000000000..de404fc39 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/2-request-consent-web.puml @@ -0,0 +1,118 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + + +title PISP Linking: Request consent (Web) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant DFSP + +autonumber 1 "REQ-#" + +activate PISP + +... + +note over PISP, DFSP + The user initiated some sort of account linking by choosing the appropriate DFSP from a screen inside the PISP application. +end note + +... + +PISP -> Switch ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ + "" {""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234", ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234", ""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ + "" {""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234", ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" + +DFSP -> DFSP: Verify the consentRequest validity +DFSP -> DFSP: In this case, DFSP chooses to use the Web channel, \n and adds the PISP's callback uri to an allow-list +deactivate Switch + +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + "" {""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + "" authUri: "dfspa.com/authorize?consentRequestId=11111111-0000-0000-0000-000000000000" ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + "" {""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + "" authUri: "dfspa.com/authorize?consentRequestId=11111111-0000-0000-0000-000000000000" ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch + +note over PISP, DFSP + At this point, the PISP knows that the Web authChannel is in use and the PISP App should redirect the user to the provided ""authUri"". +end note + + + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/2-request-consent-web.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/2-request-consent-web.svg new file mode 100644 index 000000000..ecffd688a --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/2-request-consent-web.svg @@ -0,0 +1,311 @@ + + + PISP Linking: Request consent (Web) + + + + Mojaloop + + + + + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + + + + + + The user initiated some sort of account linking by choosing the appropriate DFSP from a screen inside the PISP application. + + + + REQ-1 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "Web", "OTP" ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-2 + + + 202 Accepted + + + + REQ-3 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "Web", "OTP" ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-4 + + + 202 Accepted + + + + REQ-5 + + + Verify the consentRequest validity + + + + REQ-6 + + + In this case, DFSP chooses to use the Web channel, + + + and adds the PISP's callback uri to an allow-list + + + + REQ-7 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "Web" ], + + + callbackUri: "pisp-app://callback... + + + " + + + authUri: "dfspa.com/authorize?consentRequestId=11111111-0000-0000-0000-000000000000" + + + } + + + + + REQ-8 + + + 200 OK + + + + REQ-9 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "Web" ], + + + callbackUri: "pisp-app://callback... + + + " + + + authUri: "dfspa.com/authorize?consentRequestId=11111111-0000-0000-0000-000000000000" + + + } + + + + + REQ-10 + + + 200 OK + + + + + At this point, the PISP knows that the Web authChannel is in use and the PISP App should redirect the user to the provided + + + authUri + + + . + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-otp.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-otp.puml new file mode 100644 index 000000000..2fdb17e5d --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-otp.puml @@ -0,0 +1,62 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Authentication (OTP) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "AUTH-#" + +... + +note over PISP, DFSP + Here the user provides the OTP sent directly to them by the DFSP into the PISP App. It's then used as the secret to prove to the DFSP that the user trusts the PISP. +end note + +... + +PISP -> Switch ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Verify the OTP is correct. + +note over PISP, DFSP + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. +end note + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-otp.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-otp.svg new file mode 100644 index 000000000..3372bda19 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-otp.svg @@ -0,0 +1,116 @@ + + + PISP Linking: Authentication (OTP) + + + + Mojaloop + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + + Here the user provides the OTP sent directly to them by the DFSP into the PISP App. It's then used as the secret to prove to the DFSP that the user trusts the PISP. + + + + AUTH-1 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<OTP>" + + + } + + + + + AUTH-2 + + + 202 Accepted + + + + AUTH-3 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<OTP>" + + + } + + + + + AUTH-4 + + + 202 Accepted + + + + AUTH-5 + + + Verify the OTP is correct. + + + + + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.puml new file mode 100644 index 000000000..9d05ec448 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.puml @@ -0,0 +1,45 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Authentication (Third-party FIDO registration) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "3P-FIDO-AUTH-#" + +... + +note over PISP, DFSP + Here the user goes through the web authentication process with their DFSP. + The end result is a redirect back to the PISP with a special URL parameter indicating to the PISP that it should wait to be notified about a credential. +end note + +... + +autonumber 1 "AUTH-#" + +note over PISP, DFSP + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. +end note + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.svg new file mode 100644 index 000000000..32fdc6524 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.svg @@ -0,0 +1,50 @@ + + + PISP Linking: Authentication (Third-party FIDO registration) + + + + Mojaloop + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + Here the user goes through the web authentication process with their DFSP. + + + The end result is a redirect back to the PISP with a special URL parameter indicating to the PISP that it should wait to be notified about a credential. + + + + + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-web.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-web.puml new file mode 100644 index 000000000..f31a9ed55 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-web.puml @@ -0,0 +1,65 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Authentication (Web) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "WEB-AUTH-#" + +... + +note over PISP, DFSP + Here the user goes through the web authentication process with their DFSP. + The end result is a redirect back to the PISP with a special URL parameter with a secret provided by the DFSP. +end note + +... + +autonumber 1 "AUTH-#" + +PISP -> Switch ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Verify the auth token is correct. + +note over PISP, DFSP + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. +end note + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-web.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-web.svg new file mode 100644 index 000000000..8ed74081e --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/3-authentication-web.svg @@ -0,0 +1,119 @@ + + + PISP Linking: Authentication (Web) + + + + Mojaloop + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + + Here the user goes through the web authentication process with their DFSP. + + + The end result is a redirect back to the PISP with a special URL parameter with a secret provided by the DFSP. + + + + AUTH-1 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<SECRET>" + + + } + + + + + AUTH-2 + + + 202 Accepted + + + + AUTH-3 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<SECRET>" + + + } + + + + + AUTH-4 + + + 202 Accepted + + + + AUTH-5 + + + Verify the auth token is correct. + + + + + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/4-grant-consent.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/4-grant-consent.puml new file mode 100644 index 000000000..e0ede15d5 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/4-grant-consent.puml @@ -0,0 +1,64 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Grant consent + +participant "PISP" as PISP + +box "Mojaloop" + participant "Switch" as Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "GRANT-#" + +DFSP -> Switch ++: ""POST /consents""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSIOP-Destination: pispa""\n\ +"" {""\n\ + "" consentId: "22222222-0000-0000-0000-000000000000",""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + ""}"" +Switch --> DFSP: ""202 Accepted"" +deactivate DFSP + +Switch -> PISP ++: ""POST /consents""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSIOP-Destination: pispa""\n\ +"" {""\n\ + "" consentId: "22222222-0000-0000-0000-000000000000",""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + ""}"" + +PISP --> Switch: ""202 Accepted"" + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/4-grant-consent.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/4-grant-consent.svg new file mode 100644 index 000000000..60e2e7345 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/4-grant-consent.svg @@ -0,0 +1,134 @@ + + + + Mojaloop + + + PISP Linking: Grant consent + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + GRANT-1 + + + POST /consents + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + consentId: "22222222-0000-0000-0000-000000000000", + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + status: "ISSUED", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + } + + + + + GRANT-2 + + + 202 Accepted + + + + GRANT-3 + + + POST /consents + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + consentId: "22222222-0000-0000-0000-000000000000", + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + status: "ISSUED", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + } + + + + + GRANT-4 + + + 202 Accepted + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/5a-credential-registration.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/5a-credential-registration.puml new file mode 100644 index 000000000..7e4b6ac64 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/5a-credential-registration.puml @@ -0,0 +1,217 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Credential registration (verification) + +participant "PISP" as PISP + +box "Mojaloop" + participant "Thirdparty-API-Adapter" as Switch + participant "Account Lookup Service" as ALS + participant "Auth Service" as Auth +end box + +participant "DFSP" as DFSP + +autonumber 0 "CRED-#" + +... + +note over PISP, DFSP + The PISP uses the FIDO registration flow to generate a new keypair and sign the challenge, relying on the user performing an "unlock action" on their mobile device. + + The PISP uses the PublicKeyCredential as the fidoPayload for the credential, which can be understood by the Auth Service and DFSP + See https://webauthn.guide/#authentication for more information on this object +end note + +... + +PISP -> Switch ++: ""PUT /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: pispa""\n\ +"" FSPIOP-Destination: dfspa""\n\ +"" {""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [""\n\ + "" {""\n\ + "" accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ],""\n\ + "" },""\n\ + "" {""\n\ + "" accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ],""\n\ + "" }""\n\ + "" ],""\n\ + "" credential: { ""\n\ + "" credentialType: "FIDO",""\n\ + "" status: "PENDING",""\n\ + "" fidoPayload: { ""\n\ + "" id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", "" \n\ + "" response: { ""\n\ + "" "" authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==",\n\ + "" "" clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...",\n\ + "" "" signature: "MEUCIDcJRBu5aOLJVc..."\n\ + "" } ""\n\ + "" } ""\n\ + "" }""\n\ +"" }"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + + +Switch -> DFSP ++: ""PUT /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: pispa""\n\ +"" FSPIOP-Destination: dfspa""\n\ +"" {...}"" + +DFSP --> Switch: ""202 Accepted"" + + +rnote over DFSP + 1. DFSP checks the signed challenge against the derived challenge from the scopes + + If the DFSP opts to use the hub-hosted Auth-Service it then: + 1. Registers the consent with the Auth Service ""POST /consents"" + 2. If the DFSP recieves a `PUT /consents/{id}` and the callback contains + ""Consent.credential.status"" of ""VERIFIED"", for each scope in the + Consent, the DFSP creates a ""CredentialScope"" else, if it recieves + a `PUT /consents/{id}/error` callback, it knows that the Consent is + invalid, and can propagate the error back to the PISP + +end note + + +DFSP -> Switch: ""POST /consents"" \n\ +"" FSIOP-Source: dfspa""\n\ +"" FSPIOP-Destination: central-auth""\n\ +"" {""\n\ + "" consentId: "22222222-0000-0000-0000-000000000000"""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000"""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [""\n\ + "" {""\n\ + "" accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ],""\n\ + "" }""\n\ + "" },""\n\ + "" {""\n\ + "" accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ],""\n\ + "" }""\n\ + "" },""\n\ + "" ],""\n\ + "" credential: { ""\n\ + "" credentialType: "FIDO",""\n\ + "" status: "PENDING",""\n\ + "" fidoPayload: { ""\n\ + "" id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", "" \n\ + "" response: { ""\n\ + "" "" authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==",\n\ + "" "" clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...",\n\ + "" "" signature: "MEUCIDcJRBu5aOLJVc..."\n\ + "" } ""\n\ + "" } ""\n\ + "" }""\n\ +"" }"" + +Switch --> DFSP: "202 Accepted" + + +Switch -> Auth: ""POST /consents"" \n\ +"" FSIOP-Source: dfspa""\n\ +"" FSPIOP-Destination: central-auth""\n\ +"" {...}"" + +Auth --> Switch: "202 Accepted" + + +rnote over Auth + The Auth Service checks the signature against the challenge +end note + +rnote over Auth + The auth service is now the authoritative source for the Consent object. + + It must register the consentId with the ALS + - `Consent` - to allow for `GET /consent/{ID}` calls etc. Will point to the fspId of the Auth Service responsible for the Consent +end note + +Auth -> ALS: ""POST /participants/CONSENTS/22222222-0000-0000-0000-000000000000"" \n\ +"" FSIOP-Source: central-auth""\n\ +"" {""\n\ +"" fspId: "central-auth",""\n\ +"" }"" +ALS --> Auth: ""202 Accepted"" + +rnote over ALS #LightGray + ALS registers a new entry in the Consents oracle +end note + +ALS -> Auth: ""PUT /participants/CONSENTS/22222222-0000-0000-0000-000000000000"" \n\ +"" FSIOP-Source: account-lookup-service""\n\ +"" FSIOP-Destination: central-auth""\n\ +"" {""\n\ +"" fspId: "central-auth",""\n\ +"" }"" +Auth --> ALS: ""200 OK"" + +rnote over Auth #LightGray + The auth service now informs the DFSP that the credential is valid +end note + + +Auth -> Switch: ""PUT /consents/22222222-0000-0000-0000-000000000000"" \n\ +"" FSIOP-Source: central-auth""\n\ +"" FSPIOP-Destination: dfspa""\n\ +"" {""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [""\n\ + "" {""\n\ + "" accountId: "dfsp.username.1234",""\n\ + "" actions: [ "accounts.transfer", "accounts.getBalance" ],""\n\ + "" },""\n\ + "" {""\n\ + "" accountId: "dfsp.username.5678",""\n\ + "" actions: [ "accounts.transfer", "accounts.getBalance" ],""\n\ + "" },""\n\ + "" ],""\n\ + "" credential: { ""\n\ + "" credentialType: "FIDO",""\n\ + "" status: "VERIFIED",""\n\ + "" fidoPayload: { ""\n\ + "" id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", "" \n\ + "" response: { ""\n\ + "" "" authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==",\n\ + "" "" clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...",\n\ + "" "" signature: "MEUCIDcJRBu5aOLJVc..."\n\ + "" } ""\n\ + "" } ""\n\ + "" }""\n\ +"" }"" +Switch --> Auth: "200 OK" + +Switch -> DFSP: ""PUT /consents/22222222-0000-0000-0000-000000000000"" \n\ +"" FSIOP-Source: central-auth""\n\ +"" FSPIOP-Destination: dfspa""\n\ +"" {...}"" + +DFSP --> Switch: "200 OK" + +rnote over DFSP + DFSP is now satisfied that the Consent registered by the PISP is valid. +end note + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/5a-credential-registration.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/5a-credential-registration.svg new file mode 100644 index 000000000..8a792580e --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/5a-credential-registration.svg @@ -0,0 +1,577 @@ + + + + Mojaloop + + + PISP Linking: Credential registration (verification) + + + + + + + + + + + + + + + + + + + + + + + + + + + + PISP + + + + Thirdparty-API-Adapter + + + + Account Lookup Service + + + + Auth Service + + + + DFSP + + + + + The PISP uses the FIDO registration flow to generate a new keypair and sign the challenge, relying on the user performing an "unlock action" on their mobile device. + + + The PISP uses the PublicKeyCredential as the fidoPayload for the credential, which can be understood by the Auth Service and DFSP + + + See https://webauthn.guide/#authentication for more information on this object + + + + CRED-0 + + + PUT /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + status: "ISSUED", + + + scopes: [ + + + { + + + accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ], + + + }, + + + { + + + accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ], + + + } + + + ], + + + credential: { + + + credentialType: "FIDO", + + + status: "PENDING", + + + fidoPayload: { + + + id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", + + + response: { + + + authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==", + + + clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...", + + + signature: "MEUCIDcJRBu5aOLJVc..." + + + } + + + } + + + } + + + } + + + + + CRED-1 + + + 202 Accepted + + + + CRED-2 + + + PUT /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + {...} + + + + + CRED-3 + + + 202 Accepted + + + + 1. DFSP checks the signed challenge against the derived challenge from the scopes + + + If the DFSP opts to use the hub-hosted Auth-Service it then: + + + 1. Registers the consent with the Auth Service + + + POST /consents + + + 2. If the DFSP recieves a `PUT /consents/{id}` and the callback contains + + + Consent.credential.status + + + of + + + VERIFIED + + + , for each scope in the + + + Consent, the DFSP creates a + + + CredentialScope + + + else, if it recieves + + + a `PUT /consents/{id}/error` callback, it knows that the Consent is + + + invalid, and can propagate the error back to the PISP + + + + CRED-4 + + + POST /consents + + + FSIOP-Source: dfspa + + + FSPIOP-Destination: central-auth + + + { + + + consentId: "22222222-0000-0000-0000-000000000000 + + + " + + + consentRequestId: "11111111-0000-0000-0000-000000000000 + + + " + + + status: "ISSUED", + + + scopes: [ + + + { + + + accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ], + + + } + + + }, + + + { + + + accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ], + + + } + + + }, + + + ], + + + credential: { + + + credentialType: "FIDO", + + + status: "PENDING", + + + fidoPayload: { + + + id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", + + + response: { + + + authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==", + + + clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...", + + + signature: "MEUCIDcJRBu5aOLJVc..." + + + } + + + } + + + } + + + } + + + + + CRED-5 + + + "202 Accepted" + + + + CRED-6 + + + POST /consents + + + FSIOP-Source: dfspa + + + FSPIOP-Destination: central-auth + + + {...} + + + + + CRED-7 + + + "202 Accepted" + + + + The Auth Service checks the signature against the challenge + + + + The auth service is now the authoritative source for the Consent object. + + + It must register the consentId with the ALS + + + - `Consent` - to allow for `GET /consent/{ID}` calls etc. Will point to the fspId of the Auth Service responsible for the Consent + + + + CRED-8 + + + POST /participants/CONSENTS/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + { + + + fspId: "central-auth", + + + } + + + + + CRED-9 + + + 202 Accepted + + + + ALS registers a new entry in the Consents oracle + + + + CRED-10 + + + PUT /participants/CONSENTS/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: account-lookup-service + + + FSIOP-Destination: central-auth + + + { + + + fspId: "central-auth", + + + } + + + + + CRED-11 + + + 200 OK + + + + The auth service now informs the DFSP that the credential is valid + + + + CRED-12 + + + PUT /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + FSPIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000 + + + " + + + status: "ISSUED", + + + scopes: [ + + + { + + + accountId: "dfsp.username.1234", + + + actions: [ "accounts.transfer", "accounts.getBalance" ], + + + }, + + + { + + + accountId: "dfsp.username.5678", + + + actions: [ "accounts.transfer", "accounts.getBalance" ], + + + }, + + + ], + + + credential: { + + + credentialType: "FIDO", + + + status: "VERIFIED", + + + fidoPayload: { + + + id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", + + + response: { + + + authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==", + + + clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...", + + + signature: "MEUCIDcJRBu5aOLJVc..." + + + } + + + } + + + } + + + } + + + + + CRED-13 + + + "200 OK" + + + + CRED-14 + + + PUT /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + FSPIOP-Destination: dfspa + + + {...} + + + + + CRED-15 + + + "200 OK" + + + + DFSP is now satisfied that the Consent registered by the PISP is valid. + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.puml new file mode 100644 index 000000000..791a929de --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.puml @@ -0,0 +1,97 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Credential registration (verification) + +participant "PISP" as PISP + +box "Mojaloop" + participant "Switch" as Switch + participant "Account Lookup Service" as ALS +end box + +participant "DFSP" as DFSP + +autonumber 16 "CRED-#" + +... + + +rnote over DFSP + DFSP is now satisfied that the Consent registered by the PISP is valid, + and now proceeds to register with the ALS: + - `THIRD_PARTY_LINK` (optional - for routing of funds to a Third Party Link) + ALS +end note + +loop for each scope in ""Consents.scopes"" + +DFSP -> ALS: ""POST /participants/THIRD_PARTY_LINK/dfsp.username.5678"" \n\ +"" FSIOP-Source: dfspa""\n\ +"" {""\n\ +"" fspId: "dfspa",""\n\ +"" }"" +ALS --> DFSP: ""202 Accepted"" + +rnote over ALS #LightGray + ALS registers a new entry in the THIRD_PARTY_LINK oracle +end note + +ALS -> DFSP: ""PUT /participants/THIRD_PARTY_LINK/dfsp.username.5678"" \n\ +"" FSIOP-Source: account-lookup-service""\n\ +"" FSIOP-Destination: dfspa""\n\ +"" {""\n\ +"" fspId: "dfspa",""\n\ +"" }"" +DFSP --> ALS: ""200 OK"" +end + + +rnote over DFSP + Now that the Credentials are verified and registered with the Auth Service, + the DFSP can update the PISP with the final status +end note + +DFSP -> Switch: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSPIOP-Destination: pispa""\n\ +"" Content-Type: application/merge-patch+json""\n\ +"" {""\n\ + "" credential: {""\n\ + "" **status: "VERIFIED", //this is new!**""\n\ + "" }""\n\ +"" }"" +DFSP --> Switch: ""200 OK"" + +Switch -> PISP ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSPIOP-Destination: pispa""\n\ +"" Content-Type: application/merge-patch+json""\n\ +"" {""\n\ + "" credential: {""\n\ + "" **status: "VERIFIED", //this is new!**""\n\ + "" }""\n\ +"" }"" +PISP --> Switch: ""200 OK"" + + +note over PISP, DFSP + Now we have a new identifier that the PISP can use to initiate transactions, a registered credential, and that credential is stored in the auth-service +end note + + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.svg new file mode 100644 index 000000000..54ba44707 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.svg @@ -0,0 +1,215 @@ + + + + Mojaloop + + + PISP Linking: Credential registration (verification) + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + Account Lookup Service + + + + DFSP + + + + DFSP is now satisfied that the Consent registered by the PISP is valid, + + + and now proceeds to register with the ALS: + + + - `THIRD_PARTY_LINK` (optional - for routing of funds to a Third Party Link) + + + ALS + + + + + loop + + + [for each scope in + + + Consents.scopes + + + ] + + + + CRED-16 + + + POST /participants/THIRD_PARTY_LINK/dfsp.username.5678 + + + FSIOP-Source: dfspa + + + { + + + fspId: "dfspa", + + + } + + + + + CRED-17 + + + 202 Accepted + + + + ALS registers a new entry in the THIRD_PARTY_LINK oracle + + + + CRED-18 + + + PUT /participants/THIRD_PARTY_LINK/dfsp.username.5678 + + + FSIOP-Source: account-lookup-service + + + FSIOP-Destination: dfspa + + + { + + + fspId: "dfspa", + + + } + + + + + CRED-19 + + + 200 OK + + + + Now that the Credentials are verified and registered with the Auth Service, + + + the DFSP can update the PISP with the final status + + + + CRED-20 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + Content-Type: application/merge-patch+json + + + { + + + credential: { + + + status: "VERIFIED", //this is new! + + + } + + + } + + + + + CRED-21 + + + 200 OK + + + + CRED-22 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + Content-Type: application/merge-patch+json + + + { + + + credential: { + + + status: "VERIFIED", //this is new! + + + } + + + } + + + + + CRED-23 + + + 200 OK + + + + + Now we have a new identifier that the PISP can use to initiate transactions, a registered credential, and that credential is stored in the auth-service + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.puml new file mode 100644 index 000000000..4c2ff1b57 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.puml @@ -0,0 +1,72 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Unlinking + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "UNLINK-A-#" + +activate PISP + +... + +note over PISP, DFSP + In this scenario there is no Hub-hosted Auth Service. The DFSP is the authority on the ""Consent"" object. +end note + +... + +PISP -> Switch ++: ""DELETE /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: pispa""\n\ +"" FSIOP-Destination: dfspa"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""DELETE /consents/22222222-0000-0000-0000-000000000000"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Mark the ""Consent"" object as "REVOKED" + +DFSP -> Switch ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSIOP-Destination: pispa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSIOP-Destination: pispa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000""\n\ +""}"" +PISP --> Switch: ""200 OK"" + + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.svg new file mode 100644 index 000000000..14dabe215 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.svg @@ -0,0 +1,172 @@ + + + + Mojaloop + + + PISP Linking: Unlinking + + + + + + + + + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + In this scenario there is no Hub-hosted Auth Service. The DFSP is the authority on the + + + Consent + + + object. + + + + UNLINK-A-1 + + + DELETE /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + + + UNLINK-A-2 + + + 202 Accepted + + + + UNLINK-A-3 + + + DELETE /consents/22222222-0000-0000-0000-000000000000 + + + + + UNLINK-A-4 + + + 202 Accepted + + + + UNLINK-A-5 + + + Mark the + + + Consent + + + object as "REVOKED" + + + + UNLINK-A-6 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + status: "REVOKED", + + + revokedAt: "2020-06-15T13:00:00.000 + + + " + + + } + + + + + UNLINK-A-7 + + + 200 OK + + + + UNLINK-A-8 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + status: "REVOKED", + + + revokedAt: "2020-06-15T13:00:00.000 + + + } + + + + + UNLINK-A-9 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.puml new file mode 100644 index 000000000..914dc7704 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.puml @@ -0,0 +1,105 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Unlinking + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch + participant "Account Lookup Service" as ALS + participant "Auth Service" as Auth +end box + +participant "DFSP" as DFSP + +autonumber 1 "UNLINK-B-#" + +activate PISP + +... + +note over PISP, DFSP + In this scenario there is no Hub-hosted Auth Service. The DFSP is the authority on the ""Consent"" object. +end note + +... + +PISP -> Switch ++: ""DELETE /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: pispa""\n\ +"" FSIOP-Destination: dfspa"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> ALS: ""GET /participants/CONSENT/22222222-0000-0000-0000-000000000000"" +ALS --> Switch: ""200 OK""\n\ +"" { "fspId": "central-auth" }"" + +rnote over Switch #LightGray + Hub has determined that 'central-auth- is responsible for ""Consent"" 22222222-0000-0000-0000-000000000000 +end note + +Switch -> Auth ++: ""DELETE /consents/22222222-0000-0000-0000-000000000000"" +Auth --> Switch: ""202 Accepted"" +deactivate Switch + +Auth -> Auth: Mark the ""Consent"" object as "REVOKED" + +Auth -> Switch ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: central-auth""\n\ +"" FSIOP-Destination: pispa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +Switch --> Auth: ""200 OK"" +deactivate Auth + +Switch -> PISP ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: central-auth""\n\ +"" FSIOP-Destination: pispa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +PISP --> Switch: ""200 OK"" + + +rnote over Auth #LightGray + Auth Service must also inform the DFSP of the updated status +end note + +Auth -> Switch ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: central-auth""\n\ +"" FSIOP-Destination: dfspa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +Switch --> Auth: ""200 OK"" +deactivate Auth + +Switch -> DFSP ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: central-auth""\n\ +"" FSIOP-Destination: dfspa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +DFSP --> Switch: ""200 OK"" + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.svg new file mode 100644 index 000000000..bb3c50196 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.svg @@ -0,0 +1,298 @@ + + + + Mojaloop + + + PISP Linking: Unlinking + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + Account Lookup Service + + + + Auth Service + + + + DFSP + + + + + In this scenario there is no Hub-hosted Auth Service. The DFSP is the authority on the + + + Consent + + + object. + + + + UNLINK-B-1 + + + DELETE /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + + + UNLINK-B-2 + + + 202 Accepted + + + + UNLINK-B-3 + + + GET /participants/CONSENT/22222222-0000-0000-0000-000000000000 + + + + + UNLINK-B-4 + + + 200 OK + + + { "fspId": "central-auth" } + + + + Hub has determined that 'central-auth- is responsible for + + + Consent + + + 22222222-0000-0000-0000-000000000000 + + + + UNLINK-B-5 + + + DELETE /consents/22222222-0000-0000-0000-000000000000 + + + + + UNLINK-B-6 + + + 202 Accepted + + + + UNLINK-B-7 + + + Mark the + + + Consent + + + object as "REVOKED" + + + + UNLINK-B-8 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + FSIOP-Destination: pispa + + + { + + + status: "REVOKED", + + + revokedAt: "2020-06-15T13:00:00.000 + + + " + + + } + + + + + UNLINK-B-9 + + + 200 OK + + + + UNLINK-B-10 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + FSIOP-Destination: pispa + + + { + + + status: "REVOKED", + + + revokedAt: "2020-06-15T13:00:00.000 + + + " + + + } + + + + + UNLINK-B-11 + + + 200 OK + + + + Auth Service must also inform the DFSP of the updated status + + + + UNLINK-B-12 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + FSIOP-Destination: dfspa + + + { + + + status: "REVOKED", + + + revokedAt: "2020-06-15T13:00:00.000 + + + " + + + } + + + + + UNLINK-B-13 + + + 200 OK + + + + UNLINK-B-14 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + FSIOP-Destination: dfspa + + + { + + + status: "REVOKED", + + + revokedAt: "2020-06-15T13:00:00.000 + + + " + + + } + + + + + UNLINK-B-15 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.puml new file mode 100644 index 000000000..bf5d76ca5 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.puml @@ -0,0 +1,79 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Discovery error case + +box "PISP" + participant PISP +end box + +box "Mojaloop" + participant Switch +end box + +participant DFSP + +autonumber 1 "DISC-#" +activate PISP + +PISP -> Switch ++: ""GET /accounts/username1234""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""GET /accounts/username1234""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Lookup a user for **username1234** +DFSP -> DFSP: No user found + +DFSP -> Switch ++: ""PUT /accounts/username1234/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6205", ""\n\ + "" errorDescription: "No accounts found" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /accounts/username1234/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6205", ""\n\ + "" errorDescription: "No accounts found" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +... + +note over Switch + The PISP can now show error message and user can try again with another username or different DFSP. +end note + +... + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.svg new file mode 100644 index 000000000..d3d18465e --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.svg @@ -0,0 +1,182 @@ + + + PISP Linking: Discovery error case + + + + PISP + + + + Mojaloop + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + DISC-1 + + + GET /accounts/username1234 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + + + DISC-2 + + + 202 Accepted + + + + DISC-3 + + + GET /accounts/username1234 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + + + DISC-4 + + + 202 Accepted + + + + DISC-5 + + + Lookup a user for + + + username1234 + + + + DISC-6 + + + No user found + + + + DISC-7 + + + PUT /accounts/username1234/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6205", + + + errorDescription: "No accounts found" + + + } + + + } + + + + + DISC-8 + + + 200 OK + + + + DISC-9 + + + PUT /accounts/username1234/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6205", + + + errorDescription: "No accounts found" + + + } + + + } + + + + + DISC-10 + + + 200 OK + + + + + The PISP can now show error message and user can try again with another username or different DFSP. + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.puml new file mode 100644 index 000000000..e3cbf4565 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.puml @@ -0,0 +1,162 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title **PISP Linking: consentRequest error cases** + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +== NO_SUPPORTED_SCOPE_ACTIONS == + +autonumber 1 "REQ-#" +PISP -> Switch ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234", ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.91011",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "WEB", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.91011",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "WEB", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +autonumber 1 "DFSP-#" +DFSP -> DFSP: The PISP requested permissions \nfor accountId dfsp.username.91011 which \n isn't owned by username1234 + +autonumber 5 "REQ-#" +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6101", ""\n\ + "" errorDescription: "Unsupported scopes were requested" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6101", ""\n\ + "" errorDescription: "Unsupported scopes were requested" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +== UNTRUSTED_CALLBACK_URI == + +autonumber 1 "REQ-#" +PISP -> Switch ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234", ""\n\ + "" scopes: [ ""\n\ + "" { **accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "WEB", "OTP" ],""\n\ + "" callbackUri: "http://phishing.com"""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "WEB", "OTP" ],""\n\ + "" callbackUri: "http://phishing.com"""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +autonumber 1 "DFSP-#" +DFSP -> DFSP: The callbackUri uses http scheme \ninstead of https. Reject the consentRequest + +autonumber 5 "REQ-#" +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6204", ""\n\ + "" errorDescription: "Bad callbackUri" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6204", ""\n\ + "" errorDescription: "Bad callbackUri" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.svg new file mode 100644 index 000000000..50cacb14f --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.svg @@ -0,0 +1,455 @@ + + + PISP Linking: consentRequest error cases + + + + Mojaloop + + + + + + PISP + + + + Switch + + + + DFSP + + + + + + + NO_SUPPORTED_SCOPE_ACTIONS + + + + REQ-1 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.91011", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "WEB", "OTP" ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-2 + + + 202 Accepted + + + + REQ-3 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.91011", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "WEB", "OTP" ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-4 + + + 202 Accepted + + + + DFSP-1 + + + The PISP requested permissions + + + for accountId dfsp.username.91011 which + + + isn't owned by username1234 + + + + REQ-5 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6101", + + + errorDescription: "Unsupported scopes were requested" + + + } + + + } + + + + + REQ-6 + + + 200 OK + + + + REQ-7 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6101", + + + errorDescription: "Unsupported scopes were requested" + + + } + + + } + + + + + REQ-8 + + + 200 OK + + + + + + UNTRUSTED_CALLBACK_URI + + + + REQ-1 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { **accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "WEB", "OTP" ], + + + callbackUri: "http://phishing.com + + + " + + + } + + + + + REQ-2 + + + 202 Accepted + + + + REQ-3 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "WEB", "OTP" ], + + + callbackUri: "http://phishing.com + + + " + + + } + + + + + REQ-4 + + + 202 Accepted + + + + DFSP-1 + + + The callbackUri uses http scheme + + + instead of https. Reject the consentRequest + + + + REQ-5 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6204", + + + errorDescription: "Bad callbackUri" + + + } + + + } + + + + + REQ-6 + + + 200 OK + + + + REQ-7 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6204", + + + errorDescription: "Bad callbackUri" + + + } + + + } + + + + + REQ-8 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.puml new file mode 100644 index 000000000..c88560017 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.puml @@ -0,0 +1,87 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Authentication Invalid authToken + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "AUTH-#" + +== Failure case == + +... + +note over PISP, DFSP + The user enters an incorrect OTP for authentication. +end note + +... + +PISP -> Switch ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: The OTP is incorrect. + +note over PISP, DFSP + We respond with an error that the OTP is incorrect so the PISP can inform the user. +end note + +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6203", ""\n\ + "" errorDescription: "Invalid authentication token" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6203", ""\n\ + "" errorDescription: "Invalid authentication token" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.svg new file mode 100644 index 000000000..4320e199d --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.svg @@ -0,0 +1,197 @@ + + + PISP Linking: Authentication Invalid authToken + + + + Mojaloop + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + + + Failure case + + + + + The user enters an incorrect OTP for authentication. + + + + AUTH-1 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<OTP>" + + + } + + + + + AUTH-2 + + + 202 Accepted + + + + AUTH-3 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<OTP>" + + + } + + + + + AUTH-4 + + + 202 Accepted + + + + AUTH-5 + + + The OTP is incorrect. + + + + + We respond with an error that the OTP is incorrect so the PISP can inform the user. + + + + AUTH-6 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6203", + + + errorDescription: "Invalid authentication token" + + + } + + + } + + + + + AUTH-7 + + + 200 OK + + + + AUTH-8 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6203", + + + errorDescription: "Invalid authentication token" + + + } + + + } + + + + + AUTH-9 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.puml new file mode 100644 index 000000000..c9e4f772d --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.puml @@ -0,0 +1,82 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + + +!pragma teoz true + +title PISP Linking: Grant consent scope retrieval error + +participant "PISP" as PISP + +box "Mojaloop" + participant "Thirdparty-API-Adapter" as Switch + participant "Account Lookup Service" as ALS + participant "Auth Service" as Auth +end box + +participant "DFSP" as DFSP + +autonumber 1 "GRANT-#" + +== Failure case == + +PISP -> Switch ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Verify the OTP is correct. + +DFSP -> DFSP: Unable to fetch stored scopes + +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "7207", ""\n\ + "" errorDescription: "FSP failed retrieve scopes for consent request" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "7207", ""\n\ + "" errorDescription: "FSP failed retrieve scopes for consent request" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.svg new file mode 100644 index 000000000..cc0b292ec --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.svg @@ -0,0 +1,191 @@ + + + + Mojaloop + + + PISP Linking: Grant consent scope retrieval error + + + + + + + + PISP + + + + Thirdparty-API-Adapter + + + + Account Lookup Service + + + + Auth Service + + + + DFSP + + + + + + Failure case + + + + GRANT-1 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<OTP>" + + + } + + + + + GRANT-2 + + + 202 Accepted + + + + GRANT-3 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<OTP>" + + + } + + + + + GRANT-4 + + + 202 Accepted + + + + GRANT-5 + + + Verify the OTP is correct. + + + + GRANT-6 + + + Unable to fetch stored scopes + + + + GRANT-7 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "7207", + + + errorDescription: "FSP failed retrieve scopes for consent request" + + + } + + + } + + + + + GRANT-8 + + + 200 OK + + + + GRANT-9 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "7207", + + + errorDescription: "FSP failed retrieve scopes for consent request" + + + } + + + } + + + + + GRANT-10 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-1-discovery.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-1-discovery.puml new file mode 100644 index 000000000..4cbf4dc6d --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-1-discovery.puml @@ -0,0 +1,72 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.1 Discovery + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box + + +== Discovery (Lookup) == +rnote right of D1 #Light +**""GET /parties/MSISDN/+4412345678""** +""FSPIOP-Source: pispa"" +end note +D1 -> S: ""GET /parties/MSISDN/+4412345678"" +S --> D1: ""202 Accepted"" + +... ALS lookup flow not shown here ... + +rnote over S #Light +**""GET /parties/MSISDN/+4412345678""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspb"" +end note +S -> D3: ""GET /parties/MSISDN/+4412345678"" +D3 --> S: ""202 Accepted"" + +rnote left of D3 #Light +**""PUT /parties/MSISDN/+4412345678""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: pispa"" +{ + partyIdType: "MSISDN", + partyIdentifier: "+4412345678", + party: { + partyIdInfo: { + partyIdType: "MSISDN", + partyIdentifier: "+4412345678", + fspId: 'dfspb", + }, + name: "Bhavesh S.", + } +} +end note +D3 -> S: ""PUT /parties/MSISDN/+4412345678"" +S --> D3: ""200 OK"" +S -> D1: ""PUT /parties/MSISDN/+4412345678"" +D1 --> S: ""200 OK"" + +... PISP confirms payee party with their user ... + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-1-discovery.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-1-discovery.svg new file mode 100644 index 000000000..3517b835d --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-1-discovery.svg @@ -0,0 +1,156 @@ + + + Transfer: 1.1 Discovery + + + + PISP + + + + Mojaloop + + + + DFSP B + + + + + + + + + + + + + + + + + PISP Server + + + + Switch + + + + DFSP B + + + (Payee) + + + + + + Discovery (Lookup) + + + + GET /parties/MSISDN/+4412345678 + + + FSPIOP-Source: pispa + + + + GET /parties/MSISDN/+4412345678 + + + + + 202 Accepted + + + ALS lookup flow not shown here + + + + GET /parties/MSISDN/+4412345678 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspb + + + + GET /parties/MSISDN/+4412345678 + + + + + 202 Accepted + + + + PUT /parties/MSISDN/+4412345678 + + + FSPIOP-Source: dfspb + + + FSPIOP-Destination: pispa + + + { + + + partyIdType: "MSISDN", + + + partyIdentifier: "+4412345678", + + + party: { + + + partyIdInfo: { + + + partyIdType: "MSISDN", + + + partyIdentifier: "+4412345678", + + + fspId: 'dfspb", + + + }, + + + name: "Bhavesh S.", + + + } + + + } + + + + PUT /parties/MSISDN/+4412345678 + + + + + 200 OK + + + + PUT /parties/MSISDN/+4412345678 + + + + + 200 OK + + + PISP confirms payee party with their user + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.puml new file mode 100644 index 000000000..3d5aabd80 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.puml @@ -0,0 +1,87 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.1 Agreement + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +== Agreement Phase == +rnote right of D1 #Light +**""POST /thirdpartyRequests/transactions""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T22:17:28.985-01:00" +} +end note +D1 -> S: ""POST /thirdpartyRequests/transactions"" +S --> D1: ""202 Accepted"" +S -> D2: ""POST /thirdpartyRequests/transactions"" +D2 --> S: ""202 Accepted"" +D2 -> D2: Lookup the consent for this ""payer"", verify that they exist, and consent \nis granted with a valid credential +D2 -> D2: Store a referece to the ""consentId"" with the ""transactionRequestId"" +D2 -> D2: Generate a unique transactionId for this transaction request:\n**""11111111-0000-0000-0000-000000000000""** + + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestState": "RECEIVED" +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.svg new file mode 100644 index 000000000..4c898f7e1 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.svg @@ -0,0 +1,224 @@ + + + Transfer: 1.2.1 Agreement + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + + + Agreement Phase + + + + POST /thirdpartyRequests/transactions + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + + + "payee": { + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "+4412345678", + + + "fspId": "dfspb" + + + } + + + }, + + + "payer": { + + + "partyIdType": "THIRD_PARTY_LINK", + + + "partyIdentifier": "qwerty-56789", + + + "fspId": "dfspa" + + + }, + + + "amountType": "SEND", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "transactionType": { + + + "scenario": "TRANSFER", + + + "initiator": "PAYER", + + + "initiatorType": "CONSUMER" + + + }, + + + "expiration": "2020-06-15T22:17:28.985-01:00" + + + } + + + + POST /thirdpartyRequests/transactions + + + + + 202 Accepted + + + + POST /thirdpartyRequests/transactions + + + + + 202 Accepted + + + + Lookup the consent for this + + + payer + + + , verify that they exist, and consent + + + is granted with a valid credential + + + + Store a referece to the + + + consentId + + + with the + + + transactionRequestId + + + + Generate a unique transactionId for this transaction request: + + + 11111111-0000-0000-0000-000000000000 + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "transactionRequestState": "RECEIVED" + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.puml new file mode 100644 index 000000000..798e8224b --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.puml @@ -0,0 +1,150 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.2 Authorization + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box + +rnote left of D2 #Light +**""POST /quotes""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "quoteId": "22222222-0000-0000-0000-000000000000", + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "personalInfo": { + "complexName": { + "firstName": "Ayesha", + "lastName": "Takia" + } + }, + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "123456789", + "fspId": "dfspa" + }, + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "note": "quote note" +} +end note +D2 -> S: ""POST /quotes"" +S --> D2: ""202 Accepted"" +S -> D3: ""POST /quotes"" +D3 --> S: ""202 Accepted"" + +rnote left of D2 #Light +**""PUT /quotes/22222222-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: dfspa"" +{ + "transferAmount": { + "amount": "100", + "currency": "USD" + }, + "payeeReceiveAmount": { + "amount": "99", + "currency": "USD" + }, + "payeeFspFee": { + "amount": "1", + "currency": "USD" + }, + "expiration": "2020-06-15T12:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +D3 -> S: ""PUT /quotes/22222222-0000-0000-0000-000000000000"" +S --> D3: ""200 OK"" +S -> D2: ""PUT /quotes/22222222-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +note left of D2 + DFSP A has the quote, they can now ask + the PISP for authorization +end note + +D2 -> D2: Generate a UUID for the authorization Request:\n""33333333-0000-0000-0000-000000000000"" +D2 -> D2: Derive the challenge based \non ""PUT /quotes/{ID}"" + +rnote left of D2 #Light +**""POST /thirdpartyRequests/authorizations""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "authorizationRequestId": "33333333-0000-0000-0000-000000000000", + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "challenge": """", + "transferAmount": {"amount": "100", "currency": "USD"}, + "payeeReceiveAmount": {"amount": "99", "currency": "USD"}, + "fees": {"amount": "1", "currency": "USD"}, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T12:00:00.000", +} +end note +D2 -> S: ""POST /thirdpartyRequests/authorizations"" +S --> D2: ""202 Accepted"" +S -> D1: ""POST /thirdpartyRequests/authorizations"" +D1 --> S: ""202 Accepted"" + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.svg new file mode 100644 index 000000000..a483f8633 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.svg @@ -0,0 +1,396 @@ + + + Transfer: 1.2.2 Authorization + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + DFSP B + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + DFSP B + + + (Payee) + + + + POST /quotes + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: dfspb + + + { + + + "quoteId": "22222222-0000-0000-0000-000000000000", + + + "transactionId": "11111111-0000-0000-0000-000000000000", + + + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + + + "payee": { + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "+4412345678", + + + "fspId": "dfspb" + + + } + + + }, + + + "payer": { + + + "personalInfo": { + + + "complexName": { + + + "firstName": "Ayesha", + + + "lastName": "Takia" + + + } + + + }, + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "123456789", + + + "fspId": "dfspa" + + + }, + + + }, + + + "amountType": "SEND", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "transactionType": { + + + "scenario": "TRANSFER", + + + "initiator": "PAYER", + + + "initiatorType": "CONSUMER" + + + }, + + + "note": "quote note" + + + } + + + + POST /quotes + + + + + 202 Accepted + + + + POST /quotes + + + + + 202 Accepted + + + + PUT /quotes/22222222-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspb + + + FSPIOP-Destination: dfspa + + + { + + + "transferAmount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "payeeReceiveAmount": { + + + "amount": "99", + + + "currency": "USD" + + + }, + + + "payeeFspFee": { + + + "amount": "1", + + + "currency": "USD" + + + }, + + + "expiration": "2020-06-15T12:00:00.000", + + + "ilpPacket": "...", + + + "condition": "...", + + + } + + + + PUT /quotes/22222222-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /quotes/22222222-0000-0000-0000-000000000000 + + + + + 200 OK + + + + + DFSP A has the quote, they can now ask + + + the PISP for authorization + + + + Generate a UUID for the authorization Request: + + + 33333333-0000-0000-0000-000000000000 + + + + Derive the challenge based + + + on + + + PUT /quotes/{ID} + + + + POST /thirdpartyRequests/authorizations + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "authorizationRequestId": "33333333-0000-0000-0000-000000000000", + + + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + + + "challenge": + + + <base64 encoded binary - the encoded challenge> + + + , + + + "transferAmount": {"amount": "100", "currency": "USD"}, + + + "payeeReceiveAmount": {"amount": "99", "currency": "USD"}, + + + "fees": {"amount": "1", "currency": "USD"}, + + + "payer": { + + + "partyIdType": "THIRD_PARTY_LINK", + + + "partyIdentifier": "qwerty-56789", + + + "fspId": "dfspa" + + + }, + + + "payee": { + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "+4412345678", + + + "fspId": "dfspb" + + + } + + + }, + + + "transactionType": { + + + "scenario": "TRANSFER", + + + "initiator": "PAYER", + + + "initiatorType": "CONSUMER" + + + }, + + + "expiration": "2020-06-15T12:00:00.000", + + + } + + + + POST /thirdpartyRequests/authorizations + + + + + 202 Accepted + + + + POST /thirdpartyRequests/authorizations + + + + + 202 Accepted + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.puml new file mode 100644 index 000000000..01205b804 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.puml @@ -0,0 +1,76 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.3 Rejected Authorization + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +== Agreement Phase == +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the quote with the user, + + + User rejects the terms of the transcationRequest +end note + +rnote right of D1 #Light +**""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "REJECTED" +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Look up the ""transactionRequestId"" for this ""authorizationId"" + +note over D2 + User has rejected the transaction request. +end note + +rnote over D2 #Light +**""PATCH /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionRequestState": "REJECTED", + "transactionId": "11111111-0000-0000-0000-000000000000", +} +end note +D2 -> S: ""PATCH /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" + +S -> D1: ""PATCH /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + +note over D1 + PISP can inform the user the transaction did not proceed +end note + + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.svg new file mode 100644 index 000000000..0187f0d38 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.svg @@ -0,0 +1,165 @@ + + + Transfer: 1.2.3 Rejected Authorization + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + + + Agreement Phase + + + + + PISP looks up the + + + transactionRequestId + + + and + + + checks the quote with the user, + + + User rejects the terms of the transcationRequest + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "responseType": "REJECTED" + + + } + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + Look up the + + + transactionRequestId + + + for this + + + authorizationId + + + + + User has rejected the transaction request. + + + + PATCH /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "transactionRequestState": "REJECTED", + + + "transactionId": "11111111-0000-0000-0000-000000000000", + + + } + + + + PATCH /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PATCH /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + + PISP can inform the user the transaction did not proceed + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.puml new file mode 100644 index 000000000..90b1b7b83 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.puml @@ -0,0 +1,74 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.3 Signed Authorization FIDO + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +== Agreement Phase == +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the terms with the user. + + If the user agrees to the terms, the PISP + uses the FIDO API on the user's device to sign the + the **""challenge""** string +end note + +rnote right of D1 #Light +**""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Look up the ""transactionRequestId"" for this ""authorizationId"" +D2 -> D2: Look up the ""consentId"" for this ""transactionRequestId"" + +note over D2 + DFSP has the signed challenge. + It now needs to ask the Auth-Service to verify + the signed challenge. +end note + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.svg new file mode 100644 index 000000000..789519f61 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.svg @@ -0,0 +1,187 @@ + + + Transfer: 1.2.3 Signed Authorization FIDO + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + + + Agreement Phase + + + + + PISP looks up the + + + transactionRequestId + + + and + + + checks the terms with the user. + + + If the user agrees to the terms, the PISP + + + uses the FIDO API on the user's device to sign the + + + the + + + challenge + + + string + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "responseType": "ACCEPTED" + + + "signedPayload": { + + + "signedPayloadType": "FIDO", + + + "fidoSignedPayload": { + + + "id": "string", + + + "rawId": "string - base64 encoded utf-8", + + + "response": { + + + "authenticatorData": "string - base64 encoded utf-8", + + + "clientDataJSON": "string - base64 encoded utf-8", + + + "signature": "string - base64 encoded utf-8", + + + "userHandle": "string - base64 encoded utf-8", + + + }, + + + "type": "public-key" + + + } + + + } + + + } + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + Look up the + + + transactionRequestId + + + for this + + + authorizationId + + + + Look up the + + + consentId + + + for this + + + transactionRequestId + + + + + DFSP has the signed challenge. + + + It now needs to ask the Auth-Service to verify + + + the signed challenge. + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.puml new file mode 100644 index 000000000..28d5c723a --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.puml @@ -0,0 +1,63 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.3 Signed Authorization + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +== Agreement Phase == +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the quote with the user. + + If the user agrees to the terms, the PISP uses + the Credential's privateKey to sign the challenge +end note + +rnote right of D1 #Light +**""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "GENERIC", + "genericSignedPayload": "utf-8 base64 encoded signature" + } +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Look up the ""transactionRequestId"" for this ""authorizationId"" +D2 -> D2: Look up the ""consentId"" for this ""transactionRequestId"" + +note over D2 + DFSP has the signed challenge. + It now needs to ask the Auth-Service to verify + the signed challenge. +end note + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.svg new file mode 100644 index 000000000..474f7023b --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.svg @@ -0,0 +1,148 @@ + + + Transfer: 1.2.3 Signed Authorization + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + + + Agreement Phase + + + + + PISP looks up the + + + transactionRequestId + + + and + + + checks the quote with the user. + + + If the user agrees to the terms, the PISP uses + + + the Credential's privateKey to sign the challenge + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "responseType": "ACCEPTED" + + + "signedPayload": { + + + "signedPayloadType": "GENERIC", + + + "genericSignedPayload": "utf-8 base64 encoded signature" + + + } + + + } + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + Look up the + + + transactionRequestId + + + for this + + + authorizationId + + + + Look up the + + + consentId + + + for this + + + transactionRequestId + + + + + DFSP has the signed challenge. + + + It now needs to ask the Auth-Service to verify + + + the signed challenge. + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.puml new file mode 100644 index 000000000..8bde91c2c --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.puml @@ -0,0 +1,82 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.4 Verify Authorization + + +box "Mojaloop" + participant Switch as S + participant "Auth-Service" as AUTHS +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +D2 -> D2: Generate a new ""verificationRequestId"", and associate \n it with the ""thirdpartyTransactionRequestId"" + +rnote left of D2 #Light +**""POST /thirdpartyRequests/verifications""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: central-auth"" +{ + "verificationRequestId": "44444444-0000-0000-0000-000000000000", + "challenge": """", + "consentId": "123", + "signedPayloadType": "FIDO", + "fidoValue": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } +} +end note +D2 -> S: ""POST /thirdpartyRequests/verifications"" +S --> D2: ""202 Accepted"" +S -> AUTHS: ""POST /thirdpartyRequests/verifications"" +AUTHS --> S: ""202 Accepted"" + +AUTHS -> AUTHS: Lookup this consent based on consentId +AUTHS -> AUTHS: Ensure the accountAddress matches what is in Consent +AUTHS -> AUTHS: Check that the signed bytes match the \npublickey we have stored for the consent + +rnote right of AUTHS #Light +**""PUT /thirdpartyRequests/verifications/44444444-0000-0000-0000-000000000000""** +""FSPIOP-Source: central-auth"" +""FSPIOP-Destination: dfspa"" +{ + "authenticationResponse": "VERIFIED" +} +end note +AUTHS -> S: ""PUT /thirdpartyRequests/verifications""\n"" /44444444-0000-0000-0000-000000000000"" +S --> AUTHS: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/verifications""\n"" /44444444-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +note over D2 + DFSPA now knows that the user signed this transaction + and can go ahead and initiate the transfer +end note + + + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.svg new file mode 100644 index 000000000..1c7b39fe0 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.svg @@ -0,0 +1,196 @@ + + + Transfer: 1.2.4 Verify Authorization + + + + Mojaloop + + + + DFSP A + + + + + Switch + + + + Auth-Service + + + + DFSP A + + + (Payer) + + + + Generate a new + + + verificationRequestId + + + , and associate + + + it with the + + + thirdpartyTransactionRequestId + + + + POST /thirdpartyRequests/verifications + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: central-auth + + + { + + + "verificationRequestId": "44444444-0000-0000-0000-000000000000", + + + "challenge": + + + <base64 encoded binary - the encoded challenge> + + + , + + + "consentId": "123", + + + "signedPayloadType": "FIDO", + + + "fidoValue": { + + + "id": "string", + + + "rawId": "string - base64 encoded utf-8", + + + "response": { + + + "authenticatorData": "string - base64 encoded utf-8", + + + "clientDataJSON": "string - base64 encoded utf-8", + + + "signature": "string - base64 encoded utf-8", + + + "userHandle": "string - base64 encoded utf-8", + + + }, + + + "type": "public-key" + + + } + + + } + + + + POST /thirdpartyRequests/verifications + + + + + 202 Accepted + + + + POST /thirdpartyRequests/verifications + + + + + 202 Accepted + + + + Lookup this consent based on consentId + + + + Ensure the accountAddress matches what is in Consent + + + + Check that the signed bytes match the + + + publickey we have stored for the consent + + + + PUT /thirdpartyRequests/verifications/44444444-0000-0000-0000-000000000000 + + + FSPIOP-Source: central-auth + + + FSPIOP-Destination: dfspa + + + { + + + "authenticationResponse": "VERIFIED" + + + } + + + + PUT /thirdpartyRequests/verifications + + + /44444444-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/verifications + + + /44444444-0000-0000-0000-000000000000 + + + + + 200 OK + + + + + DFSPA now knows that the user signed this transaction + + + and can go ahead and initiate the transfer + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-3-transfer.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-3-transfer.puml new file mode 100644 index 000000000..1af60155e --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-3-transfer.puml @@ -0,0 +1,178 @@ +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +hide footbox + +title Transfer: 1.3 Final transfer + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box +actor "<$actor>\nPayee" as CB + + + +== Transfer Phase == + +... DFSP A initiates a normal Mojaloop P2P Transfer ... + +D2 -> D2: Generate a new ""transferId"", and associate \n it with the ""transactionRequestId"" + +rnote over D2 #Light +**""POST /transfers""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +D2 -> S: ""POST /transfers"" +S --> D2: ""202 Accepted"" + +rnote over S #Light +**""POST /transfers""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +S -> D3: ""POST /transfers"" +D3 --> S: ""202 Accepted"" + +rnote left of D3 #Light +**""PUT /transfers/55555555-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: dfspa"" +{ + "fulfilment": "...", + "completedTimestamp": "2020-06-15T12:01:00.000", + "transferState": "COMMITTED" +} +end note +D3 -> S: ""PUT /transfers/55555555-0000-0000-0000-000000000000"" +S --> D3: ""200 OK"" +D3 -> CB: You have received funds! +S -> D2: ""PUT /transfers/55555555-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + + +D2 -> D2: Look up ""transactionRequestId"" from the ""transferId"" + +rnote over D2 #Light +**""PATCH /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionRequestState": "ACCEPTED", + "transactionState": "COMMITTED" +} +end note +D2 -> S: ""PATCH /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" + +S -> D1: ""PATCH /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + +note over D1 + PISP can now inform the user the + funds have been sent +end note + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-3-transfer.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-3-transfer.svg new file mode 100644 index 000000000..4adab1df0 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/1-3-transfer.svg @@ -0,0 +1,309 @@ + + + Transfer: 1.3 Final transfer + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + DFSP B + + + + + + + + + + + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + DFSP B + + + (Payee) + + + + Payee + + + + + + + + Transfer Phase + + + DFSP A initiates a normal Mojaloop P2P Transfer + + + + Generate a new + + + transferId + + + , and associate + + + it with the + + + transactionRequestId + + + + POST /transfers + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: dfspb + + + { + + + "transferId": "55555555-0000-0000-0000-000000000000", + + + "payerFsp": "dfspa", + + + "payeeFsp": "dfspb", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "expiration": "2020-06-15T13:00:00.000", + + + "ilpPacket": "...", + + + "condition": "...", + + + } + + + + POST /transfers + + + + + 202 Accepted + + + + POST /transfers + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: dfspb + + + { + + + "transferId": "55555555-0000-0000-0000-000000000000", + + + "payerFsp": "dfspa", + + + "payeeFsp": "dfspb", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "expiration": "2020-06-15T13:00:00.000", + + + "ilpPacket": "...", + + + "condition": "...", + + + } + + + + POST /transfers + + + + + 202 Accepted + + + + PUT /transfers/55555555-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspb + + + FSPIOP-Destination: dfspa + + + { + + + "fulfilment": "...", + + + "completedTimestamp": "2020-06-15T12:01:00.000", + + + "transferState": "COMMITTED" + + + } + + + + PUT /transfers/55555555-0000-0000-0000-000000000000 + + + + + 200 OK + + + + You have received funds! + + + + PUT /transfers/55555555-0000-0000-0000-000000000000 + + + + + 200 OK + + + + Look up + + + transactionRequestId + + + from the + + + transferId + + + + PATCH /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "transactionRequestState": "ACCEPTED", + + + "transactionState": "COMMITTED" + + + } + + + + PATCH /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PATCH /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + + PISP can now inform the user the + + + funds have been sent + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.puml new file mode 100644 index 000000000..1252be904 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.puml @@ -0,0 +1,90 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.2.1 Bad Thirdparty Transaction Request + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +== Agreement Phase == +rnote right of D1 #Light +**""POST /thirdpartyRequests/transactions""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T22:17:28.985-01:00" +} +end note +D1 -> S: ""POST /thirdpartyRequests/transactions"" +S --> D1: ""202 Accepted"" +S -> D2: ""POST /thirdpartyRequests/transactions"" +D2 --> S: ""202 Accepted"" + +D2 -> D2: DFSP finds something wrong with this transaction request. + + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6104", + "errorDescription": "Thirdparty request rejection", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.svg new file mode 100644 index 000000000..c62356dfc --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.svg @@ -0,0 +1,207 @@ + + + Transfer: 3.2.1 Bad Thirdparty Transaction Request + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + + + Agreement Phase + + + + POST /thirdpartyRequests/transactions + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + + + "payee": { + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "+4412345678", + + + "fspId": "dfspb" + + + } + + + }, + + + "payer": { + + + "partyIdType": "THIRD_PARTY_LINK", + + + "partyIdentifier": "qwerty-56789", + + + "fspId": "dfspa" + + + }, + + + "amountType": "SEND", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "transactionType": { + + + "scenario": "TRANSFER", + + + "initiator": "PAYER", + + + "initiatorType": "CONSUMER" + + + }, + + + "expiration": "2020-06-15T22:17:28.985-01:00" + + + } + + + + POST /thirdpartyRequests/transactions + + + + + 202 Accepted + + + + POST /thirdpartyRequests/transactions + + + + + 202 Accepted + + + + DFSP finds something wrong with this transaction request. + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "errorInformation": { + + + "errorCode": "6104", + + + "errorDescription": "Thirdparty request rejection", + + + "extensionList": [] + + + } + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.puml new file mode 100644 index 000000000..b6ebf6ce3 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.puml @@ -0,0 +1,141 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.3.1 Bad Quote Request + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box + +... PISP has initiated Thirdparty Transaction Request with ""POST /thirdpartyRequests/transactions""... + +D2 -> D2: Generate a unique transactionId for this transaction request:\n**""11111111-0000-0000-0000-000000000000""** + + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestState": "RECEIVED" +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + +rnote left of D2 #Light +**""POST /quotes""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "quoteId": "22222222-0000-0000-0000-000000000000", + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "personalInfo": { + "complexName": { + "firstName": "Ayesha", + "lastName": "Takia" + } + }, + "partyIdInfo": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + }, + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "note": "quote note" +} +end note +D2 -> S: ""POST /quotes"" +S --> D2: ""202 Accepted"" +S -> D3: ""POST /quotes"" +D3 --> S: ""202 Accepted"" + +D3 -> D3: Quote fails for some reason. + +rnote left of D3 #Light +**""PUT /quotes/22222222-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: dfspa"" +{ + "errorInformation": { + "errorCode": "XXXX", + "errorDescription": "XXXX", + "extensionList": [] + } +} +end note +D3 -> S: ""PUT /quotes/22222222-0000-0000-0000-000000000000/error"" +S --> D3: ""200 OK"" +S -> D2: ""PUT /quotes/22222222-0000-0000-0000-000000000000/error"" +D2 --> S: ""200 OK"" + +note left of D2 + Quote failed, DFSP needs to inform PISP +end note + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6003", + "errorDescription": "Downstream Failure", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.svg new file mode 100644 index 000000000..841d82c6d --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.svg @@ -0,0 +1,369 @@ + + + Transfer: 3.3.1 Bad Quote Request + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + DFSP B + + + + + + + + + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + DFSP B + + + (Payee) + + + PISP has initiated Thirdparty Transaction Request with + + + POST /thirdpartyRequests/transactions + + + + Generate a unique transactionId for this transaction request: + + + 11111111-0000-0000-0000-000000000000 + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "transactionId": "11111111-0000-0000-0000-000000000000", + + + "transactionRequestState": "RECEIVED" + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + POST /quotes + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: dfspb + + + { + + + "quoteId": "22222222-0000-0000-0000-000000000000", + + + "transactionId": "11111111-0000-0000-0000-000000000000", + + + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + + + "payee": { + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "+4412345678", + + + "fspId": "dfspb" + + + } + + + }, + + + "payer": { + + + "personalInfo": { + + + "complexName": { + + + "firstName": "Ayesha", + + + "lastName": "Takia" + + + } + + + }, + + + "partyIdInfo": { + + + "partyIdType": "THIRD_PARTY_LINK", + + + "partyIdentifier": "qwerty-56789", + + + "fspId": "dfspa" + + + }, + + + }, + + + }, + + + "amountType": "SEND", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "transactionType": { + + + "scenario": "TRANSFER", + + + "initiator": "PAYER", + + + "initiatorType": "CONSUMER" + + + }, + + + "note": "quote note" + + + } + + + + POST /quotes + + + + + 202 Accepted + + + + POST /quotes + + + + + 202 Accepted + + + + Quote fails for some reason. + + + + PUT /quotes/22222222-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspb + + + FSPIOP-Destination: dfspa + + + { + + + "errorInformation": { + + + "errorCode": "XXXX", + + + "errorDescription": "XXXX", + + + "extensionList": [] + + + } + + + } + + + + PUT /quotes/22222222-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /quotes/22222222-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + + Quote failed, DFSP needs to inform PISP + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "errorInformation": { + + + "errorCode": "6003", + + + "errorDescription": "Downstream Failure", + + + "extensionList": [] + + + } + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.puml new file mode 100644 index 000000000..3a7f78799 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.puml @@ -0,0 +1,122 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.3.2 Bad Transfer Request + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box + +... PISP has initiated Thirdparty Transaction Request with ""POST /thirdpartyRequests/transactions""... + +... DFSP A has received quote, and asked PISP to verify... + +... DFSP A has received ""PUT /thirdpartyRequests/verifications from Auth-Service""... + +... DFSP A initiates a normal Mojaloop P2P Transfer ... + +D2 -> D2: Generate a new ""transferId"", and associate \n it with the ""transactionRequestId"" + +rnote over D2 #Light +**""POST /transfers""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +D2 -> S: ""POST /transfers"" +S --> D2: ""202 Accepted"" + +rnote over S #Light +**""POST /transfers""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +S -> D3: ""POST /transfers"" +D3 --> S: ""202 Accepted"" + +rnote left of D3 #Light +**""PUT /transfers/55555555-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: dfspa"" +{ + "errorInformation": { + "errorCode": "XXXX", + "errorDescription": "XXXX", + "extensionList": [] + } +} +end note +D3 -> S: ""PUT /transfers/55555555-0000-0000-0000-000000000000/error"" +S --> D3: ""200 OK"" +S -> D2: ""PUT /transfers/55555555-0000-0000-0000-000000000000/error"" +D2 --> S: ""200 OK"" + +note left of D2 + Transfer failed, DFSP needs to inform PISP +end note + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6003", + "errorDescription": "Downstream failure", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.svg new file mode 100644 index 000000000..85626c5b2 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.svg @@ -0,0 +1,332 @@ + + + Transfer: 3.3.2 Bad Transfer Request + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + DFSP B + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + DFSP B + + + (Payee) + + + PISP has initiated Thirdparty Transaction Request with + + + POST /thirdpartyRequests/transactions + + + DFSP A has received quote, and asked PISP to verify + + + DFSP A has received + + + PUT /thirdpartyRequests/verifications from Auth-Service + + + DFSP A initiates a normal Mojaloop P2P Transfer + + + + Generate a new + + + transferId + + + , and associate + + + it with the + + + transactionRequestId + + + + POST /transfers + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: dfspb + + + { + + + "transferId": "55555555-0000-0000-0000-000000000000", + + + "payerFsp": "dfspa", + + + "payeeFsp": "dfspb", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "expiration": "2020-06-15T13:00:00.000", + + + "ilpPacket": "...", + + + "condition": "...", + + + } + + + + POST /transfers + + + + + 202 Accepted + + + + POST /transfers + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: dfspb + + + { + + + "transferId": "55555555-0000-0000-0000-000000000000", + + + "payerFsp": "dfspa", + + + "payeeFsp": "dfspb", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "expiration": "2020-06-15T13:00:00.000", + + + "ilpPacket": "...", + + + "condition": "...", + + + } + + + + POST /transfers + + + + + 202 Accepted + + + + PUT /transfers/55555555-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspb + + + FSPIOP-Destination: dfspa + + + { + + + "errorInformation": { + + + "errorCode": "XXXX", + + + "errorDescription": "XXXX", + + + "extensionList": [] + + + } + + + } + + + + PUT /transfers/55555555-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /transfers/55555555-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + + Transfer failed, DFSP needs to inform PISP + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "errorInformation": { + + + "errorCode": "6003", + + + "errorDescription": "Downstream failure", + + + "extensionList": [] + + + } + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.puml new file mode 100644 index 000000000..5bc586ee2 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.puml @@ -0,0 +1,95 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.4.1 Bad Signed Challenge - Self Hosted Auth-Service + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + +... PISP has initiated Thirdparty Transaction Request with ""POST /thirdpartyRequests/transactions""... + +... DFSP A has received quote, and asked PISP to verify... + +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the quote with the user, + and uses the FIDO API to sign the + the **""challenge""** string +end note + +rnote right of D1 #Light +**""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Look up the ""transactionRequestId"" for this ""authorizationId"" +D2 -> D2: Look up the ""consentId"" for this ""transactionRequestId"" +D2 -> D2: Look up the ""publicKey"" for this ConsentId. Check the signing of the signed challenge + +note over D2 + Signed challenge is invalid. Transaction Request failed. +end note + + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6201", + "errorDescription": "Invalid transaction signature", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.svg new file mode 100644 index 000000000..213f6fc07 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.svg @@ -0,0 +1,261 @@ + + + Transfer: 3.4.1 Bad Signed Challenge - Self Hosted Auth-Service + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + + + + + + + + + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + PISP has initiated Thirdparty Transaction Request with + + + POST /thirdpartyRequests/transactions + + + DFSP A has received quote, and asked PISP to verify + + + + + PISP looks up the + + + transactionRequestId + + + and + + + checks the quote with the user, + + + and uses the FIDO API to sign the + + + the + + + challenge + + + string + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "responseType": "ACCEPTED" + + + "signedPayload": { + + + "signedPayloadType": "FIDO", + + + "fidoSignedPayload": { + + + "id": "string", + + + "rawId": "string - base64 encoded utf-8", + + + "response": { + + + "authenticatorData": "string - base64 encoded utf-8", + + + "clientDataJSON": "string - base64 encoded utf-8", + + + "signature": "string - base64 encoded utf-8", + + + "userHandle": "string - base64 encoded utf-8", + + + }, + + + "type": "public-key" + + + } + + + } + + + } + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + Look up the + + + transactionRequestId + + + for this + + + authorizationId + + + + Look up the + + + consentId + + + for this + + + transactionRequestId + + + + Look up the + + + publicKey + + + for this ConsentId. Check the signing of the signed challenge + + + + + Signed challenge is invalid. Transaction Request failed. + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "errorInformation": { + + + "errorCode": "6201", + + + "errorDescription": "Invalid transaction signature", + + + "extensionList": [] + + + } + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.puml new file mode 100644 index 000000000..ce3645d30 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.puml @@ -0,0 +1,149 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.4.2 Bad Signed Challenge - Hub Hosted Auth-Service + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S + participant "Auth-Service" as AUTHS +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +... PISP has initiated Thirdparty Transaction Request with ""POST /thirdpartyRequests/transactions""... + +... DFSP A has received quote, and asked PISP to verify... + +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the quote with the user, + and uses the FIDO API to sign the + the **""challenge""** string +end note + +rnote right of D1 #Light +**""PUT /thirdpartyRequests/authorizations""** +**"" /33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Lookup ""transactionRequestId"" for this ""authorizationId"" +D2 -> D2: Lookup ""consentId"" for this ""transactionRequestId"" + + +D2 -> D2: Generate a new ""verificationRequestId"", and associate \n it with the ""thirdpartyTransactionRequestId"" + +rnote left of D2 #Light +**""POST /thirdpartyRequests/verifications""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: central-auth"" +{ + "verificationRequestId": "44444444-0000-0000-0000-000000000000", + "challenge": """", + "consentId": "123", + "signedPayloadType": "FIDO", + "fidoValue": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } +} +end note +D2 -> S: ""POST /thirdpartyRequests/verifications"" +S --> D2: ""202 Accepted"" +S -> AUTHS: ""POST /thirdpartyRequests/verifications"" +AUTHS --> S: ""202 Accepted"" + +AUTHS -> AUTHS: Lookup this consent based on consentId +AUTHS -> AUTHS: Ensure the accountAddress matches what is in Consent +AUTHS -> AUTHS: Check that the signed bytes match the \npublickey we have stored for the consent + +rnote right of AUTHS #Light +**""PUT /thirdpartyRequests/verifications""** +**"" /44444444-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: central-auth"" +""FSPIOP-Destination: dfspa"" +{ + "errorInformation": { + "errorCode": "6201", + "errorDescription": "Invalid transaction signature", + "extensionList": [] + } +} +end note +AUTHS -> S: ""PUT /thirdpartyRequests/verifications""\n"" /44444444-0000-0000-0000-000000000000/error"" +S --> AUTHS: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/verifications""\n"" /44444444-0000-0000-0000-000000000000/error"" +D2 --> S: ""200 OK"" + +note over D2 + Signed challenge is invalid. Transaction Request failed. +end note + + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6201", + "errorDescription": "Invalid transaction signature", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.svg new file mode 100644 index 000000000..58c8e9957 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.svg @@ -0,0 +1,439 @@ + + + Transfer: 3.4.2 Bad Signed Challenge - Hub Hosted Auth-Service + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + + + + + + + + + + + + + + + + + PISP Server + + + + Switch + + + + Auth-Service + + + + DFSP A + + + (Payer) + + + PISP has initiated Thirdparty Transaction Request with + + + POST /thirdpartyRequests/transactions + + + DFSP A has received quote, and asked PISP to verify + + + + + PISP looks up the + + + transactionRequestId + + + and + + + checks the quote with the user, + + + and uses the FIDO API to sign the + + + the + + + challenge + + + string + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "responseType": "ACCEPTED" + + + "signedPayload": { + + + "signedPayloadType": "FIDO", + + + "fidoSignedPayload": { + + + "id": "string", + + + "rawId": "string - base64 encoded utf-8", + + + "response": { + + + "authenticatorData": "string - base64 encoded utf-8", + + + "clientDataJSON": "string - base64 encoded utf-8", + + + "signature": "string - base64 encoded utf-8", + + + "userHandle": "string - base64 encoded utf-8", + + + }, + + + "type": "public-key" + + + } + + + } + + + } + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + Lookup + + + transactionRequestId + + + for this + + + authorizationId + + + + Lookup + + + consentId + + + for this + + + transactionRequestId + + + + Generate a new + + + verificationRequestId + + + , and associate + + + it with the + + + thirdpartyTransactionRequestId + + + + POST /thirdpartyRequests/verifications + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: central-auth + + + { + + + "verificationRequestId": "44444444-0000-0000-0000-000000000000", + + + "challenge": + + + <base64 encoded binary - the encoded challenge> + + + , + + + "consentId": "123", + + + "signedPayloadType": "FIDO", + + + "fidoValue": { + + + "id": "string", + + + "rawId": "string - base64 encoded utf-8", + + + "response": { + + + "authenticatorData": "string - base64 encoded utf-8", + + + "clientDataJSON": "string - base64 encoded utf-8", + + + "signature": "string - base64 encoded utf-8", + + + "userHandle": "string - base64 encoded utf-8", + + + }, + + + "type": "public-key" + + + } + + + } + + + + POST /thirdpartyRequests/verifications + + + + + 202 Accepted + + + + POST /thirdpartyRequests/verifications + + + + + 202 Accepted + + + + Lookup this consent based on consentId + + + + Ensure the accountAddress matches what is in Consent + + + + Check that the signed bytes match the + + + publickey we have stored for the consent + + + + PUT /thirdpartyRequests/verifications + + + /44444444-0000-0000-0000-000000000000/error + + + FSPIOP-Source: central-auth + + + FSPIOP-Destination: dfspa + + + { + + + "errorInformation": { + + + "errorCode": "6201", + + + "errorDescription": "Invalid transaction signature", + + + "extensionList": [] + + + } + + + } + + + + PUT /thirdpartyRequests/verifications + + + /44444444-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /thirdpartyRequests/verifications + + + /44444444-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + + Signed challenge is invalid. Transaction Request failed. + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "errorInformation": { + + + "errorCode": "6201", + + + "errorDescription": "Invalid transaction signature", + + + "extensionList": [] + + + } + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.puml new file mode 100644 index 000000000..dfcae6698 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.puml @@ -0,0 +1,77 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.Thirdparty Transaction Request Times Out + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +rnote right of D1 #Light +**""POST /thirdpartyRequests/transactions""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T22:17:28.985-01:00" +} +end note +D1 -> S: ""POST /thirdpartyRequests/transactions"" +S --> D1: ""202 Accepted"" +S -> D2: ""POST /thirdpartyRequests/transactions"" +D2 --> S: ""202 Accepted"" + + +... DFSP doesn't respond for some reason... + + +D1 -> D1: Thirdparty Transaction Request expiration reached + +note over D1 + PISP informs their user that the transaction failed. + +end note + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.svg new file mode 100644 index 000000000..e9ba78514 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.svg @@ -0,0 +1,157 @@ + + + Transfer: 3.Thirdparty Transaction Request Times Out + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + + + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + POST /thirdpartyRequests/transactions + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + + + "payee": { + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "+4412345678", + + + "fspId": "dfspb" + + + } + + + }, + + + "payer": { + + + "partyIdType": "THIRD_PARTY_LINK", + + + "partyIdentifier": "qwerty-56789", + + + "fspId": "dfspa" + + + }, + + + "amountType": "SEND", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "transactionType": { + + + "scenario": "TRANSFER", + + + "initiator": "PAYER", + + + "initiatorType": "CONSUMER" + + + }, + + + "expiration": "2020-06-15T22:17:28.985-01:00" + + + } + + + + POST /thirdpartyRequests/transactions + + + + + 202 Accepted + + + + POST /thirdpartyRequests/transactions + + + + + 202 Accepted + + + DFSP doesn't respond for some reason + + + + Thirdparty Transaction Request expiration reached + + + + + PISP informs their user that the transaction failed. + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/get_transaction_request.puml b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/get_transaction_request.puml new file mode 100644 index 000000000..c8ca6b83b --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/get_transaction_request.puml @@ -0,0 +1,67 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISPGetTransactionRequest + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + +autonumber 1 "GTR-#" + +note over S + Assuming a previously created thirdparty transaction request with id: ""00000000-0000-0000-0000-000000000000"" + +end note + + + +rnote right of D1 #Light +**""GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +end note + +D1 -> S: ""GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" +S --> D1: ""202 Accepted"" + +S -> D2: ""GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" +D2 --> S: ""202 Accepted"" + +D2 -> D2: DFSP looks up already created \nthirdparty transaction request +D2 -> D2: DFSP ensures that the FSPIOP-Source (pisp)\nis the same as the original sender of \n""POST /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionRequestState": "ACCEPTED", +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" + +S -> D1: ""PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/get_transaction_request.svg b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/get_transaction_request.svg new file mode 100644 index 000000000..ffaa28ada --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/assets/diagrams/transfer/get_transaction_request.svg @@ -0,0 +1,153 @@ + + + PISPGetTransactionRequest + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + + Assuming a previously created thirdparty transaction request with id: + + + 00000000-0000-0000-0000-000000000000 + + + + GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + + GTR-1 + + + GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + + + GTR-2 + + + 202 Accepted + + + + GTR-3 + + + GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + + + GTR-4 + + + 202 Accepted + + + + GTR-5 + + + DFSP looks up already created + + + thirdparty transaction request + + + + GTR-6 + + + DFSP ensures that the FSPIOP-Source (pisp) + + + is the same as the original sender of + + + POST /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + + PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "transactionRequestState": "ACCEPTED", + + + } + + + + GTR-7 + + + PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + + + GTR-8 + + + 200 OK + + + + GTR-9 + + + PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + + + GTR-10 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md b/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md new file mode 100644 index 000000000..d9afaea7d --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md @@ -0,0 +1,990 @@ +# Data Models + +Third Party API + +### Table Of Contents + +1. [Preface](#Preface) + 1.1 [Conventions Used in This Document](#ConventionsUsedinThisDocument) + 1.2 [Document Version Information](#DocumentVersionInformation) + 1.3 [References](#References) +2. [Introduction](#Introduction) + 2.1 [Third Party API Specification](#ThirdPartyAPISpecification) +3. [Third Party API Elements](#ThirdPartyAPIElements) + 3.1 [Resources](#Resources) + 3.2 [Data Models](#DataModels) + 3.3 [Error Codes](#ErrorCodes) +# 1. Preface +This section contains information about how to use this document. + +## 1.1 Conventions Used in This Document + +The following conventions are used in this document to identify the +specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics with in angle brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature and API Encryption_ should be used instead.| + +## 1.2 Document Version Information + +| Version | Date | Change Description | +| --- | --- | --- | +| **1.0** | 2021-10-03 | Initial Version + +## 1.3 References + +The following references are used in this specification: + +| Reference | Description | Version | Link | +| --- | --- | --- | --- | +| Ref. 1 | Open API for FSP Interoperability | `1.1` | [API Definition v1.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md)| + + +# 2. Introduction + +This document specifies the data model used by the Mojaloop Third Party API ("the API"). + +## 2.1 Third Party API Specification + +The Mojaloop Third Party API Specification includes the following documents: + +- [Data Models](./data-models.md) +- [Transaction Patterns - Linking](./transaction-patterns-linking.md) +- [Transaction Patterns - Transfer](./transaction-patterns-transfer.md) +- [Third Party Open API Definition - DFSP](./thirdparty-dfsp-v1.0.yaml) +- [Third Party Open API Definition - PISP](./thirdparty-dfsp-v1.0.yaml) + + +# 3. Third Party API Elements + +This section describes the content of the API which will be used by PISPs and DFSPs. + +The content of the API falls into two sections: + +1. [Transaction Patterns - Linking](./transaction-patterns-linking.md) describes the process for linking customer accounts and providing a general permission mechanism for PISPs to perform operations on those accounts +2. [Transaction Patterns - Transfer](./transaction-patterns-transfer.md) describes the transfer of funds at the instigation of a PISP. + +The API is used by the following different types of participant, as follows: + 1. PISPs + 2. DFSPs who offer services to their customer which allow the customer to access their account via one or more PISPs + 3. Auth-Services + 4. The Mojaloop switch + +Each resource in the API definition is accompanied by a definition of the type(s) of participant allowed to access it. + +## 3.1 Resources + +The API contains the following resources: + +### 3.1.1 **/accounts** + +The **/accounts** resource is used to request information from a DFSP relating to the accounts +it holds for a given identifier. The identifier is a user-provided value which the user +uses to access their account with the DFSP, such as a phone number, email address, or +some other identifier previously provided by the DFSP. + +The DFSP returns a set of information about the accounts it is prepared to divulge to the PISP. +The PISP can then display the names of the accounts to the user, and allow the user to select +the accounts with which they wish to link via the PISP. + +The **/accounts** resource supports the endpoints described below. + +#### 3.1.1.1 Requests + +This section describes the services that a PISP can request on the /accounts resource. + +##### 3.1.1.1.1 **GET /accounts/**_{ID}_ + +Used by: PISP + +The HTTP request **GET /accounts/**_{ID}_ is used to lookup information about the requested +user's accounts, defined by an identifier *{ID}*, where *{ID}* is an identifier a user +uses to access their account with the DFSP, such as a phone number, email address, or +some other identifier previously provided by the DFSP. + +Callback and data model information for **GET /accounts/**_{ID}_: +- Callback - **PUT /accounts/**_{ID}_ +- Error Callback - **PUT /accounts/**_{ID}_**/error** +- Data Model – Empty body + +#### 3.1.1.2 Callbacks + +The responses for the **/accounts** resource are as follows + +##### 3.1.1.2.1 **PUT /accounts/**_{ID}_ + +Used by: DFSP + +The **PUT /accounts/**_{ID}_ response is used to inform the requester of the result of a request +for accounts information. The identifier ID given in the call are the +values given in the original request (see Section 3.1.1.1.1 above.) + +The data content of the message is given below. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| accountList | 1 | AccountList | Information about the accounts that the DFSP associates with the identifier sent by the PISP. | + +##### 3.1.1.2.2 **PUT /accounts/**_{ID}_**/error** + +Used by: DFSP + +The **PUT /accounts/**_{ID}_**/error** response is used to inform the requester that an account list +request has given rise to an error. The identifier ID given in the call are +the values given in the original request (see Section 3.1.1.1.1 above.) + +The data content of the message is given below. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + +### 3.1.2 **/consentRequests** + +The **/consentRequests** resource is used by a PISP to initiate the process of linking with a DFSP’s +account on behalf of a user. The PISP contacts the DFSP and sends a list of the permissions that +it wants to obtain and the accounts for which it wants permission. + +#### 3.1.2.1 Requests + +This section describes the services that can be requested by a client on the API resource +**/consentRequests**. +##### 3.1.2.1.1 **GET /consentRequests/**_{ID}_ + +Used by: PISP + +The HTTP request **GET /consentRequests/**_{ID}_ is used to get information about a previously +requested consent. The *{ID}* in the URI should contain the consentRequestId that was assigned to the +request by the PISP when the PISP originated the request. + +Callback and data model information for **GET /consentRequests/**_{ID}_: +- Callback – **PUT /consentRequests/**_{ID}_ +- Error Callback – **PUT /consentRequests/**_{ID}_**/error** +- Data Model – Empty body + +##### 3.1.2.1.2 **POST /consentRequests** + +Used by: PISP + +The HTTP request **POST /consentRequests** is used to request a DFSP to grant access to one or more +accounts owned by a customer of the DFSP for the PISP who sends the request. + +Callback and data model for **POST /consentRequests**: +- Callback: **PUT /consentRequests/**_{ID}_ +- Error callback: **PUT /consentRequests/**_{ID}_**/error** +- Data model – see below + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| consentRequestId | 1 | CorrelationId | Common ID between the PISP and the Payer DFSP for the consent request object. The ID should be reused for resends of the same consent request. A new ID should be generated for each new consent request. | +| userId | 1 | String(1..128) | The identifier used in the **GET /accounts/**_{ID}_. Used by the DFSP to correlate an account lookup to a `consentRequest` | +| scopes | 1..256 | Scope | One or more requests for access to a particular account. In each case, the address of the account and the types of access required are given. | +| authChannels | 1..256 | ConsentRequestChannelType | A collection of the types of authentication that the DFSP may use to verify that its customer has in fact requested access for the PISP to the accounts requested. | +| callbackUri | 1 | Uri | The callback URI that the user will be redirected to after completing verification via the WEB authorization channel. This field is mandatory as the PISP does not know ahead of time which AuthChannel the DSFP will use to authenticate their user. | + +#### 3.1.2.2 Callbacks + +This section describes the callbacks that are used by the server under the resource /consentRequests. + +##### 3.1.2.2.1 **PUT /consentRequests/**_{ID}_ + +Used by: DFSP + +A DFSP uses this callback to (1) inform the PISP that the consentRequest has been accepted, +and (2) communicate to the PISP which `authChannel` it should use to authenticate their user +with. + +When a PISP requests a series of permissions from a DFSP on behalf of a DFSP’s customer, not all +the permissions requested may be granted by the DFSP. Conversely, the out-of-band authorization +process may result in additional privileges being granted by the account holder to the PISP. The +**PUT /consentRequests/**_{ID}_ resource returns the current state of the permissions relating to a +particular authorization request. The data model for this call is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| scopes | 1..256 | Scope | One or more requests for access to a particular account. In each case, the address of the account and the types of access required are given. | +| authChannels | 1 | ConsentRequestChannelType | A list of one element, which the DFSP uses to inform the PISP of the selected authorization channel. | +| callbackUri | 0..1 | Uri |The callback URI that the user will be redirected to after completing verification via the WEB authorization channel | +| authUri | 0..1 | Uri | The URI that the PISP should call to complete the linking procedure if completion is required. | + + +##### 3.1.2.2.2 **PATCH /consentRequests/**_{ID}_ + +Used by: PISP + +After the user completes an out-of-band authorization with the DFSP, the PISP will receive +a token which they can use to prove to the DFSP that the user trusts this PISP. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| authToken | 1 | BinaryString |The token given to the PISP by the DFSP as part of the out-of-band authentication process | + +#### 3.1.2.3 Error callbacks + +This section describes the error callbacks that are used by the server under the resource +**/consentRequests**. + +##### 3.1.2.3.1 **PUT /consentRequests/**_{ID}_**/error** + +Used by: DFSP + +If the server is unable to complete the consent request, or if an out-of-band processing error or +another processing error occurs, the error callback **PUT /consentRequests/**_{ID}_**/error** is used. The +*{ID}* in the URI should contain the *{ID}* that was used in the **GET /consentRequests/**_{ID}_ +request or the **POST /consentRequests** request. The data model for this resource is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + + +### 3.1.3 **/consents** + +The **/consents** resource is used to negotiate a series of permissions between the PISP and the +DFSP which owns the account(s) on behalf of which the PISP wants to transact. + +A **/consents** call is originally sent to the PISP by the DFSP following the original consent +request process described in Section 3.1.2.1.2 above. At the close of this process, the DFSP +which owns the customer’s account(s) will have satisfied itself that its customer really has +requested that the PISP be allowed access to their accounts, and will have defined the accounts in +question and the type of access which is to be granted. +#### 3.1.3.1 Requests +The **/consents** resource will support the following requests. +##### 3.1.3.1.1 **GET /consents/**_{ID}_ + +Used by: DFSP + +The **GET /consents/**_{ID}_ resource allows a party to enquire after the status of a consent. The +*{ID}* used in the URI of the request should be the consent request ID which was used to identify +the consent when it was created. + +Callback and data model information for **GET /consents/**_{ID}_: +- Callback – **PUT /consents/**_{ID}_ +- Error Callback – **PUT /consents/**_{ID}_**/error** +- Data Model – Empty body +##### 3.1.3.1.2 **POST /consents** + +Used by: DFSP + +The **POST /consents** request is used to request the creation of a consent for interactions between +a PISP and the DFSP who owns the account which a PISP’s customer wants to allow the PISP access to. + +Callback and data model information for **POST /consents/**: + +- Callback – **PUT /consents/**_{ID}_ +- Error Callback – **PUT /consents/**_{ID}_**/error** +- Data Model – defined below + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| consentId | 1 | CorrelationId | Common ID between the PISP and the Payer DFSP for the consent object. The ID should be reused for resends of the same consent. A new ID should be generated for each new consent.| +| consentRequestId | 1 | CorrelationId | The ID given to the original consent request on which this consent is based. | +| scopes | 1..256 | Scope | A list Scope objects, which represent the accounts and attached permissions on which the DFSP is prepared to grant specified permissions to the PISP. | +| status | 1 | ConsentStatus | The status of the Consent. | +| credential | 0..1 | Credential | The credential which is being used to support the consents. | +| extensionList | 0..1 | ExtensionList |Optional extension, specific to deployment | +##### 3.1.3.1.3 **DELETE /consents/**_{ID}_ + +Used by PISP, DFSP + +The **DELETE /consents/**_{ID}_ request is used to request the revocation of a previously agreed consent. +For tracing and auditing purposes, the switch should be sure not to delete the consent physically; +instead, information relating to the consent should be marked as deleted and requests relating to the +consent should not be honoured. + +> Note: the ALS should verify that the participant who is requesting the deletion is either the +> initiator named in the consent or the account holding institution named in the consent. If any +> other party attempts to delete a consent, the request should be rejected, and an error raised. + +Callback and data model information for **DELETE /consents/**_{ID}_: +- Callback – **PATCH /consents/**_{ID}_ +- Error Callback – **PUT /consents/**_{ID}_**/error** + +#### 3.1.3.2 Callbacks +The **/consents** resource supports the following callbacks: +##### 3.1.3.2.1 **PATCH/consents/**_{ID}_ + +Used by: Auth-Service, DFSP + +**PATCH /consents/**_{ID}_ is used in 2 places: +1. To inform the PISP that the `consent.credential` is valid and the account linking process completed + successfully. +2. To inform the PISP or the DFSP that the Consent has been revoked. + +In the first case, a DFSP sends a **PATCH/consents/**_{ID}_ request to the PISP with a `credential.status` +of `VERIFIED`. + +In the second case, an Auth-Service or DFSP sends a **PATCH/consents/**_{ID}_ request with a `status` of +`REVOKED`, and the `revokedAt` field set. + +The syntax of this call complies with the JSON Merge Patch specification [RFC-7386](https://datatracker.ietf.org/doc/html/rfc7386) +rather than the JSON Patch specification [RFC-6902](https://datatracker.ietf.org/doc/html/rfc6902). +The **PATCH /consents/**_{ID}_ resource contains a set of proposed changes to the current state of the +permissions relating to a particular authorization grant. The data model +for this call is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| status | 0..1 | ConsentStatus | The status of the Consent. | +| revokedAt | 0..1 | DateTime | The DateTime the consent was revoked at. | +| credential | 0..1 | Credential | The credential which is being used to support the consents. | +| extensionList | 0..1 | ExtensionList | Optional extension, specific to deployment | + +##### 3.1.3.2.2 **PUT /consents/**_{ID}_ + +Used by: PISP + +The **PUT /consents/**_{ID}_ resource is used to return information relating to the consent object +whose `consentId` is given in the URI. And for registering a credential for the consent. The +data returned by the call is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| scopes | 1..256 | Scope | The scopes covered by the consent. | +| status | 0..1 | ConsentStatus | The status of the Consent. | +| credential | 1 | Credential | The credential which is being used to support the consents. | +| extensionList | 0..1 | ExtensionList | Optional extension, specific to deployment | +#### 3.1.3.3 Error callbacks +This section describes the error callbacks that are used by the server under the resource **/consents**. +##### 3.1.3.3.1 **PUT /consents/**_{ID}_**/error** + +Used by: PISP, DFSP, Auth-Service + +If the server is unable to complete the consent, or if an out-of-loop processing error or another +processing error occurs, the error callback **PUT /consents/**_{ID}_**/error** is used. The *{ID}* in the +URI should contain the *{ID}* that was used in the **GET /consents/**_{ID}_ request or the +**POST /consents** request. The data model for this resource is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + +### 3.1.4 **/parties** + +The **/parties** resource will be used by the PISP to identify a party to a transfer. This will be +used by the PISP to identify the payee DFSP when it requests a transfer. + +The PISP will be permitted to issue a **PUT /parties** response. Although it does not own any +transaction accounts, there are circumstances in which another party may want to pay a customer +via their PISP identification: for instance, where the customer is at a merchant’s premises and +tells the merchant that they would like to pay via their PISP app. In these circumstances, the PISP +will need to be able to confirm that it does act for the customer. +#### 3.1.4.1 Requests + +The **/parties** resource will support the following requests. +##### 3.1.4.1.1 **GET /parties** + +Used by: PISP + +The **GET /parties** resource will use the same form as the resource described in +[Section 6.3.3.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#6331-get-partiestypeid) of Ref. 1 above. +#### 3.1.4.2 Callbacks +The parties resource will support the following callbacks. +##### 3.1.4.2.1 **PUT /parties** + +Used by: DFSP + +The **PUT /parties** resource will use the same form as the resource described in +[Section 6.3.4.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#6341-put-partiestypeid) of Ref. 1 above. + +### 3.1.5 **/services** +The **/services** resource is a new resource which enables a participant to query for other +participants who offer a particular service. The requester will issue a `GET` request, specifying +the type of service for which information is required as part of the query string. The switch will +respond with a list of the current DFSPs in the scheme which are registered as providing that +service. +#### 3.1.5.1 Requests +The services resource will support the following requests. +#### 3.1.5.2 **GET /services/**_{ServiceType}_ + +Used by: DFSP, PISP + +The HTTP request **GET /services/**_{ServiceType}_ is used to find out the names of the participants in a +scheme which provide the type of service defined in the *{ServiceType}* parameter. The *{ServiceType}* parameter +should specify a value from the ServiceType enumeration. If it does not, the request will be +rejected with an error. + +Callback and data model information for **GET /services/**_{ServiceType}_: +- Callback - **PUT /services/**_{ServiceType}_ +- Error Callback - **PUT /services/**_{ServiceType}_**/error** +- Data Model – Empty body +#### 3.1.5.3 Callbacks +This section describes the callbacks that are used by the server for services provided by the +resource **/services**. +##### 3.1.5.3.1 **PUT /services/**_{ServiceType}_ + +Used by: Switch + +The callback **PUT /services/**_{ServiceType}_ is used to inform the client of a successful result of +the service information lookup. The information is returned in the following form: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| providers | 0...256 | FspId | A list of the Ids of the participants who provide the service requested. | + +##### 3.1.5.3.2 **PUT /services/**_{ServiceType}_**/error** + +Used by: Switch + +If the server encounters an error in fulfilling a request for a list of participants who +provide a service, the error callback **PUT /services/**_{ServiceType}_**/error** is used to inform the +client that an error has occurred. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + +### 3.1.6 **thirdpartyRequests/authorizations** + +The **/thirdpartyRequests/authorizations** resource is analogous to the **/authorizations** resource + described in [Section 6.6](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#66-api-resource-authorizations) of Ref. 1 above. The DFSP uses it to request the PISP to: + +1. Display the information defining the terms of a proposed transfer to its customer; +2. Obtain the customer’s confirmation that they want the transfer to proceed; +3. Return a signed version of the terms which the DFSP can use to verify the consent + +The **/thirdpartyRequests/authorizations** resource supports the endpoints described below. +#### 3.1.6.1 Requests + +This section describes the services that a client can request on the +**/thirdpartyRequests/authorizations** resource. +##### 3.1.6.1.1 **GET /thirdpartyRequests/authorizations/**_{ID}_ + +Used by: DFSP + +The HTTP request **GET /thirdpartyRequests/authorizations/**_{ID}_ is used to get information relating +to a previously issued authorization request. The *{ID}* in the request should match the +`authorizationRequestId` which was given when the authorization request was created. + +Callback and data model information for **GET /thirdpartyRequests/authorizations/**_{ID}_: +- Callback - **PUT /thirdpartyRequests/authorizations/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/authorizations/**_{ID}_**/error** +- Data Model – Empty body +##### 3.1.6.1.2 **POST /thirdpartyRequests/authorizations** + +Used by: DFSP + +The HTTP request **POST /thirdpartyRequests/authorizations** is used to request the validation by a + customer for the transfer described in the request. + +Callback and data model information for **POST /thirdpartyRequests/authorizations:** + +- Callback - **PUT /thirdpartyRequests/authorizations/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/authorizations/**_{ID}_**/error** +- Data Model – See Table below + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| authorizationRequestId | 1 | CorrelationId | Common ID between the PISP and the Payer DFSP for the authorization request object. The ID should be reused for resends of the same authorization request. A new ID should be generated for each new authorization request. | +| transactionRequestId | 1 | CorrelationId | The unique identifier of the transaction request for which authorization is being requested. | +| challenge | 1 | BinaryString | The challenge that the PISP’s client is to sign. | +| transferAmount | 1 | Money | The amount that will be debited from the sending customer’s account as a consequence of the transaction. | +| payeeReceiveAmount | 1 | Money | The amount that will be credited to the receiving customer’s account as a consequence of the transaction. | +| fees | 1 | Money | The amount of fees that the paying customer will be charged as part of the transaction. | +| payer | 1 | PartyIdInfo | Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction. | +| payee | 1 | Party | Information about the Payee in the proposed transaction | +| transactionType | 1 | TransactionType | The type of the transaction. | +| expiration | 1 | DateTime | The time by which the transfer must be completed, set by the payee DFSP. | +| extensionList | 0..1 | ExtensionList |Optional extension, specific to deployment. | + +#### 3.1.6.2 Callbacks +The following callbacks are supported for the **/thirdpartyRequests/authorizations** resource +##### 3.1.6.2.1 **PUT /thirdpartyRequests/authorizations/**_{ID}_ + +Used by: PISP + +After receiving the **POST /thirdpartyRequests/authorizations**, the PISP will present the details of the +transaction to their user, and request that the client sign the `challenge` field using the credential +they previously registered. + +The signed challenge will be sent back by the PISP in **PUT /thirdpartyRequests/authorizations/**_{ID}_: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| responseType | 1 | AuthorizationResponseType | `ACCEPTED` or `REJECTED` | +| signedPayload | 0..1 | SignedPayload | If the `responseType` is `ACCEPTED`, `signedPayload` is required. | + +#### 3.1.6.3 Error callbacks +This section describes the error callbacks that are used by the server under the resource +**/thirdpartyRequests/authorizations**. +##### 3.1.6.3.1 **PUT /thirdpartyRequests/authorizations/**_{ID}_**/error** + +Used by: DFSP + +The **PUT /thirdpartyRequests/authorizations/**_{ID}_**/error** resource will have the same content +as the **PUT /authorizations/**_{ID}_**/error** resource described in [Section 6.6.5.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#6651-put-authorizationsiderror) +of Ref. 1 above. +### 3.1.7 **/thirdpartyRequests/transactions** +The **/thirdpartyRequests/transactions` resource is analogous to the `/transactionRequests** +resource described in [Section 6.4](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#64-api-resource-transactionrequests) of Ref. 1 above. The PISP uses it to request the +owner of the PISP’s customer’s account to transfer a specified amount from the customer’s +account with the DFSP to a named Payee. + +The **/thirdpartyRequests/transactions** resource supports the endpoints described below. +#### 3.1.7.1 Requests + +This section describes the services that a client can request on the +**/thirdpartyRequests/transactions** resource. +##### 3.1.7.1.1 **GET /thirdpartyRequests/transactions/**_{ID}_ + +Used by: PISP + +The HTTP request **GET /thirdpartyRequests/transactions/**_{ID}_ is used to get information +relating to a previously issued transaction request. The *{ID}* in the request should +match the `transactionRequestId` which was given when the transaction request was created. + +Callback and data model information for **GET /thirdpartyRequests/transactions/**_{ID}_: +- Callback - **PUT /thirdpartyRequests/transactions/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** +- Data Model – Empty body +##### 3.1.7.1.2 **POST /thirdpartyRequests/transactions** + +Used by: PISP + +The HTTP request **POST /thirdpartyRequests/transactions** is used to request the creation +of a transaction request on the server for the transfer described in the request. + +Callback and data model information for **POST /thirdpartyRequests/transactions**: +- Callback - **PUT /thirdpartyRequests/transactions/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** +- Data Model – See Table below + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| transactionRequestId | 1 | CorrelationId |Common ID between the PISP and the Payer DFSP for the transaction request object. The ID should be reused for resends of the same transaction request. A new ID should be generated for each new transaction request. | +| payee | 1 | Party |Information about the Payee in the proposed financial transaction. | +| payer | 1 | PartyIdInfo |Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction. | +| amountType | 1 | AmountType | SEND for send amount, RECEIVE for receive amount. | +| amount | 1 | Money | Requested amount to be transferred from the Payer to Payee. | +| transactionType | 1 | TransactionType |Type of transaction | +| note | 0..1 | Note | Memo assigned to Transaction. | +| expiration | 0..1 | DateTime |Can be set to get a quick failure in case the peer FSP takes too long to respond. Also, it may be beneficial for Consumer, Agent, Merchant to know that their request has a time limit. | +| extensionList | 0..1 | ExtensionList |Optional extension, specific to deployment. | +#### 3.1.7.2 Callbacks +The following callbacks are supported for the **/thirdpartyRequests/transactions** resource +##### 3.1.7.2.1 **PUT /thirdpartyRequests/transactions/**_{ID}_ + +Used by: DFSP + +After a PISP requests the creation of a Third Party Transaction request (**POST /thirdpartyRequests/transactions**) +or the status of a previously created Third Party Transaction request +(**GET /thirdpartyRequests/transactions/**_{ID}_), the DFSP will send this callback. + +The data model for this endpoint is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| transactionRequestState | 1 | TransactionRequestState | State of the transaction request. | +| extensionList | 0..1 | ExtensionList | Optional extension, specific to deployment | + +##### 3.1.7.2.2 **PATCH /thirdpartyRequests/transactions/**_{ID}_ + +Used by: DFSP + +The issuing PISP will expect a response to their request for a transfer which describes +the finalised state of the requested transfer. This response will be given by a `PATCH` call on the +**/thirdpartyRequests/transactions/**_{ID}_ resource. The *{ID}* given in the query string should be +the `transactionRequestId` which was originally used by the PISP to identify the transaction +request (see [Section 3.1.8.1.2](#31812-post-thirdpartyrequestsverifications) above.) + +The data model for this endpoint is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| completedTimestamp | 0..1 | DateTime |Time and date when the transaction was completed, if it was completed. | +| transactionRequestState | 1 | TransactionRequestState | State of the transaction request | +| transactionState | 1 | TransactionState | State of the transaction created by the DFSP in response to this transaction request | +| extensionList | 0..1 | ExtensionList |Optional extension, specific to deployment | + +#### 3.1.7.3 Error callbacks +This section describes the error callbacks that are used by the server under the resource +**/thirdpartyRequests/transactions**. +##### 3.1.7.3.1 **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** + +Used by: DFSP + +The **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** resource will have the same content as +the **PUT /transactionRequests/**_{ID}_**/error** resource described in [Section 6.4.5.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#6451-put-transactionrequestsiderror) of Ref. 1 above. + +### 3.1.8 **/thirdpartyRequests/verifications** + +The **/thirdpartyRequests/verifications** resource is used by a Payer DFSP to verify that an authorization +response received from a PISP was signed using the correct private key, in cases where the authentication service +to be used is implemented by the switch and not internally by the DFSP. The DFSP sends the original +challenge and the signed response to the authentication service, together with the `consentId` to be used +for the verification. The authentication service compares the response with the result of signing the +challenge with the private key associated with the `consentId`, and, if the two match, it returns a +positive result. Otherwise, it returns an error. + +The **/thirdpartyRequests/verifications** resource supports the endpoints described below. +#### 3.1.8.1 Requests +This section describes the services that a client can request on the **/thirdpartyRequests/verifications** +resource. +##### 3.1.8.1.1 **GET /thirdpartyRequests/verifications/**_{ID}_ + +Used by: DFSP + +The HTTP request **/thirdpartyRequests/verifications/**_{ID}_ is used to get information regarding a previously +created or requested authorization. The *{ID}* in the URI should contain the verification request ID +(see [Section 3.1.8.1.2](#31812-post-thirdpartyrequestsverifications) below) that was used for the creation of the transfer.Callback and data model +information for **GET /thirdpartyRequests/verifications/**_{ID}_: + +- Callback – **PUT /thirdpartyRequests/verifications/**_{ID}_ +- Error Callback – **PUT /thirdpartyRequests/verifications/**_{ID}_**/error** +- Data Model – Empty body +##### 3.1.8.1.2 **POST /thirdpartyRequests/verifications** + +Used by: DFSP + +The **POST /thirdpartyRequests/verifications** resource is used to request confirmation from an authentication +service that a challenge has been signed using the correct private key. + +Callback and data model information for **POST /thirdpartyRequests/verifications**: +- Callback - **PUT /thirdpartyRequests/verifications/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/verifications /**_{ID}_**/error** +- Data Model – See Table below + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| verificationRequestId | 1 | CorrelationId |Common ID between the DFSP and authentication service for the verification request object. The ID should be reused for resends of the same authorization request. A new ID should be generated for each new authorization request. | +| challenge | 1 | BinaryString |The challenge originally sent to the PISP | +| consentId | 1 | CorrelationId |Common Id between the DFSP and the authentication service for the agreement against which the authentication service is to evaluate the signature | +| signedPayloadType | 1 | SignedPayloadType | The type of the SignedPayload, depending on the type of credential registered by the PISP | +| genericSignedPayload | 0..1 | BinaryString | Required if signedPayloadType is GENERIC. The signed challenge returned by the PISP. A BinaryString representing a signature of the challenge + private key of the credential. | +| fidoSignedPayload | 0..1 | FIDOPublicKeyCredentialAssertion | Required if signedPayloadType is FIDO. The signed challenge returned by the PISP in the form of a [`FIDOPublicKeyCredentialAssertion` Object](https://w3c.github.io/webauthn/#iface-pkcredential) | + +#### 3.1.8.2 Callbacks +This section describes the callbacks that are used by the server under the resource +**/thirdpartyRequests/verifications** +##### 3.1.8.2.1 **PUT /thirdpartyRequests/verifications/**_{ID}_ + +Used by: Auth Service + +The callback **PUT /thirdpartyRequests/verifications/**_{ID}_ is used to inform the client of the result +of an authorization check. The *{ID}* in the URI should contain the `authorizationRequestId` +(see [Section 3.1.8.1.2](#31812-post-thirdpartyrequestsverifications) above) which was used to request the check, or the *{ID}* that was +used in the **GET /thirdpartyRequests/verifications/**_{ID}_. The data model for this resource is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| authenticationResponse | 1 | AuthenticationResponse | The result of the authorization check. | +#### 3.1.8.3 Error callbacks +This section describes the error callbacks that are used by the server under the resource +**/thirdpartyRequests/verifications**. +##### 3.1.8.3.1 **PUT /thirdpartyRequests/verifications/**_{ID}_**/error** + +Used by: Auth Service + +If the server is unable to complete the authorization request, or another processing error occurs, the +error callback **PUT /thirdpartyRequests/verifications/**_{ID}_**/error** is used.The *{ID}* in the URI should +contain the `verificationRequestId` (see [Section 3.1.8.1.2](#31812-post-thirdpartyrequestsverifications) above) which was used to request the +check, or the *{ID}* that was used in the **GET /thirdpartyRequests/verifications/**_{ID}_. + +The data model for this resource is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + +## 3.2 Data Models + +The following additional data models will be required to support the Third Party API + +### 3.2.1 Element definitions +#### 3.2.1.1 Account + +The Account data model contains information relating to an account. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| address | 1 | AccountAddress | An address which can be used to identify the account | +| currency | 1 | Currency | The currency in which the account is denominated | +| accountNickname | 0..1 | Name | Display name of the account, as set by the account owning DFSP. This will normally be a type name, such as “Transaction Account” or “Savings Account” | +#### 3.2.1.2 AccountAddress + +The AccountAddress data type is a variable length string with a maximum size of 1023 characters and consists of: +- Alphanumeric characters, upper or lower case. (Addresses are case-sensitive so that they can contain data encoded in formats such as base64url.) +- Underscore (\_) +- Tilde (~) +- Hyphen (-) +- Period (.) Addresses MUST NOT end in a period (.) character + +An entity providing accounts to parties (i.e. a participant) can provide any value for an `AccountAddress` that is meaningful to that entity. +It does not need to provide an address that makes the account identifiable outside the entity’s domain. + +> ***IMPORTANT:* The policy for defining addresses and the life-cycle of these is at the discretion of the address space owner (the payer DFSP in this case).** +#### 3.2.1.3 AccountList +The AccountList data model is used to hold information about the accounts that a party controls. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| account | 1..256 | Account | Information relating to an account that a party controls. | + + +#### 3.2.1.5 AuthenticationResponse + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| AuthenticationResponse | 1 | Enum of String(1..32) | See [Section 3.2.2.1](#3221-AuthenticationResponse) below (AuthenticationResponse) for more information on allowed values.| +#### 3.2.1.6 BinaryString +The BinaryString type used in these definitions is as defined in [Section 7.2.17](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7217-binarystring) of Ref. 1 above. +#### 3.2.1.7 ConsentRequestChannelType +The ConsentRequestChannelType is used to hold an instance of the ConsentRequestChannelType enumeration. Its data model is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| ConsentRequestChannelType | 1 | Enum of String(1..32) | See [Section 3.2.2.4](#3223-consentrequestchanneltype) below ( ConsentRequestChannelType) for more information on allowed values. | + +#### 3.2.1.8 ConsentStatus +The ConsentStatus type stores the status of a consent request, as described in [Section 3.1.3.2.2](#31322-put-consentsid) above. Its data model is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| ConsentStatus | 1 | Enum of String(1..32) | See [Section 3.2.2.5](#3224-consentstatustype) below (ConsentStatusType) for more information on allowed values.| + +#### 3.2.1.9 CorrelationId +The CorrelationId type used in these definitions is as defined in [Section 7.3.8](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#738-correlationid) of Ref. 1 above. +##### 3.2.1.10 Credential +The Credential object is used to store information about a publicKey and signature that has been registered with a Consent. +This publicKey can be used to verify that transaction authorizations have been signed by the previously-registered privateKey, +which resides on a User's device. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| credentialType | 1 | CredentialType | The type of credential this is - `FIDO` or `GENERIC` | +| status | 1 | CredentialStatus | The current status of the credential. | +| genericPayload | 0..1 | GenericCredential | Required if credentialType is GENERIC. A description of the credential and information which allows the recipient of the credential to test its veracity. | +| fidoPayload | 0..1 | FIDOPublicKeyCredentialAttestation | Required if credentialType is FIDO. A description of the credential and information which allows the recipient of the credential to test its veracity. | + +##### 3.2.1.11 CredentialStatus +The CredentialStatus data type stores the state of a credential request. Its data model is as follows. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| CredentialStatus | 1 | Enum of String(1..32) |See [Section 3.2.2.6](#3225-CredentialStatus) below (CredentialStatus) for more information on allowed values. | + +##### 3.2.1.12 DateTime +The DateTime data type used in these definitions is as defined in [Section 7.2.14](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7214-datetime) of Ref. 1 above. +##### 3.2.1.13 ErrorInformation +The ErrorInformation data type used in these definitions is as defined in [Section 7.4.2](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#742-errorinformation) of Ref. 1 above + +Valid values for ErrorCode and ErrorDescription are defined in [Error Codes](#ErrorCodes) + +##### 3.2.1.14 ExtensionList +The ExtensionList data type used in these definitions is as defined in [Section 7.4.4](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#744-extensionlist) of Ref. 1 above. +##### 3.2.1.15 FspId +The FspId data type used in these definitions is as defined in [Section 7.3.16](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7316-fspid) of Ref. 1 above. + +##### 3.2.1.16 GenericCredential +The GenericCredential object stores the payload for a credential which is validated according to a comparison of the signature created from the challenge using a private key against the same challenge signed using a public key. Its content is as follows. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| publicKey | 1 | BinaryString | The public key to be used in checking the signature. | +| signature | 1 | BinaryString | The signature to be checked against the public key. | + +##### 3.2.1.17 Money +The Money type used in these definitions is a defined in [Section 7.4.10](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7410-money) of Ref. 1 above. +##### 3.2.1.18 Note +The Note data type used in these definitions is as defined in [Section 7.3.23](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7323-note) of Ref. 1 above. +##### 3.2.1.19 Party + +The Note data type used in these definitions is as defined in [Section 7.4.11](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7411-party) of Ref. 1 above. + +##### 3.2.1.20 PartyIdInfo +The PartyIdInfo data type used in these definitions is as defined in [Section 7.4.13](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7413-partyidinfo) of Ref. 1 above. + + +##### 3.2.1.21 Scope +The Scope element contains an identifier defining, in the terms of a DFSP, an account on which access types can be requested or granted. It also defines the access types which are requested or granted. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| address | 1 |AccountAddress | The address of the account to which the PISP wishes to be permitted access, or is being granted access | +| actions | 1..32 |ScopeAction | The action that the PISP wants permission to take in relation to the customer’s account, or that it has been granted in relation to the customer’s account| +##### 3.2.1.22 ScopeAction +The ScopeAction element contains an access type which a PISP can request from a DFSP, or which a DFSP can grant to a PISP. It must be a member of the appropriate enumeration. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| scopeAction | 1 | Enum of String(1..32)| See [Section 3.2.2.9](#3228-scopeenumeration) below (ScopeEnumeration) for more information on allowed values. | +##### 3.2.1.23 ServiceType +The ServiceType element contains a type of service where the requester wants a list of the participants in the scheme which provide that service. It must be a member of the appropriate enumeration. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| serviceType | 1 | Enum of String(1..32) | See [Section 3.2.2.10](#3229-servicetype) below (ServiceType) for more information on allowed values. | + +##### 3.2.1.24 TransactionType +The TransactionType type used in these definitions is as defined in [Section 7.4.18](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7418-transactiontype) of Ref. 1 above. +##### 3.2.1.25 TransactionState +The TransactionState type used in these definitions is as defined in [Section 7.3.33](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7333-transactionstate) of Ref. 1 above. +##### 3.2.1.26 Uri +The API data type Uri is a JSON string in a canonical format that is restricted by a regular expression for interoperability reasons. The regular expression for restricting the Uri type is as follows: +`^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? ` +##### 3.2.1.27 FIDOPublicKeyCredentialAttestation + +A data model representing a FIDO Attestation result. Derived from [`PublicKeyCredential` Interface](https://w3c.github.io/webauthn/#iface-pkcredential). + +The `PublicKeyCredential` interface represents the below fields with a Type of Javascript [ArrayBuffer](https://heycam.github.io/webidl/#idl-ArrayBuffer). +For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| id | 1 | String(59..118) | The identifier of a keypair created by an authenticator | +| rawId | 0..1 | String(59..118) | The identifier of a keypair created by an authenticator, base64 encoded | +| response | 1 | AuthenticatorAttestationResponse | The attestation response from the authenticator | + +##### 3.2.1.28 FIDOPublicKeyCredentialAssertion + +A data model representing a FIDO Assertion result. Derived from [`PublicKeyCredential` Interface](https://w3c.github.io/webauthn/#iface-pkcredential) in [WebAuthN](https://w3c.github.io/webauthn/). + +The `PublicKeyCredential` interface represents the below fields with a Type of Javascript [ArrayBuffer](https://heycam.github.io/webidl/#idl-ArrayBuffer). +For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| id | 1 | String(59..118) | The identifier of a keypair created by an authenticator | +| rawId | 0..1 | String(59..118) | The identifier of a keypair created by an authenticator, base64 encoded | +| response | 1 | AuthenticatorAssertionResponse | The assertion response from the authenticator | + +##### 3.2.1.29 AuthenticatorAttestationResponse + +A data model representing an [AttestationStatement](https://w3c.github.io/webauthn/#attestation-statement) from [WebAuthN](https://w3c.github.io/webauthn/). + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| clientDataJSON | 1 | String(121...512) | JSON string with client data | +| attestationObject | 1 | String(306...2048) | Object encoded in Concise Binary Object Representation(CBOR), as defined in [RFC-8949](https://www.rfc-editor.org/rfc/rfc8949)| + +##### 3.2.1.30 AuthenticatorAssertionResponse + +A data model representing an [AuthenticatorAssertionResponse](https://w3c.github.io/webauthn/#authenticatorassertionresponse). + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| authenticatorData | 1 | String(29..256) | Information about the authenticator. | +| clientDataJSON | 1 | String(121..512) | base64 encoded JSON string containing information about the client. | +| signature | 1 | String(59..256) | The signature generated by the private key associated with this credential. | +| userHandle | 0..1 | String(1..88) | This field is optionally provided by the authenticator, and represents the user.id that was supplied during registration, as defined in [WebAuthN's user.id](https://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-id).| + +##### 3.2.1.31 SignedPayload + +A data model representing a Third Party Transaction request signature. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| signedPayloadType | 1 | SignedPayloadType | `FIDO` or `GENERIC` | +| genericSignedPayload | 0..1 | BinaryString(256) | Required if signedPayloadType is of type `GENERIC`. A BinaryString(256) of a signature of a sha-256 hash of the challenge. | +| fidoSignedPayload | 0..1 | FIDOPublicKeyCredentialAssertion | Required if signedPayloadType is of type `FIDO`. | + +### 3.2.2 Enumerations +#### 3.2.2.1 AuthenticationResponse +The AuthenticationResponse enumeration describes the result of authenticating verification request. +| Name | Description | +| --- | ----------- | +| VERIFIED | The challenge was correctly signed. | +#### 3.2.2.2 AuthorizationResponseType +The AuthorizationResponseType enumeration is the same as the AuthorizationResponse enumeration described in [Section 7.5.3](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#753-authorizationresponse) of Ref. 1 above. +#### 3.2.2.3 ConsentRequestChannelType + +| Name | Description | +| --- | ----------- | +| WEB | DFSP can support authorization via a web-based login | +| OTP | DFSP can support authorization via a One Time PIN | + +#### 3.2.2.4 ConsentStatusType +The ConsentStatusType enumeration describes the allowed status values that a consent item can have. These are as follows: +| Name | Description | +| --- | ----------- | +| ISSUED | The consent has been issued by the DFSP. | +| REVOKED | The consent has been revoked. | + +#### 3.2.2.5 CredentialStatus +This contains the allowed values for the CredentialStatus +| Name | Description | +| --- | ----------- | +| PENDING | The credential has been created but not yet verified. | +| VERIFIED | Authentication service has verified the credential. | + +#### 3.2.2.6 CredentialType +The CredentialType enumeration contains the allowed values for the type of credential which is associated with a permission. +| Name | Description | +| --- | ----------- | +| FIDO | The credential is based on a FIDO challenge. Its payload is a FIDOPublicKeyCredentialAttestation object. | +| GENERIC | The credential is based on a simple public key validation. Its payload is a GenericCredential object | + +#### 3.2.2.7 PartyIdType +The PartyIdType enumeration is extended for PISPs to include a definition for the identifier which represents a link between a specific PISP and an account at a DFSP which a customer has given the PISP permission to access. + +| Name | Description | +| --- | ----------- | +| MSISDN | An MSISDN (Mobile Station International Subscriber Directory Number; that is, a phone number) is used in reference to a Party. The MSISDN identifier should be in international format according to the ITU-T E.16437 standard. Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix.| +| EMAIL | An email is used in reference to a Party. The format of the email should be according to the informational RFC 369638.| +| PERSONAL_ID | A personal identifier is used in reference to a participant. Examples of personal identification are passport number, birth certificate number, and national registration number. The identifier number is added in the PartyIdentifier element. The personal identifier type is added in the PartySubIdOrType element.| +| BUSINESS | A specific Business (for example, an organization or a company) is used in reference to a participant. The BUSINESS identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the PartySubIdOrType element should be used.| +| DEVICE | A specific device (for example, POS or ATM) ID connected to a specific business or organization is used in reference to a Party. For referencing a specific device under a specific business or organization, use the PartySubIdOrType element.| +| ACCOUNT_ID | A bank account number or FSP account ID should be used in reference to a participant. The ACCOUNT_ID identifier can be in any format, as formats can greatly differ depending on country and FSP.| +| IBAN | A bank account number or FSP account ID is used in reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without whitespace.| +| ALIAS | An alias is used in reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias is a username in the FSP system. The ALIAS identifier can be in any format. It is also possible to use the PartySubIdOrType element for identifying an account under an Alias defined by the PartyIdentifier.| +| THIRD_PARTY_LINK | A third-party link which represents an agreement between a specific PISP and a customer’s account at a DFSP. The content of the link is created by the DFSP at the time when it gives permission to the PISP for specific access to a given account.| + +#### 3.2.2.8 ScopeEnumeration + +| Name | Description | +| --- | ----------- | +| ACCOUNTS_GET_BALANCE | PISP can request a balance for the linked account | +| ACCOUNTS_TRANSFER | PISP can request a transfer of funds from the linked account in the DFSP | +| ACCOUNTS_STATEMENT | PISP can request a statement of individual transactions on a user’s account | + +#### 3.2.2.9 ServiceType +The ServiceType enumeration describes the types of role for which a DFSP may query using the /services resource. +| Name | Description | +| --- | ----------- | +| THIRD_PARTY_DFSP| DFSPs which will support linking with PISPs | +| PISP | PISPs | +| AUTH_SERVICE | Participants which provide Authentication Services | + +##### 3.2.2.10 SignedPayloadType +The SignedPayloadType enumeration contains the allowed values for the type of a signed payload +| Name | Description | +| --- | ----------- | +| FIDO | The signed payload is based on a FIDO Assertion Response. Its payload is a FIDOPublicKeyCredentialAssertion object. | +| GENERIC | The signed payload is based on a simple public key validation. Its payload is a BinaryString object | + +##### 3.2.2.11 AmountType +See [7.3.1 AmountType](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#731-amounttype) + +##### 3.2.2.12 TransactionRequestState +See [7.5.10 TransactionRequestState](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7510-transactionrequeststate) + + +## 3.3 Error Codes + +The Third Party API Error Codes are defined in [Section 7.6](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#76-error-codes) of ref 1 above. + +In addition, the Third Party API adds the following error codes, starting with the prefix `6`: + +- General Third Party Error -- **60**_xx_ + +| **Error Code** | **Name** | **Description** | /accounts | /consentRequests | /consents | /parties | /services | /thirdpartyRequests/authorizations | thirdpartyRequests/transactions | thirdpartyRequests/verifications | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **6000** | Third party error | Generic error. | X | X | X | X | X | X | X | X | +| **6001** | Third party request error | Third party request failed. | X | X | X | X | X | X | X | X | +| **6003** | Downstream Failure | The downstream request failed. | X | X | X | X | X | X | X | X | + +- Permission Error -- **61**_xx_ + +| **Error Code** | **Name** | **Description** | /accounts | /consentRequests | /consents | /parties | /services | /thirdpartyRequests/authorizations | thirdpartyRequests/transactions | thirdpartyRequests/verifications | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **6100** | Authentication rejection | Generic authentication rejection | | X | | | | X | | | +| **6101** | Unsupported scopes were requested | PISP requested scopes that the DFSP doesn’t allow/support | | X | X | | | | | | +| **6102** | Consent not granted | User did not grant consent to the PISP | | X | X | | | | | | +| **6103** | Consent not valid | Consent object is not valid or has been revoked | | X | X | | | X | X | X | +| **6104** | Third Party request rejection | The request was rejected | X | X | X | X | X | X | X | X | + +- Validation Error -- **62**_xx_ + +| **Error Code** | **Name** | **Description** | /accounts | /consentRequests | /consents | /parties | /services | /thirdpartyRequests/authorizations | thirdpartyRequests/transactions | thirdpartyRequests/verifications | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **6200** | Invalid Consent Credential | The signature of the credential submitted by the PISP is invalid | | | X | | | | | | +| **6201** | Invalid transaction signature | The signature of the verification response doesn't match the credential | | | | | | X | | X | +| **6203** | Invalid authentication token | DFSP receives invalid authentication token from PISP. | | X | | | | | | | +| **6204** | Bad callbackUri | The callbackUri is deemed invalid or untrustworthy. | | X | | | | | | | +| **6205** | No accounts found | No accounts were found for the given identifier | X | | | | | | | | + diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/thirdparty-dfsp-v1.0.yaml b/website/versioned_docs/v1.0.1/api/thirdparty/thirdparty-dfsp-v1.0.yaml new file mode 100644 index 000000000..8bc925308 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/thirdparty-dfsp-v1.0.yaml @@ -0,0 +1,2721 @@ +openapi: 3.0.2 +info: + title: Mojaloop Third Party API (DFSP) + version: '1.0' + description: | + A Mojaloop API for DFSPs supporting Third Party functions. + DFSPs who want to enable Payment Initiation Service Providers (PISPs) to perform actions on behalf of a DFSP's user should implement this API. + PISPs should implement the accompanying API - Mojaloop Third Party API (PISP) instead. + license: + name: Open API for FSP Interoperability (FSPIOP) (Implementation Friendly Version) + url: 'https://github.com/mojaloop/mojaloop-specification/blob/master/LICENSE.md' +servers: + - url: / +paths: + '/accounts/{ID}': + parameters: + - name: ID + in: path + required: true + schema: + type: string + description: The identifier value. + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + operationId: GetAccountsByUserId + summary: GetAccountsByUserId + description: | + The HTTP request `GET /accounts/{ID}` is used to retrieve the list of potential accounts available for linking. + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + description: | + The HTTP request `PUT /accounts/{ID}` is used to return the list of potential accounts available for linking + operationId: UpdateAccountsByUserId + summary: UpdateAccountsByUserId + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + title: AccountsIDPutResponse + type: object + description: |- + Callback and data model information for GET /accounts/{ID}: + Callback - PUT /accounts/{ID} Error Callback - PUT /accounts/{ID}/error Data Model - Empty body + The PUT /accounts/{ID} response is used to inform the requester of the result of a request for accounts information. The identifier ID given in the call are the values given in the original request. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31121--put-accountsid + properties: + accountList: + title: AccountList + type: array + description: |- + The AccountList data model is used to hold information about the accounts that a party controls. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#3213-accountlist + items: + title: Account + type: object + description: |- + Data model for the complex type Account. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#3211-account + properties: + accountNickname: + title: Name + type: string + pattern: '^(?!\s*$)[\w .,''-]{1,128}$' + description: |- + The API data type Name is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. + + Regular Expression - The regular expression for restricting the Name type is "^(?!\s*$)[\w .,'-]{1,128}$". The restriction does not allow a string consisting of whitespace only, all Unicode characters are allowed, as well as the period (.) (apostrophe (‘), dash (-), comma (,) and space characters ( ). + + **Note:** In some programming languages, Unicode support must be specifically enabled. For example, if Java is used, the flag UNICODE_CHARACTER_CLASS must be enabled to allow Unicode characters. + address: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items/properties/address' + currency: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0/properties/currency' + required: + - accountNickname + - address + - currency + minItems: 1 + maxItems: 256 + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - accounts + example: + - accountNickname: dfspa.user.nickname1 + id: dfspa.username.1234 + currency: ZAR + - accountNickname: dfspa.user.nickname2 + id: dfspa.username.5678 + currency: USD + responses: + '200': + description: OK + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/accounts/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + description: | + The HTTP request `PUT /accounts/{ID}/error` is used to return error information + operationId: UpdateAccountsByUserIdError + summary: UpdateAccountsByUserIdError + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + title: ErrorInformationObject + type: object + description: Data model for the complex type object that contains ErrorInformation. + properties: + errorInformation: + title: ErrorInformation + type: object + description: Data model for the complex type ErrorInformation. + properties: + errorCode: + title: ErrorCode + type: string + pattern: '^[1-9]\d{3}$' + description: 'The API data type ErrorCode is a JSON String of four characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. Each error code in the API is a four-digit number, for example, 1234, where the first number (1 in the example) represents the high-level error category, the second number (2 in the example) represents the low-level error category, and the last two numbers (34 in the example) represent the specific error.' + example: '5100' + errorDescription: + title: ErrorDescription + type: string + minLength: 1 + maxLength: 128 + description: Error description string. + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - errorCode + - errorDescription + required: + - errorInformation + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /consentRequests: + parameters: + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + post: + tags: + - consentRequests + - sampled + operationId: CreateConsentRequest + summary: CreateConsentRequest + description: | + The HTTP request **POST /consentRequests** is used to request a DFSP to grant access to one or more + accounts owned by a customer of the DFSP for the PISP who sends the request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: The consentRequest to create + required: true + content: + application/json: + schema: + title: ConsentRequestsPostRequest + type: object + description: |- + Used by: PISP + The HTTP request POST /consentRequests is used to request a DFSP to grant access to one or more accounts owned by a customer of the DFSP for the PISP who sends the request. + Callback and data model for POST /consentRequests: + Callback: PUT /consentRequests/{ID} Error callback: PUT /consentRequests/{ID}/error Data model - see below url + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31212-post-consentrequests + properties: + consentRequestId: + title: CorrelationId + type: string + pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' + description: 'Identifier that correlates all messages of the same sequence. The API data type UUID (Universally Unique Identifier) is a JSON String in canonical format, conforming to [RFC 4122](https://tools.ietf.org/html/rfc4122), that is restricted by a regular expression for interoperability reasons. A UUID is always 36 characters long, 32 hexadecimal symbols and 4 dashes (‘-‘).' + example: b51ec534-ee48-4575-b6a9-ead2955b8069 + userId: + type: string + description: 'The identifier used in the **GET /accounts/**_{ID}_. Used by the DFSP to correlate an account lookup to a `consentRequest`' + minLength: 1 + maxLength: 128 + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + title: Scope + type: object + description: |- + The Scope element contains an identifier defining, in the terms of a DFSP, an account on which access types can be requested or granted. It also defines the access types which are requested or granted. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#32121-scope + properties: + address: + title: AccountAddress + type: string + description: |- + The AccountAddress data type is a variable length string with a maximum size of 1023 characters and consists of: + Alphanumeric characters, upper or lower case. (Addresses are case-sensitive so that they can contain data encoded in formats such as base64url.) + - Underscore (_) - Tilde (~) - Hyphen (-) - Period (.) Addresses MUST NOT end in a period (.) character + An entity providing accounts to parties (i.e. a participant) can provide any value for an AccountAddress that is meaningful to that entity. It does not need to provide an address that makes the account identifiable outside the entity's domain. + IMPORTANT: The policy for defining addresses and the life-cycle of these is at the discretion of the address space owner (the payer DFSP in this case). + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#3212-accountaddress + pattern: '^([0-9A-Za-z_~\-\.]+[0-9A-Za-z_~\-])$' + minLength: 1 + maxLength: 1023 + actions: + type: array + minItems: 1 + maxItems: 32 + items: + title: ScopeAction + type: string + description: | + The ScopeAction element contains an access type which a PISP can request + from a DFSP, or which a DFSP can grant to a PISP. + It must be a member of the appropriate enumeration. + + - ACCOUNTS_GET_BALANCE: PISP can request a balance for the linked account + - ACCOUNTS_TRANSFER: PISP can request a transfer of funds from the linked account in the DFSP + - ACCOUNTS_STATEMENT: PISP can request a statement of individual transactions on a user's account + enum: + - ACCOUNTS_GET_BALANCE + - ACCOUNTS_TRANSFER + - ACCOUNTS_STATEMENT + required: + - address + - actions + authChannels: + type: array + minLength: 1 + maxLength: 256 + items: + title: ConsentRequestChannelType + type: string + enum: + - WEB + - OTP + description: | + The auth channel being used for the consent request. + - WEB - DFSP can support authorization via a web-based login. + - OTP - DFSP can support authorization via a One Time PIN. + callbackUri: + title: Uri + type: string + pattern: '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' + minLength: 1 + maxLength: 512 + description: | + The API data type Uri is a JSON string in a canonical format that is restricted by a regular expression for interoperability reasons. + extensionList: + title: ExtensionList + type: object + description: 'Data model for the complex type ExtensionList. An optional list of extensions, specific to deployment.' + properties: + extension: + type: array + items: + title: Extension + type: object + description: Data model for the complex type Extension. + properties: + key: + title: ExtensionKey + type: string + minLength: 1 + maxLength: 32 + description: Extension key. + value: + title: ExtensionValue + type: string + minLength: 1 + maxLength: 128 + description: Extension value. + required: + - key + - value + minItems: 1 + maxItems: 16 + description: Number of Extension elements. + required: + - extension + required: + - consentRequestId + - userId + - scopes + - authChannels + - callbackUri + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/consentRequests/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + operationId: GetConsentRequestsById + summary: GetConsentRequestsById + description: | + The HTTP request `GET /consentRequests/{ID}` is used to get information about a previously + requested consent. The *{ID}* in the URI should contain the consentRequestId that was assigned to the + request by the PISP when the PISP originated the request. + tags: + - consentRequests + - sampled + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + tags: + - consentRequests + - sampled + operationId: UpdateConsentRequest + summary: UpdateConsentRequest + description: | + A DFSP uses this callback to (1) inform the PISP that the consentRequest has been accepted, + and (2) communicate to the PISP which `authChannel` it should use to authenticate their user + with. + + When a PISP requests a series of permissions from a DFSP on behalf of a DFSP’s customer, not all + the permissions requested may be granted by the DFSP. Conversely, the out-of-band authorization + process may result in additional privileges being granted by the account holder to the PISP. The + **PUT /consentRequests/**_{ID}_ resource returns the current state of the permissions relating to a + particular authorization request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentRequestsIDPutResponseWeb + type: object + description: | + The object sent in a `PUT /consentRequests/{ID}` request. + + Schema used in the request consent phase of the account linking web flow, + the result is the PISP being instructed on a specific URL where this + supposed user should be redirected. This URL should be a place where + the user can prove their identity (e.g., by logging in). + properties: + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + authChannels: + type: array + minLength: 1 + maxLength: 1 + items: + title: ConsentRequestChannelTypeWeb + type: string + enum: + - WEB + description: | + The web auth channel being used for `PUT /consentRequest/{ID}` request. + callbackUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + authUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - scopes + - authChannels + - callbackUri + - authUri + additionalProperties: false + - title: ConsentRequestsIDPutResponseOTP + type: object + description: | + The object sent in a `PUT /consentRequests/{ID}` request. + + Schema used in the request consent phase of the account linking OTP/SMS flow. + properties: + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + authChannels: + type: array + minLength: 1 + maxLength: 1 + items: + title: ConsentRequestChannelTypeOTP + type: string + enum: + - OTP + description: | + The OTP auth channel being used for `PUT /consentRequests/{ID}` request. + callbackUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - scopes + - authChannels + additionalProperties: false + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + patch: + tags: + - consentRequests + - sampled + operationId: PatchConsentRequest + summary: PatchConsentRequest + description: | + After the user completes an out-of-band authorization with the DFSP, the PISP will receive a token which they can use to prove to the DFSP that the user trusts this PISP. + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + title: ConsentRequestsIDPatchRequest + type: object + description: |- + Used by: PISP + After the user completes an out-of-band authorization with the DFSP, the PISP will receive a token which they can use to prove to the DFSP that the user trusts this PISP. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31222-patch-consentrequestsid + properties: + authToken: + type: string + pattern: '^[A-Za-z0-9-_]+[=]{0,2}$' + description: 'The API data type BinaryString is a JSON String. The string is a base64url encoding of a string of raw bytes, where padding (character ‘=’) is added at the end of the data if needed to ensure that the string is a multiple of 4 characters. The length restriction indicates the allowed number of characters.' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - authToken + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/consentRequests/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - consentRequests + operationId: NotifyErrorConsentRequests + summary: NotifyErrorConsentRequests + description: | + DFSP responds to the PISP if something went wrong with validating an OTP or secret. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /consents: + parameters: + - name: Content-Type + in: header + schema: + type: string + required: true + description: The `Content-Type` header indicates the specific version of the API used to send the payload body. + - name: Date + in: header + schema: + type: string + required: true + description: The `Date` header field indicates the date when the request was sent. + - name: X-Forwarded-For + in: header + schema: + type: string + required: false + description: |- + The `X-Forwarded-For` header field is an unofficially accepted standard used for informational purposes of the originating client IP address, as a request might pass multiple proxies, firewalls, and so on. Multiple `X-Forwarded-For` values should be expected and supported by implementers of the API. + + **Note:** An alternative to `X-Forwarded-For` is defined in [RFC 7239](https://tools.ietf.org/html/rfc7239). However, to this point RFC 7239 is less-used and supported than `X-Forwarded-For`. + - name: FSPIOP-Source + in: header + schema: + type: string + required: true + description: The `FSPIOP-Source` header field is a non-HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing and signature verification (see header field `FSPIOP-Signature`). + - name: FSPIOP-Destination + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-Destination` header field is a non-HTTP standard field used by the API for HTTP header based routing of requests and responses to the destination. The field must be set by the original sender of the request if the destination is known (valid for all services except GET /parties) so that any entities between the client and the server do not need to parse the payload for routing purposes. If the destination is not known (valid for service GET /parties), the field should be left empty.' + - name: FSPIOP-Encryption + in: header + schema: + type: string + required: false + description: The `FSPIOP-Encryption` header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request. + - name: FSPIOP-Signature + in: header + schema: + type: string + required: false + description: The `FSPIOP-Signature` header field is a non-HTTP standard field used by the API for applying an end-to-end request signature. + - name: FSPIOP-URI + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-URI` header field is a non-HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information, see [the API Signature document](https://github.com/mojaloop/docs/tree/master/Specification%20Document%20Set).' + - name: FSPIOP-HTTP-Method + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-HTTP-Method` header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information, see [the API Signature document](https://github.com/mojaloop/docs/tree/master/Specification%20Document%20Set).' + post: + tags: + - consents + - sampled + operationId: PostConsents + summary: PostConsents + description: | + The **POST /consents** request is used to request the creation of a consent for interactions between a PISP and the DFSP who owns the account which a PISP’s customer wants to allow the PISP access to. + parameters: + - name: Accept + in: header + required: true + schema: + type: string + description: The `Accept` header field indicates the version of the API the client would like the server to use. + - name: Content-Length + in: header + required: false + schema: + type: integer + description: |- + The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body. + + **Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes). + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentPostRequestAUTH + type: object + description: | + The object sent in a `POST /consents` request to the Auth-Service + by a DFSP to store registered Consent and credential + properties: + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and FSP for the Consent object + determined by the DFSP who creates the Consent. + consentRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + scopes: + minLength: 1 + maxLength: 256 + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + credential: + allOf: + - $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential' + status: + title: ConsentStatus + type: string + enum: + - ISSUED + - REVOKED + description: |- + Allowed values for the enumeration ConsentStatus + - ISSUED - The consent has been issued by the DFSP + - REVOKED - The consent has been revoked + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - consentId + - scopes + - credential + - status + additionalProperties: false + - title: ConsentPostRequestPISP + type: object + description: | + The provisional Consent object sent by the DFSP in `POST /consents`. + properties: + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and the Payer DFSP for the consent object. The ID + should be reused for re-sends of the same consent. A new ID should be generated + for each new consent. + consentRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + The ID given to the original consent request on which this consent is based. + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + $ref: '#/paths/~1consents/post/requestBody/content/application~1json/schema/oneOf/0/properties/status' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - consentId + - consentRequestId + - scopes + - status + responses: + '202': + description: Accepted + '400': + description: Bad Request + content: + application/json: + schema: + title: ErrorInformationResponse + type: object + description: Data model for the complex type object that contains an optional element ErrorInformation used along with 4xx and 5xx responses. + properties: + errorInformation: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema/properties/errorInformation' + headers: + Content-Length: + required: false + schema: + type: integer + description: |- + The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body. + + **Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes). + Content-Type: + schema: + type: string + required: true + description: The `Content-Type` header indicates the specific version of the API used to send the payload body. + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '405': + description: Method Not Allowed + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '406': + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '501': + description: Not Implemented + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '503': + description: Service Unavailable + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '/consents/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + description: | + The **GET /consents/**_{ID}_ resource allows a party to enquire after the status of a consent. The *{ID}* used in the URI of the request should be the consent request ID which was used to identify the consent when it was created. + tags: + - consents + operationId: GetConsent + summary: GetConsent + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + patch: + description: | + The HTTP request `PATCH /consents/{ID}` is used + + - In account linking in the Credential Registration phase. Used by a DFSP + to notify a PISP a credential has been verified and registered with an + Auth service. + + - In account unlinking by a hub hosted auth service and by DFSPs + in non-hub hosted scenarios to notify participants of a consent being revoked. + + Called by a `auth-service` to notify a PISP and DFSP of consent status in hub hosted scenario. + Called by a `DFSP` to notify a PISP of consent status in non-hub hosted scenario. + tags: + - consents + - sampled + operationId: PatchConsentByID + summary: PatchConsentByID + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentsIDPatchResponseVerified + description: | + PATCH /consents/{ID} request object. + + Sent by the DFSP to the PISP when a consent is issued and verified. + Used in the "Register Credential" part of the Account linking flow. + type: object + properties: + credential: + type: object + properties: + status: + title: CredentialStatusVerified + type: string + enum: + - VERIFIED + description: | + The status of the Credential. + - "VERIFIED" - The Credential is valid and verified. + required: + - status + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - credential + - title: ConsentsIDPatchResponseRevoked + description: | + PATCH /consents/{ID} request object. + + Sent to both the PISP and DFSP when a consent is revoked. + Used in the "Unlinking" part of the Account Unlinking flow. + type: object + properties: + status: + title: ConsentStatusRevoked + type: string + enum: + - REVOKED + description: |- + Allowed values for the enumeration ConsentStatus + - REVOKED - The consent has been revoked + revokedAt: + $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/completedTimestamp' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - status + - revokedAt + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + description: | + The HTTP request `PUT /consents/{ID}` is used by the PISP and Auth Service. + + - Called by a `PISP` to after signing a challenge. Sent to an DFSP for verification. + - Called by a `auth-service` to notify a DFSP that a credential has been verified and registered. + tags: + - consents + - sampled + operationId: PutConsentByID + summary: PutConsentByID + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentsIDPutResponseSigned + type: object + description: | + The HTTP request `PUT /consents/{ID}` is used by the PISP to update a Consent with a signed challenge and register a credential. + Called by a `PISP` to after signing a challenge. Sent to a DFSP for verification. + properties: + status: + title: ConsentStatusIssued + type: string + enum: + - ISSUED + description: |- + Allowed values for the enumeration ConsentStatus + - ISSUED - The consent has been issued by the DFSP + scopes: + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + credential: + title: SignedCredential + type: object + description: | + A credential used to allow a user to prove their identity and access + to an account with a DFSP. + + SignedCredential is a special formatting of the credential to allow us to be + more explicit about the `status` field - it should only ever be PENDING when + updating a credential. + properties: + credentialType: + title: CredentialType + type: string + enum: + - FIDO + - GENERIC + description: |- + The type of the Credential. - "FIDO" - The credential is based on a FIDO challenge. Its payload is a FIDOPublicKeyCredentialAttestation object. - "GENERIC" - The credential is based on a simple public key validation. Its payload is a GenericCredential object. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#3226-credentialtype + status: + title: CredentialStatusPending + type: string + enum: + - PENDING + description: | + The status of the Credential. + - "PENDING" - The credential has been created, but has not been verified + genericPayload: + title: GenericCredential + type: object + description: | + A publicKey + signature of a challenge for a generic public/private keypair. + properties: + publicKey: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + signature: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - publicKey + - signature + additionalProperties: false + fidoPayload: + title: FIDOPublicKeyCredentialAttestation + type: object + description: | + A data model representing a FIDO Attestation result. Derived from + [`PublicKeyCredential` Interface](https://w3c.github.io/webauthn/#iface-pkcredential). + + The `PublicKeyCredential` interface represents the below fields with + a Type of Javascript [ArrayBuffer](https://heycam.github.io/webidl/#idl-ArrayBuffer). + For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + properties: + id: + type: string + description: | + credential id: identifier of pair of keys, base64 encoded + https://w3c.github.io/webauthn/#ref-for-dom-credential-id + minLength: 59 + maxLength: 118 + rawId: + type: string + description: | + raw credential id: identifier of pair of keys, base64 encoded + minLength: 59 + maxLength: 118 + response: + type: object + description: | + AuthenticatorAttestationResponse + properties: + clientDataJSON: + type: string + description: | + JSON string with client data + minLength: 121 + maxLength: 512 + attestationObject: + type: string + description: | + CBOR.encoded attestation object + minLength: 306 + maxLength: 2048 + required: + - clientDataJSON + - attestationObject + additionalProperties: false + type: + type: string + description: 'response type, we need only the type of public-key' + enum: + - public-key + required: + - id + - response + - type + additionalProperties: false + required: + - credentialType + - status + additionalProperties: false + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - scopes + - credential + additionalProperties: false + - title: ConsentsIDPutResponseVerified + type: object + description: | + The HTTP request `PUT /consents/{ID}` is used by the DFSP or Auth-Service to update a Consent object once it has been Verified. + Called by a `auth-service` to notify a DFSP that a credential has been verified and registered. + properties: + status: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/status' + scopes: + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + credential: + title: VerifiedCredential + type: object + description: | + A credential used to allow a user to prove their identity and access + to an account with a DFSP. + + VerifiedCredential is a special formatting of Credential to allow us to be + more explicit about the `status` field - it should only ever be VERIFIED when + updating a credential. + properties: + credentialType: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential/properties/credentialType' + status: + $ref: '#/paths/~1consents~1%7BID%7D/patch/requestBody/content/application~1json/schema/oneOf/0/properties/credential/properties/status' + genericPayload: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential/properties/genericPayload' + fidoPayload: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential/properties/fidoPayload' + required: + - credentialType + - status + additionalProperties: false + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - scopes + - credential + additionalProperties: false + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + delete: + description: | + Used by PISP, DFSP + + The **DELETE /consents/**_{ID}_ request is used to request the revocation of a previously agreed consent. + For tracing and auditing purposes, the switch should be sure not to delete the consent physically; + instead, information relating to the consent should be marked as deleted and requests relating to the + consent should not be honoured. + operationId: DeleteConsentByID + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + tags: + - consents + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/consents/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - consents + operationId: NotifyErrorConsents + summary: NotifyErrorConsents + description: | + DFSP responds to the PISP if something went wrong with validating or storing consent. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /thirdpartyRequests/authorizations: + parameters: + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + post: + description: | + The HTTP request **POST /thirdpartyRequests/authorizations** is used to request the validation by a customer for the transfer described in the request. + operationId: PostThirdpartyRequestsAuthorizations + summary: PostThirdpartyRequestsAuthorizations + tags: + - authorizations + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Authorization request details + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsAuthorizationsPostRequest + description: |- + Used by: DFSP + The HTTP request POST /thirdpartyRequests/authorizations is used to request the validation by a customer for the transfer described in the request. + Callback and data model information for POST /thirdpartyRequests/authorizations: + Callback - PUT /thirdpartyRequests/authorizations/{ID} Error Callback - PUT /thirdpartyRequests/authorizations/{ID}/error Data Model - See below url + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31612-post-thirdpartyrequestsauthorizations + type: object + properties: + authorizationRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + transactionRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + challenge: + type: string + description: The challenge that the PISP's client is to sign + transferAmount: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount that will be debited from the sending customer's account as a consequence of the transaction. + payeeReceiveAmount: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount that will be credited to the receiving customer's account as a consequence of the transaction. + fees: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount of fees that the paying customer will be charged as part of the transaction. + payer: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0' + description: 'Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction.' + payee: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payee/allOf/0' + description: Information about the Payee in the proposed financial transaction. + transactionType: + title: TransactionType + type: object + description: Data model for the complex type TransactionType. + properties: + scenario: + title: TransactionScenario + type: string + enum: + - DEPOSIT + - WITHDRAWAL + - TRANSFER + - PAYMENT + - REFUND + description: |- + Below are the allowed values for the enumeration. + - DEPOSIT - Used for performing a Cash-In (deposit) transaction. In a normal scenario, electronic funds are transferred from a Business account to a Consumer account, and physical cash is given from the Consumer to the Business User. + - WITHDRAWAL - Used for performing a Cash-Out (withdrawal) transaction. In a normal scenario, electronic funds are transferred from a Consumer’s account to a Business account, and physical cash is given from the Business User to the Consumer. + - TRANSFER - Used for performing a P2P (Peer to Peer, or Consumer to Consumer) transaction. + - PAYMENT - Usually used for performing a transaction from a Consumer to a Merchant or Organization, but could also be for a B2B (Business to Business) payment. The transaction could be online for a purchase in an Internet store, in a physical store where both the Consumer and Business User are present, a bill payment, a donation, and so on. + - REFUND - Used for performing a refund of transaction. + example: DEPOSIT + subScenario: + title: TransactionSubScenario + type: string + pattern: '^[A-Z_]{1,32}$' + description: 'Possible sub-scenario, defined locally within the scheme (UndefinedEnum Type).' + example: LOCALLY_DEFINED_SUBSCENARIO + initiator: + title: TransactionInitiator + type: string + enum: + - PAYER + - PAYEE + description: |- + Below are the allowed values for the enumeration. + - PAYER - Sender of funds is initiating the transaction. The account to send from is either owned by the Payer or is connected to the Payer in some way. + - PAYEE - Recipient of the funds is initiating the transaction by sending a transaction request. The Payer must approve the transaction, either automatically by a pre-generated OTP or by pre-approval of the Payee, or by manually approving in his or her own Device. + example: PAYEE + initiatorType: + title: TransactionInitiatorType + type: string + enum: + - CONSUMER + - AGENT + - BUSINESS + - DEVICE + description: |- + Below are the allowed values for the enumeration. + - CONSUMER - Consumer is the initiator of the transaction. + - AGENT - Agent is the initiator of the transaction. + - BUSINESS - Business is the initiator of the transaction. + - DEVICE - Device is the initiator of the transaction. + example: CONSUMER + refundInfo: + title: Refund + type: object + description: Data model for the complex type Refund. + properties: + originalTransactionId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + refundReason: + title: RefundReason + type: string + minLength: 1 + maxLength: 128 + description: Reason for the refund. + example: Free text indicating reason for the refund. + required: + - originalTransactionId + balanceOfPayments: + title: BalanceOfPayments + type: string + pattern: '^[1-9]\d{2}$' + description: '(BopCode) The API data type [BopCode](https://www.imf.org/external/np/sta/bopcode/) is a JSON String of 3 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed.' + example: '123' + required: + - scenario + - initiator + - initiatorType + expiration: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/completedTimestamp' + description: 'The time by which the transfer must be completed, set by the payee DFSP.' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - authorizationRequestId + - transactionRequestId + - challenge + - transferAmount + - payeeReceiveAmount + - fees + - payer + - payee + - transactionType + - expiration + additionalProperties: false + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/authorizations/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + description: | + The HTTP request **GET /thirdpartyRequests/authorizations/**_{ID}_ is used to get information relating + to a previously issued authorization request. The *{ID}* in the request should match the + `authorizationRequestId` which was given when the authorization request was created. + operationId: GetThirdpartyRequestsAuthorizationsById + summary: GetThirdpartyRequestsAuthorizationsById + tags: + - authorizations + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + description: | + After receiving the **POST /thirdpartyRequests/authorizations**, the PISP will present the details of the + transaction to their user, and request that the client sign the `challenge` field using the credential + they previously registered. + + The signed challenge will be sent back by the PISP in **PUT /thirdpartyRequests/authorizations/**_{ID}_: + operationId: PutThirdpartyRequestsAuthorizationsById + summary: PutThirdpartyRequestsAuthorizationsById + tags: + - authorizations + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Signed authorization object + required: true + content: + application/json: + schema: + oneOf: + - title: ThirdpartyRequestsAuthorizationsIDPutResponseRejected + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + title: AuthorizationResponseTypeRejected + description: | + The customer rejected the terms of the transfer. + type: string + enum: + - REJECTED + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - responseType + - title: ThirdpartyRequestsAuthorizationsIDPutResponseFIDO + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + title: AuthorizationResponseType + description: | + The customer accepted the terms of the transfer + type: string + enum: + - ACCEPTED + signedPayload: + title: SignedPayloadFIDO + type: object + properties: + signedPayloadType: + $ref: '#/paths/~1thirdpartyRequests~1verifications/post/requestBody/content/application~1json/schema/oneOf/0/properties/signedPayloadType' + fidoSignedPayload: + $ref: '#/paths/~1thirdpartyRequests~1verifications/post/requestBody/content/application~1json/schema/oneOf/0/properties/fidoSignedPayload' + required: + - signedPayloadType + - fidoSignedPayload + additionalProperties: false + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - responseType + - signedPayload + additionalProperties: false + - title: ThirdpartyRequestsAuthorizationsIDPutResponseGeneric + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + $ref: '#/paths/~1thirdpartyRequests~1authorizations~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/1/properties/responseType' + signedPayload: + title: SignedPayloadGeneric + type: object + properties: + signedPayloadType: + $ref: '#/paths/~1thirdpartyRequests~1verifications/post/requestBody/content/application~1json/schema/oneOf/1/properties/signedPayloadType' + genericSignedPayload: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - signedPayloadType + - genericSignedPayload + additionalProperties: false + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - responseType + - signedPayload + additionalProperties: false + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/authorizations/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - thirdpartyRequests + - sampled + operationId: PutThirdpartyRequestsAuthorizationsByIdAndError + summary: PutThirdpartyRequestsAuthorizationsByIdAndError + description: | + The HTTP request `PUT /thirdpartyRequests/authorizations/{ID}/error` is used by the DFSP or PISP to inform + the other party that something went wrong with a Thirdparty Transaction Authorization Request. + + The PISP may use this to tell the DFSP that the Thirdparty Transaction Authorization Request is invalid or doesn't + match a `transactionRequestId`. + + The DFSP may use this to tell the PISP that the signed challenge returned in `PUT /thirdpartyRequest/authorizations/{ID}` + was invalid. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /thirdpartyRequests/transactions: + parameters: + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + post: + operationId: ThirdpartyRequestsTransactionsPost + summary: ThirdpartyRequestsTransactionsPost + description: The HTTP request POST `/thirdpartyRequests/transactions` is used by a PISP to initiate a 3rd party Transaction request with a DFSP + tags: + - thirdpartyRequests + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Transaction request to be created. + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsPostRequest + type: object + description: |- + Used by: PISP + The HTTP request POST /thirdpartyRequests/transactions is used to request the creation of a transaction request on the server for the transfer described in the request. + Callback and data model information for POST /thirdpartyRequests/transactions: + Callback - PUT /thirdpartyRequests/transactions/{ID} Error Callback - PUT /thirdpartyRequests/transactions/{ID}/error Data Model - See link below + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31712-post-thirdpartyrequeststransactions + properties: + transactionRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and the Payer DFSP for the transaction request object. The ID should be reused for resends of the same transaction request. A new ID should be generated for each new transaction request. + payee: + allOf: + - title: Party + type: object + description: Data model for the complex type Party. + properties: + partyIdInfo: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0' + merchantClassificationCode: + title: MerchantClassificationCode + type: string + pattern: '^[\d]{1,4}$' + description: 'A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, etc.' + name: + title: PartyName + type: string + minLength: 1 + maxLength: 128 + description: Name of the Party. Could be a real name or a nickname. + personalInfo: + title: PartyPersonalInfo + type: object + description: Data model for the complex type PartyPersonalInfo. + properties: + complexName: + title: PartyComplexName + type: object + description: Data model for the complex type PartyComplexName. + properties: + firstName: + title: FirstName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: First name of the Party (Name Type). + example: Henrik + middleName: + title: MiddleName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: Middle name of the Party (Name Type). + example: Johannes + lastName: + title: LastName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: Last name of the Party (Name Type). + example: Karlsson + dateOfBirth: + title: DateofBirth (type Date) + type: string + pattern: '^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$' + description: Date of Birth of the Party. + example: '1966-06-16' + required: + - partyIdInfo + description: Information about the Payee in the proposed financial transaction. + payer: + allOf: + - title: PartyIdInfo + type: object + description: Data model for the complex type PartyIdInfo. + properties: + partyIdType: + title: PartyIdType + type: string + enum: + - MSISDN + - EMAIL + - PERSONAL_ID + - BUSINESS + - DEVICE + - ACCOUNT_ID + - IBAN + - ALIAS + - CONSENT + - THIRD_PARTY_LINK + description: | + Below are the allowed values for the enumeration. + - MSISDN - An MSISDN (Mobile Station International Subscriber Directory + Number, that is, the phone number) is used as reference to a participant. + The MSISDN identifier should be in international format according to the + [ITU-T E.164 standard](https://www.itu.int/rec/T-REC-E.164/en). + Optionally, the MSISDN may be prefixed by a single plus sign, indicating the + international prefix. + - EMAIL - An email is used as reference to a + participant. The format of the email should be according to the informational + [RFC 3696](https://tools.ietf.org/html/rfc3696). + - PERSONAL_ID - A personal identifier is used as reference to a participant. + Examples of personal identification are passport number, birth certificate + number, and national registration number. The identifier number is added in + the PartyIdentifier element. The personal identifier type is added in the + PartySubIdOrType element. + - BUSINESS - A specific Business (for example, an organization or a company) + is used as reference to a participant. The BUSINESS identifier can be in any + format. To make a transaction connected to a specific username or bill number + in a Business, the PartySubIdOrType element should be used. + - DEVICE - A specific device (for example, a POS or ATM) ID connected to a + specific business or organization is used as reference to a Party. + For referencing a specific device under a specific business or organization, + use the PartySubIdOrType element. + - ACCOUNT_ID - A bank account number or FSP account ID should be used as + reference to a participant. The ACCOUNT_ID identifier can be in any format, + as formats can greatly differ depending on country and FSP. + - IBAN - A bank account number or FSP account ID is used as reference to a + participant. The IBAN identifier can consist of up to 34 alphanumeric + characters and should be entered without whitespace. + - ALIAS An alias is used as reference to a participant. The alias should be + created in the FSP as an alternative reference to an account owner. + Another example of an alias is a username in the FSP system. + The ALIAS identifier can be in any format. It is also possible to use the + PartySubIdOrType element for identifying an account under an Alias defined + by the PartyIdentifier. + - CONSENT - A Consent represents an agreement between a PISP, a Customer and + a DFSP which allows the PISP permission to perform actions on behalf of the + customer. A Consent has an authoritative source: either the DFSP who issued + the Consent, or an Auth Service which administers the Consent. + - THIRD_PARTY_LINK - A Third Party Link represents an agreement between a PISP, + a DFSP, and a specific Customer's account at the DFSP. The content of the link + is created by the DFSP at the time when it gives permission to the PISP for + specific access to a given account. + example: PERSONAL_ID + partyIdentifier: + title: PartyIdentifier + type: string + minLength: 1 + maxLength: 128 + description: Identifier of the Party. + example: '16135551212' + partySubIdOrType: + title: PartySubIdOrType + type: string + minLength: 1 + maxLength: 128 + description: 'Either a sub-identifier of a PartyIdentifier, or a sub-type of the PartyIdType, normally a PersonalIdentifierType.' + fspId: + title: FspId + type: string + minLength: 1 + maxLength: 32 + description: FSP identifier. + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - partyIdType + - partyIdentifier + description: Information about the Payer in the proposed financial transaction. + amountType: + allOf: + - title: AmountType + type: string + enum: + - SEND + - RECEIVE + description: |- + Below are the allowed values for the enumeration AmountType. + - SEND - Amount the Payer would like to send, that is, the amount that should be withdrawn from the Payer account including any fees. + - RECEIVE - Amount the Payer would like the Payee to receive, that is, the amount that should be sent to the receiver exclusive of any fees. + example: RECEIVE + description: 'SEND for sendAmount, RECEIVE for receiveAmount.' + amount: + allOf: + - title: Money + type: object + description: Data model for the complex type Money. + properties: + currency: + title: Currency + description: 'The currency codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic codes are used as the standard naming representation for currencies.' + type: string + minLength: 3 + maxLength: 3 + enum: + - AED + - AFN + - ALL + - AMD + - ANG + - AOA + - ARS + - AUD + - AWG + - AZN + - BAM + - BBD + - BDT + - BGN + - BHD + - BIF + - BMD + - BND + - BOB + - BRL + - BSD + - BTN + - BWP + - BYN + - BZD + - CAD + - CDF + - CHF + - CLP + - CNY + - COP + - CRC + - CUC + - CUP + - CVE + - CZK + - DJF + - DKK + - DOP + - DZD + - EGP + - ERN + - ETB + - EUR + - FJD + - FKP + - GBP + - GEL + - GGP + - GHS + - GIP + - GMD + - GNF + - GTQ + - GYD + - HKD + - HNL + - HRK + - HTG + - HUF + - IDR + - ILS + - IMP + - INR + - IQD + - IRR + - ISK + - JEP + - JMD + - JOD + - JPY + - KES + - KGS + - KHR + - KMF + - KPW + - KRW + - KWD + - KYD + - KZT + - LAK + - LBP + - LKR + - LRD + - LSL + - LYD + - MAD + - MDL + - MGA + - MKD + - MMK + - MNT + - MOP + - MRO + - MUR + - MVR + - MWK + - MXN + - MYR + - MZN + - NAD + - NGN + - NIO + - NOK + - NPR + - NZD + - OMR + - PAB + - PEN + - PGK + - PHP + - PKR + - PLN + - PYG + - QAR + - RON + - RSD + - RUB + - RWF + - SAR + - SBD + - SCR + - SDG + - SEK + - SGD + - SHP + - SLL + - SOS + - SPL + - SRD + - STD + - SVC + - SYP + - SZL + - THB + - TJS + - TMT + - TND + - TOP + - TRY + - TTD + - TVD + - TWD + - TZS + - UAH + - UGX + - USD + - UYU + - UZS + - VEF + - VND + - VUV + - WST + - XAF + - XCD + - XDR + - XOF + - XPF + - XTS + - XXX + - YER + - ZAR + - ZMW + - ZWD + amount: + title: Amount + type: string + pattern: '^([0]|([1-9][0-9]{0,17}))([.][0-9]{0,3}[1-9])?$' + description: 'The API data type Amount is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons. This pattern does not allow any trailing zeroes at all, but allows an amount without a minor currency unit. It also only allows four digits in the minor currency unit; a negative value is not allowed. Using more than 18 digits in the major currency unit is not allowed.' + example: '123.45' + required: + - currency + - amount + description: Requested amount to be transferred from the Payer to Payee. + transactionType: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/transactionType' + description: Type of transaction. + note: + type: string + minLength: 1 + maxLength: 256 + description: A memo that will be attached to the transaction. + expiration: + type: string + description: | + Date and time until when the transaction request is valid. It can be set to get a quick failure in case the peer FSP takes too long to respond. + example: '2016-05-24T08:38:08.699-04:00' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - transactionRequestId + - payee + - payer + - amountType + - amount + - transactionType + - expiration + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/transactions/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + tags: + - thirdpartyRequests + - sampled + operationId: GetThirdpartyTransactionRequests + summary: GetThirdpartyTransactionRequests + description: | + The HTTP request `GET /thirdpartyRequests/transactions/{ID}` is used to request the + retrieval of a third party transaction request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + tags: + - thirdpartyRequests + - sampled + operationId: UpdateThirdPartyTransactionRequests + summary: UpdateThirdPartyTransactionRequests + description: | + The HTTP request `PUT /thirdpartyRequests/transactions/{ID}` is used by the DFSP to inform the client about + the status of a previously requested thirdparty transaction request. + + Switch(Thirdparty API Adapter) -> PISP + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsIDPutResponse + type: object + description: |- + Used by: DFSP + After a PISP requests the creation of a Third Party Transaction request (POST /thirdpartyRequests/transactions) or the status of a previously created Third Party Transaction request (GET /thirdpartyRequests/transactions/{ID}), the DFSP will send this callback. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31721-put-thirdpartyrequeststransactionsid + properties: + transactionRequestState: + title: TransactionRequestState + type: string + enum: + - RECEIVED + - PENDING + - ACCEPTED + - REJECTED + description: |- + Below are the allowed values for the enumeration. + - RECEIVED - Payer FSP has received the transaction from the Payee FSP. + - PENDING - Payer FSP has sent the transaction request to the Payer. + - ACCEPTED - Payer has approved the transaction. + - REJECTED - Payer has rejected the transaction. + example: RECEIVED + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - transactionRequestState + example: + transactionRequestState: RECEIVED + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + patch: + operationId: NotifyThirdpartyTransactionRequests + summary: NotifyThirdpartyTransactionRequests + description: | + The HTTP request `PATCH /thirdpartyRequests/transactions/{ID}` is used to + notify a thirdparty of the outcome of a transaction request. + + Switch(Thirdparty API Adapter) -> PISP + tags: + - thirdpartyRequests + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsIDPatchResponse + type: object + description: |- + Used by: DFSP + The issuing PISP will expect a response to their request for a transfer which describes the finalized state of the requested transfer. + This response will be given by a PATCH call on the /thirdpartyRequests/transactions/{ID} resource. + The {ID} given in the query string should be the transactionRequestId which was originally used by the PISP to identify the transaction request. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31612-post-thirdpartyrequestsauthorizations + properties: + completedTimestamp: + title: DateTime + type: string + pattern: '^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:(\.\d{3}))(?:Z|[+-][01]\d:[0-5]\d)$' + description: 'The API data type DateTime is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. The format is according to [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html), expressed in a combined date, time and time zone format. A more readable version of the format is yyyy-MM-ddTHH:mm:ss.SSS[-HH:MM]. Examples are "2016-05-24T08:38:08.699-04:00", "2016-05-24T08:38:08.699Z" (where Z indicates Zulu time zone, same as UTC).' + example: '2016-05-24T08:38:08.699-04:00' + transactionRequestState: + $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/transactionRequestState' + transactionState: + title: TransactionState + type: string + enum: + - RECEIVED + - PENDING + - COMPLETED + - REJECTED + description: |- + Below are the allowed values for the enumeration. + - RECEIVED - Payee FSP has received the transaction from the Payer FSP. + - PENDING - Payee FSP has validated the transaction. + - COMPLETED - Payee FSP has successfully performed the transaction. + - REJECTED - Payee FSP has failed to perform the transaction. + example: RECEIVED + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - transactionRequestState + - transactionState + example: + transactionRequestState: ACCEPTED + transactionState: COMMITTED + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/transactions/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - thirdpartyRequests + - sampled + operationId: ThirdpartyTransactionRequestsError + summary: ThirdpartyTransactionRequestsError + description: | + If the server is unable to find the transaction request, or another processing error occurs, + the error callback `PUT /thirdpartyRequests/transactions/{ID}/error` is used. + The `{ID}` in the URI should contain the `transactionRequestId` that was used for the creation of + the thirdparty transaction request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /thirdpartyRequests/verifications: + parameters: + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + post: + tags: + - thirdpartyRequests + - sampled + operationId: PostThirdpartyRequestsVerifications + summary: PostThirdpartyRequestsVerifications + description: | + The HTTP request `POST /thirdpartyRequests/verifications` is used by the DFSP to verify a third party authorization. + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: The thirdparty authorization details to verify + required: true + content: + application/json: + schema: + oneOf: + - title: ThirdpartyRequestsVerificationsPostRequestFIDO + type: object + description: The object sent in the POST /thirdpartyRequests/verifications request. + properties: + verificationRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + challenge: + type: string + description: Base64 encoded bytes - The challenge generated by the DFSP. + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + The id of the stored consent object that contains the credential with which to verify + the signed challenge against. + signedPayloadType: + title: SignedPayloadTypeFIDO + type: string + enum: + - FIDO + description: Describes a challenge that has been signed with FIDO Attestation flows + fidoSignedPayload: + title: FIDOPublicKeyCredentialAssertion + type: object + description: | + A data model representing a FIDO Assertion result. + Derived from PublicKeyCredential Interface in WebAuthN. + + The PublicKeyCredential interface represents the below fields with a Type of + Javascript ArrayBuffer. + For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#32128-fidopublickeycredentialassertion + properties: + id: + type: string + description: | + credential id: identifier of pair of keys, base64 encoded + https://w3c.github.io/webauthn/#ref-for-dom-credential-id + minLength: 59 + maxLength: 118 + rawId: + type: string + description: | + raw credential id: identifier of pair of keys, base64 encoded. + minLength: 59 + maxLength: 118 + response: + type: object + description: | + AuthenticatorAssertionResponse + properties: + authenticatorData: + type: string + description: | + Authenticator data object. + minLength: 49 + maxLength: 256 + clientDataJSON: + type: string + description: | + JSON string with client data. + minLength: 121 + maxLength: 512 + signature: + type: string + description: | + The signature generated by the private key associated with this credential. + minLength: 59 + maxLength: 256 + userHandle: + type: string + description: | + This field is optionally provided by the authenticator, and + represents the user.id that was supplied during registration. + minLength: 1 + maxLength: 88 + required: + - authenticatorData + - clientDataJSON + - signature + additionalProperties: false + type: + type: string + description: 'response type, we need only the type of public-key' + enum: + - public-key + required: + - id + - rawId + - response + - type + additionalProperties: false + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - verificationRequestId + - challenge + - consentId + - signedPayloadType + - fidoSignedPayload + - title: ThirdpartyRequestsVerificationsPostRequestGeneric + type: object + description: The object sent in the POST /thirdpartyRequests/verifications request. + properties: + verificationRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + challenge: + type: string + description: Base64 encoded bytes - The challenge generated by the DFSP. + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + The id of the stored consent object that contains the credential with which to verify + the signed challenge against. + signedPayloadType: + title: SignedPayloadTypeGeneric + type: string + enum: + - GENERIC + description: Describes a challenge that has been signed with a private key + genericSignedPayload: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - verificationRequestId + - challenge + - consentId + - signedPayloadType + - genericSignedPayload + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/verifications/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + tags: + - thirdpartyRequests + - sampled + operationId: GetThirdpartyRequestsVerificationsById + summary: GetThirdpartyRequestsVerificationsById + description: | + The HTTP request `/thirdpartyRequests/verifications/{ID}` is used to get + information regarding a previously created or requested authorization. The *{ID}* + in the URI should contain the verification request ID + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + tags: + - thirdpartyRequests + - sampled + operationId: PutThirdpartyRequestsVerificationsById + summary: PutThirdpartyRequestsVerificationsById + description: |- + The HTTP request `PUT /thirdpartyRequests/verifications/{ID}` is used by the Auth-Service to inform the DFSP of a successful result in validating the verification of a Thirdparty Transaction Request. + If the validation fails, the auth-service will send back `PUT /thirdpartyRequests/verifications/{ID}` with `authenticationResponse: 'REJECTED'`. + In unplanned error cases the Auth-Service MUST use `PUT /thirdpartyRequests/verifications/{ID}/error`. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: The result of validating the Thirdparty Transaction Request + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsVerificationsIDPutResponse + type: object + description: |- + Used by: Auth Service + The callback PUT /thirdpartyRequests/verifications/{ID} is used to inform the client of the result of an authorization check. The {ID} in the URI should contain the authorizationRequestId which was used to request the check, or the {ID} that was used in the GET /thirdpartyRequests/verifications/{ID}. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31821-put-thirdpartyrequestsverificationsid + properties: + authenticationResponse: + title: AuthenticationResponse + type: string + enum: + - VERIFIED + description: |- + The AuthenticationResponse enumeration describes the result of authenticating verification request. + Below are the allowed values for the enumeration AuthenticationResponse. - VERIFIED - The challenge was correctly signed. + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - authenticationResponse + example: + authenticationResponse: VERIFIED + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/verifications/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - thirdpartyRequests + - sampled + operationId: PutThirdpartyRequestsVerificationsByIdAndError + summary: PutThirdpartyRequestsVerificationsByIdAndError + description: | + The HTTP request `PUT /thirdpartyRequests/verifications/{ID}/error` is used by the Auth-Service to inform + the DFSP of a failure in validating or looking up the verification of a Thirdparty Transaction Request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/thirdparty-pisp-v1.0.yaml b/website/versioned_docs/v1.0.1/api/thirdparty/thirdparty-pisp-v1.0.yaml new file mode 100644 index 000000000..0a42d8dd4 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/thirdparty-pisp-v1.0.yaml @@ -0,0 +1,2923 @@ +openapi: 3.0.1 +info: + title: Mojaloop Third Party API (PISP) + version: '1.0' + description: | + A Mojaloop API for Payment Initiation Service Providers (PISPs) to perform Third Party functions on DFSPs' User's accounts. + DFSPs who want to enable Payment Initiation Service Providers (PISPs) should implement the accompanying API - Mojaloop Third Party API (DFSP) instead. + license: + name: Open API for FSP Interoperability (FSPIOP) (Implementation Friendly Version) + url: 'https://github.com/mojaloop/mojaloop-specification/blob/master/LICENSE.md' +servers: + - url: / +paths: + '/accounts/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + operationId: GetAccountsByUserId + summary: GetAccountsByUserId + description: | + The HTTP request `GET /accounts/{ID}` is used to retrieve the list of potential accounts available for linking. + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: | + The HTTP request `PUT /accounts/{ID}` is used to return the list of potential accounts available for linking + operationId: UpdateAccountsByUserId + summary: UpdateAccountsByUserId + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: AccountsIDPutResponse + type: object + description: |- + Callback and data model information for GET /accounts/{ID}: + Callback - PUT /accounts/{ID} Error Callback - PUT /accounts/{ID}/error Data Model - Empty body + The PUT /accounts/{ID} response is used to inform the requester of the result of a request for accounts information. The identifier ID given in the call are the values given in the original request. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31121--put-accountsid + properties: + accountList: + title: AccountList + type: array + description: |- + The AccountList data model is used to hold information about the accounts that a party controls. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#3213-accountlist + items: + title: Account + type: object + description: |- + Data model for the complex type Account. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#3211-account + properties: + accountNickname: + title: Name + type: string + pattern: '^(?!\s*$)[\w .,''-]{1,128}$' + description: |- + The API data type Name is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. + + Regular Expression - The regular expression for restricting the Name type is "^(?!\s*$)[\w .,'-]{1,128}$". The restriction does not allow a string consisting of whitespace only, all Unicode characters are allowed, as well as the period (.) (apostrophe (‘), dash (-), comma (,) and space characters ( ). + + **Note:** In some programming languages, Unicode support must be specifically enabled. For example, if Java is used, the flag UNICODE_CHARACTER_CLASS must be enabled to allow Unicode characters. + address: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items/properties/address' + currency: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0/properties/currency' + required: + - accountNickname + - address + - currency + minItems: 1 + maxItems: 256 + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - accounts + example: + - accountNickname: dfspa.user.nickname1 + id: dfspa.username.1234 + currency: ZAR + - accountNickname: dfspa.user.nickname2 + id: dfspa.username.5678 + currency: USD + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/accounts/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + description: | + The HTTP request `PUT /accounts/{ID}/error` is used to return error information + operationId: UpdateAccountsByUserIdError + summary: UpdateAccountsByUserIdError + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + title: ErrorInformationObject + type: object + description: Data model for the complex type object that contains ErrorInformation. + properties: + errorInformation: + title: ErrorInformation + type: object + description: Data model for the complex type ErrorInformation. + properties: + errorCode: + title: ErrorCode + type: string + pattern: '^[1-9]\d{3}$' + description: 'The API data type ErrorCode is a JSON String of four characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. Each error code in the API is a four-digit number, for example, 1234, where the first number (1 in the example) represents the high-level error category, the second number (2 in the example) represents the low-level error category, and the last two numbers (34 in the example) represent the specific error.' + example: '5100' + errorDescription: + title: ErrorDescription + type: string + minLength: 1 + maxLength: 128 + description: Error description string. + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - errorCode + - errorDescription + required: + - errorInformation + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + /consentRequests: + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + post: + tags: + - consentRequests + - sampled + operationId: CreateConsentRequest + summary: CreateConsentRequest + description: | + The HTTP request **POST /consentRequests** is used to request a DFSP to grant access to one or more + accounts owned by a customer of the DFSP for the PISP who sends the request. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: The consentRequest to create + required: true + content: + application/json: + schema: + title: ConsentRequestsPostRequest + type: object + description: |- + Used by: PISP + The HTTP request POST /consentRequests is used to request a DFSP to grant access to one or more accounts owned by a customer of the DFSP for the PISP who sends the request. + Callback and data model for POST /consentRequests: + Callback: PUT /consentRequests/{ID} Error callback: PUT /consentRequests/{ID}/error Data model - see below url + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31212-post-consentrequests + properties: + consentRequestId: + title: CorrelationId + type: string + pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' + description: 'Identifier that correlates all messages of the same sequence. The API data type UUID (Universally Unique Identifier) is a JSON String in canonical format, conforming to [RFC 4122](https://tools.ietf.org/html/rfc4122), that is restricted by a regular expression for interoperability reasons. A UUID is always 36 characters long, 32 hexadecimal symbols and 4 dashes (‘-‘).' + example: b51ec534-ee48-4575-b6a9-ead2955b8069 + userId: + type: string + description: 'The identifier used in the **GET /accounts/**_{ID}_. Used by the DFSP to correlate an account lookup to a `consentRequest`' + minLength: 1 + maxLength: 128 + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + title: Scope + type: object + description: |- + The Scope element contains an identifier defining, in the terms of a DFSP, an account on which access types can be requested or granted. It also defines the access types which are requested or granted. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#32121-scope + properties: + address: + title: AccountAddress + type: string + description: |- + The AccountAddress data type is a variable length string with a maximum size of 1023 characters and consists of: + Alphanumeric characters, upper or lower case. (Addresses are case-sensitive so that they can contain data encoded in formats such as base64url.) + - Underscore (_) - Tilde (~) - Hyphen (-) - Period (.) Addresses MUST NOT end in a period (.) character + An entity providing accounts to parties (i.e. a participant) can provide any value for an AccountAddress that is meaningful to that entity. It does not need to provide an address that makes the account identifiable outside the entity's domain. + IMPORTANT: The policy for defining addresses and the life-cycle of these is at the discretion of the address space owner (the payer DFSP in this case). + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#3212-accountaddress + pattern: '^([0-9A-Za-z_~\-\.]+[0-9A-Za-z_~\-])$' + minLength: 1 + maxLength: 1023 + actions: + type: array + minItems: 1 + maxItems: 32 + items: + title: ScopeAction + type: string + description: | + The ScopeAction element contains an access type which a PISP can request + from a DFSP, or which a DFSP can grant to a PISP. + It must be a member of the appropriate enumeration. + + - ACCOUNTS_GET_BALANCE: PISP can request a balance for the linked account + - ACCOUNTS_TRANSFER: PISP can request a transfer of funds from the linked account in the DFSP + - ACCOUNTS_STATEMENT: PISP can request a statement of individual transactions on a user's account + enum: + - ACCOUNTS_GET_BALANCE + - ACCOUNTS_TRANSFER + - ACCOUNTS_STATEMENT + required: + - address + - actions + authChannels: + type: array + minLength: 1 + maxLength: 256 + items: + title: ConsentRequestChannelType + type: string + enum: + - WEB + - OTP + description: | + The auth channel being used for the consent request. + - WEB - DFSP can support authorization via a web-based login. + - OTP - DFSP can support authorization via a One Time PIN. + callbackUri: + title: Uri + type: string + pattern: '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' + minLength: 1 + maxLength: 512 + description: | + The API data type Uri is a JSON string in a canonical format that is restricted by a regular expression for interoperability reasons. + extensionList: + title: ExtensionList + type: object + description: 'Data model for the complex type ExtensionList. An optional list of extensions, specific to deployment.' + properties: + extension: + type: array + items: + title: Extension + type: object + description: Data model for the complex type Extension. + properties: + key: + title: ExtensionKey + type: string + minLength: 1 + maxLength: 32 + description: Extension key. + value: + title: ExtensionValue + type: string + minLength: 1 + maxLength: 128 + description: Extension value. + required: + - key + - value + minItems: 1 + maxItems: 16 + description: Number of Extension elements. + required: + - extension + required: + - consentRequestId + - userId + - scopes + - authChannels + - callbackUri + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/consentRequests/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + operationId: GetConsentRequestsById + summary: GetConsentRequestsById + description: | + The HTTP request `GET /consentRequests/{ID}` is used to get information about a previously + requested consent. The *{ID}* in the URI should contain the consentRequestId that was assigned to the + request by the PISP when the PISP originated the request. + tags: + - consentRequests + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + tags: + - consentRequests + - sampled + operationId: UpdateConsentRequest + summary: UpdateConsentRequest + description: | + A DFSP uses this callback to (1) inform the PISP that the consentRequest has been accepted, + and (2) communicate to the PISP which `authChannel` it should use to authenticate their user + with. + + When a PISP requests a series of permissions from a DFSP on behalf of a DFSP’s customer, not all + the permissions requested may be granted by the DFSP. Conversely, the out-of-band authorization + process may result in additional privileges being granted by the account holder to the PISP. The + **PUT /consentRequests/**_{ID}_ resource returns the current state of the permissions relating to a + particular authorization request. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentRequestsIDPutResponseWeb + type: object + description: | + The object sent in a `PUT /consentRequests/{ID}` request. + + Schema used in the request consent phase of the account linking web flow, + the result is the PISP being instructed on a specific URL where this + supposed user should be redirected. This URL should be a place where + the user can prove their identity (e.g., by logging in). + properties: + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + authChannels: + type: array + minLength: 1 + maxLength: 1 + items: + title: ConsentRequestChannelTypeWeb + type: string + enum: + - WEB + description: | + The web auth channel being used for `PUT /consentRequest/{ID}` request. + callbackUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + authUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - scopes + - authChannels + - callbackUri + - authUri + additionalProperties: false + - title: ConsentRequestsIDPutResponseOTP + type: object + description: | + The object sent in a `PUT /consentRequests/{ID}` request. + + Schema used in the request consent phase of the account linking OTP/SMS flow. + properties: + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + authChannels: + type: array + minLength: 1 + maxLength: 1 + items: + title: ConsentRequestChannelTypeOTP + type: string + enum: + - OTP + description: | + The OTP auth channel being used for `PUT /consentRequests/{ID}` request. + callbackUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - scopes + - authChannels + additionalProperties: false + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + patch: + tags: + - consentRequests + - sampled + operationId: PatchConsentRequest + summary: PatchConsentRequest + description: | + After the user completes an out-of-band authorization with the DFSP, the PISP will receive a token which they can use to prove to the DFSP that the user trusts this PISP. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: ConsentRequestsIDPatchRequest + type: object + description: |- + Used by: PISP + After the user completes an out-of-band authorization with the DFSP, the PISP will receive a token which they can use to prove to the DFSP that the user trusts this PISP. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31222-patch-consentrequestsid + properties: + authToken: + type: string + pattern: '^[A-Za-z0-9-_]+[=]{0,2}$' + description: 'The API data type BinaryString is a JSON String. The string is a base64url encoding of a string of raw bytes, where padding (character ‘=’) is added at the end of the data if needed to ensure that the string is a multiple of 4 characters. The length restriction indicates the allowed number of characters.' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - authToken + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/consentRequests/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + tags: + - consentRequests + operationId: NotifyErrorConsentRequests + summary: NotifyErrorConsentRequests + description: | + DFSP responds to the PISP if something went wrong with validating an OTP or secret. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + /consents: + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + post: + tags: + - consents + - sampled + operationId: PostConsents + summary: PostConsents + description: | + The **POST /consents** request is used to request the creation of a consent for interactions between a PISP and the DFSP who owns the account which a PISP’s customer wants to allow the PISP access to. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentPostRequestAUTH + type: object + description: | + The object sent in a `POST /consents` request to the Auth-Service + by a DFSP to store registered Consent and credential + properties: + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and FSP for the Consent object + determined by the DFSP who creates the Consent. + consentRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + scopes: + minLength: 1 + maxLength: 256 + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + credential: + allOf: + - $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential' + status: + title: ConsentStatus + type: string + enum: + - ISSUED + - REVOKED + description: |- + Allowed values for the enumeration ConsentStatus + - ISSUED - The consent has been issued by the DFSP + - REVOKED - The consent has been revoked + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - consentId + - scopes + - credential + - status + additionalProperties: false + - title: ConsentPostRequestPISP + type: object + description: | + The provisional Consent object sent by the DFSP in `POST /consents`. + properties: + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and the Payer DFSP for the consent object. The ID + should be reused for re-sends of the same consent. A new ID should be generated + for each new consent. + consentRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + The ID given to the original consent request on which this consent is based. + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + $ref: '#/paths/~1consents/post/requestBody/content/application~1json/schema/oneOf/0/properties/status' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - consentId + - consentRequestId + - scopes + - status + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/consents/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + description: | + The **GET /consents/**_{ID}_ resource allows a party to enquire after the status of a consent. The *{ID}* used in the URI of the request should be the consent request ID which was used to identify the consent when it was created. + tags: + - consents + operationId: GetConsent + summary: GetConsent + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + patch: + description: | + The HTTP request `PATCH /consents/{ID}` is used + + - In account linking in the Credential Registration phase. Used by a DFSP + to notify a PISP a credential has been verified and registered with an + Auth service. + + - In account unlinking by a hub hosted auth service and by DFSPs + in non-hub hosted scenarios to notify participants of a consent being revoked. + + Called by a `auth-service` to notify a PISP and DFSP of consent status in hub hosted scenario. + Called by a `DFSP` to notify a PISP of consent status in non-hub hosted scenario. + tags: + - consents + - sampled + operationId: PatchConsentByID + summary: PatchConsentByID + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentsIDPatchResponseVerified + description: | + PATCH /consents/{ID} request object. + + Sent by the DFSP to the PISP when a consent is issued and verified. + Used in the "Register Credential" part of the Account linking flow. + type: object + properties: + credential: + type: object + properties: + status: + title: CredentialStatusVerified + type: string + enum: + - VERIFIED + description: | + The status of the Credential. + - "VERIFIED" - The Credential is valid and verified. + required: + - status + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - credential + - title: ConsentsIDPatchResponseRevoked + description: | + PATCH /consents/{ID} request object. + + Sent to both the PISP and DFSP when a consent is revoked. + Used in the "Unlinking" part of the Account Unlinking flow. + type: object + properties: + status: + title: ConsentStatusRevoked + type: string + enum: + - REVOKED + description: |- + Allowed values for the enumeration ConsentStatus + - REVOKED - The consent has been revoked + revokedAt: + $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/completedTimestamp' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - status + - revokedAt + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: | + The HTTP request `PUT /consents/{ID}` is used by the PISP and Auth Service. + + - Called by a `PISP` to after signing a challenge. Sent to an DFSP for verification. + - Called by a `auth-service` to notify a DFSP that a credential has been verified and registered. + tags: + - consents + - sampled + operationId: PutConsentByID + summary: PutConsentByID + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentsIDPutResponseSigned + type: object + description: | + The HTTP request `PUT /consents/{ID}` is used by the PISP to update a Consent with a signed challenge and register a credential. + Called by a `PISP` to after signing a challenge. Sent to a DFSP for verification. + properties: + status: + title: ConsentStatusIssued + type: string + enum: + - ISSUED + description: |- + Allowed values for the enumeration ConsentStatus + - ISSUED - The consent has been issued by the DFSP + scopes: + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + credential: + title: SignedCredential + type: object + description: | + A credential used to allow a user to prove their identity and access + to an account with a DFSP. + + SignedCredential is a special formatting of the credential to allow us to be + more explicit about the `status` field - it should only ever be PENDING when + updating a credential. + properties: + credentialType: + title: CredentialType + type: string + enum: + - FIDO + - GENERIC + description: |- + The type of the Credential. - "FIDO" - The credential is based on a FIDO challenge. Its payload is a FIDOPublicKeyCredentialAttestation object. - "GENERIC" - The credential is based on a simple public key validation. Its payload is a GenericCredential object. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#3226-credentialtype + status: + title: CredentialStatusPending + type: string + enum: + - PENDING + description: | + The status of the Credential. + - "PENDING" - The credential has been created, but has not been verified + genericPayload: + title: GenericCredential + type: object + description: | + A publicKey + signature of a challenge for a generic public/private keypair. + properties: + publicKey: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + signature: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - publicKey + - signature + additionalProperties: false + fidoPayload: + title: FIDOPublicKeyCredentialAttestation + type: object + description: | + A data model representing a FIDO Attestation result. Derived from + [`PublicKeyCredential` Interface](https://w3c.github.io/webauthn/#iface-pkcredential). + + The `PublicKeyCredential` interface represents the below fields with + a Type of Javascript [ArrayBuffer](https://heycam.github.io/webidl/#idl-ArrayBuffer). + For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + properties: + id: + type: string + description: | + credential id: identifier of pair of keys, base64 encoded + https://w3c.github.io/webauthn/#ref-for-dom-credential-id + minLength: 59 + maxLength: 118 + rawId: + type: string + description: | + raw credential id: identifier of pair of keys, base64 encoded + minLength: 59 + maxLength: 118 + response: + type: object + description: | + AuthenticatorAttestationResponse + properties: + clientDataJSON: + type: string + description: | + JSON string with client data + minLength: 121 + maxLength: 512 + attestationObject: + type: string + description: | + CBOR.encoded attestation object + minLength: 306 + maxLength: 2048 + required: + - clientDataJSON + - attestationObject + additionalProperties: false + type: + type: string + description: 'response type, we need only the type of public-key' + enum: + - public-key + required: + - id + - response + - type + additionalProperties: false + required: + - credentialType + - status + additionalProperties: false + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - scopes + - credential + additionalProperties: false + - title: ConsentsIDPutResponseVerified + type: object + description: | + The HTTP request `PUT /consents/{ID}` is used by the DFSP or Auth-Service to update a Consent object once it has been Verified. + Called by a `auth-service` to notify a DFSP that a credential has been verified and registered. + properties: + status: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/status' + scopes: + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + credential: + title: VerifiedCredential + type: object + description: | + A credential used to allow a user to prove their identity and access + to an account with a DFSP. + + VerifiedCredential is a special formatting of Credential to allow us to be + more explicit about the `status` field - it should only ever be VERIFIED when + updating a credential. + properties: + credentialType: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential/properties/credentialType' + status: + $ref: '#/paths/~1consents~1%7BID%7D/patch/requestBody/content/application~1json/schema/oneOf/0/properties/credential/properties/status' + genericPayload: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential/properties/genericPayload' + fidoPayload: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential/properties/fidoPayload' + required: + - credentialType + - status + additionalProperties: false + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - scopes + - credential + additionalProperties: false + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + delete: + description: | + Used by PISP, DFSP + + The **DELETE /consents/**_{ID}_ request is used to request the revocation of a previously agreed consent. + For tracing and auditing purposes, the switch should be sure not to delete the consent physically; + instead, information relating to the consent should be marked as deleted and requests relating to the + consent should not be honoured. + operationId: DeleteConsentByID + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + tags: + - consents + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/consents/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + tags: + - consents + operationId: NotifyErrorConsents + summary: NotifyErrorConsents + description: | + DFSP responds to the PISP if something went wrong with validating or storing consent. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + /thirdpartyRequests/authorizations: + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + post: + description: | + The HTTP request **POST /thirdpartyRequests/authorizations** is used to request the validation by a customer for the transfer described in the request. + operationId: PostThirdpartyRequestsAuthorizations + summary: PostThirdpartyRequestsAuthorizations + tags: + - authorizations + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Authorization request details + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsAuthorizationsPostRequest + description: |- + Used by: DFSP + The HTTP request POST /thirdpartyRequests/authorizations is used to request the validation by a customer for the transfer described in the request. + Callback and data model information for POST /thirdpartyRequests/authorizations: + Callback - PUT /thirdpartyRequests/authorizations/{ID} Error Callback - PUT /thirdpartyRequests/authorizations/{ID}/error Data Model - See below url + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31612-post-thirdpartyrequestsauthorizations + type: object + properties: + authorizationRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + transactionRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + challenge: + type: string + description: The challenge that the PISP's client is to sign + transferAmount: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount that will be debited from the sending customer's account as a consequence of the transaction. + payeeReceiveAmount: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount that will be credited to the receiving customer's account as a consequence of the transaction. + fees: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount of fees that the paying customer will be charged as part of the transaction. + payer: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0' + description: 'Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction.' + payee: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payee/allOf/0' + description: Information about the Payee in the proposed financial transaction. + transactionType: + title: TransactionType + type: object + description: Data model for the complex type TransactionType. + properties: + scenario: + title: TransactionScenario + type: string + enum: + - DEPOSIT + - WITHDRAWAL + - TRANSFER + - PAYMENT + - REFUND + description: |- + Below are the allowed values for the enumeration. + - DEPOSIT - Used for performing a Cash-In (deposit) transaction. In a normal scenario, electronic funds are transferred from a Business account to a Consumer account, and physical cash is given from the Consumer to the Business User. + - WITHDRAWAL - Used for performing a Cash-Out (withdrawal) transaction. In a normal scenario, electronic funds are transferred from a Consumer’s account to a Business account, and physical cash is given from the Business User to the Consumer. + - TRANSFER - Used for performing a P2P (Peer to Peer, or Consumer to Consumer) transaction. + - PAYMENT - Usually used for performing a transaction from a Consumer to a Merchant or Organization, but could also be for a B2B (Business to Business) payment. The transaction could be online for a purchase in an Internet store, in a physical store where both the Consumer and Business User are present, a bill payment, a donation, and so on. + - REFUND - Used for performing a refund of transaction. + example: DEPOSIT + subScenario: + title: TransactionSubScenario + type: string + pattern: '^[A-Z_]{1,32}$' + description: 'Possible sub-scenario, defined locally within the scheme (UndefinedEnum Type).' + example: LOCALLY_DEFINED_SUBSCENARIO + initiator: + title: TransactionInitiator + type: string + enum: + - PAYER + - PAYEE + description: |- + Below are the allowed values for the enumeration. + - PAYER - Sender of funds is initiating the transaction. The account to send from is either owned by the Payer or is connected to the Payer in some way. + - PAYEE - Recipient of the funds is initiating the transaction by sending a transaction request. The Payer must approve the transaction, either automatically by a pre-generated OTP or by pre-approval of the Payee, or by manually approving in his or her own Device. + example: PAYEE + initiatorType: + title: TransactionInitiatorType + type: string + enum: + - CONSUMER + - AGENT + - BUSINESS + - DEVICE + description: |- + Below are the allowed values for the enumeration. + - CONSUMER - Consumer is the initiator of the transaction. + - AGENT - Agent is the initiator of the transaction. + - BUSINESS - Business is the initiator of the transaction. + - DEVICE - Device is the initiator of the transaction. + example: CONSUMER + refundInfo: + title: Refund + type: object + description: Data model for the complex type Refund. + properties: + originalTransactionId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + refundReason: + title: RefundReason + type: string + minLength: 1 + maxLength: 128 + description: Reason for the refund. + example: Free text indicating reason for the refund. + required: + - originalTransactionId + balanceOfPayments: + title: BalanceOfPayments + type: string + pattern: '^[1-9]\d{2}$' + description: '(BopCode) The API data type [BopCode](https://www.imf.org/external/np/sta/bopcode/) is a JSON String of 3 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed.' + example: '123' + required: + - scenario + - initiator + - initiatorType + expiration: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/completedTimestamp' + description: 'The time by which the transfer must be completed, set by the payee DFSP.' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - authorizationRequestId + - transactionRequestId + - challenge + - transferAmount + - payeeReceiveAmount + - fees + - payer + - payee + - transactionType + - expiration + additionalProperties: false + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/thirdpartyRequests/authorizations/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + description: | + The HTTP request **GET /thirdpartyRequests/authorizations/**_{ID}_ is used to get information relating + to a previously issued authorization request. The *{ID}* in the request should match the + `authorizationRequestId` which was given when the authorization request was created. + operationId: GetThirdpartyRequestsAuthorizationsById + summary: GetThirdpartyRequestsAuthorizationsById + tags: + - authorizations + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: | + After receiving the **POST /thirdpartyRequests/authorizations**, the PISP will present the details of the + transaction to their user, and request that the client sign the `challenge` field using the credential + they previously registered. + + The signed challenge will be sent back by the PISP in **PUT /thirdpartyRequests/authorizations/**_{ID}_: + operationId: PutThirdpartyRequestsAuthorizationsById + summary: PutThirdpartyRequestsAuthorizationsById + tags: + - authorizations + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Signed authorization object + required: true + content: + application/json: + schema: + oneOf: + - title: ThirdpartyRequestsAuthorizationsIDPutResponseRejected + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + title: AuthorizationResponseTypeRejected + description: | + The customer rejected the terms of the transfer. + type: string + enum: + - REJECTED + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - responseType + - title: ThirdpartyRequestsAuthorizationsIDPutResponseFIDO + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + title: AuthorizationResponseType + description: | + The customer accepted the terms of the transfer + type: string + enum: + - ACCEPTED + signedPayload: + title: SignedPayloadFIDO + type: object + properties: + signedPayloadType: + title: SignedPayloadTypeFIDO + type: string + enum: + - FIDO + description: Describes a challenge that has been signed with FIDO Attestation flows + fidoSignedPayload: + title: FIDOPublicKeyCredentialAssertion + type: object + description: | + A data model representing a FIDO Assertion result. + Derived from PublicKeyCredential Interface in WebAuthN. + + The PublicKeyCredential interface represents the below fields with a Type of + Javascript ArrayBuffer. + For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#32128-fidopublickeycredentialassertion + properties: + id: + type: string + description: | + credential id: identifier of pair of keys, base64 encoded + https://w3c.github.io/webauthn/#ref-for-dom-credential-id + minLength: 59 + maxLength: 118 + rawId: + type: string + description: | + raw credential id: identifier of pair of keys, base64 encoded. + minLength: 59 + maxLength: 118 + response: + type: object + description: | + AuthenticatorAssertionResponse + properties: + authenticatorData: + type: string + description: | + Authenticator data object. + minLength: 49 + maxLength: 256 + clientDataJSON: + type: string + description: | + JSON string with client data. + minLength: 121 + maxLength: 512 + signature: + type: string + description: | + The signature generated by the private key associated with this credential. + minLength: 59 + maxLength: 256 + userHandle: + type: string + description: | + This field is optionally provided by the authenticator, and + represents the user.id that was supplied during registration. + minLength: 1 + maxLength: 88 + required: + - authenticatorData + - clientDataJSON + - signature + additionalProperties: false + type: + type: string + description: 'response type, we need only the type of public-key' + enum: + - public-key + required: + - id + - rawId + - response + - type + additionalProperties: false + required: + - signedPayloadType + - fidoSignedPayload + additionalProperties: false + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - responseType + - signedPayload + additionalProperties: false + - title: ThirdpartyRequestsAuthorizationsIDPutResponseGeneric + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + $ref: '#/paths/~1thirdpartyRequests~1authorizations~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/1/properties/responseType' + signedPayload: + title: SignedPayloadGeneric + type: object + properties: + signedPayloadType: + title: SignedPayloadTypeGeneric + type: string + enum: + - GENERIC + description: Describes a challenge that has been signed with a private key + genericSignedPayload: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - signedPayloadType + - genericSignedPayload + additionalProperties: false + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - responseType + - signedPayload + additionalProperties: false + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/thirdpartyRequests/authorizations/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + tags: + - thirdpartyRequests + - sampled + operationId: PutThirdpartyRequestsAuthorizationsByIdAndError + summary: PutThirdpartyRequestsAuthorizationsByIdAndError + description: | + The HTTP request `PUT /thirdpartyRequests/authorizations/{ID}/error` is used by the DFSP or PISP to inform + the other party that something went wrong with a Thirdparty Transaction Authorization Request. + + The PISP may use this to tell the DFSP that the Thirdparty Transaction Authorization Request is invalid or doesn't + match a `transactionRequestId`. + + The DFSP may use this to tell the PISP that the signed challenge returned in `PUT /thirdpartyRequest/authorizations/{ID}` + was invalid. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + /thirdpartyRequests/transactions: + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + post: + operationId: ThirdpartyRequestsTransactionsPost + summary: ThirdpartyRequestsTransactionsPost + description: The HTTP request POST `/thirdpartyRequests/transactions` is used by a PISP to initiate a 3rd party Transaction request with a DFSP + tags: + - thirdpartyRequests + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Transaction request to be created. + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsPostRequest + type: object + description: |- + Used by: PISP + The HTTP request POST /thirdpartyRequests/transactions is used to request the creation of a transaction request on the server for the transfer described in the request. + Callback and data model information for POST /thirdpartyRequests/transactions: + Callback - PUT /thirdpartyRequests/transactions/{ID} Error Callback - PUT /thirdpartyRequests/transactions/{ID}/error Data Model - See link below + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31712-post-thirdpartyrequeststransactions + properties: + transactionRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and the Payer DFSP for the transaction request object. The ID should be reused for resends of the same transaction request. A new ID should be generated for each new transaction request. + payee: + allOf: + - title: Party + type: object + description: Data model for the complex type Party. + properties: + partyIdInfo: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0' + merchantClassificationCode: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/party/properties/merchantClassificationCode' + name: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/party/properties/name' + personalInfo: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/party/properties/personalInfo' + required: + - partyIdInfo + description: Information about the Payee in the proposed financial transaction. + payer: + allOf: + - title: PartyIdInfo + type: object + description: Data model for the complex type PartyIdInfo. + properties: + partyIdType: + title: PartyIdType + type: string + enum: + - MSISDN + - EMAIL + - PERSONAL_ID + - BUSINESS + - DEVICE + - ACCOUNT_ID + - IBAN + - ALIAS + - CONSENT + - THIRD_PARTY_LINK + description: | + Below are the allowed values for the enumeration. + - MSISDN - An MSISDN (Mobile Station International Subscriber Directory + Number, that is, the phone number) is used as reference to a participant. + The MSISDN identifier should be in international format according to the + [ITU-T E.164 standard](https://www.itu.int/rec/T-REC-E.164/en). + Optionally, the MSISDN may be prefixed by a single plus sign, indicating the + international prefix. + - EMAIL - An email is used as reference to a + participant. The format of the email should be according to the informational + [RFC 3696](https://tools.ietf.org/html/rfc3696). + - PERSONAL_ID - A personal identifier is used as reference to a participant. + Examples of personal identification are passport number, birth certificate + number, and national registration number. The identifier number is added in + the PartyIdentifier element. The personal identifier type is added in the + PartySubIdOrType element. + - BUSINESS - A specific Business (for example, an organization or a company) + is used as reference to a participant. The BUSINESS identifier can be in any + format. To make a transaction connected to a specific username or bill number + in a Business, the PartySubIdOrType element should be used. + - DEVICE - A specific device (for example, a POS or ATM) ID connected to a + specific business or organization is used as reference to a Party. + For referencing a specific device under a specific business or organization, + use the PartySubIdOrType element. + - ACCOUNT_ID - A bank account number or FSP account ID should be used as + reference to a participant. The ACCOUNT_ID identifier can be in any format, + as formats can greatly differ depending on country and FSP. + - IBAN - A bank account number or FSP account ID is used as reference to a + participant. The IBAN identifier can consist of up to 34 alphanumeric + characters and should be entered without whitespace. + - ALIAS An alias is used as reference to a participant. The alias should be + created in the FSP as an alternative reference to an account owner. + Another example of an alias is a username in the FSP system. + The ALIAS identifier can be in any format. It is also possible to use the + PartySubIdOrType element for identifying an account under an Alias defined + by the PartyIdentifier. + - CONSENT - A Consent represents an agreement between a PISP, a Customer and + a DFSP which allows the PISP permission to perform actions on behalf of the + customer. A Consent has an authoritative source: either the DFSP who issued + the Consent, or an Auth Service which administers the Consent. + - THIRD_PARTY_LINK - A Third Party Link represents an agreement between a PISP, + a DFSP, and a specific Customer's account at the DFSP. The content of the link + is created by the DFSP at the time when it gives permission to the PISP for + specific access to a given account. + example: PERSONAL_ID + partyIdentifier: + title: PartyIdentifier + type: string + minLength: 1 + maxLength: 128 + description: Identifier of the Party. + example: '16135551212' + partySubIdOrType: + title: PartySubIdOrType + type: string + minLength: 1 + maxLength: 128 + description: 'Either a sub-identifier of a PartyIdentifier, or a sub-type of the PartyIdType, normally a PersonalIdentifierType.' + fspId: + $ref: '#/paths/~1services~1%7BServiceType%7D/put/requestBody/content/application~1json/schema/properties/providers/items' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - partyIdType + - partyIdentifier + description: Information about the Payer in the proposed financial transaction. + amountType: + allOf: + - title: AmountType + type: string + enum: + - SEND + - RECEIVE + description: |- + Below are the allowed values for the enumeration AmountType. + - SEND - Amount the Payer would like to send, that is, the amount that should be withdrawn from the Payer account including any fees. + - RECEIVE - Amount the Payer would like the Payee to receive, that is, the amount that should be sent to the receiver exclusive of any fees. + example: RECEIVE + description: 'SEND for sendAmount, RECEIVE for receiveAmount.' + amount: + allOf: + - title: Money + type: object + description: Data model for the complex type Money. + properties: + currency: + title: Currency + description: 'The currency codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic codes are used as the standard naming representation for currencies.' + type: string + minLength: 3 + maxLength: 3 + enum: + - AED + - AFN + - ALL + - AMD + - ANG + - AOA + - ARS + - AUD + - AWG + - AZN + - BAM + - BBD + - BDT + - BGN + - BHD + - BIF + - BMD + - BND + - BOB + - BRL + - BSD + - BTN + - BWP + - BYN + - BZD + - CAD + - CDF + - CHF + - CLP + - CNY + - COP + - CRC + - CUC + - CUP + - CVE + - CZK + - DJF + - DKK + - DOP + - DZD + - EGP + - ERN + - ETB + - EUR + - FJD + - FKP + - GBP + - GEL + - GGP + - GHS + - GIP + - GMD + - GNF + - GTQ + - GYD + - HKD + - HNL + - HRK + - HTG + - HUF + - IDR + - ILS + - IMP + - INR + - IQD + - IRR + - ISK + - JEP + - JMD + - JOD + - JPY + - KES + - KGS + - KHR + - KMF + - KPW + - KRW + - KWD + - KYD + - KZT + - LAK + - LBP + - LKR + - LRD + - LSL + - LYD + - MAD + - MDL + - MGA + - MKD + - MMK + - MNT + - MOP + - MRO + - MUR + - MVR + - MWK + - MXN + - MYR + - MZN + - NAD + - NGN + - NIO + - NOK + - NPR + - NZD + - OMR + - PAB + - PEN + - PGK + - PHP + - PKR + - PLN + - PYG + - QAR + - RON + - RSD + - RUB + - RWF + - SAR + - SBD + - SCR + - SDG + - SEK + - SGD + - SHP + - SLL + - SOS + - SPL + - SRD + - STD + - SVC + - SYP + - SZL + - THB + - TJS + - TMT + - TND + - TOP + - TRY + - TTD + - TVD + - TWD + - TZS + - UAH + - UGX + - USD + - UYU + - UZS + - VEF + - VND + - VUV + - WST + - XAF + - XCD + - XDR + - XOF + - XPF + - XTS + - XXX + - YER + - ZAR + - ZMW + - ZWD + amount: + title: Amount + type: string + pattern: '^([0]|([1-9][0-9]{0,17}))([.][0-9]{0,3}[1-9])?$' + description: 'The API data type Amount is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons. This pattern does not allow any trailing zeroes at all, but allows an amount without a minor currency unit. It also only allows four digits in the minor currency unit; a negative value is not allowed. Using more than 18 digits in the major currency unit is not allowed.' + example: '123.45' + required: + - currency + - amount + description: Requested amount to be transferred from the Payer to Payee. + transactionType: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/transactionType' + description: Type of transaction. + note: + type: string + minLength: 1 + maxLength: 256 + description: A memo that will be attached to the transaction. + expiration: + type: string + description: | + Date and time until when the transaction request is valid. It can be set to get a quick failure in case the peer FSP takes too long to respond. + example: '2016-05-24T08:38:08.699-04:00' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - transactionRequestId + - payee + - payer + - amountType + - amount + - transactionType + - expiration + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/thirdpartyRequests/transactions/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + tags: + - thirdpartyRequests + - sampled + operationId: GetThirdpartyTransactionRequests + summary: GetThirdpartyTransactionRequests + description: | + The HTTP request `GET /thirdpartyRequests/transactions/{ID}` is used to request the + retrieval of a third party transaction request. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + tags: + - thirdpartyRequests + - sampled + operationId: UpdateThirdPartyTransactionRequests + summary: UpdateThirdPartyTransactionRequests + description: | + The HTTP request `PUT /thirdpartyRequests/transactions/{ID}` is used by the DFSP to inform the client about + the status of a previously requested thirdparty transaction request. + + Switch(Thirdparty API Adapter) -> PISP + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsIDPutResponse + type: object + description: |- + Used by: DFSP + After a PISP requests the creation of a Third Party Transaction request (POST /thirdpartyRequests/transactions) or the status of a previously created Third Party Transaction request (GET /thirdpartyRequests/transactions/{ID}), the DFSP will send this callback. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31721-put-thirdpartyrequeststransactionsid + properties: + transactionRequestState: + title: TransactionRequestState + type: string + enum: + - RECEIVED + - PENDING + - ACCEPTED + - REJECTED + description: |- + Below are the allowed values for the enumeration. + - RECEIVED - Payer FSP has received the transaction from the Payee FSP. + - PENDING - Payer FSP has sent the transaction request to the Payer. + - ACCEPTED - Payer has approved the transaction. + - REJECTED - Payer has rejected the transaction. + example: RECEIVED + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - transactionRequestState + example: + transactionRequestState: RECEIVED + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + patch: + operationId: NotifyThirdpartyTransactionRequests + summary: NotifyThirdpartyTransactionRequests + description: | + The HTTP request `PATCH /thirdpartyRequests/transactions/{ID}` is used to + notify a thirdparty of the outcome of a transaction request. + + Switch(Thirdparty API Adapter) -> PISP + tags: + - thirdpartyRequests + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsIDPatchResponse + type: object + description: |- + Used by: DFSP + The issuing PISP will expect a response to their request for a transfer which describes the finalized state of the requested transfer. + This response will be given by a PATCH call on the /thirdpartyRequests/transactions/{ID} resource. + The {ID} given in the query string should be the transactionRequestId which was originally used by the PISP to identify the transaction request. + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31612-post-thirdpartyrequestsauthorizations + properties: + completedTimestamp: + title: DateTime + type: string + pattern: '^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:(\.\d{3}))(?:Z|[+-][01]\d:[0-5]\d)$' + description: 'The API data type DateTime is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. The format is according to [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html), expressed in a combined date, time and time zone format. A more readable version of the format is yyyy-MM-ddTHH:mm:ss.SSS[-HH:MM]. Examples are "2016-05-24T08:38:08.699-04:00", "2016-05-24T08:38:08.699Z" (where Z indicates Zulu time zone, same as UTC).' + example: '2016-05-24T08:38:08.699-04:00' + transactionRequestState: + $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/transactionRequestState' + transactionState: + title: TransactionState + type: string + enum: + - RECEIVED + - PENDING + - COMPLETED + - REJECTED + description: |- + Below are the allowed values for the enumeration. + - RECEIVED - Payee FSP has received the transaction from the Payer FSP. + - PENDING - Payee FSP has validated the transaction. + - COMPLETED - Payee FSP has successfully performed the transaction. + - REJECTED - Payee FSP has failed to perform the transaction. + example: RECEIVED + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - transactionRequestState + - transactionState + example: + transactionRequestState: ACCEPTED + transactionState: COMMITTED + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/thirdpartyRequests/transactions/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + tags: + - thirdpartyRequests + - sampled + operationId: ThirdpartyTransactionRequestsError + summary: ThirdpartyTransactionRequestsError + description: | + If the server is unable to find the transaction request, or another processing error occurs, + the error callback `PUT /thirdpartyRequests/transactions/{ID}/error` is used. + The `{ID}` in the URI should contain the `transactionRequestId` that was used for the creation of + the thirdparty transaction request. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/parties/{Type}/{ID}': + parameters: + - name: Type + in: path + required: true + schema: + type: string + description: 'The type of the party identifier. For example, `MSISDN`, `PERSONAL_ID`.' + - name: ID + in: path + required: true + schema: + type: string + description: The identifier value. + - name: Content-Type + in: header + schema: + type: string + required: true + description: The `Content-Type` header indicates the specific version of the API used to send the payload body. + - name: Date + in: header + schema: + type: string + required: true + description: The `Date` header field indicates the date when the request was sent. + - name: X-Forwarded-For + in: header + schema: + type: string + required: false + description: |- + The `X-Forwarded-For` header field is an unofficially accepted standard used for informational purposes of the originating client IP address, as a request might pass multiple proxies, firewalls, and so on. Multiple `X-Forwarded-For` values should be expected and supported by implementers of the API. + + **Note:** An alternative to `X-Forwarded-For` is defined in [RFC 7239](https://tools.ietf.org/html/rfc7239). However, to this point RFC 7239 is less-used and supported than `X-Forwarded-For`. + - name: FSPIOP-Source + in: header + schema: + type: string + required: true + description: The `FSPIOP-Source` header field is a non-HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing and signature verification (see header field `FSPIOP-Signature`). + - name: FSPIOP-Destination + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-Destination` header field is a non-HTTP standard field used by the API for HTTP header based routing of requests and responses to the destination. The field must be set by the original sender of the request if the destination is known (valid for all services except GET /parties) so that any entities between the client and the server do not need to parse the payload for routing purposes. If the destination is not known (valid for service GET /parties), the field should be left empty.' + - name: FSPIOP-Encryption + in: header + schema: + type: string + required: false + description: The `FSPIOP-Encryption` header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request. + - name: FSPIOP-Signature + in: header + schema: + type: string + required: false + description: The `FSPIOP-Signature` header field is a non-HTTP standard field used by the API for applying an end-to-end request signature. + - name: FSPIOP-URI + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-URI` header field is a non-HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information, see [the API Signature document](https://github.com/mojaloop/docs/tree/master/Specification%20Document%20Set).' + - name: FSPIOP-HTTP-Method + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-HTTP-Method` header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information, see [the API Signature document](https://github.com/mojaloop/docs/tree/master/Specification%20Document%20Set).' + get: + description: 'The HTTP request `GET /parties/{Type}/{ID}` (or `GET /parties/{Type}/{ID}/{SubId}`) is used to look up information regarding the requested Party, defined by `{Type}`, `{ID}` and optionally `{SubId}` (for example, `GET /parties/MSISDN/123456789`, or `GET /parties/BUSINESS/shoecompany/employee1`).' + summary: Look up party information + tags: + - parties + operationId: PartiesByTypeAndID + parameters: + - name: Accept + in: header + required: true + schema: + type: string + description: The `Accept` header field indicates the version of the API the client would like the server to use. + responses: + '202': + description: Accepted + '400': + description: Bad Request + content: + application/json: + schema: + title: ErrorInformationResponse + type: object + description: Data model for the complex type object that contains an optional element ErrorInformation used along with 4xx and 5xx responses. + properties: + errorInformation: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema/properties/errorInformation' + headers: + Content-Length: + required: false + schema: + type: integer + description: |- + The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body. + + **Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes). + Content-Type: + schema: + type: string + required: true + description: The `Content-Type` header indicates the specific version of the API used to send the payload body. + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '405': + description: Method Not Allowed + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '406': + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '501': + description: Not Implemented + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '503': + description: Service Unavailable + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + put: + description: 'The callback `PUT /parties/{Type}/{ID}` (or `PUT /parties/{Type}/{ID}/{SubId}`) is used to inform the client of a successful result of the Party information lookup.' + summary: Return party information + tags: + - parties + operationId: PartiesByTypeAndID2 + parameters: + - name: Content-Length + in: header + required: false + schema: + type: integer + description: |- + The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body. + + **Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes). + requestBody: + description: Party information returned. + required: true + content: + application/json: + schema: + title: PartiesTypeIDPutResponse + type: object + description: 'The object sent in the PUT /parties/{Type}/{ID} callback.' + properties: + party: + title: Party + type: object + description: Data model for the complex type Party. + properties: + partyIdInfo: + title: PartyIdInfo + type: object + description: Data model for the complex type PartyIdInfo. An ExtensionList element has been added to this reqeust in version v1.1 + properties: + partyIdType: + title: PartyIdType + type: string + enum: + - MSISDN + - EMAIL + - PERSONAL_ID + - BUSINESS + - DEVICE + - ACCOUNT_ID + - IBAN + - ALIAS + description: |- + Below are the allowed values for the enumeration. + - MSISDN - An MSISDN (Mobile Station International Subscriber Directory Number, that is, the phone number) is used as reference to a participant. The MSISDN identifier should be in international format according to the [ITU-T E.164 standard](https://www.itu.int/rec/T-REC-E.164/en). Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix. + - EMAIL - An email is used as reference to a participant. The format of the email should be according to the informational [RFC 3696](https://tools.ietf.org/html/rfc3696). + - PERSONAL_ID - A personal identifier is used as reference to a participant. Examples of personal identification are passport number, birth certificate number, and national registration number. The identifier number is added in the PartyIdentifier element. The personal identifier type is added in the PartySubIdOrType element. + - BUSINESS - A specific Business (for example, an organization or a company) is used as reference to a participant. The BUSINESS identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the PartySubIdOrType element should be used. + - DEVICE - A specific device (for example, a POS or ATM) ID connected to a specific business or organization is used as reference to a Party. For referencing a specific device under a specific business or organization, use the PartySubIdOrType element. + - ACCOUNT_ID - A bank account number or FSP account ID should be used as reference to a participant. The ACCOUNT_ID identifier can be in any format, as formats can greatly differ depending on country and FSP. + - IBAN - A bank account number or FSP account ID is used as reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without whitespace. + - ALIAS An alias is used as reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias is a username in the FSP system. The ALIAS identifier can be in any format. It is also possible to use the PartySubIdOrType element for identifying an account under an Alias defined by the PartyIdentifier. + partyIdentifier: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0/properties/partyIdentifier' + partySubIdOrType: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0/properties/partySubIdOrType' + fspId: + $ref: '#/paths/~1services~1%7BServiceType%7D/put/requestBody/content/application~1json/schema/properties/providers/items' + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - partyIdType + - partyIdentifier + merchantClassificationCode: + title: MerchantClassificationCode + type: string + pattern: '^[\d]{1,4}$' + description: 'A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, etc.' + name: + title: PartyName + type: string + minLength: 1 + maxLength: 128 + description: Name of the Party. Could be a real name or a nickname. + personalInfo: + title: PartyPersonalInfo + type: object + description: Data model for the complex type PartyPersonalInfo. + properties: + complexName: + title: PartyComplexName + type: object + description: Data model for the complex type PartyComplexName. + properties: + firstName: + title: FirstName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: First name of the Party (Name Type). + example: Henrik + middleName: + title: MiddleName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: Middle name of the Party (Name Type). + example: Johannes + lastName: + title: LastName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: Last name of the Party (Name Type). + example: Karlsson + dateOfBirth: + title: DateofBirth (type Date) + type: string + pattern: '^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$' + description: Date of Birth of the Party. + example: '1966-06-16' + required: + - partyIdInfo + required: + - party + responses: + '200': + description: OK + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/parties/{Type}/{ID}/error': + put: + description: 'If the server is unable to find Party information of the provided identity, or another processing error occurred, the error callback `PUT /parties/{Type}/{ID}/error` (or `PUT /parties/{Type}/{ID}/{SubI}/error`) is used.' + summary: Return party information error + tags: + - parties + operationId: PartiesErrorByTypeAndID + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/parties/{Type}/{ID}/{SubId}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - name: SubId + in: path + required: true + schema: + type: string + description: 'A sub-identifier of the party identifier, or a sub-type of the party identifier''s type. For example, `PASSPORT`, `DRIVING_LICENSE`.' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + description: 'The HTTP request `GET /parties/{Type}/{ID}` (or `GET /parties/{Type}/{ID}/{SubId}`) is used to look up information regarding the requested Party, defined by `{Type}`, `{ID}` and optionally `{SubId}` (for example, `GET /parties/MSISDN/123456789`, or `GET /parties/BUSINESS/shoecompany/employee1`).' + summary: Look up party information + tags: + - parties + operationId: PartiesSubIdByTypeAndID + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: 'The callback `PUT /parties/{Type}/{ID}` (or `PUT /parties/{Type}/{ID}/{SubId}`) is used to inform the client of a successful result of the Party information lookup.' + summary: Return party information + tags: + - parties + operationId: PartiesSubIdByTypeAndIDPut + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Party information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/parties/{Type}/{ID}/{SubId}/error': + put: + description: 'If the server is unable to find Party information of the provided identity, or another processing error occurred, the error callback `PUT /parties/{Type}/{ID}/error` (or `PUT /parties/{Type}/{ID}/{SubId}/error`) is used.' + summary: Return party information error + tags: + - parties + operationId: PartiesSubIdErrorByTypeAndID + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D~1%7BSubId%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/services/{ServiceType}': + parameters: + - name: ServiceType + in: path + required: true + schema: + type: string + description: 'The type of the service identifier. For example, `THIRD_PARTY_DFSP`' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + operationId: GetServicesByServiceType + summary: GetServicesByServiceType + description: | + The HTTP request `GET /services/{ServiceType}` is used to retrieve the list of participants + that support a specified service. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + tags: + - services + - sampled + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: | + The HTTP request `PUT /services/{ServiceType}` is used to return list of participants + that support a specified service. + operationId: PutServicesByServiceType + summary: PutServicesByServiceType + tags: + - services + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: ServicesServiceTypePutResponse + type: object + description: |- + Used by: Switch + The callback PUT /services/{ServiceType} is used to inform the client of a successful result of the service information lookup. + Callback and data model information for GET /services/{ServiceType}: + Callback - PUT /services/{ServiceType} Error Callback - PUT /services/{ServiceType}/error Data Model - Empty body + https://github.com/mojaloop/documentation/blob/master/website/versioned_docs/v1.0.1/api/thirdparty/data-models.md#31531-put-servicesservicetype + properties: + providers: + type: array + minLength: 0 + maxLength: 256 + items: + title: FspId + type: string + minLength: 1 + maxLength: 32 + description: FSP identifier. + extensionList: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - providers + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/services/{ServiceType}/error': + parameters: + - $ref: '#/paths/~1services~1%7BServiceType%7D/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + description: | + The HTTP request `PUT /services/{ServiceType}/error` is used to return error information + operationId: PutServicesByServiceTypeAndError + summary: PutServicesByServiceTypeAndError + tags: + - services + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/transaction-patterns-linking.md b/website/versioned_docs/v1.0.1/api/thirdparty/transaction-patterns-linking.md new file mode 100644 index 000000000..7e317db8a --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/transaction-patterns-linking.md @@ -0,0 +1,412 @@ + +# Transaction Patterns - Linking + +Mojaloop Third Party API + +### Table Of Contents + +1. [Preface](#Preface) + 1.1 [Conventions Used in This Document](#ConventionsUsedinThisDocument) + 1.2 [Document Version Information](#DocumentVersionInformation) + 1.3 [References](#References) +2. [Introduction](#Introduction) + 2.1 [Third Party API Specification](#ThirdPartyAPISpecification) +3. [Linking](#Linking) + 3.1 [Pre-linking](#Pre-linking) + 3.2 [Discovery](#Discovery) + 3.3 [Request consent](#Requestconsent) + 3.4 [Authentication](#Authentication) + 3.5 [Grant consent](#Grantconsent) + 3.6 [Credential registration](#Credentialregistration) +4. [Unlinking](#Unlinking) + 4.1 [Unlinking without a Switch Hosted Auth Service](#UnlinkingwithoutaSwitchHostedAuthService) + 4.2 [Unlinking with a Switch Hosted Auth Service](#UnlinkingwithaSwitchHostedAuthService) +5. [Error Scenarios](#ErrorScenarios) + 5.1 [Discovery](#Discovery-1) + 5.2 [Bad consentRequests](#BadconsentRequests) + 5.3 [Authentication](#Authentication-1) + 5.4 [Grant consent](#Grantconsent-1) + +# 1. Preface + +This section contains information about how to use this document. + +## 1.1. Conventions Used in This Document + +The following conventions are used in this document to identify the +specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics with in angle brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature and API Encryption_ should be used instead.| + +## 1.2. Document Version Information + +| Version | Date | Change Description | +| --- | --- | --- | +| **1.0** | 2021-10-03 | Initial Version + +## 1.3. References + +The following references are used in this specification: + +| Reference | Description | Version | Link | +| --- | --- | --- | --- | +| Ref. 1 | Open API for FSP Interoperability | `1.1` | [API Definition v1.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md)| + + +# 2. Introduction + +This document introduces the transaction patterns supported by the Third Party API relating +to the establishment of a relationship between a User, a DFSP and a PISP. + +The API design and architectural style of this API are based on [Section 3](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#3-api-definition) of Ref 1. above. + +## 2.1 Third Party API Specification + +The Mojaloop Third Party API Specification includes the following documents: + +- [Data Models](./data-models.md) +- [Transaction Patterns - Linking](./transaction-patterns-linking.md) +- [Transaction Patterns - Transfer](./transaction-patterns-transfer.md) +- [Third Party Open API Definition - DFSP](./thirdparty-dfsp-v1.0.yaml) +- [Third Party Open API Definition - PISP](./thirdparty-dfsp-v1.0.yaml) + + +# 3. Linking + +The goal of the linking process is to explain how users establish trust between +all three interested parties: + +1. User +2. DFSP where User has an account +3. PISP that User wants to rely on to initiate payments + +Linking is broken down into several separate phases: + +1. **Pre-linking** + In this phase, a PISP asks what DFSPs are available to link with. +2. **Request consent** + In this phase, a PISP attempts to establish trust between the 3 parties. +3. **Authentication** + In this phase, a User proves their identity to their DFSP. +4. **Grant consent** + In this phase, a PISP proves to the DFSP that the User and PISP have + established trust and, as a result, the DFSP confirms that mutual trust + exists between the 3 parties. +5. **Credential registration** + In this phase, a User establishes the credential they'll use to consent to + future transfers from the DFSP and initiated by the PISP. + +## 3.1 Pre-linking + +In this phase, a PISP Server needs to know what DFSPs are available to link +with. This is *unlikely* to be done on-demand (e.g., when a User clicks "link" +in the PISP mobile App), and far more likely to be done periodically and cached +by the PISP Server. The reason for this is simply that new DFSPs don't typically +join the Mojaloop network all that frequently, so calling this multiple times on +the same day would likely yield the same results. We recommend that the PISP +calls this request once per day to keep the list of available DFSPs up to date. + +The end-goal of this phase is for the PISP Server to have a final list of DFSPs +available and any relevant metadata about those DFPSs that are necessary to +begin the linking process. + +The PISP can display this list of DFSPs to their user, and the user can select +which DFSP they hold an account with for linking. + +![Pre-linking](./assets/diagrams/linking/0-pre-linking.svg) + +## 3.2 Discovery + +In this phase, we ask the user to select the type and value of identifier they use +with the DFSP they intend to link with. This could be a username, MSISDN (phone number), +or email address. + +The result of this phase is a list of potential accounts available for linking. +The user will then choose one or more of these source accounts and the PISP will +provide these to the DFSP when requesting consent. + +The DFSP MAY send back an `accountNickname` to the PISP in the list of accounts. This list +will be displayed to the user in the PISP application for them to select which accounts +they wish to link. A DFSP could obfuscate some of the nickname depending on their requirements +for displaying account information without authorizing the user. + +**NOTE:** When using the Web authentication channel, it's possible that the +choices made (i.e., the accounts to link with) will be overridden by the user in +a web view. In other words, the user may decide during the Authentication phase +that they actually would like to link a different account than those chosen at +the very beginning. This is perfectly acceptable and should be expected from +time to time. + +![Discovery](./assets/diagrams/linking/1-discovery.svg) + +## 3.3 Request consent + +In this phase, a PISP is asking a specific DFSP to start the process of +establishing consent between three parties: + +1. The PISP +2. The specified DFSP +3. A User that is presumed to be a customer of the DFSP in (2) + +The PISPs request to establish consent must include a few important pieces of +information: + +- The authentication channels that are acceptable to the User +- The scopes required as part of the consent (in this case, almost always just + the ability to view a balance of a specific account and send funds from an + account). + +Some information depends on the authentication channel used (either Web or OTP). +Specifically, if the web authentication channel is used, the following extra +information is required: + +- A callback URI of where a user can be redirected with any extra information. + +The end result of this phase depends on the authentication channel used: + +### 3.3.1 Web + +In the web authentication channel, the result is the PISP being instructed on +a specific URL where this supposed user should be redirected. This URL should be +a place where the user can prove their identity (e.g., by logging in). + +![Request consent](./assets/diagrams/linking/2-request-consent-web.svg) + +### 3.3.2 OTP / SMS + +In the OTP authentication channel, the DFSP sends an 'out of bound' OTP message +to their user (e.g. over SMS or Email). The PISP prompts the user for this OTP +message, and includes it in the `authToken` field in the **PATCH /consentRequests/**_{ID}_ +callback. + +![Request consent](./assets/diagrams/linking/2-request-consent-otp.svg) + +## 3.4 Authentication + +In the authentication phase, the user is expected to prove their identity to the +DFSP. Once this is done, the DFSP will provide the User with some sort of secret +(e.g., an OTP or access token). This secret will then be passed along to the +PISP so that the PISP can demonstrate a chain of trust: + +- The DFSP trusts the User +- The DFSP gives the User a secret +- The User trusts the PISP +- The User gives the PISP the secret that came from the DFSP +- The PISP gives the secret to the DFSP +- The DFSP verified that the secret is correct + +This chain results in the conclusion: The DFSP can trust the PISP is acting on +behalf of the User, and mutual trust exists between all three parties. + +The process of establishing this chain of trust depends on the authentication +channel being used: + +### 3.4.1 Web + +In the web authentication channel, the PISP uses the `authUri` field from +the **PUT /consentRequests/**_{ID}_ callback to redirect the user to the DFSP's +website where they can prove their identity (likely by a typical username and +password style login). + + +**Note:** Keep in mind that at this stage, the User may update their choices of +which accounts to link with. The result of this will be seen later on when +during the Grant consent phase, where the DFSP will provide the correct values +to the PISP in the `scopes` field. + +![Authentication (Web)](./assets/diagrams/linking/3-authentication-web.svg) + + +### 3.4.2 OTP + +When using the OTP authentication channel, the DFSP will send the User some sort +of one-time password over a pre-established channel (such as SMS). The PISP +should prompt the user for this one-time password and then provide it back +to the DFSP using the API call **PATCH /consentRequests/**_{ID}_. + +![Authentication (OTP)](./assets/diagrams/linking/3-authentication-otp.svg) +## 3.5 Grant consent + +Now that mutual trust has been established between all three parties, the DFSP +is able to create a record of that fact by creating a new Consent resource. +This resource will store all the relevant information about the relationship +between the three parties, and will eventually contain additional information +for how the User can prove that it consents to each individual transfer in the +future. + +This phase consists exclusively of the DFSP requesting that a new consent be +created. + +![Grant consent](./assets/diagrams/linking/4-grant-consent.svg) + + +## 3.6 Credential registration + +Once the consent resource has been created, the PISP will attempt to establish +with the DFSP the credential that should be used to verify that a user has +given consent for each transfer in the future. + +This will be done by storing a FIDO credential (e.g., a public key) on the Auth +service inside the consent resource. When future transfers are proposed, we will +require that those transfers be digitally signed by the FIDO credential (in this +case, the private key) in order to be considered valid. + +This credential registration is composed of three phases: (1) deriving the +challenge, (2) registering the credential, and (3) finalizing the consent. + +### 3.6.1 Deriving the challenge + +The PISP must derive the challenge to be used as an input to the FIDO Key +Registration step. This challenge must not be guessable ahead of time by +the PISP. + + +1. _Let `consentId` be the value of the `body.consentId` in the **POST /consents** request_ +2. _Let `scopes` be the value of `body.scopes` in the **POST /consents** request_ + +3. The PISP must build the JSON object `rawChallenge` +``` +{ + "consentId": , + "scopes": +} +``` + +4. Next, the PISP must convert this json object to a string representation using a [RFC-8785 Canonical JSON format](https://tools.ietf.org/html/rfc8785) + +5. Finally, the PISP must calculate a SHA-256 hash of the canonicalized JSON string. +i.e. `SHA256(CJSON(rawChallenge))` + +The output of this algorithm, `challenge` will be used as the challenge for the [FIDO registration flow](https://webauthn.guide/#registration) + + +### 3.6.2 Registering the credential + +Once the PISP has derived the challenge, the PISP will generate a new +credential on the device, digitally signing the challenge, and provide additional +information about the credential on the Consent resource: + +1. The `PublicKeyCredential` object - which contains the key's Id, and an [AuthenticatorAttestationResponse](https://w3c.github.io/webauthn/#iface-authenticatorattestationresponse) which contains the public key +2. A `credentialType` field set to `FIDO` +3. A `status` field set to `PENDING` + +> **Note:** Generic `Credential` objects +> While we are focused on FIDO first, we don't want to exclude PISPs who want +> to offer services to users over other channels, eg. USSD or SMS, for this +> reason, the API also supports a `GENERIC` Credential type, i.e.: +>``` +> CredentialTypeGeneric { +> credentialType: 'GENERIC' +> status: 'PENDING', +> payload: { +> publicKey: base64(...), +> signature: base64(...), +> } +> } +>``` + +The DFSP receives the **PUT /consents/**_{ID}_ call from the PISP, and optionally +validates the Credential object included in the request body. The DFSP then +asks the Auth-Service to create the `Consent` object, and validate the Credential. + +If the DFSP receives a **PUT /consents/**_{ID}_ callback from the Auth-Service, with a +`credential.status` of `VERIFIED`, it knows that the credential is valid according +to the Auth Service. + +Otherwise, if it receives a **PUT /consents/**_{ID}_**/error** callback, it knows that something +went wrong with registering the Consent and associated credential, and can inform +the PISP accordingly. + + +The Auth service is then responsible for calling **POST /participants/CONSENTS/**_{ID}_. +This call will associate the `consentId` with the auth-service's `participantId` and +allows us to look up the Auth service given a `consentId` at a later date. + +![Credential registration: Register](./assets/diagrams/linking/5a-credential-registration.svg) + + +### 3.6.3 Finalizing the Consent + +Once the DFSP is satisfied that the credential is valid, it calls +**POST /participants/THIRD_PARTY_LINK/**_{ID}_ for each account in the +`Consent.scopes` list. This entry is a representation of the account +link between the PISP and DFSP, which the PISP can use to specify +the _source of funds_ for the transaction request. + +Finally, the DFSP calls **PUT /consent/**_{ID}_ with the finalized Consent +object it received from the Auth Service. + + +![Credential registration: Finalize](./assets/diagrams/linking/5b-finalize_consent.svg) + + +# 4. Unlinking + +At some point in the future, it's possible that a User, PISP, or DFSP may decide +that the relationship of trust previously established should no longer exist. +For example, a very common scenario might be a user losing their mobile device +and using an interface from their DFSP to remove the link between the lost +device, the PISP, and the DFSP. + +To make this work, we simply need to provide a way for a member on the network +to remove the Consent resource and notify the other parties about the removal. + + +There are 2 scenarios we need to cater for with a **DELETE /consents/**_{ID}_ request: +1. A DFSP-hosted Auth Service, where no details about the Consent are stored in the Switch, and +2. A Switch hosted Auth Service, where the Switch hosted auth service is considered the Authoritative source on the `Consent` object + + +## 4.1 Unlinking without a Switch Hosted Auth Service +In this case, the switch passes on the **DELETE /consents/22222222-0000-0000-0000-000000000000** request to the DFSP in the `FSPIOP-Destination` header. + +![Unlinking-DFSP-Hosted](./assets/diagrams/linking/6a-unlinking-dfsp-hosted.svg) + +In the case where Unlinking is requested from the DFSP's side, the DFSP can +simply call **PATCH /consents/22222222-0000-0000-0000-000000000000** to inform the PISP of an update to the +`Consent` object. + +## 4.2 Unlinking with a Switch Hosted Auth Service + +In this instance, the PISP still addresses it's **DELETE /consents/22222222-0000-0000-0000-000000000000** call to the +DFSP in the `FSPIOP-Destination` header. + +Internally, the switch will lookup the Authoritative source of the `Consent` object, +using the ALS Call, **GET /participants/CONSENT/**_{ID}_. If it is determined that there +is a Switch hosted Auth Service which 'owns' this `Consent`, the HTTP call **DELETE /consents/**_{ID}_ +will be redirected to the Auth Service. + +![Unlinking-Switch-Hosted](./assets/diagrams/linking/6b-unlinking-hub-hosted.svg) + +# 5.Error Scenarios + +## 5.1 Discovery + +When the DFSP is unable to find a user for the identifier in **GET /accounts/**_{ID}_, +the DFSP responds with error code `6205` in **PUT /accounts/**_{ID}_**/error**. + +![Accounts error](./assets/diagrams/linking/error_scenarios/1-discovery-error.svg) + +## 5.2 ConsentRequest Errors +When the DFSP receives the **POST /consentRequests** request from the PISP, the following processing errors +could occur: + +1. DFSP does not support the specified scopes: `6101`. For example, the `userId` specified does not match the specified accounts, or the `scope.actions` field contains permissions that this DFSP does not support. +2. The PISP sent a bad callbackUri: `6204`. For example, the scheme of the callbackUri could be http, which +the DFSP may choose to not trust. +3. Any other checks or validation of the consentRequests on the DFSP's side fail: `6104`. For example, the user's account may be inactive or suspended. + +In this case, the DFSP must inform the PISP of the failure by sending a **PUT /consentRequests/**_{ID}_**/error** callback to the PISP. + +![consentRequests error](./assets/diagrams/linking/error_scenarios/2-request-consent-error.svg) + +## 5.3 Authentication + +When a PISP sends a **PATCH /consentRequests/**_{ID}_ to the DFSP, the `authToken` may be expired or invalid: + +![Authentication Invalid OTP](./assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.svg) diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/transaction-patterns-transfer.md b/website/versioned_docs/v1.0.1/api/thirdparty/transaction-patterns-transfer.md new file mode 100644 index 000000000..2b46f3c01 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/transaction-patterns-transfer.md @@ -0,0 +1,380 @@ +# Transaction Patterns - Transfer + +Mojaloop Third Party API + +### Table Of Contents + +1. [Preface](#Preface) + 1.1 [Conventions Used in This Document](#ConventionsUsedinThisDocument) + 1.2 [Document Version Information](#DocumentVersionInformation) + 1.3 [References](#References) +2. [Introduction](#Introduction) + 2.1 [Third Party API Specification](#ThirdPartyAPISpecification) +3. [Transfers](#Transfers) + 3.1 [Discovery](#Discovery) + 3.2 [Agreement](#Agreement) + 3.3 [Transfer](#Transfer) +4. [Request TransactionRequest Status](#RequestTransactionRequestStatus) +5. [Error Conditions](#ErrorConditions) + 5.1 [Bad Payee Lookup](#badpayeelookup) + 5.2 [Bad Thirdparty Transaction Request](#badtptr) + 5.3 [Downstream FSPIOP-API Failure](#downstreamapifailure) + 5.4 [Invalid Signed Challenge](#invalidsignedchallenge) + 5.5 [Thirdparty Transaction Request Timeout](#thirdpartytransactionrequesttimeout) +6. [Appendix](#Appendix) + 6.1 [Deriving the Challenge](#DerivingtheChallenge) + +# 1. Preface + +This section contains information about how to use this document. + +## 1.1. Conventions Used in This Document + +The following conventions are used in this document to identify the +specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics with in angle brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature and API Encryption_ should be used instead.| + +## 1.2. Document Version Information + +| Version | Date | Change Description | +| --- | --- | --- | +| **1.0** | 2021-10-03 | Initial Version + +## 1.3. References + +The following references are used in this specification: + +| Reference | Description | Version | Link | +| --- | --- | --- | --- | +| Ref. 1 | Open API for FSP Interoperability | `1.1` | [API Definition v1.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md)| + + +# 2. Introduction + +This document introduces the transaction patterns supported by the Third Party API relating +to the initiation of a Transaction Request from a PISP. + +The API design and architectural style of this API are based on [Section 3](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#3-api-definition) of Ref 1. above. + +## 2.1 Third Party API Specification + +The Mojaloop Third Party API Specification includes the following documents: + +- [Data Models](./data-models.md) +- [Transaction Patterns - Linking](./transaction-patterns-linking.md) +- [Transaction Patterns - Transfer](./transaction-patterns-transfer.md) +- [Third Party Open API Definition - DFSP](./thirdparty-dfsp-v1.0.yaml) +- [Third Party Open API Definition - PISP](./thirdparty-dfsp-v1.0.yaml) + + +# 3. Transfers + +Transfers is broken down into the separate sections: +1. **Discovery**: PISP looks up the Payee Party to send funds to + +2. **Agreement** PISP confirms the Payee Party, and looks up the terms of the transaction. If the User accepts the terms of the transaction, they sign the transaction with the credential established in the Linking API flow + +3. **Transfer** The Payer DFSP initiates the transaction, and informs the PISP of the transaction result. + +## 3.1 Discovery + +In this phase, a user enters the identifier of the user they wish to send funds to. The PISP executes a **GET /parties/**_{Type}/{ID}_** (or **GET /parties/**_{Type}/{ID}/{SubId}_) call and awaits a callback from the Mojaloop switch. [Section 6.3](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#63-api-resource-parties) +of Ref 1. above describes the **/parties** resource in detail. + +If the **GET /parties/**_{Type}/{ID}_ request is successful, the PISP will receive a **PUT /parties** callback from the Mojaloop switch. The PISP then confirms the Payee with their user. + +Should the PISP receive a **PUT /parties/**_{Type}/{ID}_**/error** (or **PUT /parties/**_{Type}/{ID}/{SubId}_**/error**) callback, the PISP should display the relevant error to their user. + + + +![Discovery](./assets/diagrams/transfer/1-1-discovery.svg) + +## 3.2 Agreement + +### 3.2.1 Thirdparty Transaction Request + +Upon confirming the details of the Payee with their user, the PISP asks the user to enter the `amount` of funds they wish to send to the Payee, and whether or not they wish the Payee to _receive_ that amount, or they wish to _send_ that amount (`amountType` field). + +If the User has linked more than 1 account with the PISP application, the PISP application can ask the user to choose an account they wish to send funds from. Upon confirming the _source of funds_ account, the PISP can determine: +1. the `FSPIOP-Destination` as the DFSP who the User's account is linked with +2. The `payer` field of the **POST /thirdpartyRequests/transactions** request body. The `partyIdType` is `THIRD_PARTY_LINK`, the `fspId` is the fspId of the DFSP who issued the link, and the `partyIdentifier` is the `accountId` specified in the **POST /consents#scopes** body. + +> See [Grant Consent](./transaction-patterns-linking.md#Grantconsent) for more information. + +The PISP then generates a random `transactionRequestId` of type UUID (see [RFC 4122 UUID](https://tools.ietf.org/html/rfc4122)). + +![1-2-1-agreement](./assets/diagrams/transfer/1-2-1-agreement.svg) + +Upon receiving the **POST /thirdpartyRequests/transactions** call from the PISP, the DFSP performs some validation such as: +1. Determine that the `payer` identifier exists, and is one that was issued by this DFSP to the PISP specified in the `FSPIOP-Source`. +2. Confirms that the `Consent` that is identified by the `payer` identifier exists, and is valid. +3. Confirm that the User's account is active and holds enough funds to complete the transaction. +4. Any other validation that the DFSP wishes to do. + +Should this validation succeed, the DFSP will generate a unique `transactionId` for the request, and call **PUT /thirdpartyRequests/transactions/**_{ID}_ with this `transactionId` and a `transactionRequestState` of `RECEIVED`. + +This call informs the PISP that the Thirdparty Transaction Request was accepted, and informs them of the final `transactionId` to watch for at a later date. + +If the above validation fail, the DFSP should send a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** call to the PISP, +with an error message communicating the failure to the PISP. See [Error Codes](./data-models.md#errorcodes) for more information. + +### 3.2.2 Thirdparty Authorization Request + +The Payer DFSP (that is, the institution sending funds at the request of the PISP) may then issue a quotation request (**POST /quotes**) to the Payee DFSP (that is, the institution receiving the funds). Upon receiving the **PUT /quotes/**_{ID}_ callback from the Payee DFSP, the Payer DFSP needs to confirm the details of the transaction with the PISP. + +They use the API call **POST /thirdpartyRequests/authorizations**. The request body is populated with the following fields: + +- `transactionRequestId` - the original id of the **POST /thirdpartyRequests/transactions**. Used by the PISP to correlate an Authorization Request to a Thirdparty Transaction Request +- `authorizationRequestId` - a random UUID generated by the DFSP to identify this Thirdparty Authorization Request +- `challenge` - the challenge is a `BinaryString` which will be signed by the private key on the User's device. While the challenge +could be a random string, we recommend that it be derived from something _meaningful_ to the actors involved in the transaction, +that can't be predicted ahead of time by the PISP. See [Section 4.1](#DerivingtheChallenge) for an example of how the challenge +could be derived. +- `transactionType` the `transactionType` field from the original **POST /thirdpartyRequests/transactions** request + + +![1-2-2-authorization](./assets/diagrams/transfer/1-2-2-authorization.svg) + + +### 3.2.3 Signed Authorization + +Upon receiving the **POST /thirdpartyRequests/authorizations** request from the Payer DFSP, the PISP presents the terms of the proposed +transaction to the user, and asks them if they want to proceed. + +The results of the authorization request are returned to the DFSP via the **PUT /thirdpartyRequests/authorizations/**_{ID}_, where +the *{ID}* is the `authorizationRequestId`. + + +If the user rejects the transaction, the following is the payload sent in **PUT /thirdpartyRequests/authorizations/**_{ID}_: + +```json +{ + "responseType": "REJECTED" +} +``` + +![1-2-3-rejected-authorization](./assets/diagrams/transfer/1-2-3-rejected-authorization.svg) + + +Should the user accept the transaction, the payload will depend on the `credentialType` of the `Consent.credential`: + +1. If `FIDO`, the PISP asks the user to complete the [FIDO Assertion](https://webauthn.guide/#authentication) flow to sign the challenge. + The `signedPayload.fidoSignedPayload` is the `FIDOPublicKeyCredentialAssertion` returned from the FIDO Assertion process. See [3.2.3.1 Signing the Challenge FIDO](#SigningTheChallengeFIDO) + +2. If `GENERIC`, the private key created during the [credential registration process](../linking/README.md#162-registering-the-credential) is + used to sign the challenge. See [3.2.3.2 Signing the Challenge with a GENERIC Credential](#SigningTheChallengeGeneric) + +#### 3.2.3.1 Signing the Challenge FIDO + +For a `FIDO` `credentialType`, the PISP asks the user to complete the [FIDO Assertion](https://webauthn.guide/#authentication) flow to sign the challenge. The `signedPayload.value` is the [`PublicKeyCredential`](https://w3c.github.io/webauthn/#publickeycredential) returned from the FIDO Assertion process, where the `ArrayBuffer`s are parsed as base64 encoded utf-8 strings. As a `PublicKeyCredential` is the response of both the FIDO Attestation and Assertion, we define the following interface: `FIDOPublicKeyCredentialAssertion`: + + +```json +FIDOPublicKeyCredentialAssertion { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" +} +``` + +The final payload of the **PUT /thirdpartyRequests/authorizations/**_{ID}_ is then: + +```json +{ + "responseType": "ACCEPTED", + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": FIDOPublicKeyCredentialAssertion + } +} +``` + +![1-2-3-signed-authorization-fido](./assets/diagrams/transfer/1-2-3-signed-authorization-fido.svg) + + +#### 3.2.3.2 Signing the Challenge with a GENERIC Credential + +For a `GENERIC` credential, the PISP will perform the following steps: + + +1. Given the inputs: + - `challenge` (`authorizationRequest.challenge`) as a base64 encoded utf-8 string + - `privatekey` (stored by the PISP when creating the credential), as a base64 encoded utf-8 string + - SHA256() is a one way hash function, as defined in [RFC6234](https://datatracker.ietf.org/doc/html/rfc6234) + - sign(data, key) is a signature function that takes some data and a private key to produce a signature +2. _Let `challengeHash` be the result of applying the SHA256() function over the `challenge`_ +3. _Let `signature` be the result of applying the sign() function to the `challengeHash` and `privateKey`_ + +The response from the PISP to the DFSP then uses this _signature_ as the `signedPayload.genericSignedPayload` field: + + +The final payload of the **PUT /thirdpartyRequests/authorizations/**_{ID}_ is then: + +```json +{ + "responseType": "ACCEPTED", + "signedPayload": { + "signedPayloadType": "GENERIC", + "genericSignedPayload": "utf-8 base64 encoded signature" + } +} +``` + +![1-2-3-signed-authorization-generic](./assets/diagrams/transfer/1-2-3-signed-authorization-generic.svg) + + +### 3.2.4 Validate Authorization + +> __Note:__ If the DFSP uses a self-hosted authorization service, this step can be skipped. + +The DFSP now needs to check that challenge has been signed correctly, and by the private key that corresponds to the +public key that is attached to the `Consent` object. + +The DFSP uses the API call **POST /thirdpartyRequests/verifications**, the body of which is comprised of: + +- `verificationRequestId` - A UUID created by the DFSP to identify this verification request. +- `challenge` - The same challenge that was sent to the PISP in [3.2.2 Thirdparty Authorization Request](#ThirdpartyAuthorizationRequest) +- `consentId` - The `consentId` of the Consent resource that contains the credential public key with which to verify this transaction. +- `signedPayloadType` - The type of the SignedPayload, depending on the type of credential registered by the PISP +- `fidoValue` or `genericValue` - The corresponding field from the **PUT /thirdpartyRequests/authorizations** request body from the PISP. +The DFSP must lookup the `consentId` based on the `payer` details of the `ThirdpartyTransactionRequest`. + +![1-2-4-verify-authorization](./assets/diagrams/transfer/1-2-4-verify-authorization.svg) + +## 3.3 Transfer + +Upon validating the signed challenge, the DFSP can go ahead and initiate a standard Mojaloop Transaction using the FSPIOP API. + +After receiving the **PUT /transfers/**_{ID}_ call from the switch, the DFSP looks up the ThirdpartyTransactionRequestId for the given transfer, +and sends a **PATCH /thirdpartyRequests/transactions/**_{ID}_ call to the PISP. + +Upon receiving this callback, the PISP knows that the transfer has completed successfully, and can inform their user. + +![1-3-transfer](./assets/diagrams/transfer/1-3-transfer.svg) + + +# 4. Request TransactionRequest Status + +A PISP can issue a **GET /thirdpartyRequests/transactions/**_{ID}_ to find the status of a transaction request. + +![PISPTransferSimpleAPI](./assets/diagrams/transfer/get_transaction_request.svg) + +1. PISP issues a **GET /thirdpartyRequests/transactions/**_{ID}_ +1. Switch validates request and responds with `202 Accepted` +1. Switch looks up the endpoint for `dfspa` for forwards to DFSP A +1. DFSPA validates the request and responds with `202 Accepted` +1. DFSP looks up the transaction request based on its `transactionRequestId` + - If it can't be found, it calls **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** to the Switch, with a relevant error message + +1. DFSP Ensures that the `FSPIOP-Source` header matches that of the originator of the **POST /thirdpartyRequests/transactions** + - If it does not match, it calls **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** to the Switch, with a relevant error message + +1. DFSP calls **PUT /thirdpartyRequests/transactions/**_{ID}_ with the following request body: + ``` + { + transactionRequestState: TransactionRequestState + } + ``` + + Where `transactionId` is the DFSP-generated id of the transaction, and `TransactionRequestState` is `RECEIVED`, `PENDING`, `ACCEPTED`, `REJECTED`, as defined in [7.5.10 TransactionRequestState](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7510-transactionrequeststate) of the API Definition + + +1. Switch validates request and responds with `200 OK` +1. Switch looks up the endpoint for `pispa` for forwards to PISP +1. PISP validates the request and responds with `200 OK` + +# 5. Error Conditions + +After the PISP initiates the Thirdparty Transaction Request with **POST /thirdpartyRequests/transactions**, the DFSP must send either a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** or **PATCH /thirdpartyRequests/transactions/**_{ID}_ callback to inform the PISP of a final status to the Thirdparty Transaction Request. + +- **PATCH /thirdpartyRequests/transactions/**_{ID}_ is used to inform the PISP of the final status of the Thirdparty Transaction Request. This could be either a Thirdparty Transaction Request that was rejected by the user, or a Thirdparty Transaction Request that was approved and resulted in a successful transfer of funds. +- **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** is used to inform the PISP of a failed Thirdparty Transaction Request. +- If a PISP doesn't receive either of the above callbacks within the `expiration` DateTime specified in the **POST /thirdpartyRequests/transactions**, it can assume the Thirdparty Transaction Request failed, and inform their user accordingly + + +## 5.1 Unsuccessful Payee Lookup + +When the PISP performs a Payee lookup (**GET /parties/**_{Type}/{ID}_), they may receive the callback **PUT /parties/**_{Type}/{ID}_**/error**. + +See [6.3.4 Parties Error Callbacks](https://docs.mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html#634-error-callbacks) of the FSPIOP API Definition for details on how to interpret use this error callback. + +In this case, the PISP may wish to display an error message to their user informing them to try a different identifier, or try again at a later stage. +## 5.2 Bad Thirdparty Transaction Request + +When the DFSP receives the **POST /thirdpartyRequests/transactions** request from the PISP, the following processing or validation errors may occur: +1. The `payer.partyIdType` or `payer.partyIdentifier` is not valid, or not linked with a valid **Consent** that the DFSP knows about +2. The user's account identified by `payer.partyIdentifier` doesn't have enough funds to complete the transaction +3. The currency specified by `amount.currency` is not a currency that the user's account transacts in +4. `payee.partyIdInfo.fspId` is not set - it's an optional property, but payee fspId will be required to properly address quote request +5. Any other checks or verifications of the transaction request on the DFSP's side fail + +In this case, the DFSP must inform the PISP of the failure by sending a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** callback to the PISP. + +![3-2-1-bad-tx-request](./assets/diagrams/transfer/3-2-1-bad-tx-request.svg) + +The PISP can then inform their user of the failure, and can ask them to restart the Thirdparty Transaction request if desired. + + +## 5.3 Downstream FSPIOP-API Failure + +The DFSP may not want to (or may not be able to) expose details about downstream failures in the FSPIOP API to PISPs. + +For example, before issuing a **POST /thirdpartyRequests/authorizations** to the PISP, if the **POST /quotes** call with the Payee FSP fails, the DFSP sends a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** callback to the PISP. + +![3-3-1-bad-quote-request](./assets/diagrams/transfer/3-3-1-bad-quote-request.svg) + +Another example is where the **POST /transfers** request fails: + +![3-3-2-bad-transfer-request](./assets/diagrams/transfer/3-3-2-bad-transfer-request.svg) + + +## 5.4 Invalid Signed Challenge + +After receiving a **POST /thirdpartyRequests/authorizations** call from the DFSP, the PISP asks the user to sign the `challenge` using the credential that was registered during the account linking flow. + +The signed challenge is returned to the DFSP with the call **PUT /thirdpartyRequest/authorizations/**_{ID}_. + +The DFSP either: +1. Performs validation of the signed challenge itself +2. Queries the Auth-Service with the **thirdpartyRequests/verifications** resource to check the validity of the signed challenge against the publicKey registered for the Consent. + +Should the signed challenge be invalid, the DFSP sends a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** callback to the PISP. + + +### Case 1: DFSP self-verifies the signed challenge + +![3-4-1-bad-signed-challenge-self-hosted](./assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.svg) + + +### Case 2: DFSP uses the hub-hosted Auth-Service to check the validity of the signed challenge against the registered credential. + +![3-4-2-bad-signed-challenge-auth-service](./assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.svg) + +## 5.5 Thirdparty Transaction Request Timeout + +If a PISP doesn't receive either of the above callbacks within the `expiration` DateTime specified in the **POST /thirdpartyRequests/transactions**, it can assume the Thirdparty Transaction Request failed, and inform their user accordingly. + + +![3-6-tpr-timeout](./assets/diagrams/transfer/3-6-tpr-timeout.svg) + +# 6. Appendix + +## 6.1 Deriving the Challenge + +1. _Let `quote` be the value of the response body from the **PUT /quotes/**_{ID}_ call_ +2. _Let the function `CJSON()` be the implementation of a Canonical JSON to string, as specified in [RFC-8785 - Canonical JSON format](https://tools.ietf.org/html/rfc8785)_ +3. _Let the function `SHA256()` be the implementation of a SHA-256 one way hash function, as specified in [RFC-6234](https://tools.ietf.org/html/rfc6234)_ +4. The DFSP must generate the value `jsonString` from the output of `CJSON(quote)` +5. The `challenge` is the value of `SHA256(jsonString)` \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/api/thirdparty/transaction-patterns.md b/website/versioned_docs/v1.0.1/api/thirdparty/transaction-patterns.md new file mode 100644 index 000000000..5110f83e0 --- /dev/null +++ b/website/versioned_docs/v1.0.1/api/thirdparty/transaction-patterns.md @@ -0,0 +1,6 @@ +## Transaction Patterns + +The interactions and examples of how a DFSP and PISP will interact with the Third Party API can be found in the following Transaction Patterns Documents: + +1. [Linking](./transaction-patterns-linking.md) describes how an account link and credential can be established between a DFSP and a PISP +2. [Transfer](./transaction-patterns-transfer.md) describes how a PISP can initate a payment from a DFSP's account using the account link \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/community/README.md b/website/versioned_docs/v1.0.1/community/README.md new file mode 100644 index 000000000..385329179 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/README.md @@ -0,0 +1,20 @@ +# Welcome to Mojaloop Community + +## How do I get started? + +* A good first place to get started is the [Contributors' Guide](./contributing/contributors-guide.md), which provides information on how you can contribute to the project. +* If you would like an overview of the technologies used in the project, head over to the [Tools and Technologies](./tools/tools-and-technologies.md) section. +* To get a sense of the features we are building, view the [Product Roadmap](./mojaloop-roadmap.md). +* The [Project board](https://github.com/mojaloop/project#zenhub) showcases what is currently being worked on; you can start with a [good first issue](https://github.com/mojaloop/project/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). + +## Where can I get help? + +Join the [Mojaloop Slack Discussions](https://mojaloop-slack.herokuapp.com/) to connect with other members of the community. + +## What if I have more questions? +You can checkout some of our frequently asked questions in the [FAQ](../getting-started/faqs.md) section. Or better still head over to the community on [Slack](https://mojaloop-slack.herokuapp.com/). + +## How do I stay up to date with the project? +Subscribe by joining the [commmunity](https://community.mojaloop.io/) where you can be notified about upcoming [events](https://community.mojaloop.io/c/events/8) and [product announcements](https://community.mojaloop.io/c/announcements/9). + +You can also join our [Slack Announcements](https://mojaloop.slack.com/messages/CG3MAJZ5J) channel to receive information on the latest release. \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/Mojaloop Performance 2020.pdf b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/Mojaloop Performance 2020.pdf new file mode 100644 index 000000000..719dec47e Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/Mojaloop Performance 2020.pdf differ diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/README.md b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/README.md new file mode 100644 index 000000000..67fffae5f --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/README.md @@ -0,0 +1,27 @@ +# Discussion Documents (Archive) + +## PI 10 +- [Performance Project](./Mojaloop%20Performance%202020.pdf) +- [Code Improvement Project](./code-improvement.md) +- [Cross Border Project](./cross-border.md) +- [PSIP Project](./pisp.md) + +## PI 9 + +- [Versioning Draft Proposal](./versioning-draft-proposal.md) +- [Code Improvement Project](./code-improvement.md) +- [Performance Project](./performance.md) +- [Cross Border Project](./crossborder.md) +- [PSIP Project](./pisp.md) + +## PI 8 + +- [Cross Border Meeting Notes Day 1](./cross-border-day-1.md) +- [Cross Border Meeting Notes Day 2](./cross-border-day-2.md) +- [ISO integration Overivew](./iso-integration.md) +- [Mojaoop Decimal Type; Based on XML Schema Decimal Type](./mojaloop-decimal.md) + +## PI 7 + +- [Workbench Workstream](./workbench.md) + diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/aws_tagging.md b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/aws_tagging.md new file mode 100644 index 000000000..a50c7b2ef --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/aws_tagging.md @@ -0,0 +1,127 @@ +# AWS Tagging Guidelines + Policies + +> **Note:** These guidelines are specific to the Mojaloop Community's AWS Environment for testing and validating Mojaloop installations, and are primarily for internal purposes. They may, however, be a useful reference to others wishing to implement similar tagging strategies in their own organizations. + +To better manage and understand our AWS usage and spending, we are implementing the following tagging guidelines. + +## Contents +- [Proposed tags and their meanings](#proposed-tags-and-their-meanings) + - [mojaloop/cost_center](#mojaloopcost_center) + - [mojaloop/owner](#mojaloopowner) +- [Manual Tagging](#manual-tagging) +- [Automated Tagging](#automated-tagging) +- [AWS Tagging Policies](#aws-tagging-policies) + - [Viewing Tag Reports + Compliance](#viewing-tag-reports--compliance) + - [Editing Tag Policies](#editing-tag-policies) + - [Attaching/Detaching Tag Policies](#attachingdetaching-tag-policies) + +## Proposed tags and their meanings + +We propose the following 2 tag _keys_: + +- `mojaloop/cost_center` +- `mojaloop/owner` + +### `mojaloop/cost_center` + +`mojaloop/cost_center` is a breakdown of different resources in AWS by the workstream or project that is incurring the associated costs. + +It loosely follows the format of `-[-subpurpose]`, where account is something like `oss`, `tips`, or `woccu`. +> Note: It's likely that most of the resources will be under the `oss` "account", but I managed to find some older resources that fall under the `tips` and `woccu` categories. We also want to plan for future types of resources that might be launched in the future. + +Some potential values for `mojaloop/cost_center` are: + +- `oss-qa`: Open source QA work, such as the existing dev1 and dev2 environments +- `oss-perf`: Open source performance work, such as the ongoing performance workstream +- `oss-perf-poc`: Performance/Architecture POC + +We also reserve some special values: +- `unknown`: This resource was evaluated (perhaps manually, or perhaps by an automated tool), and no appropriate `cost_center` could be determined. + - This will allow us to easily filter for the `mojaloop/cost_center:unknown` tags and produce a report +- `n/a`: This resource incurrs no cost, so we're not really worried about assigning a `cost_center` to it + - This can be useful for mass tagging resources that are hard to figure out where the belong, such as EC2 Security Groups + +### `mojaloop/owner` + +`mojaloop/owner` is a person who is responsible for the managing and shutdown of a given resource. + +The goal of this tag is to prevent long running resources that everybody else thinks _someone else_ knows about, but we no longer need. By applying this tag, we will be able to have a list of _who to go to_ in order to ask questions about the resource. + +The value can simply be a person's name, all lowercase: +- `lewis` +- `miguel` +- etc. + +Once again, we will reserve the following values: +- `unknown`: This resource was evaluated (perhaps manually, or perhaps by an automated tool), and no appropriate `cost_center` could be determined. + - This will allow us to easily filter for the `mojaloop/owner:unknown` tags and see what resources are 'orphaned' + + +## Manual Tagging + +We can use the "Tag Editor" in the AWS console to search for untagged resources. + +1. Log into the AWS Console +2. Under Resource Groups, select "Tag Editor" +![](./images/tagging_01.png) +3. From the tag editor, select a Region (I typically use "All regions"), and Resource Type (I also typically use "All resource types") +4. Now select "Search Resources", and wait for the resources to appear + +You can also search by tags, or the absense of tags to see what resources have not been tagged yet. +![](./images/tagging_02.png) + +5. Once you have a list of the resources, you can select and edit tags for many resources at once! +6. You can also export a `.csv` file of resources found in your search + + +## Automated Tagging + +We currently automate tagging on the following + +As we have a firmer grasp of our tagging guidelines, we need to introduce them into our tooling so that all of the grunt work of manual tagging. + +At the moment, this will look like introducing tags into: +1. Rancher - which currently manages our Kubernetes clusters for both QA and Performance purposes +2. IAC - The upcoming IAC code that will eventually be running our dev environments + + +## AWS Tagging Policies + +As of August 3, 2020, we have started introducing [AWS Tagging Policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_tag-policies.html) to better enforce tags and monitor our resources (especially with respect to costs). + + +### Viewing Tag Reports + Compliance + +1. Log in to the AWS Console +2. "Resource Groups" > "Tag Editor" +3. On the left sidebar, select "Tag Policies" + +From here you can see the tag policies "compliance report" + +![](./images/tagging_03.png) + + +### Editing Tag Policies + +> Note: This may require special admin priviledges to access these pages + +1. Log in to the AWS Console +2. Select "username@mojaloop" in the top right > "My Organization" +3. Select "Policies" > "Tag Policies" + +![](./images/tagging_04.png) + +4. From here, you can view the current tag policies + +![](./images/tagging_05.png) + +5. In the sidebar, you can click "View details" > "Edit policy" to edit the policy + + +### Attaching/Detaching Tag Policies + +1. Go to the "My Organization" page +2. Select the relevant account > "Tag policies" in the sidebar +3. From here you can Attach + Detach tag policies + +![](./images/tagging_06.png) diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/code-improvement.md b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/code-improvement.md new file mode 100644 index 000000000..284f97299 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/code-improvement.md @@ -0,0 +1,26 @@ +# Code_Improvement Project + +## Overview +Purpose to improve code quality and security for the Mojaloop project. Includes analysis and introduction of new open sources tools, process improvments, gates checks (w/in pull requests and builds) along with documentation. + +Scope: project is focused on quality and security but can lead to other areas such as test automation and DevOps automation and tools. + +## OutPut (phase one by end of January): +- Implementation and analysis of new OSS tools +- Update Release Scripts: Security aspects need to be embedded in release/devops (CI/CD) +- Update rules for Pull Requests: Security aspects embedded in pull requests (before check-ins) +- Update documentations: Standards and contribution guides +  +Slack Channel:#code_security + + ## Discussions: + ### Implement changes at the Dockerfile and CI/CD build process to help bolster our container security + - Create a non-root user within the Dockerfile + - Enable docker-content-trust on the docker host (this will be inside CircleCI) + - Run builds with --no-cache during CircleCI step to ensure that we are pulling in any new security patches each time (I don’t think this is a major issue since we don’t have CircleCI docker image caching on anyway + + ### Move from Javascript to Typescript + - Transition to typescript (mix and match js and ts) for more security/quality + - Typescript is preferred but not required: https://github.com/mojaloop/template-typescript-public + + diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/cross-border-day-1.md b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/cross-border-day-1.md new file mode 100644 index 000000000..5c5d51d79 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/cross-border-day-1.md @@ -0,0 +1,270 @@ +# Cross Border Discussion Day 1 + +>**Links** +>- [Day 2 Notes](./cross_border_day_2.md) +>- [Relevant Issue on DA Board](https://github.com/mojaloop/design-authority/issues/32) +>- [Mojaloop Spec Pull Request](https://github.com/mojaloop/mojaloop-specification/pull/22) + +## Attendees: + +In person +- Lewis, Crosslake +- Adrian, Coil +- Nico, MB +- Sam, MB +- Miguel, MB +- Carol Benson, Glenbrook +- Michael Richards, MB +- Henrik Karlsson, Ericsson +- Rob Reeve, MB +- Vanburn, Terra Pay +- Razin, Terra Pay +- Ram, Terra Pay +- JJ, Google +- Matt Bohan, Gates Foundation +- David Power, EY +- James Bush, MB +- Warren, MB +- Judit, MB +- Bart-Jan and Bruno from GSMA - Day #2 + +Phone +- Kim Walters, Crosslake +- Istvan Molnar, DPC +- Innocent Ephraim, MB + +## Session 1 + +**Goal: Update the API definitions** + +- Privacy: + - Can I send USD? _yes/no_ + - What can I send? _list of currencies_ + +Business agreements: there are a few ways this can happen +- Global scheme, made up of scheme to scheme agreements +- bilateral scheme agreements +- scheme to scheme +- region + + +Definitions: +- Gateway FSP: An FSP that 'bridges' across 2 networks +e.g. Mowali + - 2 logical networks (USD,XOF?) + - a single mojaloop network + +- Cross Network Provider (CNP) + - FXP, same thing? + +Michael: +- there is a reason for that assumption +- other legal implications here... + +- single entity, legally in 2 different jurisdictions + - a close analogy of a scheme without jurisdiction + +- participant: + - has a tx account that can be debited or credited + - bank, fxp etc. + +>Q: Can we have a participant that doesn't settle? Or would this be covered by CNP that is a party +>e.g. Visa, doesn't always settle in a given market, but holds an account + +- Resident vs. Non-resident + - reporting requirements are different + +- what are the technical requirements for reporters? + +- settlement + - not too worried about it at this stage (our focus is on the API changes) + - we assume that settlement is possible, but need to narrow scope witht the api first + +- Not only mojaloop + - need to allow for non-mojaloop -> mojaloop transfers and vice versa (both inbound and outbound) + - must still be interoperable + + +- who provides routing? + - switch? + - ALS? + - CNP? + + +>*Follow Up:* Need a formal definition of FXP and CNP roles, along with requirements and responsibilities + + +At a scheme level + - should the sceheme maintain a list of other schemes it allows its FSPs to connect with? + - or should the CNP take care of this? + +- not scheme -> scheme, but part of the onboarding CNP process +- but the scheme can/should still maintain rules + +- how will quoting work? Should an FSP send multiple quotes, one addressed to each CNP? Or should the switch have some rules engine that helps it determine who to send quotes to? + +James: We want to be flexible. Can see instances where we would want both to happen, so we shouldn't assume too much at this stage. + +Simplest option: The switch talks to the ALS, determines a transfer is not in our network, and then finds a list of CNPs + +CNP + FXP -> essentially the same thing +- they are *Roles*, and a DFSP can assume more than 1 role +- fxps can also exist in more than 1 zone (e.g. Mowali case) + - single network fxp is just an fxp, + - multi-network fxp is likely also a CNP + + +## Session 2 + +- debate about single or multiple lookups + - we should never return "empty result" + +- are wallets addressable by MSISDN? + - only 1 account at the moment + - but this is internal to the switch + - the oracle's job is to convert MSIDN -> Mojaloop Address + +- in the future: MSISDN + accounts will be less related + - this topic is adjacently related to addressing + +- 'going outisde' mojaloop with addressing will be a little tricky +- Standardize addressing? + - not something we want to do + +Ram: There are existing tools (no need to reinvent the wheel), outside the mojaloop scheme + +- sending to unknown currency + - currently: 1 routing table answer + - future: multiple answers + +- privacy: + - no real need for hard rules at the moment (at least not at the API level, rules come along with schemes) + - we do need a method for mediating information that one switch requires from another (and rejecting quotes should these prerequesites not be met) + +--- +- Domestic vs. Cross border: USer has/needs different information + - e.g. do we only want to support discovery in domestic case? +--- + +Adrian: A lot of this stuff is business rule and scheme specific +- maintains competitive space +- How much information is in the: + - lookup? + - Quote? + +--- +- Proposal: Address lookup -> Returns multiple responses? +- MSISDN -> ID, not an address. Someone, not an account + +- there should be only 1 response from the ALS +- Michael disagrees + +- need to separate out *addressing* from *routing* + +- we need to think about the downstream affects this will have on testing + - need to find a clear way to test these lookups + + +For example, airtel UPI issue (where existing MSIDSNs were replaced when they grandfathered in their mobile customers to become mobile money customers) + - we need to avoid a situation like that + +--- + +Bring it back to first (L1P) principles +- transfers should clear immediately +- no such thing as a future + +- For domestic: we can guarantee delivery, but cross-border is much harder +- need to maintain transparency requirement on CNPs + - this comes down to business rules + +- Reversible tx's or rules abour downstream issues + - ILP takes care of *most* of this for us + +- in TIPS case: 1 ID maps to 1 account +- as always, there needs to be a compromise between privacy and features (and that's ok!) + +--- + +At the end of a quote: +- ValueDate +- how much will be received +- what are the fees? (broken down, by step and currency) + +--- + +How do we support protocols that don't support quotes (this is a question for moja to non-moja systems) + +Risk: CNP: they hold the risk in this type of transaction + +CNP as a participant? + - holds an account with a participant + - direct vs indirect approach + - this doesn't affect the technical requirements (so out of scope for this discussion) + + +--- + +- fixed send and receive: + - What direction does data need to be appended to the quote? It depends on if it is fixed receive vs fixed send + +- Either: `A send 20 USD to B` OR `B receives 1000 PHP` + +- translating fees back for user: FXP __must__ apply the same rate for fees as the principal transfer + +- From L1P Perspective: __the goal is transparency__ + +- how about quotes outside of Mojaloop? + - CNP should take care of this - it is the last bastion of Mojaloopyness + +--- + +- Participant Object + - Attached to the Quotes, one entry per hop? + - So multi-hop quotes hold _n_ participant objects, where _n_ = number of hops + 1 + +As part of this we need: +- interoperable bits of data (common defs) +- scheme for encryption +- a place to put the data (in the quotes object) + +Should we worry about encryption for now? +- perhaps not, but still should allow for it in the API + +Encryption adds extra integration challenge +- what is the need to get data in the clear? + - from a techincal perspective: just use a blank encryption key + +Do we need to encrypt to ensure the switch(es) can't see the data? + - perhaps not at this stage + + +>### Decision: +>- No encryption for now +>- in outbound quote request: have a list of data requirements +>- for inbound quote request: participants fill out those requirements +>- if requirements are not met: abort the quote +>- Don't hardcode the data requirements, we should use existing standards + + +- we need to specify whether or not fields _have_ been verified + - ties in with tiered KYC processes + +- need a common dictionary of data that can/should be requested + + +## Boards: + +_board 1: Fixed send flows_ +![board_1](./images/cb_board_1.jpg) + +_board 2: Fixed receive flows_ +![board_2](./images/cb_board_2.jpg) + + + + + + + + diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/cross-border-day-2.md b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/cross-border-day-2.md new file mode 100644 index 000000000..fbbbfd799 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/cross-border-day-2.md @@ -0,0 +1,124 @@ +# Cross Border Discussion Day 2 + +>**Links** +>- [Day 1 Notes](./cross_border_day_1.md) +>- [Relevant Issue on DA Board](https://github.com/mojaloop/design-authority/issues/32) +>- [Mojaloop Spec Pull Request](https://github.com/mojaloop/mojaloop-specification/pull/22) + +## Next Steps: + +- Updated the proposal APIs +- Present the consolidated change to the CCB in writing +- Couple of weeks to put together the changes (Michael/Adrian to split up the work) +- Mid-November CCB call + + +## Session 1 + +Unanswered Questions: +- addressing + - break it down? + - cross-mojaloop + - what does a PayerFSP do with an address? + +- ALS + routing + - what optimizations does the API need to do/allow? + +- local vs. remote DFSP ids + +- Downstream failures + - When paymnet does clear, does the payer receive a notification (esp. with 'delayed' payments that may interface with non-mojaloop systems) + - Can a CNP send a `PATCH` of the tx to update the Payee somehow? + +--- + +- multiple quotes and route responses: + - how do display to the user? + - We need to establish rules for filtering routes + - hard to do: e.g. blacklisting a switch? or express a preference for certain routes + +- how will Sender DFSP discover the scheme rules for a receiver? +- does the Sender DFSP need to 'know' the final switch? Or can it just 'know' the next one? + +--- + +Running up against ML + non-ML assumptions +- does this mean CNP needs to do more work when connecting to non-ML? + - e.g. knowing the resulting scheme/switch? + - why? Failure handling + - based on yesterday's decision: Should the CNP do the work here? + +- Take a lesson from SWIFT: + - bank doesn't know where the money is going + - can we avoid this in ML? + +--- + +CNP: Goal is to 'act like' a normal member of the network + - This minimizes the responsibilities that the scheme assumes + +When is the TX considered completed? + - There might be cases where the scheme considers it done, but it is not techincally finished end to end + +How do we deal with service deteroriation? + - Scheme rules + +--- + +Back to quotes: + +- how to express quote information? + - are quotes and routes separate? Presumably, yes + +- The quote is the most expensive step + - Can we provide QOS information here as part of the lookup? + +Addressing: +- Need for a globally unique address + - Allow an address space for DFSPs and unique persons/accounts +- sheme says "this isn't in my space" +- CNP figures out the routes to get to that space + +--- + +### Michael's Tangent: + +- did we make the wrong assumptions about the CNP? + +**switch:** Knows CNPs + FXPs +**CNPs:** holds routing table and lookup + +- if the sender or receiver is an FXP, the the tx is *not* a cross-currency tx + +--- + +## Session 2 + +*Decision:* +- header value is CNP id +- partId object is the final FSP + +valueDate +- implied that funds are expected to clear before the valueDate +- can still have short expiry times on tx + +- CNP: + - returns an obfuscated set of fees + - fits into our current model + + +- condition: + - existing object cryptographically tied to the tx object + - but for multi-hop, we don't only know this + - fixed receive makes this tricker (which is what echo data hopes to solve) + + - We want **only 1 condition for all hops** + - the idea of a multi-condition is a "perversion" (according to some) + + +## Boards: + +_board 3: Cross Network lookup and quotes flow, fixed receive of 1000 PHP from USD_ +![board_3](./images/cb_board_3.jpg) + + diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/cross-border.md b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/cross-border.md new file mode 100644 index 000000000..4deec6f8d --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/cross-border.md @@ -0,0 +1,396 @@ +**Cross-border Workstream Meeting** + +March 10th & 11th (London/remote) + +**Next Steps for PI:** + +• Proposal for how the CNP query and host oracle services and global goals - Adrian, Michael + +• Compound identifiers, ways in which this is captured in the system or expressed in apis - open + +• What information is captured in the data model or the extension list - Michael + +• Follow-up w/ SWIFT to discuss requirements - Matt + +**Open Items:** + +• Finalize CNP Requirements + +• Has to aggregate information and put them together into a single request & they will need to sign separately + +• Finalize FXP has to manage FX rates, the settlements and what expires when + +• CNPs can extend this and determine additional scheme rules + +• FXP handles rounding errors + +• FXP Guarantee a given rate + +• How do you get non-Mojaloop folks in the schema? + +• How do we integrate Mojaloop and some Mojaloop scheme to provide a full PVT payments - working group with Michael, Adrian, Sybrin, others as needed + +• How do we manage requests for regulatory reasons + +• Investigate identifier mappings (Map pathfinder accounts/mobile accounts to DFSP unique IDs) + +• Investigate Certification (Hash and PKKI) + + +Detailed Meeting Notes: +Day #1: + - Quote response + + ○ How do we code the SLA into the response + + ○ Ask a 2nd CNP to route + + ○ In the API - need to package up how to get it there + + ○ As a CMP in Mowali if I return a quote response the scheme has implications + + ○ Follow the whole route from payer to payee + + ○ Limiting the participation of CNP - they need to be the last hop + + § How to define the requirements of a CNP? + + - Message format + + ○ Http syntax + + ○ Started from the mojaloop scheme + + § Move towards the CNP should manage the conversion + + ○ SWIFT version + + ○ Security - TLS + + ○ Header/content encrypted in JWS + + - Retail system + + ○ Off network - remit to someone hub + + - Data Model + + ○ Structure: Ways in which we added new information, different routes, etc. + + ○ Privacy: Visibility and Security - only accessible to the people that can see it + + ○ Content of the data model + + - Transfer is done through the switch (movement of money) + + ○ In mowali - the amounts are expressed but the rate is important because it impacts settlements + + § Data flow - we add the rate when we send the quote back + + § Added in the extension list - should it be part of the standard? + + § Send and receive amount (differ currency) + + - Data element + + ○ Fee for each participant + + ○ Payer DFSP adds it up + + ○ Fee element for the transaction + + - Proposal + + ○ Account lookup service + + § List of local FSP + + ○ Switch - need to maintain state and lookup requests + + § Should look like a domestic transfer to the sender + + § Collect the information and send it back - + + ○ CNP - making assumptions to meet requirements + + § Do you need to see the route + + § Collecting different information downstream + + § Sending FSPs needs to know who is the receiver + + ○ CNP has to aggregate information and put them together into a single request & they will need to sign separately + + § Condition and fulfillment is part of a PKI structure + + § If there is more than one CNP - there needs to ensure the DFSP payee has to be certain the DFSP payer - connections + + § CNP needs to know everything, regulatory reporting - + + ○ Do we need to duplicate the structure in a Cross-network transfer? + + § Trying to prevent a rouge partner from joining + + § Trust the CNP to meet their SLAs + + ○ Mojaloop to another scheme - we don’t have control + + § Require they confirm receipt + + § How can I tell + + § How can I tell the person at the end got the money + + ○ External signing authority to confirm the money was received + + § If your scheme wants to participate in x-border then all the participants need to get signed + + § Public key - need to join a mojaloop network have to issue public keys + + § Central certificate issuing authority + + § Need a PKI structure in place + + ○ How do you get non-Mojaloop folks in the schema? + + § How do we integrate Mojaloop and some Mojaloop scheme to provide a full PVT payments - working group with Michael, Adrian, Sybrin, others as needed + + § Identify the participants - FSP, DFSP - all have signed + + § Parties - end users (Bob/Alice) + + § Single transaction (with multiple transfers) + + § No one commits their funds to everyone is satisfied + + § How to extend mojaloop and non-mojaloop scheme + + ○ Certification + + § Hash and PKKI + + § Gold and silver network + + § New partner - live on the network + + § Scheme decides requirement on the network + + § Self-signing cert + + ○ Liquidity + + § FXP does position mgmt + + § What requirements do we put on a FXP + + § Mobile money has less flexibility + + § Rules that happened across schemes + + ○ FXP has to manage the settlements, what expires when, etc.. + + § FXP has to manage the shortage of quote validity + + § Allow FXP to reject the requests + + ○ How do we manage requests for regulatory reasons + + § There is a dictionary + + □ Is the a requirement to share KYC? + + □ You can ask for many things - up to the participant + + □ Need to agree on the baseline scheme + +**Day #2:** + + - Switch data + + ○ Account numbers + + ○ Blacklist, white list (oversight and blocking) + + ○ Keeping it simple + + ○ Hub + + ○ Side service for folks that can do this + + § Mobile data capture + + § Side car + + § Digital process + + § Value added services for the hub (managed service) + + - Switch - need to maintain state and lookup requests + + - CNP can be an ordinary DFSP + + ○ All DFSP supports all the use cases + + ○ Full participants (might just provide a CNP or FXP service) + + - FXP definition and requirements + + ○ FXP - require rates/fees as part of the Quoting service - need standard industry rate + + § CNPs can extend this and determine additional scheme rules + + ○ FXP handles rounding errors + + ○ Guarantee a given rate + + ○ Manage settlement across schemas + + ○ FX rates + + ○ Should allow people that just do FX + + ○ Edge cases for failure + + § Details in the error messages to find the errors + + ○ FXP needs to point back the right information + + § How messages passed work + + § Edge cases - share what is done too date + + § Jo owns got a working API - identified + + § Changed the quote (intercepted the quote) -- + + § KYC extension list - extended the quote for this + + § Rates are in the extended list (are the list) + + § Where the FXP is applied ? + + § What do we do with fees downstream + + □ (payee DFSP takes place of the aggregation) + + - How to manage identifier resolution + + ○ 2 types of Identifiers + + § Global ones (pass to CNP) - to get a response + + § Local ones - expect the user to provide + + ○ Mojaloop we use identifiers as proxy + + ○ Merchant numbers might be specific to a scheme + + ○ Multiple identifiers for a single account + + ○ How do we uniquely identify the account? + + ○ Rely on CNP (restrict each identifiers in this scheme) + + ○ What sort of structures in place + + ○ Passport identification - place holders + + ○ Map pathfinder accounts/mobile accounts to DFSP unique IDs + + § Service - primary account is X + + § Each country has a service they provide + + § Each CNP understands the address scheme + + § Global one - need to know which ways to use + + ○ Sends a get parties to the switch + + § ALS never heard of them + + § 2 ways + + □ Global way (path finder and conversion to BIC) + - CNP + + ○ Not hosting anything + + ○ Route through the CNP - ask others + + ○ Constructing the alternative routes + + - Global registry does not exist + + ○ Ultimate beneficiary + + ○ Established communication + + ○ Challenge will we able to have 2 DFSPs share direct communication and will be a stretch? + + - Switch has schemes + + ○ A Hub operator following Scheme Rules may allow names of FSPs as decided by those Rules + + ○ The technology or the Admin API itself doesn’t restrict the names (apart from restrictions on length, type or characters, etc) + + ○ BGP: Border Gateway Protocol  + + - Query each CNP and then come up with optimizations, matrix that provides global route - goal would be not to query the CNP directly + +• How to connect with Mojaloop? + + - Any financial service can connect to Mowali + + - Scheme rules, technical + + - Regulatory + + - How do I assign stuff? - no one knows the steps + + - Mojaloop API - understand this. + + - 2 instances Mojaloop instances - TIPs and Mowali + + ○ WOCCU, Asia, US - applied for instance + + ○ Still pushing the boundries + + - What dos an integration look like + + ○ Need sandbox, simulators + + ○ Standard approach + +• Instance payment service + + - Get the flows flowing in a timely manner + + - Need real-time ledgers; what happens if they are offline? + + - Exception for off network (banks take advantage of float) + +• Discovery process (sending FSP) + + - Switch determines if they need to contact a FXP + + - What currency the receiving account can receive in + + - Multiple lookups + + - Data model - set of accounts, w/ one currency at a DFSP + + +Attendees: + + - Mike, Patricia - Thume + + - Michael R, Rob R, Sam - Modusbox + + - Kim, Lewis - Crosslake + + - Rolland, Greg, Phillip - Sybrin + + - Vanburn -- Terrapay + + - Megan, Simeon - Virtual diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/cb_board_1.jpg b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/cb_board_1.jpg new file mode 100644 index 000000000..e53cad0b9 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/cb_board_1.jpg differ diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/cb_board_2.jpg b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/cb_board_2.jpg new file mode 100644 index 000000000..8afa47d94 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/cb_board_2.jpg differ diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/cb_board_3.jpg b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/cb_board_3.jpg new file mode 100644 index 000000000..7cce85870 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/cb_board_3.jpg differ diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/mojaloop_spokes.png b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/mojaloop_spokes.png new file mode 100644 index 000000000..b0c67eb08 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/mojaloop_spokes.png differ diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_01.png b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_01.png new file mode 100644 index 000000000..4379443ce Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_01.png differ diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_02.png b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_02.png new file mode 100644 index 000000000..b86ac0a91 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_02.png differ diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_03.png b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_03.png new file mode 100644 index 000000000..d8ab17646 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_03.png differ diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_04.png b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_04.png new file mode 100644 index 000000000..a2913b226 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_04.png differ diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_05.png b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_05.png new file mode 100644 index 000000000..ba54dbf64 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_05.png differ diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_06.png b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_06.png new file mode 100644 index 000000000..8c4eb717f Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/images/tagging_06.png differ diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/iso-integration.md b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/iso-integration.md new file mode 100644 index 000000000..333ed8729 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/iso-integration.md @@ -0,0 +1,61 @@ +Mojaloop ISO Integration discussions + +# Mojaloop-ISO integration + +The proposed solution would be able to handle ISO to Open API translation and vice versa, by making use of an ISO-OPEN API converter/connecter plug-in or interface, similar to the Scheme Adapter in the Mojaloop system. As the Scheme adapter performs Mojaloop API to FSP API conversion, the custom plug-in/interface would function as a protocol and message translator between the ISO interface and the ML API or the Scheme Adapter. + +## Scope + +Define message flows in both and ISO and Open API networks and mappings between messages. + - Document failure scenarios and message flows for these. + - Define a mechanism for routing that is MSISDN-based . + - Mojaloop Transactions could be sent through existing payment rails conforming to their standards(such as ISO) + - Develop a scheme adapter/plug-ins that could perform ISO-Open API and vice versa. + - To be able to send Mojaloop transactions originating from ATM and POS over ISO networks, across Mojaloop systems + + ## ISO 8583 - Mojaloop - An Inter-network case study + +Africa is a great continent with a multitude of Financial Service providers who focuses on region based financial inclusion and services provision. The continent boasts of a vast network of Payment service providers and financial institutions. Some of the most prominent networks are listed below: + +- InterSwitch ( Nigeria) +- eProcess ( Ghana) +- Umoja Switch ( Tanzania) +- KenSwitch ( Kenya) +- ZimSwitch ( ZImbabwe) +- RSwitch ( Rwanda) + +Almost all of these networks make use of an ISO 8583 based Payments processing platform ( Postilion Switch) to drive ATM’s, POS & Mobile channels, process card based and non card based transactions for both acquiring and issuing verticals. + +As such, the proposition is to create a solution, where by the existing Payment networks could integrate with a Mojaloop based system like Mowali, without having to make any development or design changes to their existing infrastructure. + +In this case study, we are considering the case of Umoja Switch in Tanzania and provide them with a solution whereby, Umoja could provide Mojaloop transactions through their existing ATM deployments. + +### Umoja Switch + +UmojaSwitch was established in the year 2006 by six banks in Tanzania with the main purpose being able to establish a joint shared infrastructure for financial services and enjoying the economies of scale. + +The aim of establishment was to create a shared platform where financial institutions can integrate and interpolate through a shared switch. + +Eventually, the number of members joining the UmojaSwitch network continued to increase and as of now there are around 27 banks who has joined the Umoja Switch consortium. + +## ISO Networks to Open API + +The goal of the PoC would be to showcase how a Mojaloop transaction would be sent over a standard ISO switch/Network through to a Mojaloop system such as Mowali. + +As a part of this an ISO-Open API Adapter would be implemented which would process ISO messages originating from an ISO network like InterSwitch and send it through to an Open API network like Mowali. + +## Proposed Solution + +The proposed solution will consist of an interface or adapter/plugin that could process transactions between ISO networks and Mojaloop systems. + +The ISO payments platform makes use of an ISO interface which uses standard TCP/IP connection to send and respond to ISO messages to and from the various channels. In order to accept and process connections from the interface, our solution would have a TCP/IP listener, which would receive and process transactions from ISO network and then map it to Open API , after which the transactions will be sent over to a Mojaloop system like Mowali on a URL. + +In this case the payment networks are largely dependent on their respective (i.e. Visa/ MasterCard/Verve/etc) card or account number, which is used to define the BIN look up table for routing purposes . One of the options would be to predefine a Bin range (eg: 757575) that would identify a Mojaloop transaction and then let the payment network implement a routing logic that would send all Moja transactions through to the Open API network. + +The ISO-Open API adapter would process the ISO message received from the ISO switch and send it through to the Mojaloop system in Open API format. + +However, such changes would imply configurational changes to download applications on ATM and other terminal devices, but this could be handled as a standard operational change similar to the existing configurational changes performed as per the business requirements. + + + + diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/mojaloop-decimal.md b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/mojaloop-decimal.md new file mode 100644 index 000000000..119e51501 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/mojaloop-decimal.md @@ -0,0 +1,38 @@ +# Mojaloop Decimal Type; Based on XML Schema Decimal Type + +## Decimal value type + + Definition: decimal represents a subset of the real numbers, which can be represented by decimal numerals. The value space of decimal is the set of numbers that can be obtained by multiplying an integer by a non-positive power of ten, i.e., expressible as _i_ × 10-n where _i_ and _n_ are integers and _n_ ≥ 0. Precision is not reflected in this value space; the number 2.0 is not distinct from the number 2.00. The order relation on decimal is the order relation on real numbers, restricted to this subset. + Req: All Level One processors must support decimal numbers with a minimum of 18 decimal digits. However, Level One processors may conform to a scheme-defined limit on the maximum number of decimal digits they are prepared to support, which must be 18 or more digits, in which case that scheme-defined maximum number must be clearly documented. + +## Lexical representation + +decimal has a lexical representation consisting of a finite-length sequence of decimal digits (#x30 – #x39) separated by a period as a decimal indicator. An optional leading sign is allowed. If the sign is omitted, "+" is assumed. Leading and trailing zeroes are optional. If the fractional part is zero, the period and following zero(es) can be omitted. For example: -1.23, 12678967.543233, +100000.00, 210., 452 + +## Canonical representation + + The canonical representation for decimal is defined by prohibiting certain options from the Lexical representation (§3.2.3.1). Specifically, the preceding optional "+" sign is prohibited. The decimal point is required. Leading and trailing zeroes are prohibited subject to the following: there must be at least one digit, which may be a zero, to the right and to the left of the decimal point. + + This canonical form conforms to XML Decimal lexical representation, so it would be accepted by any XML schema conforming system. + + What others write in canonical form, we can read as a lexical representation; what we write in canonical form, others can read as a lexical representation. But we reject exponential formats on reading and we won’t write exponential form. We can directly compare the canonical string representations of two values for equality. + + When exchanging messages, a lexical form that shows implied precision using trailing zeros is preferred to pure canonical form if it improves clarity. E.g. We might write “5.00” instead of “5.0” where the unit of exchange is commonly specified precise to two decimal places, as in USD, EUR, or GBP. This lexical representation option is permitted within valid lexical forms of both XML decimal and Mojaloop decimal. + +## Validators + + Decimal Lexical Validator (what our message receivers accept): + +```^[-+]?(([0-9]+[.]?[0-9]*)|([.]?[0-9]+))$``` + +Decimal Canonical Validator (the form we store and compare; this pattern could be used to assert canonical form in generated messages): + +```^([0]|([-]?[1-9][0-9]*))[.]([0]|([0-9]*[1-9]))$``` + +## Translating Between External and Internal Forms + + When converting from lexical or canonical form to a binary internal representation, the value space of the internal representation must be large enough to hold the scheme-specific range of decimal values, with a significand defined as the signed integer range –10_m_–1..10_m_–1, and a non-positive integer exponent in the range –_m_..0, where _m_ is the maximum number of decimal digits, at least 18, and as defined by the specific Level One scheme. + +An implementation must not translate between decimal external representations and any floating-point binary internal representation. And all calculations on internal representations of decimal values must produce results as if they were performed in decimal long hand on the external representation. + +It should be noted that the value space of a signed 64-bit binary integer is sufficiently large to encode a signed 18-digit decimal significand and the value space of a signed 6-bit binary integer is sufficiently large to encode its required non-positive base-ten exponent. diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/performance-project.md b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/performance-project.md new file mode 100644 index 000000000..a554f6610 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/performance-project.md @@ -0,0 +1,175 @@ +# Performance Workstream + +Wednesday, March 11, 2020 + +## Performance Goals: + +- Current HW system achieving stable 1k TPS, peak 5k and proven horizontal scalability + 1. More instances = more performance in almost linear fashion. + 1. Validate the minimum infrastructure to do 1K TPS (fin TPS) + 1. Determine the entry level configuration and cost (AWS and on-premise) + +## POCs: + +Test the impact or a direct replace of the mysql DB with an shared memory network service like redis (using redlock alg if locks are required) + +Test a different method of sharing state, using a light version of event-drive with some CQRS + +## Resources: + +- Slack Channel: `#perf-engineering` +- [Mid-PI performance presentation](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/March2020-PI9-MidPI-Review) +- [Setting up the monitoring components](https://github.com/mojaloop/helm/tree/master/monitoring) + +## Action/Follow-up Items: + +- What Kafka metrics (client & server side) should we be reviewing? - Confluent to assist +- Explore Locking and position settlement - Sybrin to assist + 1. Review RedLock - pessimistic locking vs automatic locking + 2. Remove the shared DB in the middle (automatic locking on Reddis) + +- Combine prepare/position handler w/ distributed DB +- Review node.js client and how it impact kafka, configuration of Node and ultimate Kafka client - Nakul +- Turn back on tracing to see how latency and applications are behaving +- Ensure the call counts have been rationalized (at a deeper level) +- Validate the processing times on the handlers and we are hitting the cache +- Async patterns in Node + 1. Missing someone who is excellent on mysql and percona + 2. Are we leveraging this correctly + +- What cache layer are we using (in memory) +- Review the event modeling implementation - identify the domain events +- Node.js/kubernetes - +- Focus on application issues not as much as arch issues +- How we are doing async technology - review this (Node.JS - larger issue) threaded models need to be optimize - Nakul + +## Meeting Notes/Details + +### History + +1. Technology has been put in place, hoped the design solves an enterprise problem + +2. Community effort did not prioritize on making the slices of the system enterprise grade or cheap to run + +3. OSS technology choices + +### Goals + +1. Optimize current system +2. Make it cheaper to run +3. Make it scalable to 5K TPS +4. Ensure value added services can effectively and securely access transaction data + +### Testing Constraints + +1. Only done the golden transfer - transfer leg +2. Flow of transfer +3. Simulators (legacy and advance) - using the legacy one for continuity +4. Disabled the timeout handler +5. 8 DFSP (participant organizations) w/ more DFSPs we would be able to scale + +### Process + +1. Jmeter initiates payer request +2. Legacy simulator Receives fulfill notify callback +3. Legacy simulator Handles Payee processing, initiatives Fulfillment Callback +4. Record in the positions table for each DFSP + - a. Partial algorithm where the locking is done to reserve the funds, do calculations and do the final commits + - b. Position handler is Processing one record at a time + +5. Future algorithm would do a bulk + +- One transfer is handler by one position handler + - Transfers are all pre-funded + +1. Reduced settlement costs +2. Can control how fast DFSPs respond to the fulfill request (complete the transfers committed first before handling new requests) +- System need to timeout transfers that go longer then 30 seconds + - Any redesign of the DBs + - Test Cases + +- Financial transaction + - End-to-end + - Prepare-only + - Fulfil only + +- Individual Mojaloop Characterization + - Services & Handlers + - Streaming Arch & Libraries + - Database + - What changed: 150 to 300 TPS? + +- How we process the messages +- Position handler (run in mixed mode, random + - Latency Measurement + +1. 5 sec for DB to process, X sec for Kafka to process +2. How to measure this? + +### Targets + +1. High enough the system has to function well +2. Crank the system up to add scale (x DFSPs addition) +3. Suspicious cases for investigations +4. Observing contentions around the DB +5. Shared DB, 600MS w/ out any errors + - Contention is fully on the DB + - Bottleneck is the DB (distribute systems so they run independently + + + +- 16 databases run end to end +- GSMA - 500 TPS +- What is the optimal design? + +### Contentions + +1. System handler contention + - Where the system can be scaled +1. If there are arch changes that we need to make we can explore this + - Consistency for each DFSP + - Threading of info flows - open question + +1. Sku'ed results of single DB for all DFSPs +1. Challenge is where get to with additional HW + - What are the limits of the application design +1. Financial transfers (in and out of the system) + - Audit systems + - Settlement activity + - Grouped into DB solves some issues + - Confluent feedback + +1. Shared DB issues, multiple DBs + +1. Application design level issues + +1. Seen situations where we ran a bunch of simulators/sandboxes + - Need to rely on tracers and scans once this gets in productions + - Miguel states we disable tracing for now + +### Known Issues + +1. Load CPU resources on boxes (node waiting around) - reoptimize code +2. Processing times increase over time + +## Optimization + 1. Distributed monolithic - PRISM - getting rid of redundant reads + 2. Combine the handlers - Prepare+Position & Fulfil+Position + +### What are we trying to fix? + 1. Can we scale the system? + 2. What does this cost to do this? (scale unit cost) + 3. Need to understand - how to do this from a small and large scale + 3. Optimized the resources + 4. 2.5 sprints + 5. Need to scale horizontal + 6. Add audit and repeatability - + +### Attendees: + +- Don, Joran (newly hired perf expert) - Coil +- Sam, Miguel, Roman, Valentine, Warren, Bryan, Rajiv - ModusBox +- Pedro - Crosslake +- Rhys, Nakul Mishra - Confluent +- Miller - Gates Foundation +- In-person: Lewis (CL), Rob (MB), Roland (Sybrin), Greg (Sybrin), Megan (V), Simeon (V), Kim (CL) diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/psip-project.md b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/psip-project.md new file mode 100644 index 000000000..d517d6f10 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/psip-project.md @@ -0,0 +1,21 @@ +# PISP (3rd party payment initiation) + +## Goal: + +Updated Mojaloop specification documents, and POC implementation of a PISP + + +## Action Items: + +- Revisit /authorizaitons resource: [Michael] and raise with CCB +- Identity provider research and follow-up: [Matt de Haast] +- Share all sequence diagrams: [JJ] +- Outline proposal at high level including new API calls - Unassigned +- Mapping account information (info about accounts for PISP) - [Lewis] + +## Links: + +- [London Meeting Notes](./pisp_meeting_march_2020.md) +- [WIP Separate Docs Repo with sequence diagrams](https://github.com/jgeewax/mojaloop-pisp) +- [End to End Sequence Diagram](https://plantuml-server.kkeisuke.app/svg/xLhhRnkv4V--VmKX571iI8eaEx4Z875aoyu9Tt44hz8WWFg1sgMaFQz87ScreXRvtpl3nxuaEx7H5bVW0kJXvN1cE9pvpODvhpILEbkbWKvqoiXu58w9bfIhEPDa9MAMJlcBJ2LyGJuo6Iqfr-IM_P4nfOaMP4otv2DI7GOqqaAImPQf9ILKaSj1i0RUIPIiSLF3i1wirmrSXB_th8PCtZC90eVNuVZG40wxLRfma-XeQPR2wihWjz2o9ZNET0j7GOwECHaurhrTGbOXl724n-vmZOiblOVpmVh5-r2is6R99BD4bnS15veH0IS0rIRBH96r56kXQ4fYmHI1PIB1T8ba10svW6zWmi5uH82tCWTh1oXOaSrIa5mvu9fmefUCg6Z9LeniaZGbdB4Ozw_e7IDw8ppFVj0z9AEveSzl4fH9UA8Ju1MJsPPGSzDD4edrrb3-aQ7oagcru8eXN_oAH47l6UnoohqSVnEB9C8lCqOoPOz1LSIafd1GC2fGIZGAcko7WiV04RwhfTXmD5IQSDOEHXg9gLBP2WKigUu7hNU4WkMYJ6cuF4be1imv69dgH72aZwYK2T2BJ1DXRUwf3nI9sNqICMHZt2FETC9G8JXbQbbWI9H323I0suxP77IAQxSeinHsKmxIrap2VeYnHPP0C06n2XWie4S5Rz-IOQ8YTAmjUVisk1oqta7yz4Ta8x8qXlFUMVCwcLF-jswdWrzAJeeUdDoZAs7emU_Mks6txwBrMNmWCeVTbbNb0znJejj1p2fYO1sbV07Zet6jDB3ZseJa7TkUJ_b8muV1-wjKEG6uAOGzIRIqPePhhL30fXT7Hn-k9kIb2H6cZeuE2xr24eGj8xVNwVN9w01kVC4qcT7e3W-p5LbPJpX628TuL639U2GOj50_exP5aygfaHc8jYj4hHczKsIEm5WwueuDGz2rGpxzsYGBOyaoIpXF0IomOUAYY2Y3bWPR-87EyU2EYqrWvE1F2jq8dGvilW9VxyCFS1M880547q16dC8-gWpS454BzBaKgy0TqpiaUU2AIbxob2jwzWsLvJrwGnUxDtJS7nevzeRC1Urd1zW_F7Otz6DLGoH6xhTC0uxS5-W1iGz2LXObZ3YRIio6iFyBI0LrtKSC4S0EmI5rbFRj6l3u4Ry1pH_onT9HftooB6kPw_149pK-WL0GRfLcAq34jP1QJNdEcbF0l7tySq2w7FGd01M57Pf49ekbFaV8izo_CjK4qS0dnx3BakvBkZO92F16BS6WKux-Zy3gqe_X1yf1MaqW6kg0LGcqK82xRyZ8H1IP2RqqB6131lVY_BhleWEbkp1prOPTk2WlsEeYk35SVRnALqqvFdb6BsAsI0KsyCOfev1HgRehRQgXDWQkByOGmUj6_t48abeCLgiRvWeMj2LBxZ6HaHLJYYwOjNyg17YRpIb0BJY3R9-A3MRc0wI6ofF7LCPGF_vEWNhjzmVZJo40XpaGAY2uApWL-MKo6R_ijhi177lqQTmAHIOZrhTLXVis1Cg4cu3fU_i4_me8_6hiyXp5ZJvfdCN79_CttRWLTqxFMYUTqzFMMU_rSQiNTKvEpqvVpwFvwqRJyZ0N2PiiI_T9wkqe7a6eLXRAYvFj6dT1cJeQX8vNdGPhaNd29DALOhJH95NokLfRlQsBDVBLx-PVtqkQofgc3bRsgng9rJfbtsuWKdSMhU14AksM6zQxQaSnP2ajg2RqBg6D2ittGj_cVzU8fQHRfwxQSF2G3UbAP5nxkRTNbrUZlryrAejL2-VV6X269Q6DA9EIyMYBIv_3OQCYfkIOJbQ99LJ6dCf467FU3cx2wwlRCcTN4GjpvF7WwmEh_X2Ndsx2pn-1gA81XdTng-G-iJMzFohxjawa2Iea0ipej3gzLlVLfDVhTq_xlRFscxDNhKwt3uSsE_uHV2zL327YLWXAC5j_ED0p6Qht7m4qwEQ6lQSawfuHlKSdgBS72yaOGYyPBr4pgBgHFeTUQEpkeL0dfXU3l41D_rGaTyFF7w04kXPpUpzNzlGga3jOG6_Kj9oniI4sM3LBjmMK-YxE7kG6Vp1WZ1cJHsaMCrNKTpKSj1OsM0rPCi7QmpEgeQsh1n_4smiFjqOT6sMdKU-OdNMYdq7OadOEdb_DmIwzUUlupQpNEddJdRNEkgUiTK8xnxtESNmoxvxisVn_1V5_8VnV2FyaX2TFXlWdONWDlQ7LSDXdCSOCH_8H5rQoEsZtpDPf3Aq3bIoVIjdMfsYJV45Th3srBIh3AjRY6rOTfb4tIiCFIrY7W_85zCn2tc57q0w-i5BrZdsEW-LIYrSQTpK39N8OZYZl1_IGVEOn12hYjgtqfO2KerIz0GzcX-JMYd3ZACtaQeUCl63jHPlC6LE7NhHll8hkmIRRkWsBgT_-PFf8osTJw4ZPurFRuxIA0PrXZxE0fCtQTWXQICK43dlsuVNvOK1JJMw4w_NuWVR2XjYKcGi960G-AHh2jYUvJfnHpLJEkwOLaQUqikxbvimEwB1LfSenCHjSKtTk5DiZT9BdvReH_1srfxok_Cu1m_wra1lCv3-OoUuhAIeNjJEBnWdfbclS6D4KYePiaMwRq9D5D0FcPXQon3aWpfAmQmueEJeQVvuS7H7sBM9hRGUTXJBKswPDBZ8DKOGH3a4Yjm6TuG3Lze6WfMotsrKtxFg9Ht5Er00gGB0OHD6JHsH-r3YvFlV__hHi0dqRMcq8EZYIguMA2ieVPihDQKepQtSiWrdOo99iNHzhEpUoedmLwSzYYiAz6wezTQMenFAt7BXeutkQ9Z7LhC9iojri3UVNKApzqq2EUhalb8wEdbz-selwNsbNlkYVIXVMz1-0PbMsFIX4TulmoetX9Cd0eCyp5bHn4uYHvP7_Rbhpuwh7vvT-eFMOc18oU2CN3n8c8AHYwTmy4KI2Gscs0bT57uQb0ydyk4jW-eWW8ULF0owuLbio1x1XSYqJRlnvjRjdPuu67Gy18cXnM5oetIwc_Gy7eX_wXrLkJddFBdSKyp3WqWBSbPyVcOZ3oH6aZh4KCpe3kFezKte7dFqECm_Vm4S0BjsSSYY2uPpADsSp1ZU07dl7J6PsdgaOub8zFBgF5GzTbqH_udZFpAO5bDHTb_1iDSDNA-m4bKPNg7HoVdsHt3FktvfCJBHnokkc_kxDRPwb-D36gvAWFO3BC7wCRV34Vy-xuDA0jES7fFcppepoEpCiLVa8jcgV8F-yeLoRrq_VnLRrADSwWPZ39_lSLyp7CHct2SuXZLH4-0LSx99HI5mGBzvcPRRcKR1mDsSXZZKR68D2DiITK0skayY27LmoP3C0VsFpmc0gYo9mFJHYyLZkVD5C4inCD0v0vThZIQcE6LLAeF95KwL4PAg7ANUfn4EPlUhpwaLyOOW6xZnVyGR5joPHK5qmsIHmFUsg_6gPyVXRxGyhZOT75iRdj11_vje3Id2TxTRJVxvYPCftgf5AhL5r438QJhbnPpHmOlwlnjpNnG_cn3pU3PJcFhx_gUOhfh1vncF05Kno1JrSi1SXRPVauhPTFEHCbXYsQ6RphBtAyFy-r3995NZHBV3tU_WZMwN_1W00.svg) +- [Initial PISP Design Doc, v5](https://github.com/mojaloop/documentation-artifacts/blob/master/presentations/January%202020%20OSS%20Community%20Session/%5BEXTERNAL%5D%20Mojaloop_%20PISP%20Credit%20Transactions(3).pdf) diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/versioning-draft-proposal.md b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/versioning-draft-proposal.md new file mode 100644 index 000000000..790dd4452 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/versioning-draft-proposal.md @@ -0,0 +1,281 @@ +--- +Authors: Lewis Daly, Matthew De Haast, Samuel Kummary +Proposal Name: Mojaloop Versioning Proposal +Solution Proposal Status: Draft +Created: 26-Feb-2020 +Last Updated: 17-Mar-2020 +Approved/Rejected Date: N/A +--- + +# Mojaloop Versioning, A Proposal + +_Note: This document is a living draft of a proposal for versioning within Mojaloop. Once the proposal is ready, it will be submitted to the CCB for approval._ + +## Overview + +The aim is to produce a proposal that keeps the versioning Scheme simple to use and clear regarding compatibility issues. However, it needs to include all the details needed for a Mojaloop ecosystem as well. + +Goal: +Propose a standard for a new 'Mojaloop Version', which embodies: +1. Helm: Individual Service Versions, Monitoring Component Versions +2. API Versions: FSPIOP API, Hub Operations / Admin API, Settlement API +3. Internal Schema Versions: Database Schema and Internal Messaging Versions + +## Versioning Strategies/Background (Literature Review) + +How do current systems handle versioning? Give a brief overview of the current space. +* Most best practices follow semantic versioning for APIs, this will be covered more in [#1198](https://github.com/mojaloop/project/issues/1198) + +### Demonstrates zero-downtime deployment approaches with Kubernetes [5] + +Key observations: +* in order to support rollbacks, the services must be both forward and backwards compatible. +consecutive app versions must be schema compatible +* 'Never deploy any breaking schema changes', separate into multiple deployments instead + +For example, start with a PERSON table: +``` +PK ID + NAME + ADDRESS_LINE_1 + ADDRESS_LINE_2 + ZIPCODE + COUNTRY +``` + +And we want to break this down (normalize) into 2 tables, PERSON and ADDRESS: + +``` +#person +PK ID + NAME + +#address +PK ID +FK PERSON_ID + ADDRESS_LINE_1 + ADDRESS_LINE_2 + ZIPCODE + COUNTRY +``` + +If this change were made in one migration, 2 different versions of our application won't be compatible. Instead, the schema changes must be broken down: +1. Create ADDRESS table + * App use the PERSON table data as previously + * Trigger a copy of data to the ADDRESS table +2. The ADDRESS now becomes the 'source of truth' + * App now uses the ADDRESS table data + * Trigger a copy of new added to address to the PERSON table +3. Stop copying data +4. Remove extra columns from PERSON table + +This means for any one change of the database schema, multiple application versions will need to be created, and multiple deployments must be made in succession for this change to be made. +* [5] also notes how simple Kubernetes makes deploying such a change + * rolling upgrade deployments + * Tip: make sure your health endpoint waits for the migrations to finish! +* Q: so how do we make big changes that touch both the database schema and the API? + * this seems really hard, and would need a lot of coordination + * If we don't design it correctly, it could mean that a single schema change could require all DFSPs to be on board + * This is why I think the API version and Service version should be unrelated. We should be able to + deploy a new version of a service (which runs a migration), and supports an old API version + + +### Using a schema registry for Kafka Messages [6] + +* [6] suggests some approaches, such as using a schema registry for kafka messages, such as [Apache Arvo](https://docs.confluent.io/current/schema-registry/index.html) +* This adds a certain level of 'strictness' to the messages we produce, and will help enforce versioning +* Adds a separate 'schema registry' component, which ensures messages conform to a given schema. This doesn't really + help enforce versioning, and leaves the work up to us still, but does give more guarantees about the message formats. + +### Backwards and Forwards Compatibility [3], [4] + +* "The Robustness principle states that you should be “liberal in what you accept and conservative in what you send +”. In terms of APIs this implies a certain tolerance in consuming services." [3] +* Backwards Compatibility vs Backwards Incompatibility [4]: + * Generally, additions are considered backwards compatible + * Removing or changing names is backwards incompatible + * It's more something to assess on a case-by-case basis, but [Google's API Design Doc](https://cloud.google.com/apis/design/compatibility) helps lay out the cases. + +## Mojaloop Ecosystem +When discussing versioning we need to be clear that we are versioning interfaces for various parties. + +# Proposal +The following section will outline the versioning proposal. + +## A “Mojaloop Version” +A Mojaloop Version **x.y**.z can be defined that can encompass the versions of all the three APIs included (detailed below). +In the version **x.y**.z, ‘x’ indicates the Major version and ‘y’ a minor version, similar to the Mojaloop FSPIOP API versioning standards; ‘z’ represents the ‘hotfix’ version or a version released with the same major, minor version x.y but to keep things simple, there is a need to bundle all the components included in the Mojaloop ecosystem indicating what all items are included there. + +In effect we may say Mojaloop version **x.y** includes +1. Mojaloop FSPIOP API + * Maintained by the CCB (Change Control Board) + * Uses x.y format + * Currently version v1.0, v1.1 and v2.0 are in the pipeline +2. Settlement API + * Maintained by the CCB + * To use x.y format + * Currently version v1.1 and v2.0 is in the pipeline +3. Admin / Operations API + * Maintained by the CCB + * To use x.y format + * Can use version v1.0 +4. Helm + * Maintained by the Design Authority + * Uses x.y.z format + * PI (Program Increment) + Sprint based versioning. + > *Note:* _PI + Sprint based versioning_ make sense in the context of the current Mojaloop Program Increments, but will need to be revised at a later date. + * Bundles compatible versions of individual services together +5. Internal Schemas + * Maintained by the Design Authority + * DB Schema x.y + * Internal messaging Schema (Kafka) x.y + +| **Mojaloop** | x.y | | | +|---|---|---|--- +| | Owner/Maintainer | Format | Meaning | +| **APIs** | | | | +| - FSPIOP API | CCB | *x.y* | Major.Minor | +| - Settlement API | CCB | *x.y* | Major.Minor | +| - Admin/Operations API | CCB | *x.y* | Major.Minor | +| Helm | Design Authority | *x.y.z* | PI.Sprint.Increment | +| **Internal Schemas** | | | | +| - DB Schema | Design Authority | *x.y* | Major.Minor | +| - Internal Messaging | Design Authority | *x.y* | Major.Minor | + + + +For example: Mojaloop 1.0 includes +1. APIs + * FSPIOP API v1.0 + * Settlements API v1.1 + * Admin API v1.0 +2. Helm v9.1.0 + * Individual services' versions + * Monitoring components versions +3. Internal Schemas + * DB Schema v1.0 + * Internal messaging version v1.0 + +| **Mojaloop** | v1.0 | | | +|---|---|---|--- +| | Owner/Maintainer | Version | +| **APIs** | | | | +| - FSPIOP API | CCB | *1.0* | +| - Settlement API | CCB | *1.1* | +| - Admin/Operations API | CCB | *1.0* | +| Helm | Design Authority | *9.1.0* | +| **Internal Schemas** | | | | +| - DB Schema | Design Authority | *1.0* | +| - Internal Messaging | Design Authority | *1.0* | + +### Advantages + +1. The advantage of this strategy is primarily simplicity. A given version say - Mojaloop v1.0 can just be used in + discussions which then refers to specific versions of the three APIs - FSPIOP, Settlements, Admin APIs, along with the Helm version that is a bundle of the individual services which are compatible with each other and can be deployed together. +Along with these, the Schema versions for the DB and Internal messaging to communicate whether any changes have been made to these or not since the previously released version. +2. The other advantage, obviously, is that it caters for everyone who may be interested in differing levels of details +, whether high level or detailed. Because of the nature of the major and minor versions, it should be easy for Users and adopters to understand compatibility issues as well. + +### Compatibility +As described in [section 3.3 of the API Definition v1.0](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#33-api-versioning), whether or not a version is backwards compatible is + indicated by the **Major** version. All versions with the same major version must be compatible while those having different major versions, will most likely not be compatible. + +_Important Note: Hub operators will likely need to support multiple versions of the FSPIOP API at the same time, in order to cater for different participants as they can't all be expected to upgrade at the same time._ + +## Breaking down the “Mojaloop Version” +This section aims to break down the above proposed mojaloop version into its constituent parts, and provide support for the above proposed versioning strategy + +### APIs + +The [Mojaloop Spec](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#33-api-versioning) already outlines many of the decisions made around versioning APIs. + +In terms of common best practices, there are many approaches for requesting different versions, including adding in a + version in the url, but let's not worry about this because the spec already lays this out for us, using the HTML vendor extension: [3.3.4.1 Http Accept Header](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#3341-http-accept-header) + +As for version negotiation, the spec also states that in the event of an unsupported version being requested by a + client, a HTTP status 406 can be returned, along with an error message which describes the supported versions. [3.3.4.3 Non-Acceptable Version Requested by Client](https://github.com/mojaloop/mojaloop-specification/blob/master/documents/API%20Definition%20v1.0.md#3343-non-acceptable-version-requested-by-client) + +Another best practice around versioning is specifying to what level clients may request specific apis. +* In a development environment, many APIs will allow specificy up to the BUGFIX version, i.e. vX.X.X +* In production however, this is limited to Major versions only, e.g. v1, v2 +* e.g. The Google API Platform supports only major versions, not minor and patch versions +* Given the new features that may become available with v1.1 of the Mojaloop API, we might want to allow participants + to specify MAJOR and MINOR versions, i.e. vX.X. This practice should be avoided however, since minor versions should be backwards compatible + +Participants using the same MAJOR version of the API should be able to interact. Participants on different MAJOR +versions are not able to interact. For example, a participant on API v1.1 can send transfers to another participant on v1.0, but not to a different participant on v2.0. + +### Helm +This section deals with how Mojaloop services interact within a given deployment. Here, we attempt to propose questions such as "should an instance of central-ledger:v10.0.1 be able to talk to ml-api-adapter:v10.1.0? How about ml-api-adapter:v11.0.0?"? or "how do we make sure both central-ledger:v10.0.1 and central-ledger:v10.1.0 talk to the database at the same time?" + +There are two places where this happens: +1. Where services interact with saved state - MySQL Percona Databases +2. Where services interact with each other - Apache Kakfa and (some) internal APIs + +This implies we need to version: +* the database schema +* messages within Apache kafka + * need to make sure the right services can appropriately read the right messages. E.g. Can mojaloop/ml-api-adapter:v10 +.1.0 publish messages to kafka that mojaloop/central-ledger:v10.0.1 can understand? + * Q: If we decide to make breaking changes to the message format, how can we ensure that messages in the kafka streams + don't get picked up by the wong services? + +### Internal Schemas + +#### Database + +todo: anything to be said here? + +#### Kafka/Messaging +Currently, we use the lime protocol for our kafka message formats: https://limeprotocol.org/ + +Also refer to the mojaloop/central-services-stream readme for more information about the message format. + +The lime protocol provides for a type, field, which supports MIME type declarations. So we could potentially handle messages in a manner similar to the API above (e.g. application/vnd.specific+json). Versioning messages in this manner means that consumers reading these messages would need to be backwards and fowards compatible (consecutive message versions must be schema compatible). +* Q. does it make sense to put the version in the Kafka topic? + * One example, ml-api-adapter publishes messages to the prepare topic + * If we add versioning to this, ml-api-adapter:v10.0.0 publishes messages to a prepare_v10.0 topic, and a new instance + of the ml-api-adapter:v10.1.0 will publish to the prepare_v10.1 topic. + * subscribers can subscribe to whichever prepare topic they want, or both, depending on their own tolerance to such + messages + * This may have some serious performance side effects +* Another potential option would be to allow for a message 'adapter' in the deployment. Say the ml-api-adapter:v10.1.0 is producing messages to a prepare_v10.1 topic, and there is no corresponding central-ledger in the deployment to read such messages, we could have an adapter, which subscribes to prepare_v10.1, reformats them to be backwards compatible, and publishes them to prepare_v10.0 in the old format. + +Such an approach would allow for incremental schema changes to the messaging format as services are gradually upgraded. + +All in all, I didn't see too much about this subject, so we'll likely need to return later down the line. + +## Version Negotiation +todo: @sam Discuss how to deal with version negotiation strategy + +## Long Term Support +todo: Discuss how long term support fits into the versioning proposal. I don’t think we want to get into too much detail, but more outline what it might look like + +Mention current (lack of) lts support, current PI cadence + +## Appendix A: Definitions + +* **service**: Mojaloop follows a microservices oriented approach, where a large application is broken down into smaller + micro services. In this instance, Service refers to a containerized application running as part of a Mojaloop deployment. At the moment, this takes the form of a Docker container running inside of a Kubernetes cluster. e.g. mojaloop/central-ledger is the central-ledger service +* **service version**: The version of the given service. This currently doesn't follow semantic versioning, but may in the + future e.g. mojaloop/central-ledger:v10.0.1. The current approach is described in more detail in the [standards + /Versioning doc](https://github.com/mojaloop/documentation/blob/master/contributors-guide/standards/versioning.md). +* **helm**: Helm is an application package manager that runs on top of Kubernetes. It may also be referred to as the + "deployment". A single helm deployment runs many different services, and MAY run multiple versions of the same service simultaneously. We also refer to the deployment as it's repo, mojaloop/helm interchangeably. +* **helm version**: A helm version is the version of the packaged helm charts, e.g.mojaloop/helm:v1.1.0 +* **interface**: An interface is the protocol by which a Mojaloop switch interacts with the outside world. This includes + interactions with Participants (DFSPs) who transfer funds through the switch, hub operators running a Mojaloop switch, and admins performing administrative functions. +* **api**: Application Programming Interface - in most cases referring to the FSPIOP-API a.k.a. Open API for FSP + Interoperability defined [here](https://github.com/mojaloop/mojaloop-specification). +* **api version**: The Version of the FSPIOP-API, e.g. FSPIOP-API v1. For the purposes of this document, it refers to the + contract between a Mojaloop Switch and Participants (DFSPs) who implement the FSPIOP-API + +## References + +[1] LTS versioning within nodejs. This is a great example of an LTS strategy, and how to clearly communicate such a strategy. +[2] Semantic Versioning Reference +[3] https://www.ben-morris.com/rest-apis-dont-need-a-versioning-strategy-they-need-a-change-strategy/ +[4] https://cloud.google.com/apis/design/compatibility +[5] Nicolas Frankel - Zero-downtime deployment with Kubernetes, Spring Boot and Flyway +[6] Stackoverflow - Kafka Topic Message Versioning + diff --git a/website/versioned_docs/v1.0.1/community/archive/discussion-docs/workbench.md b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/workbench.md new file mode 100644 index 000000000..34b7f49ee --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/discussion-docs/workbench.md @@ -0,0 +1,246 @@ +# Mojaloop Lab/Workbench Discussion + +___Goal:__ This discussion document aims to lay out the case and align the community around the development of an educational Mojaloop Lab environment._ + + +## 1. Goals for the PI8 Convening: + +1. Define terms and outline assumptions +2. Outline existing efforts and how the OSS Community aligns with them (GSMA, MIFOS, ModusBox) +3. Define users and usecases, and exclude the users we won't worry about +4. Recommendations for a few different solutions to the "Lab Problem" + - Documentation around business cases and personas Dan developed + - Basic implementation of Lab Configurer, help people build labs with different features + - Simple Mojaloop-over-spreadsheets demo, to get people using mojaloop without Postman +5. Basic implementation and demo +6. Pose important questions and discuss next steps + +## 2. Nomenclature + +**1. Tools:** +- 1.1 A device used to carry out a function +- 1.2 Different tools for different functions: You wouldn't use a screwdriver to drive a nail. +- 1.3 In a Mojaloop context, one example of a tool is the Bank Oracle + - The Bank Oracle is a tool that plugs into the Account Lookup Service, can be used to allow Mojaloop to connect to existing bank accounts with an IBAN + +**2. Workbench:** +- 2.1 Combines different tools together in one place +- 2.2 For example, a hand plane, table saw and chisel can make up a woodworking workbench, while a hacksaw, file and angle grinder can make up a metalworking workbench +- 2.3 In the mojaloop parlance, tools to test my DFSP's JWS keys are in a different workbench than tools that demonstrate to a fintech how wholesale api's can work on top of Mojaloop + +**3. Lab:** +- 3.1 A lab is a place you go to run experiments +- 3.2 We run experiments in order to learn, and test our assumptions + - For example, a DFSP can set up and run an _experiment_ where they send and receive Quotes using an in-development API +- 3.3 A single lab combines multiple workbenches together in one place + +**4. Simulator:** +- 4.1 A tool that simplifies or abstracts away some function so you can test one thing at a time +- 4.2 Pilots train with simulators _before_ flying a real life, dangerous and expensive plane. +- 4.3 Within Mojaloop: a simulator can simulate interacting with some component of the system + - Replace an entire switch to test a DFSP implementation + - Simulate 2 DFSPs to test a switch deployment + - A simulator also reduces the need for someone to be with the person testing. So a DFSP can send and receive via the switch, without interaction with the Hub Operator. + + +## 3. Assumptions + +>_Some of these may go without saying, but it's noting them here anyway._ + +- 1\. The Gates Foundation wants to encourage adoption for Mojaloop at all levels (not just switches) +- 2\. We don't need a lab environment to serve the needs of a Switch deployment or implementing DFSP - these needs will be met elsewhere +- 3\. The Mojaloop OSS Community wants to make itself attractive + - This doesn't mean removing all barriers to entry; but assessing which barriers we should be removing + + +## 4. Users + +We divide users in 2 camps: Primary users and Secondary users. + +### 4.1 Primary Users +1. DFSPs needing to integrate with Mojaloop: (shorthand: Implementing DFSP) +2. Organisations/Individuals wishing to learn about Mojaloop and wanting to build and test functionality or use cases as a DFSP (shorthand: Evaluating DFSP) +3. Organisations/Individuals wishing to learn about Mojaloop and wanting to build and test functionality or use cases as a Hub Operator (shorthand: Evaluating Hub Operators) +4. Regulators, Organisations or Individuals wishing to understand and evaluate Mojaloop and how it might impact their existing service (shorthand: General Evaluators) + +### 4.2 Secondary Users +5. Systems Integrators wishing to offer Mojaloop as a Service or pieces of Mojaloop integration as a Service (Systems integrator) +6. Individual Contributors (including bug bounty hunters?) (Individual Contributor) +7. Fintechs operating on top of or who will operate on top of a mojaloop-enabled switch (Mojaloop-powered fintech) +8. 3rd Party App Provider interacting with wholesale mobile money APIs, selling integrations to fintechs and the like (3rd party app provider) +9. Financial Advocates, who are interested in promoting Mojaloop and other technologies that help drive financial inclusion (Financial Inclusion Advocates) + +In addition to thinking of each of the above users, it's important to understand at what level these users exist at in relationship to a mojaloop deployment. For that we will borrow from Dan Kleinbaum's [_Fintech primer on Mojaloop_](https://medium.com/dfs-lab/what-the-fintech-a-primer-on-mojaloop-50ae1c0ccafb) + +![the 3 levels of mojaloopyness](./images/mojaloop_spokes.png) +>_The 3 levels of Mojaloopyness, https://medium.com/dfs-lab/what-the-fintech-a-primer-on-mojaloop-50ae1c0ccafb by Dan Kleinbaum_ + +**Level 1:** Running a Mojaloop switch (e.g. Hub Operators) +**Level 2:** Interacting with a Mojaloop Switch directly (e.g. DFSPs, Systems Integrators) +**Level 3:** Interacting with a DFSP over a Mojaloop Switch (e.g. Fintechs) + + +## 5. Use Cases + +__a.__ Test a Mojaloop compatible DFSP implementation +__b.__ Validate assumptions about Mojaloop +__c.__ View and use a reference implementation +__d.__ Learn about Mojaloop internals +__e.__ Learn about Mojaloop-enabled switches and associated use cases (technology) +__f.__ Assess how Mojaloop will change fintech business landscape +__g.__ Be able to demonstrate a value proposition for DFSPs/Fintechs/etc. to use mojaloop (instead of technology _x_) + + +## 6. User/Use Case Matrix: + +We can plot the users and use cases in a matrix: + + +| __Usecase:__ | a. Test DFSP Impl | b. Validate Assumptions | c. Reference Impl | d. Learn Internals | e. Learn about Tech | f. Evaluate Business Cases | g. Demonstrate ML Value | +| :----------------------------------- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| __User:__ | | | | | | | | +| __1. Implementing DFSP__ | X | | X | | | | | +| __2. Evalutating DFSP__ | | X | X | | X | X | | +| __3. Evaluating Hub Operator__ | | | X | | X | X | | +| __4. General Evaluator__ | | | | | X | X | | +| __5. Systems Integrator__ | X | X | X | X | | | X | +| __6. Individual Contributor__ | | X | X | X | | | | +| __7. Mojaloop-powered fintech__ | | X | | | X | X | X | +| __8. 3rd Party App Provider__ | | | | X | | | X | +| __9. Financial Inclusion Advocates__ | | X | | | | X | X | + + +## 7. Usecase Inputs and outputs: + +>_Pick 2 or 3 different users/usecases and drill down into the inputs and outputs for what meeting their needs may look like_ +>>_Note: As with anything of this nature, a lot of the users/usecases and associated conclusions are somewhat squishy, and can likely be put into different or altogether new boxes. Nonetheless, we will try to define these as well as possible._ + +### 7.1 Evaluating Hub Operator + Implementing DFSP +As stated in our above assumptions, we aren't going to worry about Hub operators and Implementing DFSPs here. + +### 7.2 Evaluating DFSP + +>_We think of an evaluating DFSP as one who is not necessarily part of a current switch implementation, but a party who is mojaloop-curious, and a potential candidate to evangelize mojaloop to - without the tangible goal of a switch implementation in sight._ + +**7.2.1 Use cases:** +- 1\. Validate assumptions about Mojaloop (how it works, what it does, what it _doesn't_ do) +- 2\. View and play with a reference implementation +- 3\. Learn about mojaloop-enabled hubs and associated use cases (technology perspective) +- 4\. Assess how Mojaloop will affect their business in the future + +**7.2.2 Examples from our user personas:** +- 1\. Carbon - Enable cash-outs and OTC remittances over their agent network +- 2\. Ssnapp - Enable multi payer/payee payments and rewards points over mojaloop +- 3\. Oneload - Simplify onboarding for other DFSPs to utilize OneLoad's agent network +- 4\. Juvo - Plug in to a Mojaloop switch for a credit scoring and lending marketplace + +**7.2.3 Outputs: (How can the Mojaloop OSS Community better serve these players?)** +- 1\. help to onboard to the mojaloop ecosystem +- 2\. help to understand the technology, where it works well, and the potential pitfalls/drawbacks +- 3\. minimize investment in getting things working so they can focus on building out use case prototypes +- 4\. take them from little to no understanding of Mojaloop -> demonstrating real prototypes + +**7.2.4 Inputs: (what are the things that we need to do to meet these goals)** +- 1\. Improved mojaloop documentation specific for this role. + - 1.1 Think about and design the documentation and onboarding flow specifically for *Evaluating DFSPs* + - 1.2 Documentation should be approachable by product manager etc. with little technical knowledge +- 2\. Technical deep dive on the technology behind mojaloop, why, how it works (perhaps we can repurpose the js demonstrator in an interactive walkthrough an end to end transaction) +- 3\. Improved guides for up and running on 2-3 major kubernetes providers, self service and install scripts +- 4\. Helm charts for 1-2 simulators/labs that can be spun up alongside a switch, with opinionated pre-configured settings + + +### 7.3 Mojaloop Powered Fintech + +>_A Mojaloop Powered fintech is a fintech operating or wishing to operate on top of a mojaloop switch. There will definitely be crossover between Fintechs and DFSPs in this classification, but we will focus here on fintechs who are at the third level on the above "Mojaloop Spokes"_ + +**7.3.1 Use cases:** +- 1\. Validate assumptions about Mojaloop (how it works, what it does, what it _doesn't_ do) +- 2\. Learn how mojaloop is aligned with wholesale APIs, and what it would take to get a DFSP using these APIs over a Mojaloop switch +- 3\. Learn about mojaloop-enabled hubs and associated use cases (technology perspective) +- 4\. Assess how Mojaloop will affect their business in the future + +**7.3.2 Examples from our user personas:** +- 1\. EastPay - compare and shop around for banks/payment providers based on Mojaloop's open fee structure +- 2\. Jumo - Open up transparent and fairer lending markets on top of a Mojaloop enabled switch? + +**7.3.3 Outputs: (How can the Mojaloop OSS Community better serve these players?)** +- 1\. Understand how Mojaloop and Wholesale APIs fit together (or don't) +- 2\. Enable fintechs to interact with Mojaloop over 1 or 2 wholesale banking APIs (e.g. GSMA MM api) +- 3\. take them from little to no understanding of Mojaloop -> demonstrating real prototypes + +**7.3.4 Inputs: (what are the things that we need to do to meet these goals)** +- 1\. Improved mojaloop documentation specific for this role. +- 2\. Documentation or working document on how Mojaloop will work with wholesale apis +- 3\. Self-deployed lab environment with DFSP that expose some wholesale apis with basic functionality for fintechs to test against + + +## 8. OSS Lab/Workbench efforts alongside others + +There are others in the community working on some of these needs we outlined above. How can we align ourselves together to: (1) Not duplicate efforts (nor step on each other's toes) and (2) Provide the most impact for end users and the Mojaloop community as a whole + +In general, we reached a consensus around the following: +- any OSS Lab effort should be focused with a specific end user in mind +- Our focus should be further out on the mojaloop spokes (DFSPs, Fintechs, 3rd Party app providers) + + +### 8.1 MIFOS +- 1\. Already extensive work done here with Fineract system, which provides out-of-the-box solution for Mojaloop enabled DFSPs +- 2\. working on open api implementations +- 3\. Working on lowering the barriers to entry for DFSPs and Fintechs +- 4\. Mifos Innovation Lab: "The Locomotion on top of Mojaloop's Rails" + - 4.1 Demonstrate end to end Mojaloop systems with DFSP integration + - 4.2 Build and contribute OS tools +- 5\. Working on real world deployments already +- 6\. See a need for a "Single Point of Entry to the Mojaloop Ecosystem" +- 7\. Have an existing Lab deployment with Mojaloop that is currently being upgraded to work with the latest Helm chart deployments + + +### 8.2 GSMA +- 1\. Have mobile money api, would like to see end to end solution with fintechs/DFSPs talking over a mojaloop switch +- 2\. The GSMA Lab has a very wide scope, Mojaloop is just one piece of this +- 3\. One main goal is the mobile money API- pushing for default standard for 3rd party integration into mobile money +- 4\. where does Mojaloop sit? + - 4.1 Is one of the branches that the GSMA Lab will be working on + - 4.2 Where can GSMA add the most value to Mojaloop? + - 4.2.1 Serve a need from the market to get the most impact + - 4.2.2 See a end-to-end prototype of the MM API talking over a Mojaloop switch + + +### 8.3 ModusBox +- 1\. More on the systems integrator perspective. Building a bunch of tools already to ease the development and onboarding process for switches and DFSPs +- 2\. Have open sourced the Mojaloop JS SDK +- 3\. Interested in showing 'how the engine works' to build confidence in business parters/customers +- 4\. Also interested (especially in WOCCU case) as a Mojaloop lab as a place for Fintechs to learn and test concepts on top of Mojaloop Switches + - 4.1 Once this is connected, the interesting use cases will start to develop beyond tranfers from A to B + - 4.2 MFIs (especially small-medium) don't have much capacity for experimentation or developing new business cases, but these cases can be driven from fintechs first +- 5\. How can we assist orgs. who have little-to-no technical capability to become confident with Mojaloop? + - 5.1 A technical lab environment won't do much in this case + - 5.2 Can we demonstrate Mojaloop over a spreadsheet? Everyone can understand spreadsheets. + +## 9. Questions + +- 1\. So much of this comes back to The Gates Foundation's proposed sales cycle for growing mojaloop adoption + - 1.1 Looking at the technical briefs from the hackathon alone, there are some __big__ players (Famoco, Ethiopay, GrameenPhone) that could really take mojaloop and run with it + - 1.2 How can the initial hurdle be overcome to drive adoption and help these orgs adopt mojaloop and contribute back to the ecosystem? + - 1.3 What does the entrypoint to the industry look like for Hub operators? + +- 2\. For evaluating DFSPs, what is their resource/risk allocation like? + - 2.1 If they think Mojaloop is a viable option for a future product, what type of time and resource investment will they put into it? + - 2.2 What are their alternatives? (This will be a case-by-case thing) + +- 3\. Is a certain amount of technical gatekeeping a good or bad thing? (This is a more philisophical question) + - 3.1 If we don't make it too easy to get up and running, we make sure that only interested and determined parties are using mojaloop, which self-selects for a better community (kinda) + - 3.2 But this locks out a lot of people who aren't up to scratch with kubernetes, docker etc. but may still have a good deal of experience with financial services etc. + +- 4\. Chicken and egg problem(?) between DFSPs and Hub operators. Does it go DFSPs -> Hub Operators or the other way around? + + +## 10. Recommendations + +- 1\. Find a target user that we can build a lab for/with + - 1.1 perhaps one of the more serious hackathon teams? +- 2\. Address and improve documentation gaps: driving from a role-specific (i.e. DFSP, fintech, hub operator) perspective +- 3\. Mojaloop over Spreadsheet demo +- 4\. Build a self-service lab prototype + - 4.1 Opinionated set of helm charts that can be deployed alongside general switch + - 4.2 Gather feedback from the community, and see where and how people are using it \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/community/archive/notes/README.md b/website/versioned_docs/v1.0.1/community/archive/notes/README.md new file mode 100644 index 000000000..8f7b7868c --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/notes/README.md @@ -0,0 +1,5 @@ +# OSS Meeting Group Notes (Archive) + +- [Change Control Board](./ccb-notes.md) +- [Design Authority](./da-notes.md) +- [Scrum-of-scrum calls](./scrum-of-scrum-notes.md) diff --git a/website/versioned_docs/v1.0.1/community/archive/notes/ccb-notes.md b/website/versioned_docs/v1.0.1/community/archive/notes/ccb-notes.md new file mode 100644 index 000000000..b8c49a9df --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/notes/ccb-notes.md @@ -0,0 +1,6 @@ +## CCB meetings: Overview +The Change Control Board meets every two weeks. + +The meetings are open for the public to participate, though discussions are usually limited to the Board members. However, attendees will be promoted to panelists in meetings if they have Change Requests or Solution Proposals to discuss. + +More details can be found here: https://github.com/mojaloop/mojaloop-specification/tree/master/ccb-meetings . \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/community/archive/notes/da-notes.md b/website/versioned_docs/v1.0.1/community/archive/notes/da-notes.md new file mode 100644 index 000000000..2e04a1be9 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/notes/da-notes.md @@ -0,0 +1,125 @@ +## DA meetings: Overview +The Design Authority meets every week for a weekly update and has ad-hoc or detailed sessions for Specific topics + +The meetings are open for the public to participate, though discussions are usually limited to the Board members. However, attendees will be promoted to panelists in meetings if they have designs to be reviewed or proposals for changes. + +More details can be found [here](https://github.com/mojaloop/design-authority/issues/42#workspaces/da-issue-log-5cdd507422733779191866e9/board?notFullScreen=false&repos=186592307) + +# DA Meeting - 30 September 2020 +Discussion around the topics mentioned started - the newly implemented "patch" in version 1.1 of the API spec was discussed and the majority of the meeting was spent on how to promote wider adoption of this new pattern. + +Concerns about the implementation and use of the "patch" command was raised, stating that further discussion is required to determine if we are not trying to patch a design flaw with another potential implementation flaw. + +See: https://github.com/mojaloop/design-authority/issues/68 + + +# DA Meeting - 2 September 2020 +First we discussed the topic about the "models" folder from being excluded from the unit test coverage checks. The decision taken was that if the folder contains business logic (which generally should not be the case), it must be refactored and moved out. Once at that "business logic isolated" state, coverage testing for that folder can be ignored. See: https://github.com/mojaloop/design-authority/issues/64 + +We concluded discussions on the separate scheme-adapter for a PISP - see issue on board: https://github.com/mojaloop/design-authority/issues/51 +Please have a look at the draft document at this location: https://github.com/mojaloop/pisp/blob/scratch/api-collision/docs/api-collision.md +The above link has a detailed discussion regarding the latest thinking and some examples of mitigations. +The decision has been taken to block this topic until further development on the PoC has been done, in order for the DA to assess if the designs are still aligned with the recommended approach. + +# DA Meeting - 26 August 2020 +We discussed https://github.com/mojaloop/design-authority/issues/51 further on our DA Meeting on 26/08/2020. + +Some of the key points were noted: + +In order to take advantage of Typescript, and to help speed up development, the PISP workstream has gone ahead and separated out the thirdparty-scheme-adapter already. + +One of the challenges identified with the "multi-scheme-adapter" approach was for cases where there are shared resources between the APIs, such as GET /parties/{type}/{id}. + +Our decision to break the Thirdparty API into it's own API (and not extend the FSPIOP-API) was predicated on the idea that "not all participants will want thirdparty functions", and therefore shouldn't have to worry about them. As a part of the decision to keep a separate Thirdparty API, we decided that some resources would be duplicated between the two. + +This could lead to problems down the line, where callbacks to some resources might not be able to reach their desired destination: for example if a DFSP needs to listen for PUT /parties/{type}/{id} callbacks for both the FSPIOP API and the Thirdparty API, it may not be possible for DFSPs to route such callbacks to the right place. + +Lewis Daly will spend more time working on some diagrams and design documents, and come back to the DA shortly + +# DA Meeting (Ad-Hoc) - 24 August 2020 +The topic for discussion was: https://github.com/mojaloop/design-authority/issues/65 +The Ad-Hoc meeting was conducted with a wider issue being addressed relating to recommendations required to be taken to the CCB for consideration to change/enhance the API spec. + +Many valid points were raised and discussed and Michael and Adrian suggested some collaboration on this platform to consolidate the ideas put forward in order to formulate a recommendation to the CCB. + +# DA Meeting - 19 August 2020 +The topic for discussion was: https://github.com/mojaloop/design-authority/issues/61 +The group agreed that there needs to be a balance between the need to eliminate reconciliation and liquidity management of (Payer) FSPs by not holding/reserving funds for longer than necessary. In addition, It was proposed to use 'grace time period' before timing out transfers to compensate for differences in clocks. It was also suggested that for risky transactions, the final notification in the form of a PATCH call that was introduced with FSPIOP API v1.1 can be used to mitigate risk to the Payee FSPs. + +One point made was that after the timeout period (plus the grace period to account for clock difference), a transfer status cannot be changed - it is either finalized or it isn't, but it cannot be changed. For example, if a timeout period (expressed as a time in future and not duration) is 10 seconds, then a Payer FSP (or Switch), may add a grace period of 1second and after waiting for 11seconds can query the downstream entity to find the transfer's status; At this point, if a transfer is finalized (Committed or Aborted), then the Payer FSP can take action accordingly; however if it is in an intermediate state, then the transfer has to be timed-out since the time-out period is done. + +The group agreed on the need to revisit the topic of implementing 'telescopic timeouts', which is not currently supported in favor of end-to-end encryption of (most) messages. + +# DA Meeting - 12 August 2020 +The topic for discussion was: https://github.com/mojaloop/design-authority/issues/63 +The DA discussed the topic of where and how to create and work on issue tickets. With over 50 repositories, it makes sense to create a ticket in the repo where it originated and keep working on it there until it is resolved. The Product Owner and Scrum Master would have context and should replicate a ticket in the Design Autority Repo with a link to the originating ticket. Please have a look at the DA Board for the decisions made here: https://github.com/mojaloop/design-authority#workspaces/da-issue-log-5cdd507422733779191866e9/board?repos=186592307 + +# DA Meeting - 5 August 2020 +The topic for discussion was: https://github.com/mojaloop/project/issues/852 +The "HSM Integration Approach" was touched on a few times, and the workgroup taking care of the design and implementation, tabled this for discussion at this week's DA meeting to answer a few questions arising from the last PI-Planning session where progress on this was again presented. + +As we have not completed the discussion, an ad-hoc DA meeting has been arranged for this Friday with a sub-section of the DA Members. The reason for that was because there were a few specific questions we did not have time to go into detail for, which will be clarified with the individuals who raised those questions. Please drop me a note if you would like to participate in that meeting. + +# DA Meeting - 29 July 2020 +Issue discussed: https://github.com/mojaloop/design-authority/issues/60 +Claudio noted three observations regarding usage of best practices in the Mojaloop Core codebase. One of the issues has an active issue and will be used for tracking it; the other two will be followed up as separate stories/bugs as well (standards). Claudio will provide examples and in some cases sample snippets that can be used. + +Istvan and Michael discussed the usage of a unique ID for lookup requests and proposed to have a follow-up meeting the upcoming week for those interested. The current trace headers (optional) usage for traceability (APM) was brought up as a solution, which after the DA review can be proposed to the CCB (if accepted by the DA). + +# DA Meeting - 22 July 2020 +Canceled as a result of the PI-11 Mojaloop Convening taking place + +# DA Meeting - 15 July 2020 +Sam walked through some of the high-level changes being introduced with Helm v10.4.0 release and various sections from the release notes: https://github.com/mojaloop/helm/releases/tag/v10.4.0 +Please have a look on the DA Topic board: https://github.com/mojaloop/design-authority/issues/56 + +Neal and Michael discussed the issue of shared DB, code between central-settlement and central-ledger; they’re going to continue with the current work on Continuous Gross Settlement but after the convening will get the inputs from the Perf/Arch PoC (Event sourcing / CQRS) and then align. https://github.com/mojaloop/design-authority/issues/58 + +# DA Meeting - 8 July 2020 +The TIPS team did a presentation of the design and implementation of a **Rules Engine** satisfying their requirements of interpretation in the **Settlements Portion**, to extend fees levied as part of a transfer. The implementation allows for rules to be interpreted at any stage during a transaction. A formal presentation will be made at the convening during the week of the 20th July 2020 after which more informed decisions as to the adaption of this implementation into the Core OSS codebase can be considered as a generic approach to implementation of a rules engine. +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/53 for a detailed problem statement, progression on meetings in the notes and remarks and also, if completed, the subsequent decision. + +# DA Meeting - 1 July 2020 +As part of the "Versioning" workstream, a "zero down-time deployment proposal" PoC is being conducted and feedback from that project has been presented in the form of a problem statement, solution and a demo. The team currently working on that is Lewis Daly, Mat de Haast and Sam Kummary. The feedback was well received and as this work is ongoing, the DA will follow up with any action items to come out of the upcoming presentation for this workstream at the PI 11 Meeting. +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/54 for a detailed problem statement, progression on meetings in the notes and remarks and also, if completed, the subsequent decision. + +# DA Meeting (Ad-Hoc) - 29 June 2020 +KNEX Discussion - continued. The KNEX discussion extended into talking about the possible use of third-party tools to assist in the generation of queries to help migration efforts. This has no direct bearing on the use of KNEX itself and after exploring a bit deeper, it was decided that there was no compelling reason to continue further investigation into the use of KNEX itself, but to keep an open mind and look out for alternative solutions out there as and when they are introduced. Those libraries will be measured against the current implementation to ensure we deploy the right tools for the right purpose. This issue is now closed. +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/27 for a detailed problem statement, progression on meetings in the notes and remarks and also, if completed, the subsequent decision. + +# DA Meeting (Ad-Hoc) - 25 June 2020 +KNEX Discussion - initiated +Conversations have been started, highlighting the problem statement of difficulty in generating or creating migration scripts when database changes occur, as well as the scenario of having to perform these upgrades on a database which is online at the time. +With this context in place, continued design sessions have been scheduled to determine if KNEX would be capable of handling the above scenario and if there are alternate libraries or tools out there to replace or supplement the current implementation, which may help alleviate this difficult task. +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/27 for a detailed problem statement, progression on meetings in the notes and remarks and also, if completed, the subsequent decision. + + +# DA Meeting - 24 June 2020 +Discussion today started with: Deprecation of Helm2 support - Issue #52, where it was agreed that migration to Helm3 should continue. Documentation to assist in the use of tools available to help in the migration should be provided. Find the link to this document at https://github.com/mojaloop/design-authority/issues/52 + +The topic of having a design approach of implementing a generic rules-based system was discussed with some specific reference first, to a requirement of having the capability to interrogate completed or in-flight transactions (either in the transfer stage or even as early in the quoting stage) in order to apply "interchange fees" for that transaction, depending on the transaction type, as interpreted by certain rules. +Various design decisions are going to be discussed around this topic as the requirement is the facility to attach rules at various points of the transaction path. +The current implementation of a Rules Engine in the TIPS project was discussed and a request to demonstrate the capabilities of that solution in order for the DA to see if it was generic anough to incorporate into the core Switch will be made in a follow-up discussion. +Please track the progression of the design decisions surrounding this issue on the board at https://github.com/mojaloop/design-authority/issues/53 + + +# DA Meeting - 17 June 2020 +Topic under discussion was: Understand and Define Mojaloop Roles for PISP, x-network, etc. use cases +The DA is happy for workstreams to go ahead and split out new APIs and Role definitions (e.g. Thirdparty API, CNP API etc.) +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/44 for a detailed problem statement and subsequent decision. + +# DA Meeting - 10 June 2020 +This week, the DA discussed: Discuss the PISP Simulator: https://github.com/mojaloop/design-authority/issues/46 +The decision was made that for the time being, the PISP workstream will work on it's own branch in the sdk-scheme-adapter, and such a division/abstraction of the sdk-scheme-adapter will be revisited at a later date (see #51) + +# DA Meeting - 3 June 2020 +We continued the discussion started last week regarding the separate API for PISP and decided to go with option 4: maximum API Separation, with common swagger/open api files for definition and data model reuse: +Please see the link on the Design Authority Board here: https://github.com/mojaloop/design-authority/issues/47 for a detailed problem statement and subsequent decision. + +# DA Meeting - 27 May 2020 +Consensus relating to the issue raised and discussed some time ago, as queried by Adrian, was reached amongst the attendees. The outcome is that the Switch development will not be restrictive and prescriptive but as far as recommendation for new contributions and modules are concerned, it will be preferred if those could be done in TypeScript. + +A new discussion topic was tabled: https://github.com/mojaloop/design-authority/issues/47 seeking to answer the question of whether to have a separate API for PISP, or simply extend the existing Open API. A position statement was prepared and added as a comment. All attendees were brought up to speed with the decision to be made and Issue-#47 will be the topic for the next DA meeting. + +Another, PISP related topic was tabled and will be scheduled for another DA meeting: https://github.com/mojaloop/design-authority/issues/48 - Answer the question of how to manage notifications so that a PISP can be registered as an interested party for notification of the success of a transfer + diff --git a/website/versioned_docs/v1.0.1/community/archive/notes/scrum-of-scrum-notes.md b/website/versioned_docs/v1.0.1/community/archive/notes/scrum-of-scrum-notes.md new file mode 100644 index 000000000..648d833d3 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/archive/notes/scrum-of-scrum-notes.md @@ -0,0 +1,154 @@ +# Meeting Notes from Weekly Scrum-of-scrum meetings + +## OSS Scrum or scrum calls Thu **May 7th** 2020 + +1. Coil - Don: + a Performance: 'Big Gap' problem; changes to cs-stream; changed results; putting together a doc with changes for review; Joran's work on concurrent message processing on Kafka topics -> try to test it; seeing 40-50% throughput; + b LPS adapter: Working with Renjith (Applied Payments); putting together a lab / envt for partner teams to use it; Exploring collaboration with GSMA lab +2. Crosslake - Lewis: + a. Performance: Had report out with Confluent with Nakul, engagement wrapping up; Disseminating docs Nakul produced + b. PISP: Design discussions going on along with Implementation + c. Versioning: Figuring scope for ZDD deployments + d. Official launch related issues: DNS issues - worked on and were resolved +3. ModusBox - Sam: + a. Performance: Moving / standardizing Perf changes from PI-9 into master (not all PoCs); Working on goals, strategy for PI10 + b. Core-team: Bulk transfers - getting started by providing support in sdk-scheme-adapter + c. Maintenance (Bug Fixes): + i) Accents in names - Ongoing + ii) Mojaloop simulator on AWS deployments - almost done, working on QA scripts (on 'dev2' - second environment) + d. Testing toolkit: Currently available for testing - all resources in ML FSPIOP API Supported. Reports can be generated. Working on providing Command line options and more portability + e. CCB: Publishing v1.1 Spec this week - API Definition and corresponding Swagger (Open API) +4. Virtual / Mojaloop Foundation - Megan: + a. Launch of Mojaloop Foundation + b. Paula H - Executive Director of the Mojaloop Foundation. +5. Mojaloop Foundation - Simeon: + a. Provide feedback on the Community Survey + b. Hackathon possible in early June time-frame in collaboration with Google + c. Mojaloop Newsletter with interesting items such as ML FSPIOP v1.1 Spec, Helm v10.1.0 release, etc. to be launched next week. + +## OSS Scrum or scrum calls Thu **April 16th** 2020 + +1. Coil: + a. Don C: Perf - preliminary results - got some numbers - got individual handler numbers, to compare with individual handlers - focusing on DB - a thrid of time for one leg spent on perf + b. Don C: HSM: Renjit's team demo'ed the demo for next week - event prep +2. Crosslake: + a. Lewis D: PISP - Sprint planning - iterating designs + b. Lewis D: Hackathons - Discussed a few concepts with Innocent K (HiPiPo) + c. Lewis D: Has access to GSMA lab - will play around + d. Lewis D: Versioning: working on deck for PI10 + e. Kim W: Performance stream overall update - workshop with Confluent + f. Kim W: Performance stream update - Pedro putting together a proposal, presentation +3. Mifos: + a. Ed C: Demo Prep for PI10 meetings +4. Virtual: + a. Megan : Getting ready for the PI10 event and Logistics +5. DA: + a. Nico: Discussing PISP issue which Michael will be the owner of +6. Core team: + a. Sam K: Performance: Preparing Metrics; Doing performance runs to baseline master branches after moving some enhancements to master + b. Sam K: Accents in names issue - implementation ongoing + f. Sam K: Settlements V2 implementation being done by OSS-TIPS team ongoing - QA done for current iteration + g. Sam K: Testing toolkit: Improving unit test coverage. Assertions added for various endpoints + i. Sam K: CCB: V1.1 of the ML FSPIOP API Definition - First draft done, Reviews in progress +7. Mojaloop Community: + a. Community update by Simeon + +## OSS Scrum or scrum calls Thu **April 9th** 2020 + +1. Coil: + a. Don C: perf testing - Under utilization of resources - more tweaking to be done + b. Don C: HSM integration - demo prep + c. Don C: Legacy adapter - docs update - looking for feedback +2. Crosslake: + a. Kim W: FRMS meeting earlier today - proposals made + b. Kim W: PI10 meetings update, registrations - questions + c. Lewis D: PISP: more planning - working on stories, items, but discussing designs on Oauth, Fido + d. Lewis D: Performance: discussion with Pedro about PoC for arch changes, for Event Sourcing, CQRS, etc + e. Lewis D: Code standards - updated + f. Lewis D: Code quality & Security stream: HSM usage, demo, Security in the OSS community + g. Lewis D: Container scans working - will work with Victor, early benchmarks + h. Lewis D: Finally - versioning update +3. Mifos: + a. Ed C: Work on Payment Hub, integrating with Kafka, ML transactions going through, usiing Elastic Search, for backoffice ops moniring + b. Ed C: Demo Prep for PI10 meetings +4. Core team: + a. Sam K: Performance: Drafting reports, Moving metrics, other enhancements to master branches + b. Sam K: Performance: Wrapping-up final set of tests; Phase4 roadmap and kickoff planning + c. Sam K: Community Support: Fixing bugs (few major discussion items fixed), providing clarifications regarding implementation decisions, etc. + d. Sam K: Merchant Payment Support - Provide tests and validate Merchant "Request to Pay" use case, standardization on-going + e. Sam K: Accents in names issue - implementation ongoing + f. Sam K: Settlements V2 implementation being done by OSS-TIPS team ongoing + g. Sam K: Testing toolkit: Assertions being added for API resources, JWS done, mTLS being added + h. Sam K: Testing toolkit: Usage guide in progress along with adding Golden path related tests + i. Sam K: CCB: V1.1 of the ML FSPIOP API Definition - First draft done, waiting for review + +## OSS Scrum or scrum calls Thu **April 2nd** 2020 + +1. Mifos: + a. Ed C: Team continuing work on Payment Hub EE, Focus on Operational UI , capabilities for DFSP backends, Error event handling framework +2. Coil: + a. Don C: Performance - setup done and got started - on GCP - getting high latency times - need to troubleshoot and will probably get support from other contributors + b. Don C: ATM - OTP - Encryption +3. Crosslake: + a. Kim W: Agenda for PI10 drafted - email should good out soon + b. Kim W: Schedule for PI10: Tue - Fri; 11am - 4pm GMT - Remote / Virtual event + c. Lewis D: Perf meeting later today - architecture deep dive + d. Lewis D: Versioning - In progress + e. Lewis D: Code quality & Security - Overall Security architecture, HSM covered by Coil + f. Lewis D: Mojaloop in a Vagrant box - in progress +4. Core team: + a. Miguel dB: Performance: Wrapping up Perf work - nearing 900 TPS end-to-end; Currently attempting to identify / understand a single unit that needs this perf + b. Sam K: Performance: Wrapping-up final set of tests; Phase4 roadmap and kickoff planning + c. Sam K: Community Support: Fixing bugs (few major discussion items fixed), providing clarifications regarding implementation decisions, etc. + d. Sam K: Merchant Payment Support - Standardization on-going - Fixing issues in /authorizations + e. Sam K: Accents in names issue - implementation ongoing + f. Sam K: Settlements V2 implementation being done by OSS-TIPS team ongoing + g. Sam K: Testing toolkit: Assertions being added for API resources, JWS in progress + h. Sam K: CCB: V1.1 of the ML FSPIOP API Definition - drafting in progress + +## OSS Scrum of scrum call Thu **March 26th** 2020 + +1. DA: Nico - Versioning topic discussed by Lewis, Matt, Sam +2. Crosslake: + a. Kim W: Finalizing Agenda - Monday to Friday + b. Kim W: Reach out if you want to present / speak + c. Kim W: Preparing pre-reads + d. Kim W: Fraud & AML workshop: Justus to post summary and notes to GitHub after the workshops + e. Lewis D: Performance workshop / deep-dive possibly Monday + f. Lewis D: PISP Design discussions ongoing + g: Lewis D: Code quality and security stream: i. Docker container security recommendations. ii. GDPR Scope for Mojaloop +3. Mifos: + a. Ed C / Istvan M: Continue creating Lab + b. Ed C / Istvan M: Fineract , new instance of Payment Hub - good progress + c. Ed C / Istvan M: Working on operational monitoring of backend part (back-office debugging, monitoring, etc) +4. Simeon O - Community Manager in attendance +5. Core team: + a. Sam K: Performance: Finalized phase-3 work. Get to immediate goals for logical conclusion - still ongoing - Phase4 roadmap and kickoff + b. Sam K: Community Support: Fixing bugs, providing clarifications regarding implementation decisions, etc. + d. Sam K: Merchant Payment Support - Standardization on-going - Metrics being added, event framework added + e. Sam K: Accents in names issue - Discussing issue, designing solution + f. Sam K: Settlements V2 implementation being done by OSS-TIPS team ongoing + g. Sam K: Testing toolkit: Assertions being added for API resources, JWS in progress. Usage guide in progress + h. Sam K: CCB: V1.1 of the ML FSPIOP API Definition - drafting in progress + +## OSS Scrum or scrum call Thu **March 19th** 2020 + +1. Coil: + a. Don C: Looking at performance, network hops (avoid dup checks etc) + b. Adrian hB: Renjith & Matt working on translation ISO20022, (to JWEs, etc) - demo by the time we meet on how to use HSM +2. Crosslake: + a. Kim W: Finishing action items from the Mid-PI Workshop, follow-up items + b. Kim W: April Community event is happening but will be a Virtual event. Kim has a planning event and will confirm details: Suggestions welcome + c. Lewis D: Performance - to include Don in other discussions + d. Lewis D: Code quality - GDPR requirements proposal + e: Lewis D: Versioning - iinitial draft made as PR - will be presented to DA next week +3. Mifos: + a. Ed C, Istvan M: Payment Hub, envt in Azure, + b. Ed C, Istvan M: Transactions now going through + c. Ed C, Istvan M: Next phase: to implement back office screens to see screens for business users + d. Ed C, Istvan M: Workshop with Google on PISP +4. Core team: + a. Sam K: Perf - Combining prepare+position handler and fulfil+position handlers, characterization work ongoing + b. Sam K: Perf - Working on gaining an understanding of how 1 unit of Infrastructure looks like for a Mojaloop deployment + c. Sam K: Transaction requests service standardization: Added event framework, Adding metrics now + d. Sam K: Community Support: Fixing issues, upgrade issues, issue for allowing accents in names, etc,. diff --git a/website/versioned_docs/v1.0.1/community/assets/cla/admin_configure.png b/website/versioned_docs/v1.0.1/community/assets/cla/admin_configure.png new file mode 100644 index 000000000..1d8281bb4 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/assets/cla/admin_configure.png differ diff --git a/website/versioned_docs/v1.0.1/community/assets/cla/admin_sign_in.png b/website/versioned_docs/v1.0.1/community/assets/cla/admin_sign_in.png new file mode 100644 index 000000000..a960e2dcd Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/assets/cla/admin_sign_in.png differ diff --git a/website/versioned_docs/v1.0.1/community/assets/cla/cla_1.png b/website/versioned_docs/v1.0.1/community/assets/cla/cla_1.png new file mode 100644 index 000000000..46718fc66 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/assets/cla/cla_1.png differ diff --git a/website/versioned_docs/v1.0.1/community/assets/cla/cla_2_1.png b/website/versioned_docs/v1.0.1/community/assets/cla/cla_2_1.png new file mode 100644 index 000000000..18ae1809c Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/assets/cla/cla_2_1.png differ diff --git a/website/versioned_docs/v1.0.1/community/assets/cla/cla_2_2.png b/website/versioned_docs/v1.0.1/community/assets/cla/cla_2_2.png new file mode 100644 index 000000000..2e60fb762 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/assets/cla/cla_2_2.png differ diff --git a/website/versioned_docs/v1.0.1/community/assets/cla/cla_3.png b/website/versioned_docs/v1.0.1/community/assets/cla/cla_3.png new file mode 100644 index 000000000..5e2ddc46d Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/assets/cla/cla_3.png differ diff --git a/website/versioned_docs/v1.0.1/community/contributing/code-of-conduct.md b/website/versioned_docs/v1.0.1/community/contributing/code-of-conduct.md new file mode 100644 index 000000000..641649471 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/contributing/code-of-conduct.md @@ -0,0 +1,94 @@ +# Mojaloop Code of Conduct + + +## Vision and Mission + +Mojaloop is a portmanteau derived from the Swahili word "Moja" meaning "one" and the English word loop. Mojaloop's vision is to loop digital financial providers and customers together in one inclusive ecosystem. + +The Mojaloop open source project mission is to increase financial inclusion by empowering organizations creating trusted and interoperable payments systems to enable digital financial services for all. We believe an economy that includes everyone, benefits everyone and we are building software that will accelerate full financial inclusion. Succeeding in our mission will require diverse opinions and contributions from people reflecting differing experiences and who come from culturally diverse backgrounds. + +## Community Foundation and Values + +Our goal is a strong and diverse community that welcomes new ideas in a complex field and fosters collaboration between groups and individuals with very different needs, interests, and skills. + +We build a strong and diverse community by actively seeking participation from those who add value to it. + +We treat each other openly and respectfully, we evaluate contributions with fairness and equity, and we seek to create a project that includes everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, and orientation. + +*This code of conduct exists to ensure that diverse groups collaborate to mutual advantage and enjoyment.* + +The Code of Conduct governs how we behave in public or in private, virtually or in person. We expect it to be honoured by everyone who represents the project officially or informally, claims affiliation with the project, or participates directly. + +### We strive to: + +- **Be Considerate**\ + Our work will be used by other people, and we in turn will depend on the work of others. Any decision we take will affect everyone involved in our ecosystem, and we should consider all relevant aspects when making decisions. + +- **Be Respectful**\ + We work together to resolve conflict, assume good intentions, and do our best to act in an empathic fashion. We believe a community where people are respected and feel comfortable is a productive one. + +- **Be Accountable**\ + We are accountable for our words and actions. We all can make mistakes; when we do, we take responsibility for them. If someone has been harmed or offended, we listen carefully and respectfully and work to right the wrong. + +- **Be Collaborative**\ + What we produce is a complex whole made of many parts. Collaboration between teams that each have their own goal and vision is essential; for the whole to be more than the sum of its parts, each part must make an effort to understand the whole.\ + Collaboration reduces redundancy and improves the quality of our work. Internally and externally, we celebrate good collaboration. Wherever possible, we work closely with upstream projects and others in the open-source software community to coordinate our efforts. We prefer to work transparently and involve interested parties as early as possible. + +- **Value Decisiveness, Clarity, and Consensus**\ + Disagreements, social and technical, are normal, but we do not allow them to persist and fester leaving others uncertain of the agreed direction.\ + We expect community members to resolve disagreements constructively. When they face obstacles in doing so, we escalate the matter to structures with designated leaders to arbitrate and provide clarity and direction. + +- **Ask for help when unsure**\ + Nobody is expected to be perfect in this community. Asking questions early avoids many problems later, so questions are encouraged, though they may be directed to the appropriate forum. Those who are asked should be responsive and helpful. + +- **Step Down Considerately**\ + When somebody leaves or disengages from the project, we ask that they do so in a way that minimises disruption to the project. They should tell people they are leaving and take the proper steps to ensure that others can pick up where they left off. + +- **Open Meritocracy**\ +We invite anybody, from any company or organization, to participate in any aspect of the project. Our community is open, and any responsibility can be carried by any contributor who demonstrates the required capacity and competence. + +- **Value Diversity and Inclusion**\ +This is a community that wants to make a real difference to people's lives across the globe; and, in particular, in developing societies and economies. We value our members, first of all, for themselves; and, second, for the help they can give each of us as we work together to transform the world. Each of us will strive never to allow any other considerations to weigh with us, either consciously or unconsciously. In particular, considerations of gender identity or expression, sexual orientation, religion, ethnicity, age, neurodiversity, disability status, language, and citizenship have no place in our collaboration and we will work to eradicate them where we find them: first of all, in ourselves; but after that, and with respect and affection, in those we work with. + +- **Be Transparent**\ +We believe community members will have personal and professional interests in the development of the Mojaloop Open Source Software. These interests will, directly and indirectly, influence perceptions about the best direction of the community. Community members should make every reasonable effort to be transparent about their interests within the limits of confidentiality.  Community members who hold permanent or temporary governance roles should not use those roles in the advancement of personal or professional interests but should base their influence on the best interests of the success of the community. + +This Code of Conduct is not exhaustive or complete. It is not a rulebook; it serves to distill our common understanding of a collaborative, shared environment, and goals. We expect it to be followed in spirit as much as in the letter. + +### Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +- Using welcoming and inclusive language + +- Being respectful of differing viewpoints and experiences + +- Gracefully accepting constructive criticism + +- Focusing on what is best for the community + +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and unwelcome sexual attention or advances + +- Trolling, insulting/derogatory comments, and personal or political attacks + +- Public or private harassment + +- Publishing others' private information, such as a physical or electronic address, without explicit permission + +- Other conduct which could reasonably be considered inappropriate in a professional setting + +### Reporting and Resolution + +If you see someone violating the code of conduct, you are encouraged to address the behavior directly with those involved. Many issues can be resolved quickly and easily, and this gives people more control over the outcome of their dispute. If you are unable to resolve the matter for any reason, or if the behavior is threatening or harassing, report it. We are dedicated to providing an environment where participants feel welcome and safe. + +Reports should be directed to the Community Leadership Committee via an email sent to . This email goes to the Mojaloop Foundation Community Manager whose duty it is to receive and address reported violations of the code of conduct. They will then work with the Community Leadership Committee to address and resolve the report. + +We will investigate every complaint, but you may not receive a direct response. Whether we respond to you directly or not, you will always be able to enquire after the status of a complaint by contacting a member of the Community Leadership Committee. We will use our discretion in determining when and how to follow up on reported incidents, which may range from not taking action to permanent expulsion from the community and foundation-sponsored spaces. We will notify the accused of the report and provide them an opportunity to discuss it before any action is taken. The identity of the reporter will be omitted from the details of the report supplied to the accused. In potentially harmful situations, such as ongoing harassment or threats to anyone's safety, we may take action without notice. + +### Attribution + +This Code of Conduct is adapted from the Ubuntu Code of Conduct v2.0, available at diff --git a/website/versioned_docs/v1.0.1/community/contributing/contributors-guide.md b/website/versioned_docs/v1.0.1/community/contributing/contributors-guide.md new file mode 100644 index 000000000..c931cb732 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/contributing/contributors-guide.md @@ -0,0 +1,60 @@ +# Contributors' Guide + +We are glad that you are considering becoming a part of the Mojaloop community. + +Based on the current phase of the Mojaloop project, we are looking for one of the following types of contributors: + +## Types of contributors +- #### Individual Contributors + +> These individuals are those that want to start contributing to the Mojaloop community. This could be a software developer or quality assurance person that wants to write new code or fix a bug. This could also be a business, compliance or risk specialist that wants to help provide rules, write documentation or participate in requirements gathering. + +- #### Hub Operators + +> Typically these or organizations or individuals or government agencies that are interested in setting up their own Mojaloop Switch to become part of the ecosystem. + +- #### Implementation Teams + +> Implementation teams can assist banks, government offices, mobile operators or credit unions in deploying Mojaloop. + + +## How do I contribute? + +* Review the [Mojaloop Deployment](https://docs.mojaloop.io/documentation/deployment-guide/) Guide and the [Onboarding Guide](https://github.com/mojaloop/mojaloop/blob/master/onboarding.md). +* Browse through the [Repository Overview](https://docs.mojaloop.io/documentation/repositories/) to understand how the Mojaloop code is managed across multiple Github Repositories. +* Get familiar with our [Standards](../standards/guide.md) for contributing to this project. +* Go through the [New Contributor Checklist](./new-contributor-checklist.md), and browse through the project board and work on your [good first issue](https://github.com/mojaloop/project/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) +* Review the [Roadmap](../mojaloop-roadmap.md) and contribute to future opportunities. +* Familiarize yourself with our Community [Code of Conduct](./code-of-conduct.md). + +## What work is needed? + +Work is tracked as issues in the [mojaloop/project](https://github.com/mojaloop/project) repository GitHub. You'll see issues there that are open and marked as bugs, stories, or epics. An epic is larger work that contains multiple stories. Start with any stories that are marked with "[good first issue](https://github.com/mojaloop/project/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)". In addition, anything that is in the backlog and not assigned to someone are things we could use help with. Stories that have owners are in someone's backlog already, though you can always ask about them in the issue or on Slack. + +There's a [roadmap](../mojaloop-roadmap.md) that shows larger work that people could do or are working on. It has some main initiatives and epics and the order, but lacks dates as this work is community driven. Work is broken down from there into issues in GitHub. + +In general, we are looking for example implementations and bug fixes, and project enhancements. + +## Where do I get help? + +Join the [Mojaloop Slack Discussions](https://mojaloop-slack.herokuapp.com/) to connect with other developers. + +Also checkout the [FAQ](https://github.com/mojaloop/documentation/blob/master/contributors-guide/frequently-asked-questions.md) + +## What is the current release? + +See the [Mojaloop Slack Announcements](https://mojaloop.slack.com/messages/CG3MAJZ5J) to find out information on the latest release. + +## What's here and what's not? + +This is free code provided under an [Apache 2.0 license](https://github.com/mojaloop/mojaloop/blob/master/LICENSE.md). + +The code is released with an Apache 2.0 license but the Specification documents under the 'mojaloop-specification' documents are published with CC BY-ND 4.0 License + +We don't provide production servers to run it on. That's up to you. You are free \(and encouraged!\) to clone these repositories, participate in the community of developers, and contribute back to the code. + +We are not trying to replace any mobile wallet or financial providers. We provide code to link together new and existing financial providers using a common scheme. There are central services for identifying a customer's provider, quoting, fulfillment, deferred net settlement, and shared fraud management. Each provider can take advantage of these services to send and receive money with others on the system and there's no cost to them to onboard new providers. We provide code for a simple example mobile money provider to show how integration can be done, but our example DFSP is not meant to be a production mobile money provider. + +## Where do I send bugs, questions, and feedback? + +For bugs, see [Reporting bugs](https://github.com/mojaloop/mojaloop/blob/master/contribute/Reporting-Bugs.md). \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/community/contributing/new-contributor-checklist.md b/website/versioned_docs/v1.0.1/community/contributing/new-contributor-checklist.md new file mode 100644 index 000000000..ab7450d7b --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/contributing/new-contributor-checklist.md @@ -0,0 +1,63 @@ +# New Contributor Checklist + +This guide summarizes the steps needed to get up and running as a contributor to Mojaloop. They needn't be completed all in one sitting, but by the end of the checklist, you should have learned a good deal about Mojaloop, and be prepared to contribute to the community. + + +## 1. Tools & Documentation + +- Make sure you have a GitHub account already, or sign up for an account [here](https://github.com/join) + +- Join the slack community at the [self-invite link](https://mojaloop-slack.herokuapp.com/), and join the following channels: + - `#announcements` - Announcements for new Releases and QA Status + - `#design-authority` - Questions + Discussion around Mojaloop Design + - `#general` - General discussion about Mojaloop + - `#help-mojaloop` - Ask for help with installing or running Mojaloop + - `#ml-oss-bug-triage` - Discussion and triage for new bugs and issues + +- Say hi! Feel free to give a short introduction of yourself to the community on the `#general` channel. + +- Review the [Git workflow guide](https://mojaloop.io/documentation/contributors-guide/standards/creating-new-features.html) and ensure you are familiar with git. + - Further reading: [Introduction to Github workflow](https://www.atlassian.com/git/tutorials/comparing-workflows) + +- Familiarize yourself with our standard coding style: https://standardjs.com/ + +- Browse through the [Mojaloop Documentation](https://mojaloop.io/documentation/) and get a basic understanding of how the technology works. + +- Go through the [Developer Tools Guide](https://github.com/mojaloop/mojaloop/blob/master/onboarding.md) to get the necessary developer tools up and running on your local environment. + +- (Optional) Get the Central-Ledger up and running on local machines: + - https://github.com/mojaloop/central-ledger/blob/master/Onboarding.md + - https://github.com/mojaloop/ml-api-adapter/blob/master/Onboarding.md + +- (Optional:) Run an entire switch yourself with Kubernetes https://mojaloop.io/documentation/deployment-guide/ _(note: if running locally, your Kubernetes cluster will need 8GB or more of RAM)_ + +## 2. Finding an Issue + +- Review the [good-first-issue](https://github.com/mojaloop/project/labels/good%20first%20issue) list on [`mojaloop/project`](https://github.com/mojaloop/project), to find a good issue to start working on. Alternatively, reach out to the community on Slack at `#general` to ask for help to find an issue. + +- Leave a comment on the issue asking for it to be assigned to you -- this helps make sure we don't duplicate work. As always, reach out to us on Slack if you have any questions or concerns. + +- Fork the relevant repos for the issue, clone and create a new branch for the issue + - Refer to our [Git User Guide](https://mojaloop.io/documentation/contributors-guide/standards/creating-new-features.html) if you get lost + + +## 3. Opening your First PR + +> Complete this part of the guide once you have been added to the Mojaloop GitHub organization. If you don't have access, reach out to us on the `#general` or `#help-mojaloop` + +- Sign up for [Zenhub](https://www.zenhub.com/), and connect it to the Mojaloop Organisation, Search for the _'project'_ workspace +- Install the [Zenhub Browser extension](https://www.zenhub.com/extension) for Chrome or Firefox, and browse the (Mojaloop Project Kanban board](https://github.com/mojaloop/project#zenhub) + +- When your branch is ready for review, open a new pull request from your repository back into the mojaloop project. + >_Note: if the CI/CD pipelines don't run, this may be because your Github account isn't added to the Mojaloop repo_ +- Ensure the following: + - A good description of the feature/bugfix you implemented + - The PR is _assigned_ to yourself + - You have assigned two or more _reviewers_. GitHub often has suggested reviewers, but if you don't know who to assign, feel free to ask whoever created the issue. + +- (Optional) Post a link to your PR on the `#ml-oss-devs` channel in Slack so everyone can share in the fun + + +## 4. Signing the CLA + +After you open your first PR, our CI/CD pipelines will ask you to sign the CLA. For more information on what the CLA is and how to sign it, see [Signing the CLA](./signing-the-cla.md) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/community/contributing/signing-the-cla.md b/website/versioned_docs/v1.0.1/community/contributing/signing-the-cla.md new file mode 100644 index 000000000..a07b97826 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/contributing/signing-the-cla.md @@ -0,0 +1,97 @@ +# Signing the CLA + +Mojaloop has a [Contributor License Agreement (CLA)](https://github.com/mojaloop/mojaloop/blob/master/CONTRIBUTOR_LICENSE_AGREEMENT.md) which clarifies the intellectual property rights for contributions from individuals or entities. + +To ensure every developer has signed the CLA, we use [CLA Assistant](https://cla-assistant.io/), a well maintained, open source tool which checks to make sure that a contributor has signed the CLA before allowing a pull request to be merged. + +## How to sign the CLA + +1. Open a pull request to any Mojaloop repository +2. When the pull request performs the standard checks, you will see the `license/cla` check has run, and requests users to sign the CLA: + + + +3. Click 'Details', and you will be directed to the CLA Assistant tool, where you can read the CLA, fill out some personal details, and sign it. + + +
    + + + +4. Once you have clicked "I agree", navigate back to the Pull request, and see that the CLA Assistant check has passed. + + + + + +### Signing For A Company + +Section 3 of the [Mojaloop CLA](https://github.com/mojaloop/mojaloop/blob/master/CONTRIBUTOR_LICENSE_AGREEMENT.md) covers contributions both from individuals and contributions made by individuals on behalf of their employer. If you are contributing to the Mojaloop Community on behalf of your employer, please enter your employer's name in the "Company or Organization" field. If not, feel free to write "OSS Contributor" and leave the "role" field blank. + + +## Administering the CLA tool + +The CLA Tool is easy to install, any GitHub admin can link it with the Mojaloop organization. + +1. Create a new GitHub Gist and enter in the text of the CLA in a new file. +> Since Github doesn't allow Gists to be owned my organizations, [our gist](https://gist.github.com/mojaloopci/9b7133e1ac153a097ae4ff893add8974) is owned by the 'mojaloopci' user. + +2. Go to [CLA Assistant](https://cla-assistant.io/) and click "Sign in with GitHub" + + + +3. You can add a CLA to either a Repo or Organization. Select "Mojaloop", and then select the gist you just created + + + +4. Hit "Link" and that's it! + + +### Requesting Additional Information: + +> Reference: [request-more-information-from-the-cla-signer](https://github.com/cla-assistant/cla-assistant#request-more-information-from-the-cla-signer) + +You can also add a `metadata` file to the CLA gist, to build a custom form for the CLA tool: + +```json +{ + "name": { + "title": "Full Name", + "type": "string", + "githubKey": "name" + }, + "email": { + "title": "E-Mail", + "type": "string", + "githubKey": "email", + "required": true + }, + "country": { + "title": "Country you are based in", + "type": "string", + "required": true + }, + "company": { + "title": "Company or Organization", + "description": "If you're not affiliated with any, please write 'OSS Contributor'", + "type": "string", + "required": true + }, + "role": { + "title": "Your Role", + "description": "What is your role in your company/organization? Skip this if you're not affiliated with any", + "type": "string", + "required": false + }, + "agreement": { + "title": "I have read and agree to the CLA", + "type": "boolean", + "required": true + } +} +``` + +Produces the following form: + + + diff --git a/website/versioned_docs/v1.0.1/community/documentation/api-documentation.md b/website/versioned_docs/v1.0.1/community/documentation/api-documentation.md new file mode 100644 index 000000000..c1c8f8174 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/documentation/api-documentation.md @@ -0,0 +1,29 @@ +# API Documentation + +All APIs should be documented in RAML or Swagger, see Architecture-Documentation-Guidelines\]\(Architecture-Documentation-Guidelines.md\) + + + +**Section Headings** + +* Do not number headings - for example, "Prepare and Fulfill", not "C - Prepare and Fulfill" +* Make sure section headings \(\# \) match the heading to which they correspond in the comprehensive PDF \(built from the [dactyl config file](https://github.com/Mojaloop/Docs/blob/master/ExportDocs/dactyl-config.yml)\) +* Do not include the word "documentation" in headings + +#### Retrievability + +* For sections that contain many subsections of endpoints or methods, provide a table of contents at the beginning of the section +* Don't say the word project; use component, microservice, interfaces, etc + +#### Language + +Instead of the word "project," use a specific noun such as component, microservice, or interface. + +#### Procedures + +* Introduce procedures with H3 \(\#\#\#\) or H4 \(\#\#\#\#\) headers \(not H2 \(\#\#\)\). +* Do not use numbers in procedure section headings. +* Use ordered-list tagging for procedure steps. For example: +* Step 1 +* Step 2 +* Step 2 diff --git a/website/versioned_docs/v1.0.1/community/documentation/standards.md b/website/versioned_docs/v1.0.1/community/documentation/standards.md new file mode 100644 index 000000000..fdc339691 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/documentation/standards.md @@ -0,0 +1,29 @@ +# Documentation + +### Overview + +Mojaloop has set forward several standards to ensure that documentation throughout the project is consistent and kept up to date. + +* All documentation that is relevant for contributors is kept on the "documentation" repository. +* The "documentation" repository is sync'ed with GitBook and all content is consumed in an easily readable format on: [https://www.gitbook.com/mojaloop](https://www.gitbook.com/mojaloop) +* All documentation should include: + * Overview: business overview to provide the value or reason for the documentation page + * Details: appropriate summary information to support the documentation + +### + +[Documentation standards](https://github.com/mojaloop/mojaloop/blob/master/contribute/Documentation-and-Template-Standards.md) + +### Documentation Style Guide + +All new documentation should confirm to the documentation and styles as discussed [here](style-guide.md). + +### Code Style Guide + +#### NodeJS + +We follow the [Standard style guidelines](https://github.com/feross/standard). Add `npm install standard` to you package.json. + +#### Java + +For Java we follow [Checkstyle](http://checkstyle.sourceforge.net/).Code Quality Metrics diff --git a/website/versioned_docs/v1.0.1/community/documentation/style-guide.md b/website/versioned_docs/v1.0.1/community/documentation/style-guide.md new file mode 100644 index 000000000..2d927651f --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/documentation/style-guide.md @@ -0,0 +1,229 @@ +# Documentation Style Guide + +In most cases, Mojaloop follows the latest edition of the Associated Press Stylebook. The following are foundation-specific guidelines which have been updated and slightly modified. + +#### Acronyms + +Spell out all acronyms on first reference. Include the acronym in parentheses immediately after the full spelling only if you refer to it again in the document. Example: _Kofi Annan, chairman of the board of the Alliance for a Green Revolution in Africa \(AGRA\), traveled to Nairobi this month. It was his first visit to the AGRA office._ + +#### Ampersand + +Only use an ampersand \(&\) when it's part of a formal name like the Bill & Melinda Gates Foundation. In all other cases, spell out and. + +#### Bill & Melinda Gates Foundation + +Our formal legal name is the Bill & Melinda Gates Foundation. Use it on first reference. Always use the ampersand \(&\) and always capitalize Foundation when Bill & Melinda Gates comes before it. + +Never abbreviate the foundation's name as _BMGF_. + +Never translate the foundation name into other languages, as it is a proper noun. The one exception to this is when translating the foundation's name into Chinese, in which case translation is acceptable. + +Do not capitalize foundation when the word stands alone. Example: _The foundation's new headquarters will be built near Seattle Center._ + +Use Gates Foundation only if you are sure the context makes the foundation's identity clear. There is a Gates Family Foundation in Colorado, so we need to be careful. Example: _The Bill & Melinda Gates Foundation and the Ford Foundation co-sponsored the event. A Gates Foundation staff member gave closing remarks._ + +The entity that manages the endowment is formally and legally known as the Bill & Melinda Gates Foundation Trust. You will not need to refer to this entity often, but when you do, write it out on first reference and refer to it as the asset trust thereafter. + +#### Bold and colons + +Frequently I see structures \(like in this very comment!\) where you have introductory terms or phrases that are bolded and set apart from the contents with a colon. Should the colon also be bolded, or not? \(I frequently see it done both ways.\) + +#### Buffett + +Note the spelling: two fs and two ts \(_i.e., Warren Buffett_\). + +#### Bulleted lists + +Introduce bulleted lists with a colon when the listed items complete the lead-in sentence or phrase. Exception: never use colons in headings or subheadings to introduce bulleted lists. + +Capitalize the first words of and use periods with listed items only if they are full sentences. Examples: + +* _This is a complete sentence._ +* _not a complete sentence_ + +Never link items in a bulleted list with coordinating conjunctions and punctuation \(semicolons or commas\) as you would in a sentence-style list. In other words, never do: + +* _this,_ +* _that, or_ +* _the other thing._ + +#### Captions + +Caption photos whenever possible. It helps people understand our work. + +Write captions as single gerund \(_ing verb_\) phrases, followed by the city, state or country, and year the photo was taken in parentheses. Example: _A doctor preparing a vaccine for delivery_ \(Brazzaville, Congo, 2007\).\_ + +When writing a caption, be sure to introduce the people featured and explain what's happening in the image as it relates to our areas of focus. Be as brief as possible so you don't distract from the image or layout. Avoid verbs that state the obvious about what the photo's subject is doing _\(e.g., smiling, standing, and so on\)._ + +If one of the co-chairs appears in a photo with other people, be sure to identify the co-chair in the caption. Don't assume everyone knows what our co-chairs look like. + +#### Citations + +Most fields have their own citation conventions. Adopt those used by the field in question. When citation conventions are unavailable or uncertain, follow The Chicago Manual of Style. + +When a document uses both footnotes and endnotes, for the footnotes, use the following symbols: + +* 1st note = \* \(asterisk\) +* 2nd note = † \(dagger\) +* 3rd note = ‡ \(double dagger\) +* 4th note = § \(section sign\) +* 5th note = \*\* \(2 asterisks\) +* 6th note = †† \(2 daggers\) +* 7th note = ‡‡ \(2 double daggers\) +* 8th note = §§ \(2 section signs\) + +Separate multiple superscript references \(footnotes, endnotes\) with commas, not semicolons. + +#### Clinical trials + +Use Roman numerals when referring to clinical trial phases and always capitalize Phase. Example: The company will begin Phase III trials on the new drug this spring. + +#### Contact information + +Use periods to separate parts of phone numbers, and begin each number with a plus sign. + +Because we work with people throughout the world, omit the international access code, which differs from country to country \(it's 011 in the United States\). Examples: _+1.206.709.3100 \(United States\)_ _+91.11.4100.3100 \(India\)_ + +#### Copyright and trademark notice + +All publications, media, and materials produced by or for the foundation should contain the notice shown below. The Legal team must approve all exceptions. + + _© \(year\) Bill & Melinda Gates Foundation. All Rights Reserved._ Bill & Melinda Gates Foundation is a registered trademark in the United States and other countries. + +When possible, begin the trademark portion of the notice on a separate line. + +#### Dashes + +Use dashes—those the width of a capital M—to indicate asides or abrupt changes in thought. Use en dashes—those the width of a capital N—with numerical ranges. + +Do not include a space before or after a dash. + +Examples: _We work to make safe, affordable financial services—particularly savings accounts—more widely available to people in developing countries._ + +_In the 2004 presidential election, 76 percent of U.S. college graduates ages 25-44 voted._ + +#### Dollars \($\) + +In Global Health and Global Development materials, because more than a dozen countries use dollars, specify U.S. dollars in parentheses on first mention in a document. Example: _$100,000 \(U.S.\)_. Omit the parenthetical U.S. in subsequent references to dollar amounts in the same document. + +#### Foundation program names + +We have three programs: Global Development Program, Global Health Program, and United States Program. + +_Program_ is capitalized when used with the full name \(Global Development Program\), but not when used alone \(The program makes grants in several areas.\). + +Use periods when abbreviating the name of the United States Program: U.S. Program. + +GH, GD, and USP are fine for internal use, but inappropriate for external publications. + +#### Gates family + +William Gates III is formally referred to as Bill Gates. In internal documents, use Bill—not a nickname or abbreviation. + +Use Melinda Gates when formally referring to Melinda. + +Use William H. Gates Sr. when formally referring to Bill Gates Sr. There is no comma between Gates and Sr. Bill Sr. is acceptable in internal documents. + +Plural: Gateses. Do not use an apostrophe to form the plural of the family's name. Example: The Gateses attended the opening of the new University of Washington law building. + +Possessive: The apostrophe follows Gates when you refer to something owned by either Bill or Melinda. Example: Melinda Gates' speech was well received. The apostrophe follows Gateses when you refer to something Bill and Melinda own jointly. Example: _The Gateses' decision to provide free Internet access in U.S. public libraries has increased library usage and circulation overall._ + +You may also phrase it this way: Bill and Melinda Gates' decision to provide free Internet access … + +See the Titles of people entry for the formal titles of Bill, Melinda, Bill Sr., and other leaders of the foundation. + +#### Hyphens + +There are few hard-and-fast rules when it comes to hyphens. Generally we use them to enhance the reader's understanding. + +Examples: _When writing for the Bill & Melinda Gates Foundation, use real-world poverty examples to illustrate your point._ _When writing for the Bill & Melinda Gates Foundation, use real world-poverty examples to illustrate your point._ + +In the first example, the hyphen in real-world connects real and world to form a single adjective describing poverty. In the second example, the hyphen in world-poverty connects world and poverty to form a single adjective describing examples. + +The meaning changes depending on the placement of the hyphen. In instances where a series of adjectives creates ambiguity about what they refer to, use a hyphen to clarify the intended meaning. + +When capitalizing hyphenated words, only capitalize the first part. Example: _Co-chairs Bill and Melinda Gates._ + +For other uses of hyphens—compound modifiers, prefixes and suffixes, fractions—refer to the Associated Press Stylebook. + +#### Numerals + +When referring to dollar figures, spell out million and billion. Use figures and decimals \(not fractions\). Do not go beyond two decimal places. Example: _The foundation granted .45 million to United Way._ + +When using numbers that have nothing to do with dollar figures or percentages, write them out if they are under 10, and use numerals if they are 10 or over. Example: Four program officers went on 13 site visits. + +In cases of grammatical parallelism, parallel construction always trumps this rule. For instance: Mr. Johnson has two children, 5-year-old Kyle and 13-year-old Frances. + +Never begin a sentence with a numeral. Either spell the number out or revise the sentence so it doesn't begin with a number. + +#### Percentages + +When using percentages, write out percent \(don't use %\). Use numerals instead of writing numbers out, even if they're less than 10. + +Example: _This program accounts for 6 percent of our grantmaking._ + +#### Photographer credits + +If the foundation owns the image you are using, you don't need to credit the photographer. All images in our media asset management system are foundation-owned. If the foundation has purchased a license to use the image, you may need to credit the photographer. If you have questions about photo credit requirements, contact the Foundation Communications Service Desk. + +#### Plain language + +We could call out a few specific constructions that are needlessly wordy. One that we frequently catch at Ripple is "in order to" instead of just "to." + +#### Quotation marks + +Use double quotation marks for dialogue and the citation of printed sources. Limit use of scare quotes—quotation marks meant to call attention to a quoted word or phrase and distance the author from its meaning, typically because the language is specialized, idiomatic, ironic, or misused. Example: _The foundation has increasingly used “program-related investments” in recent years._ + +#### Quoted strings and punctuation + +When describing exact strings in technical documentation, should punctuation \(not part of the literal strings\) be included in the quotation marks? For example, valid states include "pending," "in progress," and "completed." + +#### Scientific names + +Capitalize and italicize scientific names in accordance with conventions in the scientific community. Use the full version of a scientific name on first mention and the abbreviated form thereafter. For example, _use Salmonella typhi first and S. typhi for each additional reference._ + +#### Serial commas + +With lists of three or more items in a sentence, add a final comma before the coordinating conjunction and or or. Example: _The foundation's three program areas are Global Development, Global Health, and the United States._ + +#### Spacing after punctuation + +Use only one space after punctuation, including periods, colons, and semicolons. + +#### Spelling and capitalization conventions + +_bed net:_ two words, no hyphen. + +_email:_ one word, no hyphen, lowercase. + +_foundation:_ lowercase, except as part of the full foundation name. + +_grantmaking:_ one word, no hyphen. + +_nongovernmental:_ one word, no hyphen. + +_nonprofit:_ one word, no hyphen. + +_postsecondary:_ one word, no hyphen. + +_Washington state:_ lowercase state \(unless you're referring to Washington State University, the Washington State Legislature, or something similar\). + +_website:_ one word, lowercase + +#### Titles of people + +Formal titles should not be capitalized unless the title precedes a person's name or appears in a headline. Example: _Co-chair Melinda Gates will speak at the Washington Economic Club this year._ + +Lowercase and spell out titles when they are not used with an individual's name. Example: _The foundation co-chair issued a statement._ + +Lowercase and spell out titles in constructions that use commas to set them off from a name. Example: _Bill Gates, co-chair of the foundation, commented on the grant._ + +#### United States + +Spell out United States when using it as a noun. Abbreviate it as U.S. \(including periods\) when using it as an adjective. In certain cases, as when referring to a person from the United States, it's acceptable to use American. + +Examples: _The U.S. State Department is in the United States._ _The foundation's U.S. Program…_ + +#### URL + +Reference web addresses without the http:// as follows: _www.gatesfoundation.org_ diff --git a/website/versioned_docs/v1.0.1/community/faqs.md b/website/versioned_docs/v1.0.1/community/faqs.md new file mode 100644 index 000000000..71ac45b77 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/faqs.md @@ -0,0 +1,9 @@ +# Using Vue in Markdown + +## Browser API Access Restrictions + +Because VuePress applications are server-rendered in Node.js when generating static builds, any Vue usage must conform to the [universal code requirements](https://ssr.vuejs.org/en/universal.html). In short, make sure to only access Browser / DOM APIs in `beforeMount` or `mounted` hooks. + +If you are using or demoing components that are not SSR friendly (for example containing custom directives), you can wrap them inside the built-in `` component: + +## diff --git a/website/versioned_docs/v1.0.1/community/mojaloop-publications.md b/website/versioned_docs/v1.0.1/community/mojaloop-publications.md new file mode 100644 index 000000000..f1dbb7fb1 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/mojaloop-publications.md @@ -0,0 +1,18 @@ +# Publications + +Publications are stored in the [Documentation Artifacts Github repository](https://github.com/mojaloop/documentation-artifacts). + +See below listing of current published publications. + +## OSS Community Convenings Sessions (Presentations and Notes) + +- [January 2020 (Phase 4 Kickoff) OSS Community Session](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/January%202020%20OSS%20Community%20Session) +- [September 2019 PI-8 (Phase 3 Wrap-up) OSS Community Session](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/September%202019%20PI-8_OSS_community%20session) +- [June 2019 PI-7 OSS Community Session](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/June%202019%20PI-7_OSS_community%20session) +- [April 2019 PI-6_OSS Community Session](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/April%202019%20PI-6_OSS_community%20session) +- [January 2010 PI-5 OSS Community Session](https://github.com/mojaloop/documentation-artifacts/tree/master/presentations/January%202019) + +## Mojaloop Standard Publications + +- [Moajoop Decimal Type; Based on XML Schema Decimal Type](./discussions/decimal.md) +- [Mojaloop API Specification](https://github.com/mojaloop/mojaloop-specification/blob/master/API%20Definition%20v1.0.pdf) diff --git a/website/versioned_docs/v1.0.1/community/mojaloop-roadmap.md b/website/versioned_docs/v1.0.1/community/mojaloop-roadmap.md new file mode 100644 index 000000000..2df113fa3 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/mojaloop-roadmap.md @@ -0,0 +1,171 @@ +# The Mojaloop Roadmap + + +## What makes the Mojaloop approach different? + +We've documented in our white paper [here](https://mojaloop.io/mojaloop-executive-briefing/) how we think Mojaloop supports markets towards financial inclusion through effective and efficient interoperability, by providing an alternate option for schemes choosing clearing and settlement switching technology. + +Here are 4 key reasons as to why we believe the open source approach with a vibrant community model is different: + +1. **Clearing and Settlement Hub: Business Critical Functionality** delivered with excellence, for day to day operations done well, allowing ecosystems to be able to embrace the potential of straight through processing and full automation. + +3. **Simplify Integration Complexity:** + - taking away as much complexity as possible through standardised and documented-in-the-open APIs & patterns & tools to support swift network participation & automated settlement rather than a reconciliation driven process. + - A future facing security design that allows cyber-secure safe use of the open internet (not VPNs) to create the network where ecosystems wish to embrace this cost reduction. + +4. Adopters can **take advantage of a tectonic shift in technology in financial services globally,** the post-covid demand, and the implication on future financial services: + - emergence of open banking & embedded finance as well as "merchant request to pay" models over push payments technology + - global use of opensource technologies in infrastructure projects + - COVID revolution around the need for digital transformation & bulk payments for a resilient response to such events. + + **4. Community Stronger Together** + - A solution developed & documented in the open in order to create an ability for participants to benefit from each other’s learnings: "stronger together” + - We have a community sustainability vision that enables impactful interoperability between last mile services through a community formed of a mix of mojaloop technology adopters on-the-ground putting the core technology to work, push payments & financial inclusion experts, and technology infrastructure gurus. + - An open source delivery model becomes sustainable with public-private partnership, adjacent commercial service offerings easily added as extensions (marketplace thinking), healthy co-opetition, and market-making around an open source core technology solution. + + +## Our 2021 community product strategy to help achieve the vision: + +The journey to the big vision starts with getting running hubs. So our 2021 product strategy is in service of productising what is already created to make it easier to start & to ensure existing adopters are engaged in providing feedback: + +- Remove Friction in the adoption funnel +- Cost Reduction (for new adopters & production grade deploys) +- Deliver Validated Feature asks that support Adopter Traction in Market +- Trustworthy/Quality/Credible = Secure, Performant at Scale, Cost Effective, Modular & Extensible, Resilient, Testable and Easy to Deploy & Operate + + +## Our 2021 product roadmap for workstream activity: + +**Looking closely at what areas of work might support In January 2021 we laid out this framework at our community event as important activity to shape community decisions that would support our 2021 goal of Mojaloop ground traction & community growth:** + +- Provide Better Business Process Support within the product +- Ensure the Core Hub is Secure, Performant at Scale, Modular & Extensible, Resilient, Testable and Easy to Deploy & Operate +- Make it Cost Effective for a new adopter to get Started +- Consolidate & Productise what we have for Advocacy efforts (demos, sandbox, better get-started material to ensure the product adaptation in-the-field is minimised & effective) +- Keep Innovating with Valuable Extensions to the Core Hub such as 3PPI & merchant extensions to help impact & decision making + +## **Our key initiatives in 2021 that have delivered on the above:** + +- **Better Business Process Support**: + - A business process team have created a foundational framework for a roadmap of business process improvement work. + - Key features improved around the core APIs: + - Role-Based Access Control using https://www.ory.sh/ for identity access management (authentication, authorization, access control, and delegation of users accessing the APIs) + - WSO2 as an out-of-the-box API Gateway: providing Provide role, policy-based access, security, abstraction, throttling & control, identity management + - Event Logging Framework: Better support for operational reporting and auditing of processing data + - Error Handling Framework: Consistent reporting and support of operational auditing + - Forensic Logging: to support auditing and reporting + - The team have worked to ensure that it is a community-adopted framework, so that future business process improvements can be run in parallel over this baseline, with a "home" for hub operator "need to know" reference manual documentation as a get started accelerator: + - RBAC: https://docs.mojaloop.io/mojaloop-business-docs/HubOperations/RBAC/Role-based-access-control.html + - Settlement: https://docs.mojaloop.io/mojaloop-business-docs/HubOperations/Settlement/settlement-management-introduction.html + - Participant Onboarding: https://docs.mojaloop.io/mojaloop-business-docs/HubOperations/Onboarding/business-onboarding.html + +*All contribution to improve process documentation is welcome, as in 2022 the roadmap will work to improve participant lifecycle management, settlement and merchant onboarding through a business process lens.* + +- **Make it Cost Effective for a new adopter to get Started** + - **A "get started" reference Hub UI** + - "Finance Portal 2.0" was recently contributed as this hub UI starting point by Modusbox, for those not wanting to integrate their own UI on day 1, and is in production for some adopters. + - We are an API-first product to allow the core to fit into multiple scenarios; however an optional get started hub UI has proved invaluable in demonstrating key processes to decision makers. + - The starting point for the UI is documented here: https://docs.mojaloop.io/mojaloop-business-docs/HubOperations/Portalv2/busops-portal-introduction.html + - **There is much that could be done in open source to further develop the UI. Any contributors welcome.** + + - **Payment Manager: A Tool to simplify DFSP integration work** : We are in the process of accepting a new contribution from Modusbox that make the integration process to a Mojaloop Hub in production for a DFSP much more seamless and efficient: https://rtplex.io/payment-manager-oss/ + +- **Core Hub is Modular & Extensible:** + - An architect-centred team have published the Mojaloop Reference architecture: https://mojaloop.github.io/reference-architecture-doc/ with a vision to ensuring that community growth is from a consistent base understanding of the solution. + - Not all elements of this reference are yet implemented, and **this will form the core of the technical roadmap future delivery work in 2022.** + +- **Consolidate & Productise what we have for Advocacy:** + - We have launched a sandbox to showcase our APIs and interaction with a simulated "model rural village" here: https://sandbox.mojaloop.io/ + - We ran some experiments around interoperability to last mile with CBDC technology alongside the MAS CBDC Global Hackathon participants: https://hackolosseum.apixplatform.com/hackathon/globalcbdcchallenge + - We were winners of an ISO20022 hackathon run by BIS showcasing ISO20022 and cross-border interoperability to last mile non-bank solutions: https://mojaloop.io/mojaloop-bis-iso20022-hackathon-submission/ + +**Keep Innovating with Valuable Extensions** +- Our 3PPI API (contributed by Google) is developed sufficiently for hackathon and market activity, and can be explored in detail in our sandbox. More information about its importance in bringing fintechs into the ecosystem more effectively can be seen here: https://mojaloop.io/webinar-what-pisp-means-for-inclusive-real-time-payments-systems/ +- We are exploring what valuable optional extensions to Mojaloop might support an effective accelerator for schemes around merchant ecosystems. The roadmap requires market validation, funding & community engagement to bring it to life. Here is our starting point hypothesis: [here](https://docs.google.com/presentation/d/1SoBgF5XGlsn2ZpO01DWoYUrirFQ_t0kYSLRHb2BOo8g/edit?usp=sharing) +- We are exploring with a "sister" open source FRMS project ensuring the right data is accessible from the Mojaloop solution for FRMS solutions: http://lextego.com/ + + +## 2022 Roadmap + +Here are some "big bets" we're currently thinking about in the community in 2022: + +- **One-Click Cloud Deploy:** A team from Microsoft are working to make it possible for a one-click-deploy for any potential adopter to get started on Microsoft Azure with a "vanilla" unconfigured hub sandbox in their own environment, based on the latest available release. +- **Google Pay Ready:** Our final push on the 3PPI engineering work contributed by Google will ensure that any fintechs using the Imali adapter (and Google Pay) have a swift way to get connected and transacting as a 3rd party. This will allow any Mojaloop-powered ecosystem to be able to launch an experience similar to that seen in India's UPI ecosystem. +- **ISO20022 Support:** ISO20022 is rapidly becoming the protocol of choice by banks, but it is not well known standard amongst Non-Banks - an incredibly important sector in emerging markets last mile services. Mojaloop want to ensure best practice use of ISO20022 for any adopters and will publish an accelerator for "greenfield" markets, as well as working software and adapters that make using it a simple scaled ask. +- **Cross Network Improvements:** Based on field learnings, we want to update the design to make Forex participants in a market "first class citizens" in the protocol, with robust timing management across the end to end protocol. This can lead to dynamic pricing and least cost realtime quotes becoming a reality whilst still supporting existing liqudity management models. +- **Settlement Batch Improvements:** In order to better support cross network models, settlement processing also needs some work. +- **vNext Build** - converting the existing codebase to the modular structure designed in the reference architecture. + +Each big bet has its own roadmap of what it is working on now, next and later. +This google doc holds a working space for the missions and current goals of the teams below: [Workstream Goals](https://docs.google.com/presentation/d/1CSNYZFD94qy4mh6baRPYLKYjo8N09baGQGxdZ424cWY/edit?usp=sharing) + +## How teams are structured around product improvement + +This framework is used to describe the various activites ongoing in the community. They are at different development stages from ideation to design to code development to maintenance mode. Some projects are on ice due to resourcing needs... all contributions welcome! + +**Core Clearing System Capabilities** + +1.1 Reference Architecture Completion & progression to BAU @ DA + +1.2 Improvement on v1 Hub: Supporting Services (“Business Operations Framework”) + - 1.2.1 Baseline RBAC Framework & out-of-the-box user profiles & user management + - 1.2.2 Improvement on Liquidity Monitoring & Settlement + - 1.2.3 Improvement on Participant Lifecycle Management: (Onboarding / Activating / Suspending / Terminating ) + - 1.2.4 Improvement on Reporting API + - 1.2.5 Improvement to the Reference UI + - 1.2.6 Scheme Rules Enforcement: Provide a framework to enforce, implement Scheme decisions + - 1.2.7 Automated Fees Calculation Improvements + - 1.2.8 Improvement to out-of-the-box Operational Moniitoring and Event Dashboards + +1.3 Improvement on v1 Hub - RTP Transfers Processing +- 1.3.1 Reliable Notifications to all Participants +- 1.3.2 Improved Cross-Network Timeouts +- 1.3.2 v1 Performance Improvement + +1.4 Best Practice National RTP ISO20022 Messaging +- at the hub +- at payment manager tool for DFSPs + +1.6 Deployments, Patches & Upgrades made Simple + +1.7 Deployments on Azure made Simple (Microsoft led) + +1.8 Provide Event Data to FRMS Solutions + +1.9 Deliver the Alpha release of vNext + + +**Core Clearing System Use Case Propositions, API Change & extensions into market:** + +2.1 Overlay Services (3PPI Enablement & 3rd party participant lifecycle management / adapters) + +2.2 Merchant Scheme Extension (inc ALS enhancement & QR Support) + - 2.2.1 A reference persistent Merchant Oracle & Merchant Blocklisting capability + +2.3 Bulk Payments Enhancement + + +**Adjacent tools & Marketplace:** + +3.1 Mojaloop Hosted OSS DFSP Support Tools: TTK + +3.2 Mojaloop Hosted OSS DFSP Support Tools: Payment Manager + +3.3 Mojaloop Hosted OSS DFSP Support Tools: SDKs + +3.4 Mojaloop Hosted OSS Hub Support Tools: Connection Manager + +3.5 Improvement on Reference UI (“Finance Portal 2.0”) + + + +**SUPPORTING Workstreams** + +4.1 Improve our “front of house”: API Documentation, Developer Portal, & Sandbox + +4.2 Ensure QA/UAT/Release Quality / Test Case Peer Review for Mission Critical Functionality + +4.3 Improve Hub Detailed Documentation for new adopters and contributors to hub software to get started more simply + +4.4 Add more Training Program content + diff --git a/website/versioned_docs/v1.0.1/community/standards/creating-new-features.md b/website/versioned_docs/v1.0.1/community/standards/creating-new-features.md new file mode 100644 index 000000000..a5a3ea3af --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/standards/creating-new-features.md @@ -0,0 +1,63 @@ +# Creating new Features + +### Fork + +Fork the Mojaloop repository into your own personal space. Ensure that you keep the `master` branch in sync. + +Refer to the following documentation for more information: [https://help.github.com/articles/fork-a-repo/](https://help.github.com/articles/fork-a-repo/) + +1. Clone repo using Git Fork button \(refer to the above documentation for more information\) +2. Clone your forked repo: `git clone https://github.com//.git` +3. Synchronise your forked repo with Mojaloop + + Add a new upstream repo for Mojaloop `$ git remote add mojaloop https://github.com/mojaloop/.git` + + You should now see that you have two remotes: + + ```bash + git remote -v + origin https://github.com//.git (fetch) + origin https://github.com//.git (push) + mojaloop https://github.com/mojaloop/.git (fetch) + mojaloop https://github.com/mojaloop/.git (push) + ``` + +4. To sync to your current branch: `git pull mojaloop ` This will merge any changes from Mojaloop's repo into your forked repo. +5. Push the changes back to your remote fork: `git push origin ` + +### Creating a Branch + +Create a new branch from the `master` branch with the following format: `/` where `issue#` can be attained from the Github issue, and the `issueDescription` is the issue description formatted in CamelCase. + +1. Create and checkout the branch: `git checkout -b /` +2. Push the branch to your remote: `git push origin /` + +Where `` can be one of the following: + +| branchType | Description | +| :--- | :--- | +| feature | Any new or maintenance features that are in active development. | +| hotfix | A hotfix branch is for any urgent fixes. | +| release | A release branch containing a snapshot of a release. | +| backup | A temporary backup branch. Used normally during repo maintenance. | + +### Open a Pull Request (PR) + +Once your feature is ready for review, create a Pull Request from you feature branch back into the `master` branch on the Mojaloop Repository. If you're new to GitHub or Pull Requests, take a look at [this guide](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests) for more information. + +#### Pull Request Titles + +Mojaloop uses [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) to help our automated tooling manage releases and deployments. Your Pull Request title _must_conform to the conventional commits specification to pass the CI/CD checks in CircleCI. + +By adopting Conventional Commits + Semantic Versioning we can automatically release a new version for a given component and increment the `MAJOR`, `MINOR` and `BUGFIX` versions based soley on the PR titles, and auto generate rich changelogs. (See [this example](https://github.com/mojaloop/thirdparty-scheme-adapter/releases/tag/v11.20.0) of an auto generated changelog) + +> **Note**: +> When merging (and squashing) a PR, GitHub uses the _title_ of the PR for the git commit message. This means that to specify a breaking change, you must use the `!` format: +> "If included in the type/scope prefix, breaking changes MUST be indicated by a ! immediately before the :. If ! is used, BREAKING CHANGE: MAY be omitted from the footer section, and the commit description SHALL be used to describe the breaking change." + +**Examples of good PR titles** +- feat(api): add ability to handle `PUT /thirdpartyRequests/trasactions/{ID}` endpoint +- fix: update outdated node modules +- feat(models)!: change database schema +- chore: tidy up readme + diff --git a/website/versioned_docs/v1.0.1/community/standards/guide.md b/website/versioned_docs/v1.0.1/community/standards/guide.md new file mode 100644 index 000000000..ae839fe2d --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/standards/guide.md @@ -0,0 +1,355 @@ +# Standards + +> *Note:* These standards are by no means set in stone, and as a community, we always want to be iterating and improving Mojaloop. If you want to propose a change to these standards, or suggest further improvements, please reach out to the Design Authority Channel on the Mojaloop Slack (#design-authority) + +## Style Guide + +The Mojaloop Community provides a set of guidelines for the style of code we write. These standards help ensure that the Mojaloop codebase remains high quality, maintainable and consistent. + +These style guides are chosen because they can be easily enforced and checked using popular tools with minimal customisation. While we recognise that developers will have personal preferences that may conflict with these guidelines we favour consistency over [bike-shedding](https://en.wikipedia.org/wiki/Law_of_triviality) these rules. + +The goal of these guides is to ensure an easy developer workflow and reduce code commits that contain changes for the sake of style over content. By reducing the noise in diffs we make the job of reviewers easier. + +## Code Style + +### Javascript + +Mojaloop uses the Javascript code style dictated by [StandardJS](https://standardjs.com/). For a full set of rules, refer to the [Standard Rules](https://standardjs.com/rules.html), but as a brief set of highlights: + +- Use *2 spaces* for indentation + +```js +function helloWorld (name) { + console.log('hi', name) +} +``` + +- Use *single quotes* for strings except to avoid escaping. + +```js +console.log('hello there') // ✓ ok +console.log("hello there") // ✗ avoid +console.log(`hello there`) // ✗ avoid +``` + +- No semicolons. (see: 1, 2, 3) + +```js +window.alert('hi') // ✓ ok +window.alert('hi'); // ✗ avoid +``` + +### Typescript + +>*Note: Standard and Typescript* +> +>As we start to introduce more Typescript into the codebase, Standard becomes less useful, and can even be detrimental +>to our development workflow if we try to run standard across the Javascript compiled from Typescript. +>We need to evaluate other options for Standard in Typescript, such as a combination of Prettier + ESLint. + +Refer to the [template-typescript-public](https://github.com/mojaloop/template-typescript-public) for the standard typescript configuration. + + +### YAML + +While YAML deserializers can vary from one to another, we follow the following rules when writing YAML: +> Credit: these examples were taken from the [flathub style guide](https://github.com/flathub/flathub/wiki/YAML-Style-Guide) + +- 2 space indents +- Always indent child elements + +```yaml +# GOOD: +modules: + - name: foo + sources: + - type: bar + +# BAD: +modules: +- name: foo + sources: + - type: bar +``` + +- Do not align values + +```yaml +# BAD: +id: org.example.Foo +modules: + - name: foo + sources: + - type: git +``` +### sh + bash + +- The Shebang should respect the user's local environment: + +```bash +#!/usr/bin/env bash +``` + +This ensures that the script will match the `bash` that is defined in the user's environment, instead of hardcoding to a specific bash at `/usr/bin/bash`. + +- When referring to other files, don't use relative paths: + +This is because your script will likely break if somebody runs it from a different directory from where the script is located + +```bash +# BAD: +cat ../Dockerfile | wc -l + +# GOOD: +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cat ${DIR}/../Dockerfile | wc -l +``` + +For other recommended bash conventions, refer to this blog post: [Best Practices for Writing Shell Scripts](https://kvz.io/bash-best-practices.html) + +## Documentation + +- Documentation should be written in Mark Down format. +- All discussion documents should be placed in /community/archive/discussion-docs. +- The use of Google Docs and other tools should not be used. + +## Directory Structure + +Along with guidelines for coding styles, the Mojaloop Community recommends the following directory structure. This ensures that developers can easily switch from one project to another, and also ensures that our tools and configs (such as `.circleci/config.yml` and `Dockerfile`s) can be ported easily from one project to another with minor changes. + +The directory structure guide requires: + +```bash +├── package.json # at the root of the project +├── src # directory containing project source files +├── dist # directory containing compiled javascript files (see tsconfig below) +├── test # directory for tests, containing at least: +│  ├── unit # unit tests, matching the directory structure in `./src` +│  └── integration # integration tests, matching the directory structure in `./src` +└── config + └── default.json # RC config file +``` + +## Config Files + +The following Config files help to enforce the code styles outlined above: + + +### EditorConfig +> EditorConfig is supported out of the box in many IDEs and Text editors. For more information, refer to the [EditorConfig guide](https://editorconfig.org/). + +`.editorconfig` +```ini +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 + +[{*.js,*.ts,package.json,*.yml,*.cjson}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false +``` + +### NYC (code coverage tool) + +`.nycrc.yml` +```yml +temp-directory: "./.nyc_output" +check-coverage: true +per-file: true +lines: 90 +statements: 90 +functions: 90 +branches: 90 +all: true +include: [ + "src/**/*.js" +] +reporter: [ + "lcov", + "text-summary" +] +exclude: [ + "**/node_modules/**", + '**/migrations/**' +] +``` + +### Typescript + +`.tsconfig.json` +```json +{ + "include": [ + "src" + ], + "exclude": [ + "node_modules", + "**/*.spec.ts", + "test", + "lib", + "coverage" + ], + "compilerOptions": { + "target": "es2018", + "module": "commonjs", + "lib": [ + "esnext" + ], + "importHelpers": true, + "declaration": true, + "sourceMap": true, + "rootDir": "./src", + "outDir": "./dist", + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "moduleResolution": "node", + "baseUrl": "./", + "paths": { + "*": [ + "src/*", + "node_modules/*" + ] + }, + "esModuleInterop": true + } +} +``` + +`.eslintrc.js` +```js +module.exports = { + parser: '@typescript-eslint/parser', // Specifies the ESLint parser + extends: [ + 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin + 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier + 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. + // Enforces ES6+ import/export syntax + 'plugin:import/errors', + 'plugin:import/warnings', + 'plugin:import/typescript', + ], + parserOptions: { + ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features + sourceType: 'module', // Allows for the use of imports + }, + rules: { + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off' + }, + overrides: [ + { + // Disable some rules that we abuse in unit tests. + files: ['test/**/*.ts'], + rules: { + '@typescript-eslint/explicit-function-return-type': 'off', + }, + }, + ], +}; +``` + +For a more detailed list of the recommended typescript configuration, including `package.json`, `jest.config.js` and more, refer to the [Typescript Template Project](https://github.com/mojaloop/template-typescript-public). + +## Design + Implementation Guidelines + +These guidelines are meant as recommendations for writing code in the Mojaloop community (or code that will be adopted into the community). If you are writing code that you wish to donate code to the community, we ask that you follow these guidelines as much as possible to aid with the consistency and maintainability of the codebase. Donations that adhere to these guidelines will be adopted more easily and swiftly. + +For more information, refer to the FAQ [below](#faqs). + +## Tools + Frameworks + +In the Mojaloop OSS Community, we are prefer the following tools and frameworks: + +- **Web Server:** [`HapiJS`](https://github.com/hapijs/hapi) +- **Web UI Framework:** [`ReactJS`](https://reactjs.org/) +- **Runtime Configuration:** [`rc`](https://www.npmjs.com/package/rc) (both from env variables and config files) +- **Package Management:** `npm` +- **Logging:** [`@mojaloop/central-services-logger`](https://github.com/mojaloop/central-services-logger#readme) library, built on top of Winston +- **Containers and Orchestration:** [`docker`](https://www.docker.com/) and [`kubernetes`](https://kubernetes.io/) +- **Unit Testing:** For existing tests, [`Tape`](https://github.com/substack/tape), but we are currently moving over to [`Jest`](https://jestjs.io/) for new codebases. +- **Test Coverage:** [`nyc`](https://github.com/istanbuljs/nyc) +- **CI:** [`CircleCI`](https://circleci.com/) + +By using these tools and frameworks, we maintain a high level of consistency and maintainability across the codebase, which keeps our developers productive and happy. While we don't mandate that donated codebases use these same tools and frameworks, we would like to stress that adoptions that use different tools could create an undue maintenance burden on the Community. + +## Adopting Open Source Contributions into Mojaloop + +This section provides guidelines regarding the adoption of a contribution to the Mojaloop Open Source repositories. Adoption is the process where we as the community work with a contributor to bring a contribution into alignment with our standards and guidelines to be a part of the Mojaloop OSS Codebase. + +>*Note:* Code Contributions are evaluated on a **case-by-case** basis. Contributions that don't align to these guidelines will need to go through the incubation phase as described below. Other misalignments to these standards (for example, framework choices) may be added to a roadmap for further improvement and OSS Standardization in the future. + +### Step 0: Prerequisites + +Before a contribution is to be considered for adoption, it: + +1. Should be in-line with the [Level One Project Principles](https://leveloneproject.org/). +1. Should adhere to the above Style and Design + Implementation Guides. +1. Should contain documentation to get started: the more, the better. +1. Contain tests with a high level of coverage. At a minimum, a contribution should contain unit tests, but a test suite with unit, integration and functional tests is preferred. Refer to the [contributors guide](./tools-and-technologies/automated-testing) for more information. + +### Step 1: Incubation + +1. Create a private repo within the Mojaloop GitHub organization for the adopted code. +1. Have a sub-team of the DA take a look to make sure its portable \(to OSS\) - aligns with L1P principles, etc, and ensure design is in line with standards. +1. Check Licensing of the contribution and any new dependencies it requires, and add the standard Mojaloop License with attribution to donor/contributors. +1. Assess the current state of the codebase, including documentation, tests, code quality, and address any shortfalls. +1. Assess Performance impact. +1. Create action items \(stories\) to update naming, remove/sanitize any items that are not generic +1. Inspect and discuss any framework and tooling choices. + - If a decision is made to make any changes, add them to the roadmap. + +### Step 2: Public Adoption + +1. Make the project public on Mojaloop GitHub. +1. Announce on the slack [`#announcements`](https://mojaloop.slack.com/archives/CG3MAJZ5J) channel. +1. Enable CI/CD Pipelines and publish any relevant artifacts, such as Docker Images or npm modules. +1. Review and recommend a module or course for the Mojaloop Training Program if needed and relevant for this contribution. + +## Versioning + +Review the information on [versioning](./versioning.md) for Mojaloop. + +## Creating new Features + +Process for creating new [features and branches](./creating-new-features.md) in Mojaloop. + +## Pull Request Process + +It's a good idea to ask about major changes on [Slack](https://mojaloop.slack.com). Submit pull requests which include both the change and the reason for the change. Feel free to use GitHub's "Draft Pull Request" feature to open up your changes for comments and review from the community. + +Pull requests will be denied if they violate the [Level One Principles](https://leveloneproject.org/wp-content/uploads/2016/03/L1P_Level-One-Principles-and-Perspective.pdf). + +## Code of conduct + +We use the [Mojaloop Foundation Code of Conduct](https://github.com/mojaloop/mojaloop/blob/master/CODE_OF_CONDUCT.md) + +## Licensing + +See [License](https://github.com/mojaloop/mojaloop/blob/master/contribute/License.md) policy. + +## FAQs + +__1. What if I want to contribute code, but it doesn't align with the code style and framework/tool recommendations in this guide?__ + +Contributions are accepted on a _case by case_ basis. If your contribution is not yet ready to be fully adopted, we can go through the incubation phase described above, where the code is refactored with our help and brought into alignment with the code and documentation requirements. + + +__2. These standards are outdated, and a newer, cooler tool (or framework, method or language) has come along that will solve problem _x_ for us. How can I update the standards?__ + +Writing high quality, functional code is a moving target, and we always want to be on the lookout for new tools that will improve the Mojaloop OSS codebase. So please talk to us in the design authority slack channel (`#design-authority`) if you have a recommendation. \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/community/standards/triaging-bugs.md b/website/versioned_docs/v1.0.1/community/standards/triaging-bugs.md new file mode 100644 index 000000000..92d140af8 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/standards/triaging-bugs.md @@ -0,0 +1,33 @@ +# Triaging Mojaloop OSS bugs + +### Raising a bug / issue + +If there is a bug or issue in general an issue is logged as a bug or feature request on the [project](https://github.com/mojaloop/project/issues/new/choose) repository and in some cases linked to an issue logged on the repository for that specific component. + +There is a bug [template](https://github.com/mojaloop/project/issues/new?assignees=&labels=bug&template=bug_report.md&title=) that can be used and encourages use of details such as versions, expected results and other details, which help with triage and reproducing the issue. + +### Once a bug is logged + +1. Typically, the bug is initially triaged in the [#ml-oss-bug-triage](https://mojaloop.slack.com/messages/CMCVBHPUH) public channel on Mojaloop Slack +2. For Security and other sensitive issues, the bug is triaged on a private channel with current contributors, before information is made public at an appropriate time. +3. During bug triage, priority and severity are assigned to the bug after majority consensus usually +4. Based on the priority and severity the bug is taken up by the Core team or other contributors based on a collaborative effort. +5. Once it is taken up, conversation and updates happen on the slack channl, but mostly on the issue itself. + +### Triage + +1. The discussion regarding the issue is open to a public for normal bugs / issues +2. However, to start with, the voting rights are given to current contributors and stakeholders. +3. Based on the discussions, a final call on the priority and severity of the issue is made by the Program Manager. +4. If you think you need a vote, please reach out to Kim or Sam. +5. Here are the voting members [14] for triaging bugs to start with. + 1. Kim Walters + 1. Lewis Daly + 1. Miguel deBarros + 1. Sam Kummary + 1. Sri Miryala + 1. Warren Carew + 1. Vijay Guthi + 1. Valentin Genev + 1. Shashi Hirugade +6. The list and the process will be updated as it evolves, this is a proposal to start with do a Pilot on. diff --git a/website/versioned_docs/v1.0.1/community/standards/versioning.md b/website/versioned_docs/v1.0.1/community/standards/versioning.md new file mode 100644 index 000000000..d8d759985 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/standards/versioning.md @@ -0,0 +1,126 @@ +# Versioning + +## Versioning of releases made for core Switch services + +This document provides guidelines regarding the versioning strategy used for the releases of Mojaloop Open Source repositories corresponding to the Switch services. + +### Versioning Strategy + + +#### Standard for PI-11 and beyond +1. Starting PI-11 (27th July, 2020) the Versioning guidance is to move to a versioning system that is closely aligned with Semantic versioning by removing the PI/Sprint dependency. So starting 11.x.x, the proposal is to move to pure [SemVer](https://semver.org/). +2. At a high-level, we will still follow the vX.Y.Z format, but X represents ‘Major’ version, Y represents ‘Minor’ version and Z represents ‘patch’ version. Minor fixes, patches affect increments to ‘Z’, whereas non-breaking functionality changes affect changes to ‘Y; breaking changes affect the ‘X’ version. +3. Along with these, suffixes such as “-snapshot”, “-patch”, “-hotfix” are used as relevant and on need basis (supported by CI config). +4. So starting with 11.0.0 (primarily for Helm, but for individual services as well) for PI-11, the proposal is to move to pure [SemVer](https://semver.org/). +5. This implies that for any new release of a package/service below X=11 (for existing repositories and not new ones) will first be baselined to v11.0.0 and from then on follow standard SemVer guidelines as discussed above. For new projects or repositories, versioning can start from v1.0.0 (after they reach release status) + + +#### Versioning Strategy used until PI-10 +1. The Mojaloop (up to PI-10) versioning system is inspired by the [Semantic Versioning](https://semver.org/) numbering system for releases. +2. However, this is customized to depict the timelines of the Mojaloop project, based on the Program Increment \(PI\) and Sprint numbers +3. For example, the release number v5.1.0 implies that this release was the first one made during a Sprint 5.1, where Sprint5.1 is the first Sprint in PI-5. So for a version vX.Y.Z, X.Y is the Sprint number where X is the PI number and Z represents the number of release for this specific repository. Example v4.4.4 implies that the current release is the fourth of four releases made in Sprint 4.4 \(of PI-4\) + + + +### Current Version + +The currrent version information for Mojaloop can be found [here](../../deployment-guide/releases.md). + +### Sprint schedule for PI-13 + +Below is the Sprint schedule for Program Increment 13 which ends with the PI-14 Community event in April 2021. + +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Phase-5 Kick-off On-site**|1/25/2021|1/29/2021|5 days| Virtual Zoom Webinars| +|**Sprint 13.1**|02/01/2021|02/14/2021|2 weeks | | +|**Sprint 13.2**|02/15/2021|02/28/2021|2 weeks | | +|**Sprint 13.3**|03/01/2021|03/14/2021|2 weeks | | +|**Sprint 13.4**|03/15/2021|03/28/2021|2 weeks | | +|**Sprint 13.5**|03/29/2021|04/11/2021|2 weeks | | +|**Sprint 13.6**|04/12/2021|04/25/2021|2 weeks | | +|**Phase-5 PI-14**|04/26/2021|04/30/2021|5 days| Virtual meetings | + +### Sprint schedule for PI-12 + +Below is the Sprint schedule for Program Increment 12 which ends with the PI-13 Community event in January 2021. + +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| +|**Phase-4 PI-10 Virtual**|4/21/2020|4/24/2020|4 days| Virtual Zoom Webinars| +|**Phase-4 PI-11 Virtual**|7/21/2020|7/24/2020|4 days| Virtual Zoom Webinars| +|**Phase-4 PI-12 Virtual**|10/19/2020|10/23/2020|5 days| Virtual Zoom Webinars| +|**Sprint 12.1**|10/26/2020|11/15/2020|3 weeks | | +|**Sprint 12.2**|11/16/2020|11/29/2020|2 weeks | | +|**Sprint 12.3**|11/30/2020|12/13/2020|2 weeks | | +|**Sprint 12.4**|12/14/2020|12/27/2020|2 weeks | | +|**Sprint 12.5**|12/28/2020|01/10/2021|2 weeks | | +|**Sprint 12.6**|01/11/2020|01/24/2020|2 weeks | | +|**Phase-5 Kick-off / PI-13**|01/25/2021|01/29/2021|5 days| TBD | + +### Previous Sprint Schedules: + +### Sprint schedule for PI-11 + +Below is the Sprint schedule for Program Increment 11 which ends with the PI 12 Event. + +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| +|**Phase-4 PI-10 Virtual**|4/21/2020|4/24/2020|4 days| Virtual Zoom Webinars | +|**Phase-4 PI-11 Virtual**|7/21/2020|7/24/2020|4 days| Virtual Zoom Webinars | +|**Sprint 11.1**|7/27/2020|8/9/2020|2 weeks| | +|**Sprint 11.2**|8/10/2020|8/23/2020|2 weeks| | +|**Sprint 11.3**|8/24/2020|9/6/2020|2 weeks| | +|**Sprint 11.4**|9/7/2020|9/20/2020|2 weeks| | +|**Sprint 11.5**|9/21/2020|10/4/2020|2 weeks| | +|**Sprint 11.6**|10/5/2020|10/18/2020|2 weeks | | +|**Phase-4 PI-12**|10/20/2020|10/23/2020|4 days| TBD | + +#### Sprint schedule for PI-10 + +Below is the Sprint schedule for Program Increment 10 which ends with the PI 11 Event. Please use this as guidance during the versioning and release processes. + +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Phase-3 PI6 On-site**|4/16/2019|4/18/2019|3 days| Johannesburg| +|**Phase-3 PI7 On-site**|6/25/2019|6/27/2019|3 days| Arusha| +|**Phase-3 PI8 On-site**|9/10/2019|9/12/2019|3 days| Abidjan| +|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| +|**Phase-4 PI 10 Virtual**|4/21/2020|4/24/2020|5 days| Virtual Zoom Webinars | +|**Sprint 10.1**|4/27/2020|5/10/2020|2 weeks| | +|**Sprint 10.2**|5/11/2020|5/24/2020|2 weeks| | +|**Sprint 10.3**|5/25/2020|6/7/2020|2 weeks| | +|**Sprint 10.4**|6/8/2020|6/21/2020|2 weeks| | +|**Sprint 10.5**|6/22/2020|7/5/2020|2 weeks| | +|**Sprint 10.6**|7/6/2020|7/19/2020|2 weeks | | +|**Phase-4 PI 11 On-Site**|7/21/2020|7/23/2020|3 days| Kenya (Tentative) | + +#### PI-9 +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Sprint 9.1**|2/3/2020|2/16/2020|2 weeks| | +|**Sprint 9.2**|2/17/2020|3/1/2020|2 weeks| | +|**Sprint 9.3**|3/2/2020|3/15/2020|2 weeks| | +|**Sprint 9.4**|3/16/2020|3/29/2020|2 weeks| | +|**Sprint 9.5**|3/30/2020|4/12/2020|2 weeks| | +|**Sprint 9.6**|3/13/2020|4/19/2020|1 week | | +|**Phase-4 PI 10 Virtual**|4/21/2020|4/23/2020|5 days| Virtual Zoom Webinars | + +#### PI-8 +|Phase/Milestone|Start|End|Weeks|Notes| +|---|---|---|---|---| +|**Sprint 8.1**|9/16/2019|9/29/2019|2 weeks| | +|**Sprint 8.2**|9/30/2019|10/13/2019|2 weeks| | +|**Sprint 8.3**|10/14/2019|10/27/2019|2 weeks| | +|**Sprint 8.4**|10/28/2019|11/10/2019|2 weeks| | +|**Sprint 8.5**|11/11/2019|11/24/2019|2 weeks| | +|**Sprint 8.6**|11/25/2019|12/8/2019|2 weeks| | +|**Sprint 8.7**|12/9/2019|1/5/2020|4 weeks| Christmas Break| +|**Sprint 8.8**|1/6/2020|1/26/2020|3 weeks| 1 week prep| +|**Phase-4 Kick-off On-site**|1/28/2020|1/30/2020|3 days| Johannesburg| + +### Notes + +1. A new release for **helm** repo is made based on the feature and configuration changes made to core services and requirements from thhe Community. \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_lib_master.png b/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_lib_master.png new file mode 100644 index 000000000..331087be4 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_lib_master.png differ diff --git a/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_lib_pr.png b/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_lib_pr.png new file mode 100644 index 000000000..1a64f791f Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_lib_pr.png differ diff --git a/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_lib_tag.png b/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_lib_tag.png new file mode 100644 index 000000000..13af7e59c Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_lib_tag.png differ diff --git a/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_svc_master.png b/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_svc_master.png new file mode 100644 index 000000000..6ab54d9d9 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_svc_master.png differ diff --git a/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_svc_pr.png b/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_svc_pr.png new file mode 100644 index 000000000..389f5ccba Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_svc_pr.png differ diff --git a/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_svc_tag.png b/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_svc_tag.png new file mode 100644 index 000000000..934aee684 Binary files /dev/null and b/website/versioned_docs/v1.0.1/community/tools/assets/images/ci_cd_svc_tag.png differ diff --git a/website/versioned_docs/v1.0.1/community/tools/automated-testing.md b/website/versioned_docs/v1.0.1/community/tools/automated-testing.md new file mode 100644 index 000000000..fad1f9eaf --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/tools/automated-testing.md @@ -0,0 +1,144 @@ +# QA and Regression Testing in Mojaloop +An overview of the testing framework set up in Mojaloop + +Contents: +1. [Regression requirements](#regression-topics) +2. [Developer Testing](#developer-testing) +3. [Postman and Newman Testing](#postman-and-newman-testing) +4. [Executing regression test](#executing-regression-test) +5. [Process flow of a typical Scheduled Test](#process-flow-of-a-typical-scheduled-test) +6. [Newman Commands](#newman-commands) + +## Regression Topics + In order for a deployed system to be robust, one of the last checkpoints is to determine if the environment it is deployed in, is in a healthy state and all exposed functionality works exactly the way as intended. + + Prior to that though, there are quite a number of disciplines one must put in place to ensure maximum control. + + To illustrate how the Mojaloop project reaches this goal, we are going to show you the various checkpoints put in place. + +### Developer Testing + Looking at each component and module, inside the code base, you will find a folder named "*test*" which contain three types of tests. + + Firstly, the *coverage test* which alerts one if there are unreachable or redundant code + + Unit Tests, which determines if the intended functionality works as expected + + Integration Tests, which does not test end-to-end functionality, but the immediate neighbouring interaction + + Automated code-standard checks implemented by means of packages that form part of the code base + + These tests are executed by running the command line instructions, by the developer, during the coding process. Also, the tests are automatically executed every time a *check-in* is done and a Github Pull-Request issued for the code to be integrated into the project. + + The procedure described above, falls outside the realm of Quality Assurance (QA) and Regression testing, which this document addresses. + + Once a developer has written new functionality or extended existing functionality, by having to go through the above rigorous tests, one can assume the functionality in question is executing as intended. How does one then ensure that this new portion of code does not negatively affect the project or product as a whole? + + When the code has passed all of the above and is deployed as part of the CI/CD processes implemented by our workflow, the new component(s) are accepted onto the various hosts, cloud-based or on-premise implementations. These hosts ranges from development platforms through to production environments. + +### Postman and Newman Testing + Parallel to the deployment process is the upkeep and maintenance of the [Postman](https://github.com/mojaloop/postman.git "Postman") Collection testing Framework. When a new release is done, as part of the workflow, Release Notes are published listing all of the new and/or enhanced functionality implemented as part of the release. These notes are used by the QA team to extend and enhance the existing Postman Collections where tests are written behind the request/response scripts to test both positive as well as negative scenarios agains the intended behaviour. These tests are then run in the following manner: + + Manually to determine if the tests cover all aspects and angles of the functionality, positive to assert intended behaviour and negative tests to determine if the correct alternate flows work as intended when something unexpected goes wrong + + Scheduled - as part of the Regression regime, to do exactly the same as the manual intent, but fully automated (with the *Newman Package*) with reports and logs produced to highlight any unintended behaviour and to also warn where known behaviour changed from a previous run. + +In order to facilitate the automated and scheduled testing of a Postman Collection, there are various methods one can follow and the one implemented for Mojaloop use is explained further down in this document. + +There is a complete repository containing all of the scripts, setup procedures and anything required in order to set up an automated [QA and Regression Testing Framework](https://github.com/mojaloop/ml-qa-regression-testing.git "QA and Regression Testing Framework"). This framework allows one to target any Postman Collection, specifying your intended Environment to execute against, as well as a comma-separated list of intended email recipients to receive the generated report. This framework is in daily use by Mojaloop and exists on an EC2 instance on AWS, hosting the required components like Node, Docker, Email Server and Newman, as well as various Bash Scripts and Templates for use by the framework to automatically run the intended collections every day. Using this guide will allow anyone to set up their own Framework. + +#### Postman Collections + +There are a number of Postman collections in use throughout the different processes: + +For Mojaloop Simulator: + ++ [MojaloopHub_Setup](https://github.com/mojaloop/postman/blob/master/MojaloopHub_Setup.postman_collection.json) : This collection needs to be executed once after a new deployment, normally by the Release Manager. It sets up an empty Mojaloop hub, including things such as the Hub's currency, the settlement accounts. ++ [MojaloopSims_Onboarding](https://github.com/mojaloop/postman/blob/master/MojaloopSims_Onboarding.postman_collection.json) : MojaloopSims_Onboarding sets up the DFSP simulators, and configures things such as the endpoint urls so that the Mojaloop hub knows where to send request callbacks. ++ [Golden_Path_Mojaloop](https://github.com/mojaloop/postman/blob/master/Golden_Path_Mojaloop.postman_collection.json) : The Golden_Path_Mojaloop collection is an end-to-end regression test pack which does a complete test of all the deployed functionality. This test can be run manually but is actually designed to be run from the start, in an automated fashion, right through to the end, as response values are being passed from one request to the next. (The core team uses this set to validate various releases and deployments) + + Notes: In some cases, there is need for a delay of `250ms` - `500ms` if executed through Postman UI Test Runner. This will ensure that tests have enough time to validate requests against the simulator. However, this is not always required. ++ [Bulk_API_Transfers_MojaSims](https://github.com/mojaloop/postman/blob/master/Bulk_API_Transfers_MojaSims.postman_collection.json) : This collection can be used test the bulk transfers functionality that targets Mojaloop Simulator. + +For Legacy Simulator (encouraged to use Mojaloop Simulator, as this will not be supported starting PI-12 (Oct 2020) ): + ++ [ML_OSS_Setup_LegacySim](https://github.com/mojaloop/postman/blob/master/ML_OSS_Setup_LegacySim.postman_collection.json) : This collection needs to be executed once after a new deployment (if it uses Legacy Simulator), normally by the Release Manager. It sets up the Mojaloop hub, including things such as the Hub's currency, the settlement accounts along with the Legacy Simulator(s) as FSP(s). ++ [ML_OSS_Golden_Path_LegacySim](https://github.com/mojaloop/postman/blob/master/ML_OSS_Golden_Path_LegacySim.postman_collection.json) : The Golden_Path_Mojaloop collection is an end-to-end regression test pack which does a complete test of all the deployed functionality. This test can be run manually but is actually designed to be run from the start, in an automated fashion, right through to the end, as response values are being passed from one request to the next. (The core team uses this set to validate various releases and deployments) + + Notes: In some cases, there is need for a delay of `250ms` - `500ms` if executed through Postman UI Test Runner. This will ensure that tests have enough time to validate requests against the simulator. However, this is not always required. ++ [Bulk API Transfers.postman_collection](https://github.com/mojaloop/postman/blob/master/Bulk%20API%20Transfers.postman_collection.json) : This collection can be used test the bulk transfers functionality that targets Legacy Simulator. + +#### Environment Configuration + +You will need to customize the following environment config file to match your deployment environment: ++ [Local Environment Config](https://github.com/mojaloop/postman/blob/master/environments/Mojaloop-Local.postman_environment.json) + +_Tips:_ +- _The host configurations will be the most likely changes required to match your environment. e.g. `HOST_CENTRAL_LEDGER: http://central-ledger.local`_ +- _Refer to the ingress hosts that have been configured in your `values.yaml` as part of your Helm deployment._ + +### Executing regression test +For the Mojaloop QA and Regression Testing Framework specifically, Postman regression test can be executed by going into the EC2 instance via SSH, for which you need the PEM file, and then by running a script(s). + +Following the requirements and instructions as set out in the detail in [QA and Regression Testing Framework](https://github.com/mojaloop/ml-qa-regression-testing.git "QA and Regression Testing Framework"), everyone will be able to create their own Framework and gain access to their instance to execute tests against any Postman Collection targeting any Environment they have control over. + +##### Steps to execute the script via Postman UI ++ Import the desired collection into your Postman UI. You can either download the collection from the repo or alternatively use the `RAW` link and import it directly via the **import link** option. ++ Import the environment config into your Postman UI via the Environmental Config setup. Note that you will need to download the environmental config to your machine and customize it to your environment. ++ Ensure that you have pre-loaded all prerequisite test data before executing transactions (party, quotes, transfers) as per the example collection [OSS-New-Deployment-FSP-Setup](https://github.com/mojaloop/postman/blob/master/OSS-New-Deployment-FSP-Setup.postman_collection.json): + + Hub Accounts + + FSP onboarding + + Add any test data to Simulator (if applicable) + + Oracle onboarding ++ The `p2p_money_transfer` test cases from the [Golden_Path](https://github.com/mojaloop/postman/blob/master/Golden_Path.postman_collection.json) collection are a good place to start. + +##### Steps to execute the bash script to run the Newman / Postman test via CLI ++ To run a test via this method, you will have to be in posession of the PEM-file of the server on which the Mojaloop QA and Regression Framework was deployed on an EC2 instance on Amazon Cloud. + ++ SSH into the specific EC2 instance and when running the script, it will in turn run the commands via an instantiated Docker container. + ++ You will notice that by using this approach where both the URLs for the Postman-Collection and Environment File are required as input parameters (together with a comma-delimited email recipient list for the report) you have total freedom of executing any Postman Collection you choose. + ++ Also, by having an Environment File, the specific Mojaloop services targeted can be on any server. This means you can execute any Postman test against any Mojaloop installation on any server of your choice. + ++ The EC2 instance we execute these tests from are merely containing all the tools and processes in order to execute your required test and does not host any Mojaloop Services as such. + +``` +./testMojaloop.sh +``` + +## Process flow of a typical Scheduled Test + +{% uml src="contributors-guide/tools-and-technologies/assets/diagrams/automated-testing/QARegressionTestingMojaloop-Complete.plantuml" %} +{% enduml %} + +## Newman Commands +The following section is a reference, obtained from the Newman Package site itself, highlighting the different commands that may be used in order to have access to the Postman environment by specifying some commands via the CLI. +``` +Example: ++ newman run -e -n 1 -- + +Usage: run [options] + + URL or path to a Postman Collection. + + Options: + + -e, --environment Specify a URL or Path to a Postman Environment. + -g, --globals Specify a URL or Path to a file containing Postman Globals. + --folder Specify folder to run from a collection. Can be specified multiple times to run multiple folders (default: ) + -r, --reporters [reporters] Specify the reporters to use for this run. (default: cli) + -n, --iteration-count Define the number of iterations to run. + -d, --iteration-data Specify a data file to use for iterations (either json or csv). + --export-environment Exports the environment to a file after completing the run. + --export-globals Specify an output file to dump Globals before exiting. + --export-collection Specify an output file to save the executed collection + --postman-api-key API Key used to load the resources from the Postman API. + --delay-request [n] Specify the extent of delay between requests (milliseconds) (default: 0) + --bail [modifiers] Specify whether or not to gracefully stop a collection run on encountering an errorand whether to end the run with an error based on the optional modifier. + -x , --suppress-exit-code Specify whether or not to override the default exit code for the current run. + --silent Prevents newman from showing output to CLI. + --disable-unicode Forces unicode compliant symbols to be replaced by their plain text equivalents + --global-var Allows the specification of global variables via the command line, in a key=value format (default: ) + --color Enable/Disable colored output. (auto|on|off) (default: auto) + --timeout [n] Specify a timeout for collection run (in milliseconds) (default: 0) + --timeout-request [n] Specify a timeout for requests (in milliseconds). (default: 0) + --timeout-script [n] Specify a timeout for script (in milliseconds). (default: 0) + --ignore-redirects If present, Newman will not follow HTTP Redirects. + -k, --insecure Disables SSL validations. + --ssl-client-cert Specify the path to the Client SSL certificate. Supports .cert and .pfx files. + --ssl-client-key Specify the path to the Client SSL key (not needed for .pfx files) + --ssl-client-passphrase Specify the Client SSL passphrase (optional, needed for passphrase protected keys). + -h, --help output usage information +``` \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/community/tools/ci_cd_pipelines.md b/website/versioned_docs/v1.0.1/community/tools/ci_cd_pipelines.md new file mode 100644 index 000000000..d0b25a50c --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/tools/ci_cd_pipelines.md @@ -0,0 +1,127 @@ +# CI/CD Pipelines + +The Mojaloop Community uses [CircleCI](https://circleci.com/) to automatically build, test and deploy our +software. This document describes how we use CI/CD in Mojaloop, the different checks we perform on the +software, and how we distribute the software. + +Broadly speaking, there are 2 types of workflow we use, depending on the type of project: +- Library: build node project -> test -> publish to [npm](https://www.npmjs.com/search?q=%40mojaloop) +- Service: build docker image -> test -> publish to [Docker Hub](https://hub.docker.com/u/mojaloop) + +Additionally, we also maintain a set of [Mojaloop Helm Charts](http://docs.mojaloop.io/helm/), which are +built from the [mojaloop/helm](https://github.com/mojaloop/helm) + +## Libraries + +> For a good example of this CI/CD pattern see [central-services-shared](https://github.com/mojaloop/central-services-shared/blob/master/.circleci/config.yml) + +### Pull Request (PR) Flow: + +The PR flow runs on pull requests, and during the [PR review process](https://github.com/mojaloop/documentation/blob/master/contributors-guide/standards/creating-new-features.md#creating-new-features), these checks must be satisfied +for the code to be merged in. + +![](./assets/images/ci_cd_lib_pr.png) + +| Step | Description | More Info | +| --- | ----------- | --------- | +| pr-title-check | Checks that the PR title conforms to the conventional commits specification | Defined in a CircleCI orb here: [mojaloop/ci-config](https://github.com/mojaloop/ci-config) | +| test-coverage | Runs the unit-tests and checks that code coverage is above the specified limit. | Typically this is 90% | +| test-unit | Runs the unit-tests. Fails if any unit test fails. | | +| vulnerability-check | Runs the `npm audit` tool to search for any vulnerabilities in dependencies | `npm audit` is full of false positives, or security issues that don't apply to our codebase. We use `npm-audit-resolver` to give us flexibility over vulnerabilities that may be ignored, e.g `devDependencies` | +| audit-licenses | Runs the mojaloop `license-scanner-tool` and fails if any license found doesn't match an allowlist specified in the `license-scanner-tool` | [license-scanner-tool repo](https://github.com/mojaloop/license-scanner-tool) | + + +### Master and Release Flow: + +This CI/CD pipeline runs on the master/main branch: + +![](./assets/images/ci_cd_lib_master.png) + +| Step | Description | More Info | +| --- | ----------- | --------- | +| pr-title-check | See above | | +| test-coverage | See above | | +| test-unit | See above | | +| vulnerability-check | See above | | +| audit-licenses | See above | | +| release | Runs a release which creates a git tag and pushes the git tag | | +| github-release | Adds the release metadata (e.g. changelog) to github, sends a slack alert to #announcements | | + + +### Tag Flow: + +Once a git tag is pushed to the repository, it triggers a workflow that ends +in publishing to `npm`. Importantly, the checks are all run again, to ensure +nothing has changed (e.g. dependencies) inbetween the main/master and the actual +artefact that is published to `npm`. + +![](./assets/images/ci_cd_lib_tag.png) + +| Step | Description | More Info | +| --- | ----------- | --------- | +| pr-title-check | See above | | +| test-coverage | See above | | +| test-unit | See above | | +| vulnerability-check | See above | | +| audit-licenses | See above | | +| publish | Publishes the latest version of the library based on the git tag | | + + +## Services + +> For a good example of this CI/CD pattern see [central-ledger](https://github.com/mojaloop/central-ledger/blob/master/.circleci/config.yml) + +### Pull Request (PR) Flow: + +The PR flow runs on pull requests, and during the PR review process, these checks must be satisfied +for the code to be merged in. + +![](./assets/images/ci_cd_svc_pr.png) + +| Step | Description | More Info | +| --- | ----------- | --------- | +| pr-title-check | Checks that the PR title conforms to the conventional commits specification | Defined in a CircleCI orb here: [mojaloop/ci-config](https://github.com/mojaloop/ci-config) | +| test-coverage | Runs the unit-tests and checks that code coverage is above the specified limit. | Typically this is 90% | +| test-unit | Runs the unit-tests. Fails if any unit test fails. | | +| test-integration | Runs the integration-tests. Typically by building a docker image locally | | +| vulnerability-check | Runs the `npm audit` tool to search for any vulnerabilities in dependencies | `npm audit` is full of false positives, or security issues that don't apply to our codebase. We use `npm-audit-resolver` to give us flexibility over vulnerabilities that may be ignored, e.g `devDependencies` | +| audit-licenses | Runs the mojaloop `license-scanner-tool` and fails if any license found doesn't match an allowlist specified in the `license-scanner-tool` | [license-scanner-tool repo](https://github.com/mojaloop/license-scanner-tool) | + + +### Master and Release Flow: + +This CI/CD pipeline runs on the master/main branch: + +![](./assets/images/ci_cd_svc_master.png) + +| Step | Description | More Info | +| --- | ----------- | --------- | +| pr-title-check | See above | | +| test-coverage | See above | | +| test-unit | See above | | +| test-integration | See above | | +| vulnerability-check | See above | | +| audit-licenses | See above | | +| release | Runs a release which creates a git tag and pushes the git tag | | +| github-release | Adds the release metadata (e.g. changelog) to github, sends a slack alert to #announcements | | + + +### Tag Flow: + +Once a git tag is pushed to the repository, it triggers a workflow that ends +in publishing a docker image to Docker Hub. Importantly, the checks are all run again, +and further scans are made on the docker image before the image is pushed. + +![](./assets/images/ci_cd_svc_tag.png) + +| Step | Description | More Info | +| --- | ----------- | --------- | +| pr-title-check | See above | | +| test-coverage | See above | | +| test-unit | See above | | +| vulnerability-check | See above | | +| audit-licenses | See above | | +| build | Builds the docker image | | +| image-scan | Runs `anchore/analyze_local_image` to scan the image | See [anchore-engine](https://circleci.com/developer/orbs/orb/anchore/anchore-engine) CircleCI Orb for more information. | +| license-scan | Runs the mojaloop `license-scanner-tool` on the licenses contained in the docker image | | +| publish | Publishes the latest version of the library based on the git tag | | diff --git a/website/versioned_docs/v1.0.1/community/tools/code-quality-metrics.md b/website/versioned_docs/v1.0.1/community/tools/code-quality-metrics.md new file mode 100644 index 000000000..f155be68f --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/tools/code-quality-metrics.md @@ -0,0 +1,30 @@ +# Code Quality Metrics + +## Functional quality metrics + +### Unit test metrics + +High coverage and low dependencies show that the code is testable and therefore well isolated and easy to maintain. Low complexity also makes code readable and maintainable and helps enforce single responsibility. Real unit tests run very fast as they don't call external components. + +| Code Quality Metrics | New and Project Code | +| :--- | :--- | +| Unit test coverage | >= 80% block coverage | +| Unit test speed | <= 10 seconds | +| Dependencies/method | <= 10 | +| Complexity/method | <= 7 | + +### Component + +Functional testing typically covers pair combinations of the system states. + +### Integration + +Functional tests have one test per message and error. Messages and errors that are handled the same way use the same test. + +### Contract + +Limited to what the consuming teams need that isn't covered by existing unit, component, and integration tests. Often added to over time. + +### End to End + +End to end tests cover acceptance tests from scenarios. \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/community/tools/pragmatic-rest.md b/website/versioned_docs/v1.0.1/community/tools/pragmatic-rest.md new file mode 100644 index 000000000..bb7db5ef3 --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/tools/pragmatic-rest.md @@ -0,0 +1,129 @@ +# Pragmatic REST + +## Pragmatic REST For the Mojaloop Project + +With the emergence of API strategy as a scaling tool for Internet service businesses, the focus on interconnect technology has shifted. Building on the principles that enabled the Web to form and scale, REST \(Representational State Transfer\) has become a design preference for Internet service APIs. But while the REST principles, proposed in Roy Fielding's dissertation that defined them, have academic value as a basis for research, a pure REST design is not at present practical for most applications. We are advocating a kind of Pragmatic REST-a design pattern that adopts the beneficial components of RESTful design without requiring strict adherence to academic purity. + +### The Richardson Maturity Model + +Martin Fowler has referenced a structured model of RESTful adoption developed by Leonard Richardson and [explained](http://www.crummy.com/writing/speaking/2008-QCon/act3.html) at a QCon talk. Fowler refers to this as the Richardson Maturity Model of RESTful design. + + + +Martin Fowler, referencing [Rest in Practice](https://www.amazon.com/gp/product/0596805829?ie=UTF8&tag=martinfowlerc-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0596805829),2 summarizes the genesis of RESTful design: + +> use Restful web services to handle many of the integration problems that enterprises face. At its heart . . . is the notion that the web is an existence proof of a massively scalable distributed system that works really well, and we can take ideas from that to build integrated systems more easily. + +A pragmatic approach to RESTful design uses the best parts of Fielding's conceptual framework to allow developers and integrators to understand what they can do with the API as rapidly as possible and without writing extraneous code. + +At its most fundamental, a RESTful design is resource-centric and uses HTTP verbs. At its most advanced, a design that follows pure academic REST utilizes the HATEOAS principle by implementing Hypermedia Controls. We are advocating a Level 2 RESTful design for Mojaloop. + +### Why not Hypermedia Controls? + +Although HATEOAS is a fascinating principle-it advocates that a server should respond to each client action with a list of all possible actions that can lead the client to its next application state. And further, clients _must not_ rely on out of band information \(like a written API spec\) for what actions can be performed on which resources or on the format of URIs. + +It is this final proscription that fails the test of Pragmatic REST: While HATEOAS is an interesting theoretical approach to limit coupling, it does not easily apply to Mojaloop \(or any other contract API design\). When we take into account our audience for the interconnect APIs, we find a group of commercial entities that will be operating under a set of highly specific scheme rules. Interactions between the participants, and between participant and central service hub, will be highly specified to assign acceptable commercial risk that can be priced at very low cost to end-users. This requires _ex-ante_ predictability of the API which is anathema to the HATEOAS principle defined by Fielding. + +### Pragmatic RESTful Principles + +#### URIs Define Resources + +A well-designed URI pattern makes an API easy to consume, discover, and extend, just as a carefully designed API does in a traditional programming language. Pure REST disdains this principle in favor of HATEOAS. But pragmatic REST follows a normal pattern for URI definitions to improve human understanding, even if HATEOAS principles are employed for discovery. + +URI paths that refer to a collection of objects should consist of a plural noun, e.g. /customers, to refer to a set of customers. When a collection can have only one instance, the singular noun should be used to avoid confusion. E.g. GET /transfers/:id/fulfillment is correct, since there is only one fulfillment object per identified transfer. + +URI paths that refer to a single object should consist of a plural noun \(representing the collection\), followed by a predefined unique identifier. E.g., /customers/123456 to refer to the specific customer with number 123456. The identifier must be unique within the containing collection and persist for the life of the object within that collection. IDs must not be ordinal values-ordinal retrieval of objects from a collection is possible using query parameters on the collection URI. + +URI paths may have a prefix to identify the environment, version, or other context of the resource. Nothing should follow the identifying path but collections and object references. + +URI path and query segment identifiers should be chosen from the Roman character set, \[0-9A-Za-z\]. Use _camelCase_ to define the elements of the URI path. Do not use snake\_case. + +For the avoidance of doubt, "\_" \(underscore\) and "-" \(hyphen\) should not be used in URI path or query segment identifiers. + +This probably seems a bit parochial. The purpose is to find a well-defined URI format that is consistent with wide-spread practice, easy to define, predictable, and that maps to native environments and conventions. It isn't going to satisfy everyone. Here is reasoning behind this constraint: + +CapitalCase and camelCase are the defacto standard for NodeJS and JavaScript and are a common constraint in URI definition: URI path segments are often mapped to JS internal resources and so conforming to JS naming conventions makes sense. + +Field names in JSON and SQL should also follow this convention since they are often automatically mapped into variable name space and can be referenced in URIs as path or query segment identifiers. + +We should also avoid the use of "$" unless it is required by a library \(e.g. JQuery\). IBM JCL has passed away; let it rest in peace. There are better scope control tools to separate name spaces than introducing non-roman symbols. + +We should avoid "-" \(hyphen\) in path segment and query parameter names as it does not map into variable names, SQL, or JSON field name identifiers. + +Underscore characters must be escaped in markdown source by prefixing each with a "\" character. + +Snake\_case has been reported to be slightly easier to read than camelCase in variable names, but it actually does not improve readability of URIs, as it visually interferes with path and query segment delimiters making it difficult to visually parse them. And when URIs are underlined in presentation, the underscores become illegible. + +#### URI Parameters + +Use a standard and predictable set of optional parameters in a consistent way. + +A set of standard query parameters should be used for collections to enable caller control over how much of the collection they see. E.g. "count" to determine how many objects to return, "start" to determine where to start counting in the result set, and "q" as a generic free-form search query. We will define the standard set of parameters as we go and will apply them consistently. + +#### Verbs + +Singular objects should support GET for read, PUT for complete replacement \(or creation when the primary key is specified by the client and is persistent, e.g. a payment card PAN\), and DELETE for delete. + +Collections should support GET to read back the whole or part of a collection, and POST to add a new object to the collection. + +Singular objects may support POST as a way to change their state in specified ways. Posting a JSON document to a singular object URI may allow selected field values to be updated or trigger a state change or action without replacing the whole object. + +GET must be implemented in a _nullipotent_ manner-that is, GET never causes side effects and never modifies client-visible system state \(other than logging events or updating instrumentation, e.g.\). + +PUT and DELETE must be implemented in an _idempotent_ manner-that is, changes are applied consistently to the system data in a way that is dependent only on the state of the resource and inputs but on nothing else. The action has no additional effect if it is executed more than once with the same input parameters and does not depend on the order of other operations on a containing collection or other resources held in the collection. For example, removing a resource from a collection can be considered an idempotent operation on the collection. Using PUT to fully replace \(or create\) a uniquely identified resource when the URI is fully known to the client is also idempotent. This implies that the system may reorder operations to improve efficiency, and the client does not need to know whether a resource exists before attempting to replace it. + +POST and PATCH3 are not idempotent operations. POST is used to create new resources where the resource identifier is assigned by the server or where a single identified internal resource is implied by the target URI \(e.g. POST /transfers, but PUT /transfers/:id/fulfillment\). + +#### Data Format + +We favor [JSON](http://json.org/)4 related data formats over XML. In some cases, data formats will be binary or XML, as defined by pre-existing standards, and these will be precisely specified. Binary formats should have a formal syntax to avoid ambiguous representational translations \(e.g. character set translations, big- or little-endian representations of numeric values, etc\). + +Date and time values used in APIs should comply to the ISO 8601 standard, and further profiled by the w3c Note on Date and Time Formats.5 This w3c note should lead to the reduction in complexity and error scope of communicating components that must exchange tangible dates and times. There will be cases where we use non-ISO format date or time as required by an external standard, e.g. ISO 7813 expiry dates. + +Existing standard XML formats should have an XSD schema for the acceptable subset profile used within the project. For particularly complex data formats, we may use a common format profile translator to map between our project subset of the standard format and the wire format used by a standardized protocol \(e.g.\). This will limit coupling to complex formats in a more maintainable way. + +When specifying the PATCH action for a resource, we will use a consistent patch document format \(e.g. [JSON Patch](http://jsonpatch.com/)6\). + +#### Return Codes + +Use HTTP return codes in a consistent way and according to their standard definitions. The standard codes are defined in RFC 2616.7 + +#### Machine Readable Error Format + +The API should provide a machine readable error result in a well-defined JSON format. {TBD whether to use a response envelope and how to format errors, faults, and success envelopes. RESTful design relies on headers to carry protocol-defined errors, debug info can also be carried in headers. We should be clear on why we are using an envelope and how this supports normal production communication between client and server. + +#### Versioning + +API URIs should include a version identifier in the format v_M_ as a leading path element \(where _"M"_ is the Major component of the multi-part version number\). The API and its version identifier element must conform to the [semantic versioning](http://semver.org/)8 2.0 specification for API versioning. + +A client must specify the Major version number in each request. It is not possible for a client to express a requirement for a specific minor version. + +The full API version number is specified in the response header \(TBD\) for all successful and error responses. + +While an API version contract will be influenced by Major, minor, _and_ patch levels, only the Major version number is a production API binding element-that is, a production client cannot request a particular minor version or patch level and a production server will not accept a URI request that specifies these extra elements. + +However, in pre-production environments, it is anticipated that some combination of minor, patch, pre-release, and metadata suffixes would be supported in client requests \(as defined in _semver_ \[3\]\) and _may_ be expressed in _pre-production_ URIs to assist with development and integration scenarios. + +### We May Need to Give REST a Rest + +As we design the interconnection APIs between components and between participating systems, we may find API requirements that don't precisely match the Pragmatic REST pattern defined here. We will evaluate these case-by-case and make the best choice to support the project goals. + +### Non-Functional Requirements + +As we develop the APIs, we will make consistent choices about non-functional requirements to reinforce the project goals. + +1: [http://martinfowler.com/articles/richardsonMaturityModel.html](Richardson%20Maturity%20Model), retrieved August 18, 2016. + +2: [https://www.amazon.com/gp/product/0596805829](https://www.amazon.com/gp/product/0596805829?ie=UTF8&tag=martinfowlerc-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0596805829), retrieved August 18, 2016. + +3: RFC 5789, _PATCH Method for HTTP_, [https://tools.ietf.org/html/rfc5789](https://tools.ietf.org/html/rfc5789), retrieved August 18, 2016. + +4: _Introducing JSON_, [http://json.org/](http://json.org/), retrieved August 18, 2016. + +5: [http://www.w3.org/TR/1998/NOTE-datetime-19980827](http://www.w3.org/TR/1998/NOTE-datetime-19980827), retrieved August 22, 2016. + +6: _JSON Patch_, [http://jsonpatch.com/](http://jsonpatch.com/), retrieved August 18, 2016. + +7: [https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) + +8: _Semantic Versioning 2.0.0_, [http://semver.org/](http://semver.org/), retrieved August 18, 2016. \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/community/tools/tools-and-technologies.md b/website/versioned_docs/v1.0.1/community/tools/tools-and-technologies.md new file mode 100644 index 000000000..f92bfc47d --- /dev/null +++ b/website/versioned_docs/v1.0.1/community/tools/tools-and-technologies.md @@ -0,0 +1,50 @@ +# Tools and Technologies + +Here we document the reasoning behind certain tools, technology and process choices for Mojaloop. We also have included the recommendation links/versions for each of these tools. + +**TOOL CHOICES** + +* **API Development** + * **RAML** and **Swagger 2.0** is leveraged for API development. + * **WSO2** offers an enterprise platform for integrating APIs, applications, and web services—locally and across the Internet. It also provides Mojaloop with a Security Layer, and Development Portal. +* **Circle-CI** - This tool is used for continuous build and continuous deployment. We needed an online continuous build and testing system that can work with many small projects and a distributed team. Jenkins was considered, but it requires hosting a server and a lot of configuration. CircleCI allowed for a no host solution that could be started with no cost and very limited configuration. We thought we might start with CircleCI and move off later if we outgrew it, but that hasn’t been needed. +* **Dactyl** – We need to be able to print the online documentation. While it’s possible to print markdown files directly one at a time, we’d like to put the files into set of final PDF documents, where one page might end up in more than one final manual. [Dactyl](https://github.com/ripple/dactyl) is a maintained open source conversion tool that converts between markdown and PDF. We originally tried Pandoc, but it had bugs with converting tables. Dactyl fixes that and is much more flexible. +* **DBeaver** - [DBeaver](https://dbeaver.io/) is a free multi-platform database tool for developers, SQL programmers, database administrators and analysts. Supports all popular databases: MySQL, PostgreSQL, MariaDB, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Derby, etc. +* **Docker** - The Docker container engine creates and runs the Docker container from the Docker image file. +* **Docker hub** is used to link, build, test and push the Mojaloop code repositories. We needed to support both local and cloud execution. We have many small microservices that have very simple specific configurations and requirements. The easiest way to guarantee that the service works the same way in every environment from local development, to cloud, to hosted production is to put each microservice in a Docker container along with all the prerequisites it needs to run. The container becomes a secure, closed, pre-configured, runnable unit. +* **Draw.io** – We need to create pictures for our documents and architecture diagrams using an \(ideally free\) open source friendly tool, that is platform agnostic, supports vector and raster formats, allows WYSIWYG drawing, works with markdown, and is easy to use. We looked at many tools including: Visio, Mermaid, PlantUML, Sketchboard.io, LucidChart, Cacoo, Archi, and Google Drawings. Draw.io scored at the top for our needs. It’s free, maintained, easy to use, produces our formats, integrates with DropBox and GitHub, and platform agnostic. In order to save our diagrams, we have to save two copies – one in SVG \(scalable vector\) format and the other in PNG \(raster\). We use the PNG format within the docs since it can be viewed directly in GitHub. The SVG is used as the master copy as it is editable. +* **ESLint** - Within JavaScript code, we use [ESLint](https://eslint.org/) as a code style guide and style enforcement tool. +* **GitHub** – [GitHub](https://github.com/Mojaloop) is a widely-used source code repository service, based on git, the standard source code version control system for open source projects. So the decision to use GitHub was straightforward. We create a story every time for integration work. Create bugs for any issues. Ensure all stories are tracked throughout the pipeline to ensure reliable metrics. +* **Helm** - The Helm package manager for Kubernetes provides templatized deployments and configurations and allow for overall complexity management. +* **Kafka** - This technology is leveraged to support Mojaloop’s demand for a high velocity and high volume data messaging but keep our hardware requirements minimum. +* **JavaScript** - The Mojaloop application is primarily written in JavaScript. +* **Kubectl** - This is a command line interface for running commands against Kubernetes clusters. +* **Kubernetes** - This enterprise tool provides an extraction layer, infrastructure management and a container-orchestration system. +* **Markdown** – Documentation is a deliverable for this project, just like the code, and so we want to treat it like the code in terms of versioning, review, check in, and tracking changes. We also want the documentation to be easily viewable online without constantly opening a viewer. GitHub has a built-in format called Markdown which solves this well. The same files work for the Wiki and the documents. They can be reviewed with the check in using the same tools and viewed directly in GitHub. We considered Google Docs, Word and PDF, but these binary formats aren’t easily diff-able. A disadvantage is that markdown only allows simple formatting – no complex tables or font changes - but this should be fine when our main purpose is clarity. +* **MySQLWorkbench** – [MySQL Workbench](https://www.mysql.com/products/workbench/) is a unified visual tool for database architects, developers, and DBAs. MySQL Workbench provides data modeling, SQL development, and comprehensive administration tools for server configuration, user administration, backup, and much more. MySQL Workbench is available on Windows, Linux and Mac OS X. +* **NodeJS** - This development tool is a JavaScript runtime built on Chrome's V8 JavaScript engine that runs Mojaloop. NodeJS is designed to create simple microservices and it has a huge set of open source libraries available. Node performance is fine and while Node components don’t scale vertically a great deal, but we plan to scale horizontally, which it does fine. The original Interledger code was written in NodeJS as was the level one prototype. Most teams used Node already, so this made sense as a language. Within NodeJS code, we use [Standard](https://www.npmjs.com/package/standard) as a code style guide and to enforce code style. +* **NPM** - NPM is the package manager for Mojaloop since JavaScript is the default programming language. +* **Percona** for **MySQL** - These tools are leveraged as a relational database management system to ensure high performance and enterprise-grade functionality for the Mojaloop system. We needed a SQL backend that is open source friendly and can scale in a production environment. Thus, we chose MySQL, an open-source relational database management system. +* **Postman** is a Google Chrome application for interacting with HTTP APIs. It presents you with a friendly GUI for constructing requests and reading responses. +* **Rancher 2.0** - The Infrastructure management, provisioning and monitoring is provided by Rancher 2.0 which is an enterprise Kubernetes platform that manage Kubernetes deployments, clusters, on cloud & on-prem. Rancher makes it easy for DevOps teams to test, deploy and manage the Mojaloop system no matter where it is running. +* **Slack** – Slack is used for internal team communication. This was largely picked because several team already used it and liked it as a lightweight approach compared to email. +* **SonarQube** – We need an online dashboard of code quality \(size, complexity, issues, and coverage\) that can aggregate the code from all the repos. We looked at several online services \(CodeCov, Coveralls, and Code Climate\), but most couldn’t do complexity or even number of lines of code. Code Climate has limited complexity \(through ESLint\), but costs 6.67/seat/month. SonarQube is free, though it required us to setup and maintain our own server. It gave the P1 features we wanted. +* **SourceTree** – [Sourcetree](https://www.sourcetreeapp.com/) simplifies how you interact with your Git repositories so you can focus on coding. Visualize and manage your repositories through Sourcetree's simple Git GUI. +* **Stories On Board** - We use Stories on Board to help capture our high level Epics at a portfolio level before they are commmitted and moved to Github. Our Story Board for Mojaloop is located [here](https://mojaloop.storiesonboard.com/m/ml-phase3-planning) +* **Visual Studio Code** - [Visual Studio Code](https://code.visualstudio.com/) is a code editor redefined and optimized for building and debugging modern web and cloud applications. Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows. +* **ZenHub** – We needed a project management solution that was very light weight and cloud based to support distributed teams. It had to support epics, stories, and bugs and a basic project board. VS and Jira online offerings were both considered. For a small distributed development team an online service was better. For an open source project, we didn’t want ongoing maintenance costs of a server. Direct and strong GitHub integration was important. It was very useful to track work for each microservice with that microservice. Jira and VS both have more overhead than necessary for a project this size and don’t integrate as cleanly with GitHub as we’d want. ZenHub allowed us to start work immediately. A disadvantage is the lack of support for cumulative flow diagrams and support for tracking \# of stories instead of points, so we do these manually with a spreadsheet updated daily and the results published to the "Project Management" Slack channel. + +**TECHNOLOGY CHOICES** + +* **Agile development** - This methodology is used to track and run the project. The requirements need to be refined as the project is developed, therefore we picked agile development over waterfall or lean. +* **APIs** - In order to avoid confusion from too many changing microservices, we use strongly defined APIs that conform to our [Pragmatic REST](pragmatic-rest.md) design pattern. APIs will be defined using OpenAPI or RAML. Teams document their APIs with Swagger v2.0 or RAML v0.8 so they can automatically test, document, and share their work. Swagger is slightly preferred as there are free tools. Mule will make use of RAML 0.8. Swagger can be automatically converted to RAML v0.8, or manually to RAML v1.0 if additional readability is desired. +* **Automated Testing** - For the most part, most testing will be automated to allow for easy regression. See the [automated testing strategy](automated-testing.md) and [code quality metrics](code-quality-metrics.md) for standards. +* **Hosting** - Mojaloop has been designed to be infrastructure agnostic and as such is supported by AWS, Azure and On-Premise installations. +* **Interledger** – Mojaloop needed a lightweight, open, and secure transport protocol for funds. [Interledger.org](http://Interledger.org) provides all that. It also provides the ability to connect to other systems. We also considered block chain systems, but block chain systems send very large messages which will be harder to guarantee delivery of in third world infrastructure. Also, while blockchain systems provide good anonymity, that is not a project goal. To enable fraud detection, regulatory authorities need to be able to request records of transfers by account and person. +* **Open source** - The entire project has been released as open source in accordance with the [Level One Project principles](https://leveloneproject.org/wp-content/uploads/2016/03/L1P_Level-One-Principles-and-Perspective.pdf). All tools and processes must be open source friendly and support projects that use an Apache 2.0 license with no restrictive licenses requirements on developers. +* **Operating System** – Microsoft Windows is widely used in many target countries, but we need an operating system that is free of license fees and is open source compatible. We are using Linux. We don’t have a dependency on the particular flavor, but are using the basic Amazon Linux. In the Docker containers, [Alpine Linux](https://alpinelinux.org/) is used. +* **Microservices** - Because the architecture needs to easily deploy, scale, and have components be easily replaced or upgraded, it will be built as a set of microservices. +* **Scaled Agile Framework** - There were four initial development teams that are geographically separate. To keep the initial phase of the project on track, the [scaled agile framework \(SAFe\)](https://www.scaledagileframework.com/) was picked. This means work is divided into program increments \(PI\) that are typically four 2 week sprints long. As with the sprints, the PI has demo-able objective goals defined in each PI meeting. +* **Services** - Microservices are grouped and deployed in a few services such as the DFSP, Central Directory, etc. Each of these will have simple defined interfaces, configuration scripts, tests, and documentation. +* **Threat Modeling, Resilience Modeling, and Health Modeling** - Since the Mojaloop code needs to exchange money in an environment with very flaky infrastructure it must have good security, resilience, and easily report it's health state and automatically attempt to return to it. +* **USSD** - Smart phones are only 25% of the target market and not currently supported by most money transfer service, so we need a protocol that will work on simple feature phones. Like M-Pesa, we are using USSD between the phone and the digital financial service provider \(DFSP\). diff --git a/website/versioned_docs/v1.0.1/getting-started/README.md b/website/versioned_docs/v1.0.1/getting-started/README.md new file mode 100644 index 000000000..edf01f06d --- /dev/null +++ b/website/versioned_docs/v1.0.1/getting-started/README.md @@ -0,0 +1,10 @@ +# Your First Action + +To help get you started with Mojaloop, select which of the options below best suits your needs: + +1. [View the quickstarts](/getting-started/quickstart/) +1. [Watch a demo](/getting-started/demo/) +1. [Read the documentation](/technical/) +1. [Test out Mojaloop APIs](/technical/) +1. [Take a training program](https://mojaloop.io/mojaloop-training-program/) +1. [Contribute to Mojaloop](https://docs.mojaloop.io/documentation/) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/getting-started/demo-one.md b/website/versioned_docs/v1.0.1/getting-started/demo-one.md new file mode 100644 index 000000000..e8071921d --- /dev/null +++ b/website/versioned_docs/v1.0.1/getting-started/demo-one.md @@ -0,0 +1,3 @@ +# Demo One + +Details of Demo one goes here diff --git a/website/versioned_docs/v1.0.1/getting-started/demo.md b/website/versioned_docs/v1.0.1/getting-started/demo.md new file mode 100644 index 000000000..245a52d18 --- /dev/null +++ b/website/versioned_docs/v1.0.1/getting-started/demo.md @@ -0,0 +1,6 @@ +# Demos + +## Demos List + +TODO: A list of demos + diff --git a/website/versioned_docs/v1.0.1/getting-started/faqs.md b/website/versioned_docs/v1.0.1/getting-started/faqs.md new file mode 100644 index 000000000..7193a2036 --- /dev/null +++ b/website/versioned_docs/v1.0.1/getting-started/faqs.md @@ -0,0 +1,6 @@ +# Frequently Asked Questions + +This document contains some of the most frequently asked questions from the community. + +- [General FAQs](/getting-started/general-faqs) +- [Technical FAQs](/getting-started/technical-faqs) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/getting-started/general-faqs.md b/website/versioned_docs/v1.0.1/getting-started/general-faqs.md new file mode 100644 index 000000000..5afab4b63 --- /dev/null +++ b/website/versioned_docs/v1.0.1/getting-started/general-faqs.md @@ -0,0 +1,59 @@ +# General FAQs + +This document contains some of the most frequently asked questions from the community. + +## 1. What is Mojaloop? + +Mojaloop is open-source software for building interoperable digital payments platforms on a national scale. It makes it easy for different kinds of providers to link up their services and deploy low-cost financial services in new markets. + + +## 2. How does it work? + +Most digital financial providers run on their own networks, which prevents customers who use different services from transacting with each other. Mojaloop functions like a universal switchboard, routing payments securely between all customers, regardless of which network they're on. It consists of three primary layers, each with a specific function: an interoperability layer, which connects bank accounts, mobile money wallets, and merchants in an open loop; a directory service layer, which navigates the different methods that providers use to identify accounts on each side of a transaction; a transactions settlement layer, which makes payments instant and irrevocable; and components which protect against fraud. + +## 3. Who is it for? + +There are many components to the code, and everyone either directly or indirectly working with digital financial transactions-fintech developers, bankers, entrepreneurs, startups-is invited to explore and use whatever parts are useful or appealing. The software as a whole is meant to be implemented on a national scale, and so it will be most applicable to mobile money providers, payments associations, central banks, and country regulators. + +Developers at fintech and financial services companies can use the code in three ways: adapt the code to the financial services standards for a country, use the code to update their own products and services or create new ones, and improve the code by proposing updates and new versions of it for other users. + +For example: + +- A central bank may commission the use of the software by their commercial partners to speed up the deployment of a national payment gateway. +- A major payment processor can use the software to modernize their current offering, to achieve lower transaction costs without major R&D investments. +- A fintech startup can use the code to understand practically how to comply with interoperable payment APIs. +- A bank can use the code to modify their internal systems so that they easily interoperate with other payment providers. + +## 4. Why does it exist? + +Providers trying to reach developing markets with innovative, low-cost digital financial services have to build everything on their own. This raises costs and segregates services from each other. Mojaloop can be used as a foundation to help build interoperable platforms, lowering costs for providers and allowing them to integrate their services with others in the market. + +## 5. Who's behind it? + +Mojaloop was built in collaboration with a group of leading tech and fintech companies: [Ripple](https://github.com/ripple), [Dwolla](https://github.com/dwolla), [Software Group](http://www.softwaregroup-bg.com/), [ModusBox](http://www.modusbox.com/) and [Crosslake Technologies](http://www.crosslaketech.com/). Mojaloop was created by the Gates Foundation's Mojaloop, which is aimed at leveling the economic playing field by crowding in expertise and resources to build inclusive payment models to benefit the world's poor. It is free to the public as open-source software under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0). + +## 6. What platforms does Mojaloop run on? + +The Mojaloop platform was developed for modern cloud-computing environments. Open-source methods and widely used platforms, like Node.js, serve as the foundation layer for Mojaloop. The microservices are packaged in Docker and can be deployed to local hardware or to cloud computing environments like Amazon Web Services or Azure. + +## 7. Is it really open-source? + +Yes, it is really open-source. All core modules, documentation and white papers are available under a [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0). Mojaloop relies on commonly used open-source software, including node.js, MuleCE, Java and PostgreSQL. Mojaloop also uses the [Interledger Protocol](https://github.com/interledger) to choreograph secure money transfers. The licenses for all of these platforms and their imported dependencies allow for many viable uses of the software. + +## 8. How can I contribute to Mojaloop? + +You can contribute by helping us create new functionality on our roadmap or by helping us improve the platform. For our roadmap, go to the [Mojaloop Roadmap](../mojaloop-roadmap.md). We recommend starting with the onboarding guide and sample problem. This has been designed by the team to introduce the core ideas of the platform and software, the build methods, and our process for check-ins. + +## 9. Using Mojaloop to do payment using crypto-currency? + +Not with the current Specification and with this platform. Currently this is limited to currencies listed in the ISO 4217. Since the specification and platform is all about digital transfers, it should be possible to investigate a use-case for this possible requirement. Alternatively, I guess an FSP can provide that conversion (like many do already from crypto to one of the listed currencies). + +## 10. How is the Mojaloop source accessible? + +Here are some resources to start with: +1. Docs: https://github.com/mojaloop/documentation. +2. Look at the repos that have “CORE COMPONENT (Mojaloop)” in the description and these are core components. “CORE RELATED (Mojaloop)” repos are the ones that are needed to support the current Mojaloop Switch implementation/deployment. +3. As a generic point of note, for latest code, please use the ‘develop’ branch for the time-being. +4. Current architecture: https://github.com/mojaloop/docs/tree/master/Diagrams/ArchitectureDiagrams. Please note that these are currently being migrated to https://github.com/mojaloop/documents. +5. You may use this for current deployment architecture and deployment information: https://github.com/mojaloop/documentation/tree/master/deployment-guide. + diff --git a/website/versioned_docs/v1.0.1/getting-started/quickstart-one.md b/website/versioned_docs/v1.0.1/getting-started/quickstart-one.md new file mode 100644 index 000000000..4148ea4d6 --- /dev/null +++ b/website/versioned_docs/v1.0.1/getting-started/quickstart-one.md @@ -0,0 +1,3 @@ +# Quickstart One + +Quickstart goes here \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/getting-started/quickstart-two.md b/website/versioned_docs/v1.0.1/getting-started/quickstart-two.md new file mode 100644 index 000000000..ada2469e4 --- /dev/null +++ b/website/versioned_docs/v1.0.1/getting-started/quickstart-two.md @@ -0,0 +1,3 @@ +# Quickstart Two + +Quickstart two goes here \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/getting-started/quickstart.md b/website/versioned_docs/v1.0.1/getting-started/quickstart.md new file mode 100644 index 000000000..0ed1d5a64 --- /dev/null +++ b/website/versioned_docs/v1.0.1/getting-started/quickstart.md @@ -0,0 +1,3 @@ +# Quickstarts + +View a list of quickstarts here \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/getting-started/technical-faqs.md b/website/versioned_docs/v1.0.1/getting-started/technical-faqs.md new file mode 100644 index 000000000..3529d878b --- /dev/null +++ b/website/versioned_docs/v1.0.1/getting-started/technical-faqs.md @@ -0,0 +1,158 @@ +# Technical FAQs + +This document contains some of the frequently asked technical questions from the community. + +## 1. What is supported? + +Currently the Central ledger components are supported by the team. The DFSP components are outdated and thus the end-to-end environment and full setup is challenging to install. + +## 2. Can we connect directly to Pathfinder in a development environment? + +For the local and test environment, we recommend interfacing with the 'mock-pathfinder' service instead. Pathfinder is a 'paid by usage' service. + +Access the https://github.com/mojaloop/mock-pathfinder repository to download and install mock-pathfinder. Run command npm install in mock-pathfinder directory to install dependencies after this update Database_URI in mock-pathfinder/src/lib/config.js. + +## 3. Should i register DFSP via url http://central-directory/commands/register or i need to update configuration in default.json? + +You should register using the API provided, using postman or curl. Client is using LevelOne code. Needs to implement the current Mojaloop release with the current Postman scripts. + +## 4. Status of the pod pi3-kafka-0 is still on CrashLoopBackOff? + +- More background related to the question: + + When I tired to get logs of the container centralledger-handler-admin-transfer, I get the following error: + Error from server (BadRequest): container "centralledger-handler-admin-transfer" in pod "pi3-centralledger-handler-admin-transfer-6787b6dc8d-x68q9" is waiting to start: PodInitializing + And the status of the pod pi3-kafka-0 is still on CrashLoopBackOff. + I am using a vps on ubuntu 16.04 with RAM 12GB, 2vCores, 2.4GHz, Rom 50GB at OVH for the deployment. + +Increased RAM to 24 GB and CPU to 4 resolved the issues. Appears to be a timeout on Zookeeper due depletion of available resources, resulting in the services shutting down. + +## 5. Why am I getting an error when we try to create new DFSP using Admin? + +Please insure you are using the most current Postman scripts available on https://github.com/mojaloop/mock-pathfinder repository. + + +## 6. Can I spread Mojaloop components over different physical machines and VM's? + +You should be able to setup on different VM's or physical machines. The distribution pretty much depend on your requirements and would be implementation specific. We utilise Kubernetes to assist with the Container Orchestration. This enables us to schedule the deployments through the Kubernetes runtime to specific machines if required, and request specific resources if required. The helm charts in the helm repository could be used as guideline to how best allocate and group the components in your deployment. Naturally you would need to update the configurations to complement your custom implementation. + +## 7. Can we expect all the endpoints defined in the API document are implemented in Mojaloop? + +The Mojaloop Specification API for transfers and the Mojaloop Open Source Switch implementation are independent streams, though obviously the implementation is based on the Specification. Based on the use-cases prioritized for a time-frame and based on the end-points needed to support those use-cases, implementation will be done. If a few end-points are not prioritized then implementation for them may not be available. However, I think the goal is to eventually support all the end-points specified though it may take time. Thanks for the collection. We do have some of these on the ‘postman’ repo in the mojaloop GitHub org. + +## 8. Does Mojaloop store the payment initiator FSP’s quote/status info? + +At the moment, the Mojaloop Open source Switch implementation does *not* store Quotes related information. The onus is on the Payer, Payee involved in the process to store the relevant information. + +## 9. Does Mojaloop handle workflow validation? + +Not at the moment, but this may happen in the future. Regarding correlating requests that are related to a specific transfer, you may look at the ‘transaction’ end-point/resource in the Specification for more information on this. In addition to this, I can convey that some background work is ongoing regarding the specification to make this correlation more straight-forward and simpler i.e., to correlate quote and transfer requests that come under a single transaction. + + +## 10. How to register a new party in Mojaloop? + +There is no POST on /parties resource, as specified in section 6.1.1 of the API Defintion. Please refer to section: 6.2.2.3 `POST /participants//` in the API Defintion. + +” _The HTTP request `POST /participants//` (or `POST /participants///`) is used to create information on the server regarding the provided identity, defined by ``, ``, and optionally `` (for example, POST_ + _/participants/MSISDN/123456789 or POST /participants/BUSINESS/shoecompany/employee1). See Section 5.1.6.11 for more information regarding addressing of a Party._ ”. + +## 11. Does the participant represent an account of a customer in a bank? + +For more on this, please refer to this doc (Section 3..2): https://github.com/mojaloop/mojaloop-specification/blob/develop/Generic%20Transaction%20Patterns.pdf. + +” _In the API, a Participant is the same as an FSP that is participating in an Interoperability Scheme. The primary purpose of the logical API resource Participants is for FSPs to find out in which other FSP a counterparty in an interoperable financial transaction is located. There are also services defined for the FSPs to provision information to a common system._ ” + +In essence, a participant is any FSP participating in the Scheme (usually not a customer). For account lookup, a directory service such as *Pathfinder* can be used, which provides user lookup and the mapping. If such a directory service is not provided, an alternative is provided in the Specification, where the Switch hosts an Account Lookup Service (ALS) but to which the participants need to register parties. I addressed this earlier. But one thing to note here is that the Switch does not store the details, just the mapping between an ID and an FSP and then the calls to resolve the party are sent to that FSP. + +https://github.com/mojaloop/mojaloop-specification CORE RELATED (Mojaloop): + +This repo contains the specification document set of the Open API for FSP Interoperability - mojaloop/mojaloop-specification. + +## 12. How to register _trusted_ payee to a payer, to skip OTP? + +To skip the OTP, the initial request on the /transactionRequests from the Payee can be programmatically (or manually for that matter) made to be approved without the use of the /authorizations endpoint (that is need for OTP approval). Indeed the FSP needs to handle this, the Switch does not. This is discussed briefly in section 6.4 of the Specification. + +## 13. Receiving a 404 error when attempting to access or load kubernetes-dashboard.yaml file? + +From the official kubernetes github repository in the README.md, the latest link to use is "https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml". Be sure to always verify 3rd party links before implementing. Open source applications are always evolving. + +## 14. When installing nginx-ingress for load balancing & external access - Error: no available release name found? + +Please have a look at the following addressing a similar issue. To summarise - it is most likely an RBAC issue. Have a look at the documentation to set up Tiller with RBAC. https://docs.helm.sh/using_helm/#role-based-access-control goes into detail about this. The issue logged: helm/helm#3839. + +## 15. Received "ImportError: librdkafka.so.1: cannot open shared object file: No such file or directory" when running `npm start' command. + +Found a solution here https://github.com/confluentinc/confluent-kafka-python/issues/65#issuecomment-269964346 +GitHub +ImportError: librdkafka.so.1: cannot open shared object file: No such file or directory · Issue #65 · confluentinc/confluent-kafka-python +Ubuntu 14 here, pip==7.1.2, setuptools==18.3.2, virtualenv==13.1.2. First, I want to build latest stable (seems it's 0.9.2) librdkafka into /opt/librdkafka. curl https://codeload.github.com/ede... + +Here are the steps to rebuild librdkafka: + +git clone https://github.com/edenhill/librdkafka && cd librdkafka && git checkout ` + +cd librdkafka && ./configure && make && make install && ldconfig + +After that I'm able to import stuff without specifying LD_LIBRARY_PATH. +GitHub +edenhill/librdkafka +The Apache Kafka C/C++ library. Contribute to edenhill/librdkafka development by creating an account on GitHub. + +## 16. Can we use mojaloop as open-source mobile wallet software or mojaloop does interoperability only? + +We can use mojaloop for interoperability to support mobile wallet and other such money transfers. This is not a software for a DFSP (there are open source projects that cater for these such as Finserv etc). Mojaloop is for a Hub/Switch primarily and an API that needs to be implemented by a DFSP. But this is not for managing mobile wallets as such. + +## 17. Describe companies that helps to deploy & support for mojaloop? + +Mojaloop is an open source software and specification. + +## 18. Can you say something about mojaloop & security? + +The Specification is pretty standard and has good security standards. But these need to be implemented by the adopters and deployers. Along with this, the security measures need to be coupled with other Operational and Deployment based security measures. Moreover, the coming few months will focus on security perspective for the Open Source community. + +## 19. What are the benefit(s) from using mojaloop as interoperabilty platform? + +Benefits: Right now for example, an Airtel mobile money user can transfer to another Airtel mobile money user only. With this, he/she can transfer to any Financial service provider such as another mobile money provider or any other bank account or Merchant that is connected to the Hub, irrespective of their implementation. They just need to be connected to the same Switch. Also, this is designed for feature phones so everyone can use it. + +## 20. What are the main challenges that companies face using mojaloop? + +At this point, the main challenges are around expectations. Expectations of the adopters of mojaloop and what really mojaloop is. A lot of adopters have different understanding of what mojaloop is and about its capabilities. If they have a good understanding, a lot of current challenges are mitigated.. +Yes, forensic logging is a security measure as well for auditing purposes which will ensure there is audit-able log of actions and that everything that is a possible action of note is logged and rolled up, securely after encryption at a couple of levels. + +## 21. Is forensic logging/audit in mojaloop , is it related with securing the inter-operability platform? + +This also ensures all the services always run the code they’re meant to run and anything wrong/bad is stopped from even starting up. Also, for reporting and auditors, reports can have a forensic-log to follow. + +## 22. How do the financial service providers connect with mojaloop? + +There is an architecture diagram that presents a good view of the integration between the different entities. https://github.com/mojaloop/docs/blob/master/Diagrams/ArchitectureDiagrams/Arch-Flows.svg. + +## 23. Is there any open source ISO8583-OpenAPI converter/connector available? + +I don't believe a generic ISO8583 `<-> Mojaloop integration is available currently. We're working on some "traditional payment channel" to Mojaloop integrations (POS and ATM) which we hope to demo at the next convening. These would form the basis for an ISO8583 integration we might build and add to the OSS stack but bare in mind that these integrations will be very use case specific. + +## 24. How do I know the end points to setup postman for testing the deployment? + +On the Kubernetes dashboard, select the correct NAMESPACE. Go to Ingeresses. Depending on how you deployed the helm charts, look for 'moja-centralledger-service'. Click on edit, and find the tag ``. This would contain the endpoint for this service. + +## 25. Why are there no reversals allowed on a Mojaloop? + +*Irrevocability* is a core Level One Principle (edited) and not allowing reversals is essential for that. Here is the section from the API Definition addressing this: + +_*6.7.1.2 Transaction Irrevocability*_ +_The API is designed to support irrevocable financial transactions only; this means that a financial transaction cannot be changed, cancelled, or reversed after it has been created. This is to simplify and reduce costs for FSPs using the API. A large percentage of the operating costs of a typical financial system is due to reversals of transactions._ +_As soon as a Payer FSP sends a financial transaction to a Payee FSP (that is, using POST /transfers including the end-to-end financial transaction), the transaction is irrevocable from the perspective of the Payer FSP. The transaction could still be rejected in the Payee FSP, but the Payer FSP can no longer reject or change the transaction. An exception to this would be if the transfer’s expiry time is exceeded before the Payee FSP responds (see Sections 6.7.1.3 and 6.7.1.5 for more information). As soon as the financial transaction has been accepted by the Payee FSP, the transaction is irrevocable for all parties._ + +However, *Refunds* is a use case supported by the API. + +## 26. ffg. error with microk8s installation "MountVolume.SetUp failed"? + +Would appear if it is a space issue, but more the 100GiB of EBS storage was allocated. +The issue resolved itself after 45 minutes. Initial implementation of the mojaloop project can take a while to stabilize. + +## 27. Why am I getting this error when trying to create a participant: "Hub reconciliation account for the specified currency does not exist"? + +You need to create the corresponding Hub accounts (HUB_MULTILATERAL_SETTLEMENT and HUB_RECONCILIATION) for the specified currency before setting up the participants. +In this Postman collection you can find the requests to perform the operation in the "Hub Account" folder: https://github.com/mojaloop/postman/blob/master/OSS-New-Deployment-FSP-Setup.postman_collection.json + +Find also the related environments in the Postman repo: https://github.com/mojaloop/postman diff --git a/website/versioned_docs/v1.0.1/index.md b/website/versioned_docs/v1.0.1/index.md new file mode 100644 index 000000000..ee7c7c068 --- /dev/null +++ b/website/versioned_docs/v1.0.1/index.md @@ -0,0 +1,15 @@ +--- +home: true +heroImage: /mojaloop_logo_med.png +tagline: This is the official documentation of the Mojaloop project. +actionText: Getting Started → +actionLink: /getting-started/ +features: +- title: Commmunity + details: Feature 1 Description +- title: Technical + details: Feature 2 Description +- title: API Specification + details: Feature 3 Description +footer: Made by Mojaloop with ❤️ +--- \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/quickstarts/README.md b/website/versioned_docs/v1.0.1/quickstarts/README.md new file mode 100644 index 000000000..ee06bcdbe --- /dev/null +++ b/website/versioned_docs/v1.0.1/quickstarts/README.md @@ -0,0 +1,10 @@ +# Your First Action + +To help get you started with Mojaloop, select which of the options below best suits your needs: + +1. [View the quickstarts](/1-overview/) +1. [Watch a demo](/99-demos/) +1. [Read the documentation](/1-overview/) +1. [Test out Mojaloop APIs](/1-overview/#apis) +1. [Take a training program](/3-guides/1_dfsp_setup/) +1. [Contribute to Mojaloop](https://docs.mojaloop.io/documentation/) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/quickstarts/one.md b/website/versioned_docs/v1.0.1/quickstarts/one.md new file mode 100644 index 000000000..ee06bcdbe --- /dev/null +++ b/website/versioned_docs/v1.0.1/quickstarts/one.md @@ -0,0 +1,10 @@ +# Your First Action + +To help get you started with Mojaloop, select which of the options below best suits your needs: + +1. [View the quickstarts](/1-overview/) +1. [Watch a demo](/99-demos/) +1. [Read the documentation](/1-overview/) +1. [Test out Mojaloop APIs](/1-overview/#apis) +1. [Take a training program](/3-guides/1_dfsp_setup/) +1. [Contribute to Mojaloop](https://docs.mojaloop.io/documentation/) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/quickstarts/two.md b/website/versioned_docs/v1.0.1/quickstarts/two.md new file mode 100644 index 000000000..ee06bcdbe --- /dev/null +++ b/website/versioned_docs/v1.0.1/quickstarts/two.md @@ -0,0 +1,10 @@ +# Your First Action + +To help get you started with Mojaloop, select which of the options below best suits your needs: + +1. [View the quickstarts](/1-overview/) +1. [Watch a demo](/99-demos/) +1. [Read the documentation](/1-overview/) +1. [Test out Mojaloop APIs](/1-overview/#apis) +1. [Take a training program](/3-guides/1_dfsp_setup/) +1. [Contribute to Mojaloop](https://docs.mojaloop.io/documentation/) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/sidebar.config.json b/website/versioned_docs/v1.0.1/sidebar.config.json new file mode 100644 index 000000000..0dea9bf80 --- /dev/null +++ b/website/versioned_docs/v1.0.1/sidebar.config.json @@ -0,0 +1,610 @@ +{ + "sidebar": { + "/v1.0.1/getting-started/": [ + { + "title": "Getting Started", + "collapsable": false, + "children": [ + "" + ] + }, + { + "title": "Quickstarts", + "collapsable": false, + "children": [ + [ + "quickstart", + "Quickstarts" + ], + [ + "quickstart-one", + "Quickstart One" + ], + [ + "quickstart-two", + "Quickstart Two" + ] + ] + }, + { + "title": "Demos", + "collapsable": false, + "children": [ + "demo", + "demo-one" + ] + }, + { + "title": "FAQs", + "collapsable": false, + "children": [ + [ + "faqs", + "Frequently Asked Questions" + ], + [ + "general-faqs", + "General FAQs" + ], + [ + "technical-faqs", + "Technical FAQs" + ] + ], + "sidebarDepth": 2 + } + ], + "/v1.0.1/community/": [ + { + "title": "Community", + "collapsable": false, + "children": [ + [ + "contributing/contributors-guide", + "Contributors' Guide" + ], + [ + "contributing/new-contributor-checklist", + "New Contributor Checklist" + ], + [ + "contributing/code-of-conduct", + "Code of Conduct" + ], + [ + "contributing/signing-the-cla", + "Signing the CLA" + ] + ], + "sidebarDepth": 2 + }, + { + "title": "Community Standards", + "collapsable": false, + "children": [ + [ + "standards/guide", + "Our Standards" + ], + [ + "standards/versioning", + "Versioning" + ], + [ + "standards/creating-new-features", + "Creating New Features" + ], + [ + "standards/triaging-bugs", + "Triaging Bugs" + ] + ], + "sidebarDepth": 2 + }, + { + "title": "Tools and Technologies", + "collapsable": false, + "children": [ + [ + "tools/tools-and-technologies", + "Tools" + ], + [ + "tools/pragmatic-rest", + "Pragmatic Rest" + ], + [ + "tools/code-quality-metrics", + "Code Quality Metrics" + ], + [ + "tools/automated-testing", + "Automated Testing" + ] + ], + "sidebarDepth": 2 + }, + { + "title": "Documentation", + "collapsable": false, + "children": [ + [ + "documentation/standards", + "Standards" + ], + [ + "documentation/api-documentation", + "API Documentation" + ], + [ + "documentation/style-guide", + "Style Guide" + ] + ] + }, + { + "title": "Community Resources", + "collapsable": false, + "children": [ + { + "title": "Resources", + "collapsable": false, + "children": [ + [ + "mojaloop-roadmap", + "Product Roadmap" + ], + [ + "mojaloop-publications", + "Mojaloop Publications" + ] + ] + }, + { + "title": "Notes Archive", + "collapsable": true, + "path": "archive/notes/", + "children": [ + [ + "archive/notes/ccb-notes", + "CCB Notes" + ], + [ + "archive/notes/da-notes", + "Meeting Notes" + ], + [ + "archive/notes/scrum-of-scrum-notes", + "Scrum Notes" + ] + ] + }, + { + "title": "Discussion Docs Archive", + "collapsable": true, + "path": "archive/discussion-docs/", + "children": [ + { + "title": "PI 10", + "collapsable": true, + "children": [ + [ + "archive/discussion-docs/performance-project", + "Performance Project" + ], + [ + "archive/discussion-docs/code-improvement", + "Code Improvement Project" + ], + [ + "archive/discussion-docs/cross-border", + "Cross Border Project" + ], + [ + "archive/discussion-docs/psip-project", + "PSIP Project" + ] + ] + }, + { + "title": "PI 9", + "collapsable": true, + "children": [ + [ + "archive/discussion-docs/versioning-draft-proposal", + "Versioning Draft Proposal" + ] + ] + }, + { + "title": "PI 8", + "collapsable": true, + "children": [ + [ + "archive/discussion-docs/cross-border-day-1", + "CB Day 1 Meeting Notes" + ], + [ + "archive/discussion-docs/cross-border-day-2", + "CB Day 2 Meeting Notes" + ], + [ + "archive/discussion-docs/iso-integration", + "ISO Integration Overview" + ], + [ + "archive/discussion-docs/mojaloop-decimal", + "Mojaloop Decimal Type" + ] + ] + }, + { + "title": "PI 7", + "collapsable": true, + "children": [ + [ + "archive/discussion-docs/workbench", + "Workbench Workstream" + ] + ] + } + ] + } + ], + "sidebarDepth": 4 + } + ], + "/v1.0.1/api/": [ + { + "title": "Mojaloop APIs", + "collapsable": false, + "children": [ + "" + ] + }, + { + "title": "FSPIOP API", + "collapsable": false, + "children": [ + { + "title": "Overview", + "path": "fspiop/" + }, + { + "title": "API Definitions", + "collapsable": false, + "path": "fspiop/definitions", + "children": [ + { + "title": "v1.1 (Current)", + "path": "fspiop/v1.1/api-definition" + }, + { + "title": "Older versions", + "path": "fspiop/v1.0/", + "children": [ + [ + "fspiop/v1.0/api-definition", + "v1.0" + ] + ] + } + ] + }, + { + "title": "Logical Data Model", + "path": "fspiop/logical-data-model", + "collapsable": true + }, + { + "title": "Generic Transaction Patterns", + "path": "fspiop/generic-transaction-patterns", + "collapsable": true + }, + { + "title": "Use Cases", + "path": "fspiop/use-cases" + }, + { + "title": "JSON Binding Rules", + "path": "fspiop/json-binding-rules" + }, + { + "title": "Scheme Rules", + "path": "fspiop/scheme-rules" + }, + { + "title": "PKI Best Practices", + "path": "fspiop/pki-best-practices" + }, + { + "title": "Signature (v1.1)", + "path": "fspiop/v1.1/signature" + }, + { + "title": "Encryption (v1.1)", + "path": "fspiop/v1.1/encryption" + }, + { + "title": "Glossary", + "path": "fspiop/glossary" + } + ], + "sidebarDepth": 4 + }, + { + "title": "Administration API", + "collapsable": false, + "children": [ + { + "title": "Overview", + "path": "administration/" + }, + { + "title": "Central Ledger API", + "path": "administration/central-ledger-api" + } + ], + "sidebarDepth": 2 + }, + { + "title": "Settlement API", + "collapsable": false, + "children": [ + [ + "settlement/", + "Overview" + ] + ], + "sidebarDepth": 2 + }, + { + "title": "Thirdparty API", + "collapsable": false, + "path": "thirdparty/", + "children": [ + { + "title": "API Definitions", + "path": "fspiop/logical-data-model", + "collapsable": true + }, + { + "title": "Transaction Patterns", + "path": "thirdparty/transaction-patterns", + "collapsable": true, + "children": [ + { + "title": "Transaction Patterns Linking", + "path": "thirdparty/transaction-patterns-linking" + }, + { + "title": "Transaction Patterns Transfer", + "path": "thirdparty/transaction-patterns-transfer" + } + ] + }, + { + "title": "Data Models", + "path": "thirdparty/data-models", + "collapsable": true + } + ], + "sidebarDepth": 2 + }, + { + "title": "Glossary", + "collapsable": false, + "children": [ + [ + "fspiop/glossary", + "Overview" + ] + ] + } + ], + "/v1.0.1/technical/": [ + { + "title": "Mojaloop Hub", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "overview/" + }, + { + "title": "Current Architecture - PI 14", + "path": "overview/components-PI14" + }, + { + "title": "Current Architecture - PI 12", + "path": "overview/components-PI12" + }, + { + "title": "Current Architecture - PI 11", + "path": "overview/components-PI11" + }, + { + "title": "Current Architecture - PI 8", + "path": "overview/components-PI8" + }, + { + "title": "Current Architecture - PI 7", + "path": "overview/components-PI7" + }, + { + "title": "Current Architecture - PI 6", + "path": "overview/components-PI6" + }, + { + "title": "Current Architecture - PI 5", + "path": "overview/components-PI5" + }, + { + "title": "Current Architecture - PI 3", + "path": "overview/components-PI3" + } + ], + "sidebarDepth": 2 + }, + { + "title": "Account Lookup Service", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "account-lookup-service/" + }, + { + "title": "GET Participants", + "path": "account-lookup-service/als-get-participants" + }, + { + "title": "POST Participants", + "path": "account-lookup-service/als-post-participants" + }, + { + "title": "POST Participants (Batch)", + "path": "account-lookup-service/als-post-participants-batch" + }, + { + "title": "DEL Participants", + "path": "account-lookup-service/als-del-participants" + }, + { + "title": "GET Parties", + "path": "account-lookup-service/als-get-parties" + } + ], + "sidebarDepth": 2 + }, + { + "title": "Quoting Service", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "quoting-service/" + }, + { + "title": "GET Quote", + "path": "quoting-service/qs-get-quotes" + }, + { + "title": "POST Quote", + "path": "quoting-service/qs-post-quotes" + }, + { + "title": "GET Bulk Quote", + "path": "quoting-service/qs-get-bulk-quotes" + }, + { + "title": "POST Bulk Quote", + "path": "quoting-service/qs-post-bulk-quotes" + } + ], + "sidebarDepth": 2 + }, + { + "title": "Transaction Requests Service", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "transaction-requests-service/" + }, + { + "title": "GET Transaction Requests", + "path": "transaction-requests-service/transaction-requests-get" + }, + { + "title": "POST Transaction Requests", + "path": "transaction-requests-service/transaction-requests-post" + }, + { + "title": "Authorizations", + "path": "transaction-requests-service/authorizations" + } + ], + "sidebarDepth": 2 + }, + { + "title": "Central Event Processor Service", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-event-processor/" + }, + { + "title": "Event Handler (Placeholder)", + "path": "central-event-processor/event-handler-placeholder" + }, + { + "title": "Notiification Handler for Rejections", + "path": "central-event-processor/notification-handler-for-rejections" + }, + { + "title": "Signature Validation", + "path": "central-event-processor/signature-validation" + } + ], + "sidebarDepth": 2 + }, + { + "title": "Event Framework", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "event-framework/" + }, + { + "title": "Event Stream Processor", + "path": "event-stream-processor/" + } + ], + "sidebarDepth": 2 + }, + { + "title": "Fraud Services", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "fraud-services/" + }, + { + "title": "Usage", + "path": "fraud-services/related-documents/documentation" + } + ], + "sidebarDepth": 2 + }, + { + "title": "SDK Scheme Adapter", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "sdk-scheme-adapter/" + }, + { + "title": "Usage", + "path": "sdk-scheme-adapter/usage/" + } + ], + "sidebarDepth": 2 + }, + { + "title": "ML Testing Toolkit", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "ml-testing-toolkit/" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/README.md b/website/versioned_docs/v1.0.1/technical/README.md new file mode 100644 index 000000000..35d07fe6c --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/README.md @@ -0,0 +1,16 @@ +# Mojaloop Technical Overview + +## Mojaloop Services + +The basic idea behind Mojaloop is that we need to connect multiple Digital Financial Services Providers (DFSPs) together into a competitive and interoperable network in order to maximize opportunities for poor people to get access to financial services with low or no fees. We don't want a single monopoly power in control of all payments in a country, or a system that shuts out new players. It also doesn't help if there are too many isolated subnetworks. The following diagrams shows the Mojaloop interconnects between DFSPs and the Mojaloop Hub (schema implementation example) for a Peer-to-Peer (P2P) Transfer: + +Mojaloop addresses these issues in several key ways: +* A set of central services provides a hub through which money can flow from one DFSP to another. This is similar to how money moves through a central bank or clearing house in developed countries. Besides a central ledger, central services can provide identity lookup, fraud management, and enforce scheme rules. +* A standard set of interfaces a DFSP can implement to connect to the system, and example code that shows how to use the system. A DFSP that wants to connect up can adapt our example code or implement the standard interfaces into their own software. The goal is for it to be as straightforward as possible for a DFSP to connect to the interoperable network. +* Complete working open-source implementations of both sides of the interfaces - an example DFSP that can send and receive payments and the client that an existing DFSP could host to connect to the network. + +![Mojaloop End-to-end Architecture Flow PI5](./assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg) + +The Mojaloop Hub is the primary container and reference we use to describe the Mojaloop ecosystem which is split in to the following domains: +* Mojaloop Open Source Services - Core Mojaloop Open Source Software (OSS) that has been supported by the Bill & Melinda Gates Foundation in partnership with the Open Source Community. +* Mojaloop Hub - Overall Mojaloop reference (and customizable) implementation for Hub Operators is based on the above OSS solution. \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/README.md b/website/versioned_docs/v1.0.1/technical/account-lookup-service/README.md new file mode 100644 index 000000000..4475e8255 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/README.md @@ -0,0 +1,128 @@ +--- +version: 1.1 +--- + + +# Account Lookup Service + +The **Account Lookup Service** (**ALS**) _(refer to section `6.2.1.2`)_ as per the [Mojaloop {{ $page.frontmatter.version }} Specification](/api) implements the following use-cases: + +* Participant Look-up +* Party Look-up +* Manage Participants Registry information + * Adding Participant Registry information + * Deleting Participant Registry information + +Use-cases that have been implemented over and above for Hub Operational use: +* Admin Operations + * Manage Oracle End-point Routing information + * Manage Switch End-point Routing information + +## 1. Design Considerations + +### 1.1. Account Lookup Service (ALS) +The ALS design provides a generic Central-Service component as part of the core Mojaloop. The purpose of this component is to provide routing and alignment to the Mojaloop API Specification. This component will support multiple Look-up registries (Oracles). This ALS will provide an Admin API to configure routing/config for each of the Oracles similiar to the Central-Service API for the End-point configuration for DFSP routing by the Notification-Handler (ML-API-Adapter Component). The ALS will in all intense purpose be a switch with a persistence store for the storage/management of the routing rules/config. + +#### 1.1.1. Assumptions + +* The ALS design will only cater for a single switch for the time being. +* Support for multiple switches will utilise the same DNS resolution mechanism that is being developed for the Cross Border/Network design. + +#### 1.1.2. Routing + +The routing configuration will be based on the following: +* PartyIdType - See section `7.5.6` of the Mojaloop Specification +* Currency - See section `7.5.5` of the Mojaloop Specification. Currency code defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic string. This will be optional, however `isDefault` indicator must be set to `true` if the `Currency` is not provided. +* isDefault - Indicator that a specific Oracle is the default provider for a specific PartyIdType. Note that there can be many default Oracles, but there can only be a single Oracle default for a specific PartyIdType. The default Oracle for a specific PartyIdType will only be selected if the originating request does not include a Currency filter. + + +### 1.2. ALS Oracle +The ALS Oracle be implemented as either a **Service** or **Adapter** (semantic dependant on use - Mediation = Adapter, Service = Implementation) will provide a look-up registry component with similar functionality of the `/participants` Mojaloop API resources. It has however loosely based on the ML API specification as it's interface implements a sync pattern which reduces the correlation/persistence requirements of the Async Callback pattern implemented directly by the ML API Spec. This will provide all ALS Oracle Services/Adapters with a standard interface which will be mediated by the ALS based on its routing configuration. +This component (or back-end systems) will also be responsible for the persistence & defaulting of the Participant details. + +## 2. Participant Lookup Design + +### 2.1. Architecture overview +![Architecture Flow Account-Lookup for Participants](./assets/diagrams/architecture/arch-flow-account-lookup-participants.svg) + +_Note: The Participant Lookup use-case similarly applies to for a Payee Initiated use-case such as transactionRequests. The difference being that the Payee is the initiation in the above diagram._ + +### 2.2. Sequence diagrams + +#### 2.2.1. GET Participants + +- [Sequence Diagram for GET Participants](als-get-participants.md) + +#### 2.2.2. POST Participants + +- [Sequence Diagram for POST Participants](als-post-participants.md) + +#### 2.2.3. POST Participants (Batch) + +- [Sequence Diagram for POST Participants (Batch)](als-post-participants-batch.md) + +#### 2.2.4. DEL Participants + +- [Sequence Diagram for DEL Participants](als-del-participants.md) + +## 3. Party Lookup Design + +### 3.1. Architecture overview +![Architecture Flow Account-Lookup for Parties](./assets/diagrams/architecture/arch-flow-account-lookup-parties.svg) + +### 3.2. Sequence diagram + +#### 3.2.1. GET Parties + +- [Sequence Diagram for GET Parties](als-get-parties.md) + +## 4. ALS Admin Design + +### 4.1. Architecture overview +![Architecture Flow Account-Lookup for Admin Get Oracles](./assets/diagrams/architecture/arch-flow-account-lookup-admin.svg) + +### 4.2. Sequence diagram + +#### 4.2.1 GET Oracles + +- [Sequence Diagram for GET Oracles](als-admin-get-oracles.md) + +#### 4.2.2 POST Oracle + +- [Sequence Diagram for POST Oracle](als-admin-post-oracles.md) + +#### 4.2.3 PUT Oracle + +- [Sequence Diagram for PUT Oracle](als-admin-put-oracles.md) + +#### 4.2.4 DELETE Oracle + +- [Sequence Diagram for DELETE Oracle](als-admin-del-oracles.md) + +#### 4.2.5 DELETE Endpoint Cache + +- [Sequence Diagram for DELETE Endpoint Cache](als-del-endpoint.md) + +## 5. Database Design + +### 5.1. ALS Database Schema + +#### Notes +- `partyIdType` - Values are currently seeded as per section _`7.5.6`_ [Mojaloop {{ $page.frontmatter.version }} Specification](./api). +- `currency` - See section `7.5.5` of the Mojaloop Specification. Currency code defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic string. This will be optional, and must provide a "default" config if no Currency is either provided or provide a default if the Currency is provided, but only the "default" End-point config exists. +- `endPointType` - Type identifier for the end-point (e.g. `URL`) which provides flexibility for future transport support. +- `migration*` - Meta-data tables used by Knex Framework engine. +- A `centralSwitchEndpoint` must be associated to the `OracleEndpoint` by the Admin API upon insertion of a new `OracleEndpoint` record. If the `centralSwitchEndpoint` is not provided as part of the API Request, then it must be defaulted. + +![Acount Lookup Service ERD](./assets/entities/AccountLookupService-schema.png) + +* [Acount Lookup Service DBeaver ERD](./assets/entities/AccountLookupDB-schema-DBeaver.erd) +* [Acount Lookup Service MySQL Workbench Export](./assets/entities/AccountLookup-ddl-MySQLWorkbench.sql) + +## 6. ALS Oracle Design + +Detail design for the Oracle is out of scope for this document. The Oracle design and implementation is specific to each Oracle's requirements. + +### 6.1. API Specification + +Refer to **ALS Oracle API** in the [API Specifications](../../api/README.md#als-oracle-api) section. diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-admin-del-oracles.md b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-admin-del-oracles.md new file mode 100644 index 000000000..bb5426368 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-admin-del-oracles.md @@ -0,0 +1,7 @@ +# DELETE Oracles + +Design for the Deletion of an Oracle Endpoint by a Hub Operator. + +## Sequence Diagram + +![seq-acct-lookup-admin-delete-oracle-7.3.4.svg](assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.svg) diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-admin-get-oracles.md b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-admin-get-oracles.md new file mode 100644 index 000000000..45be49841 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-admin-get-oracles.md @@ -0,0 +1,7 @@ +# GET Oracles + +Design for getting a list of all Oracle Endpoints by the Hub Operator with the option of querying but currency and/or type. + +## Sequence Diagram + +![seq-acct-lookup-admin-get-oracle-7.3.1.svg](./assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.svg) diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-admin-post-oracles.md b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-admin-post-oracles.md new file mode 100644 index 000000000..9f2b210e0 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-admin-post-oracles.md @@ -0,0 +1,7 @@ +# POST Oracles + +Design for the creation of an Oracle Endpoint by a Hub Operator. + +## Sequence Diagram + +![seq-acct-lookup-admin-post-oracle-7.3.2.svg](./assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.svg) diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-admin-put-oracles.md b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-admin-put-oracles.md new file mode 100644 index 000000000..46446c731 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-admin-put-oracles.md @@ -0,0 +1,7 @@ +# PUT Oracles + +Design for the Update of an Oracle Endpoint by a Hub Operator. + +## Sequence Diagram + +![seq-acct-lookup-admin-put-oracle-7.3.3.svg](./assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.svg) diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-del-endpoint.md b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-del-endpoint.md new file mode 100644 index 000000000..e8123a537 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-del-endpoint.md @@ -0,0 +1,7 @@ +# DELETE Endpoint Cache + +Design for the disabling of an Oracle by the Hub Operator. + +## Sequence Diagram + +![seq-acct-lookup-del-endpoint-cache-7.3.0.svg](./assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.svg) diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-del-participants.md b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-del-participants.md new file mode 100644 index 000000000..7e2621e74 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-del-participants.md @@ -0,0 +1,11 @@ +# DEL Participants + +Design for the deletion of a Participant by a DFSP. + +## Notes + +- Reference section 6.2.2.4 - Note: The ALS should verify that it is the Party’s current FSP that is deleting the FSP information. ~ This has been addressed in the design by insuring that the Party currently belongs to the FSPs requesting the deletion of the record. Any other validations are out of scope for the Switch and should be addressed at the schema level. + +## Sequence Diagram + +![seq-acct-lookup-del-participants-7.1.2.svg](./assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.svg) diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-get-participants.md b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-get-participants.md new file mode 100644 index 000000000..8844c37c2 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-get-participants.md @@ -0,0 +1,7 @@ +# GET Participants + +Design for the retrieval of a Participant by a DFSP. + +## Sequence Diagram + +![seq-acct-lookup-get-participants-7.1.0.svg](./assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.svg) diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-get-parties.md b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-get-parties.md new file mode 100644 index 000000000..02bc1c311 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-get-parties.md @@ -0,0 +1,7 @@ +# GET Parties + +Design for the retrieval of a Party by a DFSP. + +## Sequence Diagram + +![seq-acct-lookup-get-parties-7.2.0.svg](./assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.svg) diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-post-participants-batch.md b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-post-participants-batch.md new file mode 100644 index 000000000..9610b7a1d --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-post-participants-batch.md @@ -0,0 +1,13 @@ +# Sequence Diagram for POST Participants (Batch) + +Design for the creation of a Participant by a DFSP via a batch request. + +## Notes +- Operation only supports requests which contain: + - All Participant's FSPs match the FSPIOP-Source7 + - All Participant's will be of the same Currency, per the `POST /participants` call in the [Mojaloop FSPIOP API](/api/fspiop/v1.1/api-definition.html#post-participants) +- Duplicate POST Requests with matching TYPE and optional CURRENCY will be considered an __update__ operation. The existing record must be completely **replaced** in its entirety. + +## Sequence Diagram + +![seq-acct-lookup-post-participants-batch-7.1.1.svg](./assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.svg) diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-post-participants.md b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-post-participants.md new file mode 100644 index 000000000..bc7c3bd29 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/als-post-participants.md @@ -0,0 +1,7 @@ +# POST Participant + +Design for the creation of a Participant by a DFSP via a request. + +## Sequence Diagram + +![seq-acct-lookup-post-participants-7.1.3.svg](./assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.svg) diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/.gitkeep b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-admin.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-admin.svg new file mode 100644 index 000000000..d46ffa284 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-admin.svg @@ -0,0 +1,3 @@ + + +
    Account Lookup Service Admin
    (ALS)
    Account Lookup Service Adm...
    HUB
    Backend



    HUB...
    Account Lookup Admin
    Account Lookup Admin
    HUB Operator
    HUB Operator
    A1. Request Oracle Endpoints 
    GET /oracles
    A1. Requ...
    A1.3. Return List of Oracles
    A1.3. Re...
    ALS
    DB
    ALS...
    Key
    Key
    A1.2. Lookup All Oracle Registry Service End-points 
    API
    Internal Use-Only
    API...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-participants.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-participants.svg new file mode 100644 index 000000000..2bb5d7029 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-participants.svg @@ -0,0 +1,3 @@ + + +
    Account Lookup Service
    (ALS)

    [Not supported by viewer]
    FSP
    Backend

    (Does not natively speak Mojaloop API)



    [Not supported by viewer]
    Scheme-Adapter

    (Converts from Mojaloop API to backend FSP API)

    [Not supported by viewer]
    FSP
    Backend
      

    (Natively speaks Mojaloop API)



    [Not supported by viewer]
    Participants Account Lookup
    [Not supported by viewer]
    Payer FSP
    [Not supported by viewer]
    Payee FSP
    [Not supported by viewer]
    Party Store
    [Not supported by viewer]
    Party
    Store
    [Not supported by viewer]
    Persistance store
    [Not supported by viewer]
    Central Ledger
    Service
    [Not supported by viewer]
    A5. Retrieve Participant End-points GET /participants/<participantId>/endpoints
    A1. Request Participant Lookup
    GET /participants/<idType>/<id>
    [Not supported by viewer]
    A3. Request Participant Lookup via Oracle
    GET /participants/<idType>/<id>
    [Not supported by viewer]
    Oracle Merchant
    Registry Service
    <idType = 'BUSINESS'>
    [Not supported by viewer]
    A4. Alt
    A4. Alt

    <font color="#000000"><br></font>
    Persistance store
    [Not supported by viewer]
    Oracle Bank Account
    Registry Service
    <idType = 'ACCOUNT_ID'>
    [Not supported by viewer]
    A4. Alt
    A4. Alt

    <font color="#000000"><br></font>
    Oracle Pathfinder
    Registry Service
    Adapter
    <idType = 'MSISDN'>
    [Not supported by viewer]
    A4. Retrieve Participant Data
    [Not supported by viewer]

    <font color="#000000"><br></font>
    A3. Alt
    A3. Alt

    <font color="#000000"><br></font>
    A3. Alt
    A3. Alt

    <font color="#000000"><br></font>
    Mojaloop Central Services
    [Not supported by viewer]
    A7. User Lookup
    PUT /participants/<idType>/<id>
    A7. User Lookup <br>PUT /participants/<idType>/<id>
    Central Ledger DB
    Central Ledger DB
    A6. Retrieve Participant End-point Data
    A6. Retrieve Participant End-point Data

    <font color="#000000"><br></font>
    ALS
    DB
    [Not supported by viewer]
    A2. Lookup Oracle Adapter/Service End-points based on <idType>
    Hub Operator Schema Hosted
    [Not supported by viewer]
    Externally Hosted
    [Not supported by viewer]
    PathFinder GSMA
    [Not supported by viewer]
    API
    Internal Use-Only
    API <br>Internal Use-Only
    Mojaloop API
    Specification v1.0
    Mojaloop API<br>Specification v1.0<br>
    Key
    [Not supported by viewer]
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-parties.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-parties.svg new file mode 100644 index 000000000..0dd8b76e6 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/architecture/arch-flow-account-lookup-parties.svg @@ -0,0 +1,3 @@ + + +
    Account Lookup Service
    (ALS)

    [Not supported by viewer]
    FSP
    Backend

    (Does not natively speak Mojaloop API)



    [Not supported by viewer]
    Scheme-Adapter

    (Converts from Mojaloop API to backend FSP API)

    [Not supported by viewer]
    FSP
    Backend
      

    (Natively speaks Mojaloop API)



    [Not supported by viewer]
    Parties Account Lookup
    [Not supported by viewer]
    Payer FSP
    [Not supported by viewer]
    Payee FSP
    [Not supported by viewer]
    Party Store
    [Not supported by viewer]
    Party
    Store
    [Not supported by viewer]
    A10. Get 
    receiver 
    details
    [Not supported by viewer]
    Persistance store
    [Not supported by viewer]
    Central Ledger
    Service
    [Not supported by viewer]
    A7. Retrieve PayeeFSP Participant End-pointsGET /participants/<participantId>/endpoints
    A1. Request Party Lookup
    GET /parties/<idType>/<id>
    [Not supported by viewer]
    A4. Request Participant Lookup via Oracle
    GET /participants/<idType>/<id>
    [Not supported by viewer]
    A9. User Lookup
    GET /parties/<idType>/<id>
    A9. User Lookup <br>GET /parties/<idType>/<id>
    Oracle Merchant
    Registry Service
    <idType = 'BUSINESS'>
    [Not supported by viewer]
    A5. Alt
    [Not supported by viewer]

    <font color="#000000"><br></font>
    Persistance store
    [Not supported by viewer]
    Oracle Bank Account
    Registry Service
    <idType = 'ACCOUNT_ID'>
    [Not supported by viewer]
    A5. Alt
    A5. Alt

    <font color="#000000"><br></font>
    Oracle Pathfinder
    Registry Service
    Adapter
    <idType = 'MSISDN'>
    [Not supported by viewer]
    A5. Retrieve Participant Data
    [Not supported by viewer]

    <font color="#000000"><br></font>
    A4. Alt
    A4. Alt

    <font color="#000000"><br></font>
    A4. Alt
    A4. Alt

    <font color="#000000"><br></font>
    Mojaloop Central Services
    [Not supported by viewer]
    A11. User Lookup
    PUT /parties/<idType>/<id>
    A11. User Lookup <br>PUT /parties/<idType>/<id>
    A14. User Lookup
    PUT /parties/<idType>/<id>
    A14. User Lookup <br>PUT /parties/<idType>/<id>
    Central Ledger DB
    Central Ledger DB
    A8. Retrieve Participant End-point Data
    A8. Retrieve Participant End-point Data

    <font color="#000000"><br></font>
    ALS
    DB
    [Not supported by viewer]
    Hub Operator Schema Hosted
    [Not supported by viewer]
    Externally Hosted
    [Not supported by viewer]
    PathFinder GSMA
    [Not supported by viewer]
    API
    Internal Use-Only
    API <br>Internal Use-Only
    Mojaloop API
    Specification v1.0
    Mojaloop API<br>Specification v1.0<br>
    Key
    [Not supported by viewer]
    A3. Lookup Oracle Registry ServiceEnd-points based on <idType>A12. Retrieve PayerFSP Participant End-pointsGET /participants/<participantId>/endpointsA6. Retrieve PayeeFSP Data for ValidationGET /participants/<participantId>(retrieve FSP Data)
    A13. Retrieve Participant End-point Data
    <font style="font-size: 13px">A13. Retrieve Participant End-point Data</font>
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.puml b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.puml new file mode 100644 index 000000000..3a6a6eecb --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.puml @@ -0,0 +1,92 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.4 Delete Oracle Endpoint + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS Admin Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service Admin API" as ALSADM +control "DELETE Oracle Handler" as ORC_HANDLER +database "ALS Store" as DB + +box "Account Lookup Service" #LightYellow +participant ALSADM +participant ORC_HANDLER +participant DB +end box + +' start flow + +activate OPERATOR +group Get Oracle Endpoint + OPERATOR -> ALSADM: Request to Delete Oracle Endpoint -\nDELETE /oracles/{ID} + activate ALSADM + + ALSADM -> ORC_HANDLER: Delete Oracle Endpoint + + activate ORC_HANDLER + ORC_HANDLER -> DB: Update existing Oracle Endpoint By ID + hnote over DB #lightyellow + Update isActive = false + end note + alt Delete existing Oracle Endpoint (success) + activate DB + DB -> ORC_HANDLER: Return Success + deactivate DB + + ORC_HANDLER -> ALSADM: Return success response + deactivate ORC_HANDLER + ALSADM --> OPERATOR: Return HTTP Status: 204 + + deactivate ALSADM + deactivate OPERATOR + end + alt Delete existing Oracle Endpoint (failure) + DB -> ORC_HANDLER: Throws Error (Not Found) + ORC_HANDLER -> ALSADM: Throw Error + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + ALSADM --> OPERATOR: Return HTTP Status: 502 + end +end + +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.svg new file mode 100644 index 000000000..6cbc84f40 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-delete-oracle-7.3.4.svg @@ -0,0 +1,197 @@ + + + + + + + + + + + 7.3.4 Delete Oracle Endpoint + + + + Account Lookup Service + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Account Lookup Service Admin API + + + + + Account Lookup Service Admin API + + + + + DELETE Oracle Handler + + + + + DELETE Oracle Handler + + + + + ALS Store + + + + + ALS Store + + + + + + + + Get Oracle Endpoint + + + + + 1 + + + Request to Delete Oracle Endpoint - + + + DELETE /oracles/{ID} + + + + + 2 + + + Delete Oracle Endpoint + + + + + 3 + + + Update existing Oracle Endpoint By ID + + + + Update isActive = false + + + + + alt + + + [Delete existing Oracle Endpoint (success)] + + + + + 4 + + + Return Success + + + + + 5 + + + Return success response + + + + + 6 + + + Return + + + HTTP Status: + + + 204 + + + + + alt + + + [Delete existing Oracle Endpoint (failure)] + + + + + 7 + + + Throws Error (Not Found) + + + + + 8 + + + Throw Error + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 9 + + + Return + + + HTTP Status: + + + 502 + + diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.puml b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.puml new file mode 100644 index 000000000..b800d83f9 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.puml @@ -0,0 +1,116 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.1 Get All Oracle Endpoints + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS Admin Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service Admin API" as ALSADM +control "Get Oracles Handler" as ORC_HANDLER +database "ALS Store" as DB + +box "Account Lookup Service" #LightYellow +participant ALSADM +participant ORC_HANDLER +participant DB +end box + +' start flow + +activate OPERATOR +group Get Oracle Endpoints + OPERATOR -> ALSADM: Request to GET all Oracle Endpoints -\nGET /oracles?currency=USD&type=MSISDN + activate ALSADM + + ALSADM -> ORC_HANDLER: Get Oracle Endpoints + activate ORC_HANDLER + ORC_HANDLER -> DB: Get oracle endpoints + activate DB + + alt Get Oracle Endpoints (success) + DB --> ORC_HANDLER: Return Oracle Endpoints + deactivate DB + + deactivate DB + ORC_HANDLER -> ALSADM: Return Oracle Endpoints + deactivate ORC_HANDLER + note left of ALSADM #yellow + Message: + { + [ + { + "oracleId": , + "oracleIdType": , + "endpoint": { + "value": , + "endpointType": + }, + "currency": , + "isDefault": + } + ] + } + end note + ALSADM --> OPERATOR: Return HTTP Status: 200 + + deactivate ALSADM + deactivate OPERATOR + end + + alt Get Oracle Endpoints (failure) + DB --> ORC_HANDLER: Throw Error + deactivate DB + ORC_HANDLER -> ALSADM: Throw Error + deactivate ORC_HANDLER + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + + ALSADM --> OPERATOR: Return HTTP Status: 502 + + deactivate ALSADM + deactivate OPERATOR + + + end +end + +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.svg new file mode 100644 index 000000000..7447557a3 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-get-oracle-7.3.1.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + 7.3.1 Get All Oracle Endpoints + + + + Account Lookup Service + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Account Lookup Service Admin API + + + + + Account Lookup Service Admin API + + + + + Get Oracles Handler + + + + + Get Oracles Handler + + + + + ALS Store + + + + + ALS Store + + + + + + + + Get Oracle Endpoints + + + + + 1 + + + Request to GET all Oracle Endpoints - + + + GET /oracles?currency=USD&type=MSISDN + + + + + 2 + + + Get Oracle Endpoints + + + + + 3 + + + Get oracle endpoints + + + + + alt + + + [Get Oracle Endpoints (success)] + + + + + 4 + + + Return Oracle Endpoints + + + + + 5 + + + Return Oracle Endpoints + + + + + Message: + + + { + + + [ + + + { + + + "oracleId": <string>, + + + "oracleIdType": <PartyIdType>, + + + "endpoint": { + + + "value": <string>, + + + "endpointType": <EndpointType> + + + }, + + + "currency": <Currency>, + + + "isDefault": <boolean> + + + } + + + ] + + + } + + + + + 6 + + + Return + + + HTTP Status: + + + 200 + + + + + alt + + + [Get Oracle Endpoints (failure)] + + + + + 7 + + + Throw Error + + + + + 8 + + + Throw Error + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 9 + + + Return + + + HTTP Status: + + + 502 + + diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.puml b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.puml new file mode 100644 index 000000000..083b0fac2 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.puml @@ -0,0 +1,112 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.2 Create Oracle Endpoints + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS Admin Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service Admin API" as ALSADM +control "POST Oracle Handler" as ORC_HANDLER +database "ALS Store" as DB + +box "Account Lookup Service" #LightYellow +participant ALSADM +participant ORC_HANDLER +participant DB +end box + +' start flow + +activate OPERATOR +group Get Oracle Endpoint + OPERATOR -> ALSADM: Request to Create Oracle Endpoint -\nPOST /oracles + note left of ALSADM #yellow + Message: + { + "oracleIdType": , + "endpoint": { + "value": , + "endpointType": + }, + "currency": , + "isDefault": + } + end note + activate ALSADM + + ALSADM -> ORC_HANDLER: Create Oracle Endpoint + + activate ORC_HANDLER + ORC_HANDLER -> ORC_HANDLER: Build Oracle Endpoint Data Object + ORC_HANDLER -> DB: Insert Oracle Endpoint Data Object + activate DB + + alt Create Oracle Entry (success) + DB --> ORC_HANDLER: Return success response + deactivate DB + + ORC_HANDLER -> ALSADM: Return success response + deactivate ORC_HANDLER + ALSADM --> OPERATOR: Return HTTP Status: 201 + + deactivate ALSADM + deactivate OPERATOR + end + + alt Create Oracle Entry (failure) + DB --> ORC_HANDLER: Throw Error + deactivate DB + ORC_HANDLER -> ALSADM: Throw Error + deactivate ORC_HANDLER + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + + ALSADM --> OPERATOR: Return HTTP Status: 502 + + deactivate ALSADM + deactivate OPERATOR + + + end +end + +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.svg new file mode 100644 index 000000000..0638bdb48 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-post-oracle-7.3.2.svg @@ -0,0 +1,233 @@ + + + + + + + + + + + 7.3.2 Create Oracle Endpoints + + + + Account Lookup Service + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Account Lookup Service Admin API + + + + + Account Lookup Service Admin API + + + + + POST Oracle Handler + + + + + POST Oracle Handler + + + + + ALS Store + + + + + ALS Store + + + + + + + + Get Oracle Endpoint + + + + + 1 + + + Request to Create Oracle Endpoint - + + + POST /oracles + + + + + Message: + + + { + + + "oracleIdType": <PartyIdType>, + + + "endpoint": { + + + "value": <string>, + + + "endpointType": <EndpointType> + + + }, + + + "currency": <Currency>, + + + "isDefault": <boolean> + + + } + + + + + 2 + + + Create Oracle Endpoint + + + + + 3 + + + Build Oracle Endpoint Data Object + + + + + 4 + + + Insert Oracle Endpoint Data Object + + + + + alt + + + [Create Oracle Entry (success)] + + + + + 5 + + + Return success response + + + + + 6 + + + Return success response + + + + + 7 + + + Return + + + HTTP Status: + + + 201 + + + + + alt + + + [Create Oracle Entry (failure)] + + + + + 8 + + + Throw Error + + + + + 9 + + + Throw Error + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 10 + + + Return + + + HTTP Status: + + + 502 + + diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.puml b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.puml new file mode 100644 index 000000000..142eae685 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.puml @@ -0,0 +1,131 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.3 Update Oracle Endpoint + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS Admin Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service Admin API" as ALSADM +control "PUT Oracle Handler" as ORC_HANDLER +database "ALS Store" as DB + +box "Account Lookup Service" #LightYellow +participant ALSADM +participant ORC_HANDLER +participant DB +end box + +' start flow + +activate OPERATOR +group Get Oracle Endpoint + OPERATOR -> ALSADM: Request to Update Oracle Endpoint -\nPUT /oracles/{ID} + note left of ALSADM #yellow + Message: + { + "oracleIdType": , + "endpoint": { + "value": , + "endpointType": + }, + "currency": , + "isDefault": + } + end note + activate ALSADM + + ALSADM -> ORC_HANDLER: Update Oracle Endpoint + + activate ORC_HANDLER + ORC_HANDLER -> DB: Find existing Oracle Endpoint + alt Find existing Oracle Endpoint (success) + activate DB + DB -> ORC_HANDLER: Return Oracle Endpoint Result + deactivate DB + ORC_HANDLER -> ORC_HANDLER: Update Returned Oracle Data Object + ORC_HANDLER -> DB: Update Oracle Data Object + activate DB + alt Update Oracle Entry (success) + DB --> ORC_HANDLER: Return success response + deactivate DB + + ORC_HANDLER -> ALSADM: Return success response + deactivate ORC_HANDLER + ALSADM --> OPERATOR: Return HTTP Status: 204 + + deactivate ALSADM + deactivate OPERATOR + end + + alt Update Oracle Entry (failure) + DB --> ORC_HANDLER: Throw Error + deactivate DB + ORC_HANDLER -> ALSADM: Throw Error + deactivate ORC_HANDLER + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + + ALSADM --> OPERATOR: Return HTTP Status: 502 + + deactivate ALSADM + deactivate OPERATOR + + + end + end + alt Find existing Oracle Endpoint (failure) + DB -> ORC_HANDLER: Returns Empty Object + ORC_HANDLER -> ALSADM: Throw Error + note left of ALSADM #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + ALSADM --> OPERATOR: Return HTTP Status: 502 + end +end + +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.svg new file mode 100644 index 000000000..98da55c5c --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-admin-put-oracle-7.3.3.svg @@ -0,0 +1,319 @@ + + + + + + + + + + + 7.3.3 Update Oracle Endpoint + + + + Account Lookup Service + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Account Lookup Service Admin API + + + + + Account Lookup Service Admin API + + + + + PUT Oracle Handler + + + + + PUT Oracle Handler + + + + + ALS Store + + + + + ALS Store + + + + + + + + Get Oracle Endpoint + + + + + 1 + + + Request to Update Oracle Endpoint - + + + PUT /oracles/{ID} + + + + + Message: + + + { + + + "oracleIdType": <PartyIdType>, + + + "endpoint": { + + + "value": <string>, + + + "endpointType": <EndpointType> + + + }, + + + "currency": <Currency>, + + + "isDefault": <boolean> + + + } + + + + + 2 + + + Update Oracle Endpoint + + + + + 3 + + + Find existing Oracle Endpoint + + + + + alt + + + [Find existing Oracle Endpoint (success)] + + + + + 4 + + + Return Oracle Endpoint Result + + + + + 5 + + + Update Returned Oracle Data Object + + + + + 6 + + + Update Oracle Data Object + + + + + alt + + + [Update Oracle Entry (success)] + + + + + 7 + + + Return success response + + + + + 8 + + + Return success response + + + + + 9 + + + Return + + + HTTP Status: + + + 204 + + + + + alt + + + [Update Oracle Entry (failure)] + + + + + 10 + + + Throw Error + + + + + 11 + + + Throw Error + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 12 + + + Return + + + HTTP Status: + + + 502 + + + + + alt + + + [Find existing Oracle Endpoint (failure)] + + + + + 13 + + + Returns Empty Object + + + + + 14 + + + Throw Error + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 15 + + + Return + + + HTTP Status: + + + 502 + + diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.puml b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.puml new file mode 100644 index 000000000..3095e7bad --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.puml @@ -0,0 +1,104 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.3.0 Delete Endpoint Cache + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' control - ALS API Handler +' database - Database Persistent Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Account Lookup Service API" as ALSAPI +control "Delete Endpoint Cache Handler" as DEL_HANDLER +database "Cache" as Cache + +box "Account Lookup Service" #LightYellow +participant ALSAPI +participant DEL_HANDLER +participant Cache +end box + +' start flow + +activate OPERATOR +group Delete Endpoint Cache + OPERATOR -> ALSAPI: Request to DELETE Endpoint Cache - DELETE /endpointcache + activate ALSAPI + activate ALSAPI + + ALSAPI -> DEL_HANDLER: Delete Cache + activate DEL_HANDLER + DEL_HANDLER -> Cache: Stop Cache + activate Cache + + + alt Stop Cache Status (success) + Cache --> DEL_HANDLER: Return status + deactivate Cache + + DEL_HANDLER -> Cache: Initialize Cache + activate Cache + Cache -> DEL_HANDLER: Return Status + deactivate Cache + DEL_HANDLER -> ALSAPI: Return Status + deactivate DEL_HANDLER + ALSAPI --> OPERATOR: Return HTTP Status: 202 + + deactivate ALSAPI + deactivate OPERATOR + end + + alt Validate Status (service failure) + Cache --> DEL_HANDLER: Throw Error + deactivate Cache + DEL_HANDLER -> ALSAPI: Throw Error + deactivate DEL_HANDLER + note left of ALSAPI #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + + ALSAPI --> OPERATOR: Return HTTP Status: 502 + + deactivate ALSAPI + deactivate OPERATOR + + + end +end + +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.svg new file mode 100644 index 000000000..ab60d1d1b --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-endpoint-cache-7.3.0.svg @@ -0,0 +1,208 @@ + + + + + + + + + + + 7.3.0 Delete Endpoint Cache + + + + Account Lookup Service + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Account Lookup Service API + + + + + Account Lookup Service API + + + + + Delete Endpoint Cache Handler + + + + + Delete Endpoint Cache Handler + + + + + Cache + + + + + Cache + + + + + + + + + Delete Endpoint Cache + + + + + 1 + + + Request to DELETE Endpoint Cache - DELETE /endpointcache + + + + + 2 + + + Delete Cache + + + + + 3 + + + Stop Cache + + + + + alt + + + [Stop Cache Status (success)] + + + + + 4 + + + Return status + + + + + 5 + + + Initialize Cache + + + + + 6 + + + Return Status + + + + + 7 + + + Return Status + + + + + 8 + + + Return + + + HTTP Status: + + + 202 + + + + + alt + + + [Validate Status (service failure)] + + + + + 9 + + + Throw Error + + + + + 10 + + + Throw Error + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 11 + + + Return + + + HTTP Status: + + + 502 + + diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.plantuml b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.plantuml new file mode 100644 index 000000000..978a1e303 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.plantuml @@ -0,0 +1,213 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.1.2. Delete Participant Details + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +actor "Payer FSP" as PAYER_FSP +actor "Payee FSP" as PAYEE_FSP +boundary "Account Lookup\nService (ALS)" as ALS_API +control "ALS Participant\nHandler" as ALS_PARTICIPANT_HANDLER +entity "ALS CentralService\nEndpoint DAO" as ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +entity "ALS CentralService\nParticipant DAO" as ALS_CENTRALSERVICE_PARTICIPANT_DAO +'entity "ALS Participant Oracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +entity "ALS Parties\nFSP DAO" as ALS_PARTIES_FSP_DAO +entity "ALS Participant Endpoint\nOracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +database "ALS Database" as ALS_DB +boundary "Oracle Service API" as ORACLE_API +boundary "Central Service API" as CENTRALSERVICE_API + +box "Financial Service Provider" #LightGrey +participant PAYER_FSP +end box + +box "Account Lookup Service" #LightYellow +participant ALS_API +participant ALS_PARTICIPANT_HANDLER +participant ALS_PARTICIPANT_ORACLE_DAO +participant ALS_DB +participant ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +participant ALS_CENTRALSERVICE_PARTICIPANT_DAO +participant ALS_PARTIES_FSP_DAO +end box + +box "Central Services" #LightGreen +participant CENTRALSERVICE_API +end box + +box "ALS Oracle Service/Adapter" #LightBlue +participant ORACLE_API +end box + +box "Financial Service Provider" #LightGrey +participant PAYEE_FSP +end box + +' START OF FLOW + +group Get Party Details + PAYER_FSP ->> ALS_API: Request to delete Participant details\nDEL - /participants/{TYPE}/{ID}?currency={CURRENCY}\nResponse code: 202\nError code: 200x, 300x, 310x, 320x + activate ALS_API + note left ALS_API #lightgray + Validate request against + Mojaloop Interface Specification. + Error code: 300x, 310x + end note + + ALS_API -> ALS_PARTICIPANT_HANDLER: Request to delete Participant details + + alt oracleEndpoint match found & parties information retrieved + activate ALS_PARTICIPANT_HANDLER + '********************* Retrieve Oracle Routing Information - START ************************ + ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Oracle Routing Config\nError code: 200x, 310x, 320x + ref over ALS_PARTICIPANT_HANDLER, ALS_DB + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Oracle Routing Config Sequence]] + ||| + end ref + '********************* Retrieve Oracle Routing Information - END ************************ + ||| + '********************* Retrieve Switch Routing Information - START ************************ +' ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Switch Routing Config\nError code: 200x, 310x, 320x +' ref over ALS_PARTICIPANT_HANDLER, ALS_DB +' GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Switch Routing Config Sequence]] +' ||| +' end ref + '********************* Retrieve Switch Routing Information - END ************************ + + ||| + + '********************* Validate FSPIOP-Source Participant - START ************************ + group Validate FSPIOP-Source Participant + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Request FSPIOP-Source participant information\nError code: 200x + activate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_CENTRALSERVICE_PARTICIPANT_DAO -> CENTRALSERVICE_API: GET - /participants/{FSPIOP-Source}\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Return FSPIOP-Source participant information + deactivate CENTRALSERVICE_API + + ALS_CENTRALSERVICE_PARTICIPANT_DAO --> ALS_PARTICIPANT_HANDLER: Return FSPIOP-Source participant information + + deactivate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate FSPIOP-Source participant\nError code: 320x + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate that PARTICIPANT.fspId == FSPIOP-Source\nError code: 3100 + end group + '********************* Validate Participant - END ************************ + + ||| + + '********************* Request Oracle Participant Information - START ************************ + + ALS_PARTICIPANT_HANDLER <-> ORACLE_API: Get Participant Information for PayerFSP\nError code: 200x, 310x, 320x + ref over ALS_PARTICIPANT_HANDLER, ORACLE_API + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Request Participant Information from Oracle Sequence]] + ||| + end ref + + '********************* Request Oracle Participant Information - END ************************ + + ||| + + '********************* Validate Participant Ownership - START ************************ + ' Reference section 6.2.2.4 - Note: The ALS should verify that it is the Party’s current FSP that is deleting the FSP information. Is this adequate? + group Validate Participant Ownership + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate that PARTICIPANT.fspId matches Participant Information retrieved from Oracle.\nError code: 3100 + end group + '********************* Validate Participant - END ************************ + + ||| + + '********************* Delete Oracle Participant Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_ORACLE_DAO: Request to delete Participant's FSP details DEL - /participants/{TYPE}/{ID}?currency={CURRENCY}\nError code: 200x, 310x, 320x + activate ALS_PARTICIPANT_ORACLE_DAO + ALS_PARTICIPANT_ORACLE_DAO -> ORACLE_API: Request to delete Participant's FSP details DEL - /participants/{TYPE}/{ID}?currency={CURRENCY}\nResponse code: 200 \nError code: 200x, 310x, 320x + activate ORACLE_API + ORACLE_API --> ALS_PARTICIPANT_ORACLE_DAO: Return result + deactivate ORACLE_API + ALS_PARTICIPANT_ORACLE_DAO --> ALS_PARTICIPANT_HANDLER: Return result + deactivate ALS_PARTICIPANT_ORACLE_DAO + + '********************* Delete Oracle Participant Information - END ************************ + ||| + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP Participant Callback Endpoint\nError code: 200x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Return delete request result + ALS_API ->> PAYER_FSP: Callback indiciating success:\nPUT - /participants/{TYPE}/{ID}?currency={CURRENCY} + + else Validation failure or Oracle was unable process delete request + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{TYPE}/{ID}/error + + else Empty list of switchEndpoint results returned + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Handle error\nError code: 200x + hnote right ALS_PARTICIPANT_HANDLER #red + Error Handling Framework + end note + end alt + + deactivate ALS_PARTICIPANT_HANDLER +end +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.svg new file mode 100644 index 000000000..4612fee5f --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-del-participants-7.1.2.svg @@ -0,0 +1,632 @@ + + + + + + + + + + + 7.1.2. Delete Participant Details + + + + Financial Service Provider + + + + Account Lookup Service + + + + Central Services + + + + ALS Oracle Service/Adapter + + + + Financial Service Provider + + + + + + + + + Payer FSP + + + + + Payer FSP + + + + + Account Lookup + + + Service (ALS) + + + + + Account Lookup + + + Service (ALS) + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Handler + + + + + ALS Participant Endpoint + + + Oracle DAO + + + + + ALS Participant Endpoint + + + Oracle DAO + + + + + ALS Database + + + + + ALS Database + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Participant DAO + + + + + ALS CentralService + + + Participant DAO + + + + + ALS Parties + + + FSP DAO + + + + + ALS Parties + + + FSP DAO + + + + + Central Service API + + + + + Central Service API + + + + + Oracle Service API + + + + + Oracle Service API + + + + + Payee FSP + + + + + Payee FSP + + + + + + + + Get Party Details + + + + 1 + + + Request to delete Participant details + + + DEL - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + Response code: + + + 202 + + + Error code: + + + 200x, 300x, 310x, 320x + + + + + Validate request against + + + Mojaloop Interface Specification. + + + Error code: + + + 300x, 310x + + + + + 2 + + + Request to delete Participant details + + + + + alt + + + [oracleEndpoint match found & parties information retrieved] + + + + + 3 + + + Get Oracle Routing Config + + + Error code: + + + 200x, 310x, 320x + + + + + ref + + + GET Participants - + + + + Get Oracle Routing Config Sequence + + + + + + + Validate FSPIOP-Source Participant + + + + + 4 + + + Request FSPIOP-Source participant information + + + Error code: + + + 200x + + + + + 5 + + + GET - /participants/{FSPIOP-Source} + + + Error code: + + + 200x, 310x, 320x + + + + + 6 + + + Return FSPIOP-Source participant information + + + + + 7 + + + Return FSPIOP-Source participant information + + + + + 8 + + + Validate FSPIOP-Source participant + + + Error code: + + + 320x + + + + + 9 + + + Validate that PARTICIPANT.fspId == FSPIOP-Source + + + Error code: + + + 3100 + + + + + 10 + + + Get Participant Information for PayerFSP + + + Error code: + + + 200x, 310x, 320x + + + + + ref + + + GET Participants - + + + + Request Participant Information from Oracle Sequence + + + + + + + Validate Participant Ownership + + + + + 11 + + + Validate that PARTICIPANT.fspId matches Participant Information retrieved from Oracle. + + + Error code: + + + 3100 + + + + + 12 + + + Request to delete Participant's FSP details DEL - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + Error code: + + + 200x, 310x, 320x + + + + + 13 + + + Request to delete Participant's FSP details DEL - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 14 + + + Return result + + + + + 15 + + + Return result + + + + + 16 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + Error code: + + + 200x + + + + + 17 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Error code: + + + 200x, 310x, 320x + + + + + 18 + + + List of PayerFSP Participant Callback Endpoints + + + + + 19 + + + List of PayerFSP Participant Callback Endpoints + + + + + 20 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + + + + 21 + + + Return delete request result + + + + 22 + + + Callback indiciating success: + + + PUT - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + + [Validation failure or Oracle was unable process delete request] + + + + + 23 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 24 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 25 + + + List of PayerFSP Participant Callback Endpoints + + + + + 26 + + + List of PayerFSP Participant Callback Endpoints + + + + + 27 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + + + + 28 + + + Handle error + + + Error code: + + + 200x, 310x, 320x + + + + 29 + + + Callback: PUT - /participants/{TYPE}/{ID}/error + + + + [Empty list of switchEndpoint results returned] + + + + + 30 + + + Handle error + + + Error code: + + + 200x + + + + Error Handling Framework + + diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.plantuml b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.plantuml new file mode 100644 index 000000000..09be5f1df --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.plantuml @@ -0,0 +1,180 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.1.0. Get Participant Details + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +actor "Payer FSP" as PAYER_FSP +boundary "Account Lookup\nService (ALS)" as ALS_API +control "ALS Participant\nHandler" as ALS_PARTICIPANT_HANDLER +entity "ALS Endpoint Type\nConfig DAO" as ALS_TYPE_ENDPOINT_CONFIG_DAO +entity "ALS CentralService\nEndpoint DAO" as ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +entity "ALS Participant\nOracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +entity "ALS Participant Endpoint\nOracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +database "ALS Database" as ALS_DB +boundary "Oracle Service API" as ORACLE_API +boundary "Central Service API" as CENTRALSERVICE_API + +box "Financial Service Provider" #LightGrey +participant PAYER_FSP +end box + +box "Account Lookup Service" #LightYellow +participant ALS_API +participant ALS_PARTICIPANT_HANDLER +participant ALS_TYPE_ENDPOINT_CONFIG_DAO +participant ALS_PARTICIPANT_ORACLE_DAO +participant ALS_DB +participant ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +end box + +box "Central Services" #LightGreen +participant CENTRALSERVICE_API +end box + +box "ALS Oracle Service/Adapter" #LightBlue +participant ORACLE_API +end box + +' START OF FLOW + +group Get Participant's FSP Details + + + PAYER_FSP ->> ALS_API: Request to get participant's FSP details \nGET - /participants/{TYPE}/{ID}?currency={CURRENCY}\nResponse code: 202 \nError code: 200x, 300x, 310x, 320x + activate ALS_API + note left ALS_API #lightgray + Validate request against + Mojaloop Interface Specification. + Error code: 300x, 310x + end note + + ALS_API -> ALS_PARTICIPANT_HANDLER: Request to get participant's FSP details + + alt oracleEndpoint match found + group #lightskyblue IMPLEMENTATION: Get Oracle Routing Config Sequence [CACHED] + activate ALS_PARTICIPANT_HANDLER + ALS_PARTICIPANT_HANDLER -> ALS_TYPE_ENDPOINT_CONFIG_DAO: Fetch Oracle Routing information based on\n{TYPE} and {CURRENCY} if provided\nError code: 200x + activate ALS_TYPE_ENDPOINT_CONFIG_DAO + ALS_TYPE_ENDPOINT_CONFIG_DAO -> ALS_DB: Retrieve oracleEndpoint\nError code: 200x + activate ALS_DB + hnote over ALS_DB #lightyellow + oracleEndpoint + endpointType + partyIdType + currency (optional) + end note + ALS_DB --> ALS_TYPE_ENDPOINT_CONFIG_DAO: Return oracleEndpoint result set + deactivate ALS_DB + ALS_TYPE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of **oracleEndpoint** for the Participant + deactivate ALS_TYPE_ENDPOINT_CONFIG_DAO + opt #lightskyblue oracleEndpoint IS NULL + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Error code: 3200 + end + end group + + group #lightskyblue IMPLEMENTATION: Request Participant Information from Oracle Sequence + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_ORACLE_DAO: Request to get participant's FSP details \nGET - /participants/{TYPE}/{ID}?currency={CURRENCY}\nError code: 200x, 310x, 320x + activate ALS_PARTICIPANT_ORACLE_DAO + ALS_PARTICIPANT_ORACLE_DAO -> ORACLE_API: Request to get participant's FSP details \nGET - /participants/{TYPE}/{ID}?currency={CURRENCY}\nResponse code: 200 \nError code: 200x, 310x, 320x + activate ORACLE_API + ORACLE_API --> ALS_PARTICIPANT_ORACLE_DAO: Return list of Participant information + deactivate ORACLE_API + ALS_PARTICIPANT_ORACLE_DAO --> ALS_PARTICIPANT_HANDLER: Return list of Participant information + deactivate ALS_PARTICIPANT_ORACLE_DAO + end group + +' group #lightskyblue IMPLEMENTATION: Get Switch Routing Config Sequence [CACHED] +' note right of ALS_PARTICIPANT_HANDLER #lightgray +' **REFERENCE**: Get Oracle Routing Config Sequence: oracleEndpoint +' end note +' alt #lightskyblue oracleEndpoint IS NOT NULL +' ALS_PARTICIPANT_HANDLER -> ALS_TYPE_ENDPOINT_CONFIG_DAO: Fetch Switch Routing information\nError code: 200x +' ALS_TYPE_ENDPOINT_CONFIG_DAO -> ALS_DB: Retrieve switchEndpoint\nError code: 200x +' activate ALS_DB +' hnote over ALS_DB #lightyellow +' switchEndpoint +' endpointType +' end note +' ALS_DB -> ALS_TYPE_ENDPOINT_CONFIG_DAO: Return switchEndpoint result set +' deactivate ALS_DB +' ALS_TYPE_ENDPOINT_CONFIG_DAO -> ALS_PARTICIPANT_HANDLER: Return **switchEndpoint** +' else +' ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Error code: 2000 +' end alt +' end group + + '********************* Get PayerFSP Participant End-point Information - START ************************ + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Return list of Participant information + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{TYPE}/{ID}?currency={CURRENCY} + else oracleEndpoint IS NULL OR error occurred + + '********************* Get PayerFSP Participant End-point Information - START ************************ + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints. \nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{TYPE}/{ID}/error + else switchEndpoint IS NULL + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Handle error\nError code: 200x + hnote right ALS_PARTICIPANT_HANDLER #red + Error Handling Framework + end note + end alt + deactivate ALS_API + + deactivate ALS_PARTICIPANT_HANDLER + +end +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.svg new file mode 100644 index 000000000..74687dae8 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-participants-7.1.0.svg @@ -0,0 +1,558 @@ + + + + + + + + + + + 7.1.0. Get Participant Details + + + + Financial Service Provider + + + + Account Lookup Service + + + + Central Services + + + + ALS Oracle Service/Adapter + + + + + + + + + + Payer FSP + + + + + Payer FSP + + + + + Account Lookup + + + Service (ALS) + + + + + Account Lookup + + + Service (ALS) + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Handler + + + + + ALS Endpoint Type + + + Config DAO + + + + + ALS Endpoint Type + + + Config DAO + + + + + ALS Participant + + + Oracle DAO + + + + + ALS Participant + + + Oracle DAO + + + + + ALS Database + + + + + ALS Database + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Endpoint DAO + + + + + Central Service API + + + + + Central Service API + + + + + Oracle Service API + + + + + Oracle Service API + + + + + + + + Get Participant's FSP Details + + + + 1 + + + Request to get participant's FSP details + + + GET - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + Response code: + + + 202 + + + Error code: + + + 200x, 300x, 310x, 320x + + + + + Validate request against + + + Mojaloop Interface Specification. + + + Error code: + + + 300x, 310x + + + + + 2 + + + Request to get participant's FSP details + + + + + alt + + + [oracleEndpoint match found] + + + + + IMPLEMENTATION: Get Oracle Routing Config Sequence + + + [CACHED] + + + + + 3 + + + Fetch Oracle Routing information based on + + + {TYPE} and {CURRENCY} if provided + + + Error code: + + + 200x + + + + + 4 + + + Retrieve oracleEndpoint + + + Error code: + + + 200x + + + + oracleEndpoint + + + endpointType + + + partyIdType + + + currency (optional) + + + + + 5 + + + Return oracleEndpoint result set + + + + + 6 + + + List of + + + oracleEndpoint + + + for the Participant + + + + + opt + + + [oracleEndpoint IS NULL] + + + + + 7 + + + Error code: + + + 3200 + + + + + IMPLEMENTATION: Request Participant Information from Oracle Sequence + + + + + 8 + + + Request to get participant's FSP details + + + GET - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + Error code: + + + 200x, 310x, 320x + + + + + 9 + + + Request to get participant's FSP details + + + GET - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 10 + + + Return list of Participant information + + + + + 11 + + + Return list of Participant information + + + + + 12 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 13 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 14 + + + List of PayerFSP Participant Callback Endpoints + + + + + 15 + + + List of PayerFSP Participant Callback Endpoints + + + + + 16 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + + + + 17 + + + Return list of Participant information + + + + 18 + + + Callback: PUT - /participants/{TYPE}/{ID}?currency={CURRENCY} + + + + [oracleEndpoint IS NULL OR error occurred] + + + + + 19 + + + Retrieve the Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 20 + + + Retrieve the Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints. + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 21 + + + List of Participant Callback Endpoints + + + + + 22 + + + List of Participant Callback Endpoints + + + + + 23 + + + Match Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + + + + 24 + + + Handle error + + + Error code: + + + 200x, 310x, 320x + + + + 25 + + + Callback: PUT - /participants/{TYPE}/{ID}/error + + + + [switchEndpoint IS NULL] + + + + + 26 + + + Handle error + + + Error code: + + + 200x + + + + Error Handling Framework + + diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.plantuml b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.plantuml new file mode 100644 index 000000000..776445cc5 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.plantuml @@ -0,0 +1,215 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.2.0. Get Party Details + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +actor "Payer FSP" as PAYER_FSP +actor "Payee FSP" as PAYEE_FSP +boundary "Account Lookup\nService (ALS)" as ALS_API +control "ALS Participant\nHandler" as ALS_PARTICIPANT_HANDLER +entity "ALS CentralService\nEndpoint DAO" as ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +entity "ALS CentralService\nParticipant DAO" as ALS_CENTRALSERVICE_PARTICIPANT_DAO +'entity "ALS Participant Oracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +entity "ALS Parties\nFSP DAO" as ALS_PARTIES_FSP_DAO +database "ALS Database" as ALS_DB +boundary "Oracle Service API" as ORACLE_API +boundary "Central Service API" as CENTRALSERVICE_API + +box "Financial Service Provider" #LightGrey +participant PAYER_FSP +end box + +box "Account Lookup Service" #LightYellow +participant ALS_API +participant ALS_PARTICIPANT_HANDLER +participant ALS_DB +participant ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +participant ALS_CENTRALSERVICE_PARTICIPANT_DAO +participant ALS_PARTIES_FSP_DAO +end box + +box "Central Services" #LightGreen +participant CENTRALSERVICE_API +end box + +box "ALS Oracle Service/Adapter" #LightBlue +participant ORACLE_API +end box + +box "Financial Service Provider" #LightGrey +participant PAYEE_FSP +end box + +' START OF FLOW + +group Get Party Details + PAYER_FSP ->> ALS_API: Request to get parties's FSP details\nGET - /parties/{TYPE}/{ID}?currency={CURRENCY}\nResponse code: 202\nError code: 200x, 300x, 310x, 320x + activate ALS_API + note left ALS_API #lightgray + Validate request against + Mojaloop Interface Specification. + Error code: 300x, 310x + end note + + ALS_API -> ALS_PARTICIPANT_HANDLER: Request to get parties's FSP details + + alt oracleEndpoint match found & parties information retrieved + activate ALS_PARTICIPANT_HANDLER + '********************* Retrieve Oracle Routing Information - START ************************ + ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Oracle Routing Config\nError code: 200x, 310x, 320x + ref over ALS_PARTICIPANT_HANDLER, ALS_DB + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Oracle Routing Config Sequence]] + ||| + end ref + '********************* Retrieve Oracle Routing Information - END ************************ + ||| + '********************* Retrieve Switch Routing Information - START ************************ +' ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Switch Routing Config\nError code: 200x, 310x, 320x +' ref over ALS_PARTICIPANT_HANDLER, ALS_DB +' GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Switch Routing Config Sequence]] +' ||| +' end ref + '********************* Retrieve Switch Routing Information - END ************************ + ||| + group Validate FSPIOP-Source Participant + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Request FSPIOP-Source participant information\nError code: 200x + activate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_CENTRALSERVICE_PARTICIPANT_DAO -> CENTRALSERVICE_API: GET - /participants/{FSPIOP-Source}\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Return FSPIOP-Source participant information + deactivate CENTRALSERVICE_API + + ALS_CENTRALSERVICE_PARTICIPANT_DAO --> ALS_PARTICIPANT_HANDLER: Return FSPIOP-Source participant information + + deactivate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate FSPIOP-Source participant\nError code: 320x + end group + ||| + + '********************* Request Oracle Participant Information - START ************************ + + ALS_PARTICIPANT_HANDLER <-> ORACLE_API: Get Participant Information for PayeeFSP\nError code: 200x, 310x, 320x + ref over ALS_PARTICIPANT_HANDLER, ORACLE_API + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Request Participant Information from Oracle Sequence]] + ||| + end ref + + '********************* Request Oracle Participant Information - END ************************ + ||| + '********************* Request Parties Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_PARTIES_FSP_DAO: Request Parties information from FSP.\nError code: 200x + + activate ALS_PARTIES_FSP_DAO + ALS_PARTIES_FSP_DAO ->> PAYEE_FSP: Parties Callback to Destination:\nGET - /parties/{TYPE}/{ID}?currency={CURRENCY}\nResponse code: 202\nError code: 200x, 310x, 320x + deactivate ALS_PARTIES_FSP_DAO + activate PAYEE_FSP + + PAYEE_FSP ->> ALS_API: Callback with Participant Information:\nPUT - /parties/{TYPE}/{ID}?currency={CURRENCY}\nError code: 200x, 300x, 310x, 320x + deactivate PAYEE_FSP + + ALS_API -> ALS_API: Validate request against\nMojaloop Interface Specification\nError code: 300x, 310x + ALS_API -> ALS_PARTICIPANT_HANDLER: Process Participant Callback Information for PUT + + '********************* Request Parties Information - END ************************ + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP Participant Callback Endpoint\nError code: 200x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTIES_PUT + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Return Participant Information to PayerFSP + ALS_API ->> PAYER_FSP: Callback with Parties Information:\nPUT - /parties/{TYPE}/{ID}?currency={CURRENCY} + + else Empty list of End-Points returned for either (PayeeFSP or Oracle) config information or Error occurred for PayerFSP + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{TYPE}/{ID}/error + else Empty list of End-Points returned for PayerFSP config information or Error occurred for PayeeFSP + + '********************* Get PayeeFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayeeFSP Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayeeFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200\nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayeeFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayeeFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayeeFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYEE_FSP: Callback: PUT - /participants/{TYPE}/{ID}/error + else Empty list of switchEndpoint results returned + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Handle error\nError code: 200x + hnote right ALS_PARTICIPANT_HANDLER #red + Error Handling Framework + end note + end alt + + deactivate ALS_PARTICIPANT_HANDLER +end +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.svg new file mode 100644 index 000000000..7b3342d7b --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-get-parties-7.2.0.svg @@ -0,0 +1,699 @@ + + + + + + + + + + + 7.2.0. Get Party Details + + + + Financial Service Provider + + + + Account Lookup Service + + + + Central Services + + + + ALS Oracle Service/Adapter + + + + Financial Service Provider + + + + + + + + + Payer FSP + + + + + Payer FSP + + + + + Account Lookup + + + Service (ALS) + + + + + Account Lookup + + + Service (ALS) + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Handler + + + + + ALS Database + + + + + ALS Database + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Participant DAO + + + + + ALS CentralService + + + Participant DAO + + + + + ALS Parties + + + FSP DAO + + + + + ALS Parties + + + FSP DAO + + + + + Central Service API + + + + + Central Service API + + + + + Oracle Service API + + + + + Oracle Service API + + + + + Payee FSP + + + + + Payee FSP + + + + + + + + Get Party Details + + + + 1 + + + Request to get parties's FSP details + + + GET - /parties/{TYPE}/{ID}?currency={CURRENCY} + + + Response code: + + + 202 + + + Error code: + + + 200x, 300x, 310x, 320x + + + + + Validate request against + + + Mojaloop Interface Specification. + + + Error code: + + + 300x, 310x + + + + + 2 + + + Request to get parties's FSP details + + + + + alt + + + [oracleEndpoint match found & parties information retrieved] + + + + + 3 + + + Get Oracle Routing Config + + + Error code: + + + 200x, 310x, 320x + + + + + ref + + + GET Participants - + + + + Get Oracle Routing Config Sequence + + + + + + + Validate FSPIOP-Source Participant + + + + + 4 + + + Request FSPIOP-Source participant information + + + Error code: + + + 200x + + + + + 5 + + + GET - /participants/{FSPIOP-Source} + + + Error code: + + + 200x, 310x, 320x + + + + + 6 + + + Return FSPIOP-Source participant information + + + + + 7 + + + Return FSPIOP-Source participant information + + + + + 8 + + + Validate FSPIOP-Source participant + + + Error code: + + + 320x + + + + + 9 + + + Get Participant Information for PayeeFSP + + + Error code: + + + 200x, 310x, 320x + + + + + ref + + + GET Participants - + + + + Request Participant Information from Oracle Sequence + + + + + + + 10 + + + Request Parties information from FSP. + + + Error code: + + + 200x + + + + 11 + + + Parties Callback to Destination: + + + GET - /parties/{TYPE}/{ID}?currency={CURRENCY} + + + Response code: + + + 202 + + + Error code: + + + 200x, 310x, 320x + + + + 12 + + + Callback with Participant Information: + + + PUT - /parties/{TYPE}/{ID}?currency={CURRENCY} + + + Error code: + + + 200x, 300x, 310x, 320x + + + + + 13 + + + Validate request against + + + Mojaloop Interface Specification + + + Error code: + + + 300x, 310x + + + + + 14 + + + Process Participant Callback Information for PUT + + + + + 15 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + Error code: + + + 200x + + + + + 16 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Error code: + + + 200x, 310x, 320x + + + + + 17 + + + List of PayerFSP Participant Callback Endpoints + + + + + 18 + + + List of PayerFSP Participant Callback Endpoints + + + + + 19 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTIES_PUT + + + + + 20 + + + Return Participant Information to PayerFSP + + + + 21 + + + Callback with Parties Information: + + + PUT - /parties/{TYPE}/{ID}?currency={CURRENCY} + + + + [Empty list of End-Points returned for either (PayeeFSP or Oracle) config information or Error occurred for PayerFSP] + + + + + 22 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 23 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 24 + + + List of PayerFSP Participant Callback Endpoints + + + + + 25 + + + List of PayerFSP Participant Callback Endpoints + + + + + 26 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR + + + + + 27 + + + Handle error + + + Error code: + + + 200x, 310x, 320x + + + + 28 + + + Callback: PUT - /participants/{TYPE}/{ID}/error + + + + [Empty list of End-Points returned for PayerFSP config information or Error occurred for PayeeFSP] + + + + + 29 + + + Retrieve the PayeeFSP Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 30 + + + Retrieve the PayeeFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 31 + + + List of PayeeFSP Participant Callback Endpoints + + + + + 32 + + + List of PayeeFSP Participant Callback Endpoints + + + + + 33 + + + Match PayeeFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR + + + + + 34 + + + Handle error + + + Error code: + + + 200x, 310x, 320x + + + + 35 + + + Callback: PUT - /participants/{TYPE}/{ID}/error + + + + [Empty list of switchEndpoint results returned] + + + + + 36 + + + Handle error + + + Error code: + + + 200x + + + + Error Handling Framework + + diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.plantuml b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.plantuml new file mode 100644 index 000000000..7769e3a8d --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.plantuml @@ -0,0 +1,213 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.1.3 Post Participant Details by Type and ID + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +actor "Payer FSP" as PAYER_FSP +boundary "Account Lookup\nService (ALS)" as ALS_API +control "ALS Participant\nHandler" as ALS_PARTICIPANT_HANDLER +entity "ALS CentralService\nEndpoint DAO" as ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +entity "ALS CentralService\nParticipant DAO" as ALS_CENTRALSERVICE_PARTICIPANT_DAO +entity "ALS Participant\nOracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +database "ALS Database" as ALS_DB +boundary "Oracle Service API" as ORACLE_API +boundary "Central Service API" as CENTRALSERVICE_API + +box "Financial Service Provider" #LightGrey +participant PAYER_FSP +end box + +box "Account Lookup Service" #LightYellow +participant ALS_API +participant ALS_PARTICIPANT_HANDLER +participant ALS_PARTICIPANT_ORACLE_DAO +participant ALS_DB +participant ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +participant ALS_CENTRALSERVICE_PARTICIPANT_DAO +end box + +box "Central Services" #LightGreen +participant CENTRALSERVICE_API +end box + +box "ALS Oracle Service/Adapter" #LightBlue +participant ORACLE_API +end box + +' START OF FLOW + +group Post Participant's FSP Details + note right of PAYER_FSP #yellow + Headers - postParticipantsByTypeIDHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - postParticipantsByTypeIDMessage: + { + "fspId": "string" + } + end note + PAYER_FSP ->> ALS_API: Request to add participant's FSP details\nPOST - /participants/{Type}/{ID}\nResponse code: 202 \nError code: 200x, 300x, 310x, 320x + + activate ALS_API + note left ALS_API #lightgray + Validate request against + Mojaloop Interface Specification. + Error code: 300x, 310x + end note + + ALS_API -> ALS_PARTICIPANT_HANDLER: Process create participant's FSP details + deactivate ALS_API + activate ALS_PARTICIPANT_HANDLER + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate that PARTICIPANT.fspId == FSPIOP-Source\nError code: 3100 + + '********************* Sort into Participant buckets based on {TYPE} - END ************************ + + alt Validation passed + + + '********************* Fetch Oracle Routing Information - START ************************ + + '********************* Retrieve Oracle Routing Information - START ************************ + + ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Oracle Routing Config based on Type (and optional Currency)\nError code: 300x, 310x + ref over ALS_PARTICIPANT_HANDLER, ALS_DB + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Oracle Routing Config Sequence]] + ||| + end ref + + '********************* Retrieve Oracle Routing Information - END ************************ + + ||| + +' '********************* Fetch Oracle Routing Information - END ************************ +' +' '********************* Retrieve Switch Routing Information - START ************************ +' +' ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Switch Routing Config\nError code: 300x, 310x +' ref over ALS_PARTICIPANT_HANDLER, ALS_DB +' ||| +' GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Switch Routing Config Sequence]] +' ||| +' end ref +' +' '********************* Retrieve Switch Routing Information - END ************************ +' ||| + + '********************* Validate Participant - START ************************ + group Validate Participant's FSP + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Request participant (PARTICIPANT.fspId) information for {Type}\nError code: 200x + activate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_CENTRALSERVICE_PARTICIPANT_DAO -> CENTRALSERVICE_API: GET - /participants/{PARTICIPANT.fspId}\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Return participant information + deactivate CENTRALSERVICE_API + + ALS_CENTRALSERVICE_PARTICIPANT_DAO --> ALS_PARTICIPANT_HANDLER: Return participant information + + deactivate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate participant\nError code: 320x + end group + '********************* Validate Participant - END ************************ + + '********************* Create Participant Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_ORACLE_DAO: Create participant's FSP details\nPOST - /participants\nError code: 200x, 310x, 320x + activate ALS_PARTICIPANT_ORACLE_DAO + ALS_PARTICIPANT_ORACLE_DAO -> ORACLE_API: Create participant's FSP details\nPOST - /participants\nResponse code: 204 \nError code: 200x, 310x, 320x + activate ORACLE_API + + ORACLE_API --> ALS_PARTICIPANT_ORACLE_DAO: Return result of Participant Create request + deactivate ORACLE_API + + ALS_PARTICIPANT_ORACLE_DAO --> ALS_PARTICIPANT_HANDLER: Return result of Participant Create request + deactivate ALS_PARTICIPANT_ORACLE_DAO + + '********************* Create Participant Information - END ************************ + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Return list of Participant information from ParticipantResult + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{Type}/{ID} + + else Validation failure + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{Type}/{ID}/error + end alt + + + deactivate ALS_PARTICIPANT_HANDLER +end +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.svg new file mode 100644 index 000000000..07a5a256d --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-7.1.3.svg @@ -0,0 +1,598 @@ + + + + + + + + + + + 7.1.3 Post Participant Details by Type and ID + + + + Financial Service Provider + + + + Account Lookup Service + + + + Central Services + + + + ALS Oracle Service/Adapter + + + + + + + + + Payer FSP + + + + + Payer FSP + + + + + Account Lookup + + + Service (ALS) + + + + + Account Lookup + + + Service (ALS) + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Oracle DAO + + + + + ALS Participant + + + Oracle DAO + + + + + ALS Database + + + + + ALS Database + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Participant DAO + + + + + ALS CentralService + + + Participant DAO + + + + + Central Service API + + + + + Central Service API + + + + + Oracle Service API + + + + + Oracle Service API + + + + + + + + Post Participant's FSP Details + + + + + Headers - postParticipantsByTypeIDHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - postParticipantsByTypeIDMessage: + + + { + + + "fspId": "string" + + + } + + + + 1 + + + Request to add participant's FSP details + + + POST - /participants/{Type}/{ID} + + + Response code: + + + 202 + + + Error code: + + + 200x, 300x, 310x, 320x + + + + + Validate request against + + + Mojaloop Interface Specification. + + + Error code: + + + 300x, 310x + + + + + 2 + + + Process create participant's FSP details + + + + + 3 + + + Validate that PARTICIPANT.fspId == FSPIOP-Source + + + Error code: + + + 3100 + + + + + alt + + + [Validation passed] + + + + + 4 + + + Get Oracle Routing Config based on Type (and optional Currency) + + + Error code: + + + 300x, 310x + + + + + ref + + + GET Participants - + + + + Get Oracle Routing Config Sequence + + + + + + + Validate Participant's FSP + + + + + 5 + + + Request participant (PARTICIPANT.fspId) information for {Type} + + + Error code: + + + 200x + + + + + 6 + + + GET - /participants/{PARTICIPANT.fspId} + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 7 + + + Return participant information + + + + + 8 + + + Return participant information + + + + + 9 + + + Validate participant + + + Error code: + + + 320x + + + + + 10 + + + Create participant's FSP details + + + POST - /participants + + + Error code: + + + 200x, 310x, 320x + + + + + 11 + + + Create participant's FSP details + + + POST - /participants + + + Response code: + + + 204 + + + Error code: + + + 200x, 310x, 320x + + + + + 12 + + + Return result of Participant Create request + + + + + 13 + + + Return result of Participant Create request + + + + + 14 + + + Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 15 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 16 + + + List of PayerFSP Participant Callback Endpoints + + + + + 17 + + + List of PayerFSP Participant Callback Endpoints + + + + + 18 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT + + + + + 19 + + + Return list of Participant information from ParticipantResult + + + + 20 + + + Callback: PUT - /participants/{Type}/{ID} + + + + [Validation failure] + + + + + 21 + + + Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 22 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 23 + + + List of PayerFSP Participant Callback Endpoints + + + + + 24 + + + List of PayerFSP Participant Callback Endpoints + + + + + 25 + + + Match Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR + + + + + 26 + + + Handle error + + + Error code: + + + 200x, 310x, 320x + + + + 27 + + + Callback: PUT - /participants/{Type}/{ID}/error + + diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.plantuml b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.plantuml new file mode 100644 index 000000000..c92838dc9 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.plantuml @@ -0,0 +1,238 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + -------------- + ******'/ + + +@startuml +' declare title +title 7.1.1. Post Participant (Batch) Details + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +actor "Payer FSP" as PAYER_FSP +boundary "Account Lookup\nService (ALS)" as ALS_API +control "ALS Participant\nHandler" as ALS_PARTICIPANT_HANDLER +entity "ALS CentralService\nEndpoint DAO" as ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +entity "ALS CentralService\nParticipant DAO" as ALS_CENTRALSERVICE_PARTICIPANT_DAO +entity "ALS Participant\nOracle DAO" as ALS_PARTICIPANT_ORACLE_DAO +database "ALS Database" as ALS_DB +boundary "Oracle Service API" as ORACLE_API +boundary "Central Service API" as CENTRALSERVICE_API + +box "Financial Service Provider" #LightGrey +participant PAYER_FSP +end box + +box "Account Lookup Service" #LightYellow +participant ALS_API +participant ALS_PARTICIPANT_HANDLER +participant ALS_PARTICIPANT_ORACLE_DAO +participant ALS_DB +participant ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO +participant ALS_CENTRALSERVICE_PARTICIPANT_DAO +end box + +box "Central Services" #LightGreen +participant CENTRALSERVICE_API +end box + +box "ALS Oracle Service/Adapter" #LightBlue +participant ORACLE_API +end box + +' START OF FLOW + +group Post Participant's FSP Details + note right of PAYER_FSP #yellow + Headers - postParticipantsHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - postParticipantsMessage: + { + "requestId": "string", + "partyList": [ + { + "partyIdType": "string", + "partyIdentifier": "string", + "partySubIdOrType": "string", + "fspId": "string" + } + ], + "currency": "string" + } + end note + PAYER_FSP ->> ALS_API: Request to add participant's FSP details\nPOST - /participants\nResponse code: 202 \nError code: 200x, 300x, 310x, 320x + + activate ALS_API + note left ALS_API #lightgray + Validate request against + Mojaloop Interface Specification. + Error code: 300x, 310x + end note + + ALS_API -> ALS_PARTICIPANT_HANDLER: Process create participant's FSP details + deactivate ALS_API + activate ALS_PARTICIPANT_HANDLER + + '********************* Sort into Participant buckets based on {TYPE} - START ************************ + loop for Participant in ParticipantList + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate that PARTICIPANT.fspId == FSPIOP-Source\nError code: 3100 + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Group Participant lists into a Map (ParticipantMap) based on {TYPE} + + end loop + + '********************* Sort into Participant buckets based on {TYPE} - END ************************ + + alt Validation passed and the ParticipantMap was created successfully + + loop for keys in ParticipantMap -> TypeKey + + '********************* Fetch Oracle Routing Information - START ************************ + + '********************* Retrieve Oracle Routing Information - START ************************ + + ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Oracle Routing Config based on TypeKey (and optional Currency)\nError code: 300x, 310x + ref over ALS_PARTICIPANT_HANDLER, ALS_DB + GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Oracle Routing Config Sequence]] + ||| + end ref + + '********************* Retrieve Oracle Routing Information - END ************************ + + ||| + +' '********************* Fetch Oracle Routing Information - END ************************ +' +' '********************* Retrieve Switch Routing Information - START ************************ +' +' ALS_PARTICIPANT_HANDLER <-> ALS_DB: Get Switch Routing Config\nError code: 300x, 310x +' ref over ALS_PARTICIPANT_HANDLER, ALS_DB +' ||| +' GET Participants - [[https://docs.mojaloop.live/mojaloop-technical-overview/account-lookup-service/als-get-participants.html Get Switch Routing Config Sequence]] +' ||| +' end ref +' +' '********************* Retrieve Switch Routing Information - END ************************ +' ||| + + '********************* Validate Participant - START ************************ + group Validate Participant's FSP + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Request participant (PARTICIPANT.fspId) information for {TypeKey}\nError code: 200x + activate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_CENTRALSERVICE_PARTICIPANT_DAO -> CENTRALSERVICE_API: GET - /participants/{PARTICIPANT.fspId}\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_PARTICIPANT_DAO: Return participant information + deactivate CENTRALSERVICE_API + + ALS_CENTRALSERVICE_PARTICIPANT_DAO --> ALS_PARTICIPANT_HANDLER: Return participant information + + deactivate ALS_CENTRALSERVICE_PARTICIPANT_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Validate participant\nError code: 320x + end group + '********************* Validate Participant - END ************************ + + '********************* Create Participant Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_ORACLE_DAO: Create participant's FSP details\nPOST - /participants\nError code: 200x, 310x, 320x + activate ALS_PARTICIPANT_ORACLE_DAO + ALS_PARTICIPANT_ORACLE_DAO -> ORACLE_API: Create participant's FSP details\nPOST - /participants\nResponse code: 204 \nError code: 200x, 310x, 320x + activate ORACLE_API + + ORACLE_API --> ALS_PARTICIPANT_ORACLE_DAO: Return result of Participant Create request + deactivate ORACLE_API + + ALS_PARTICIPANT_ORACLE_DAO --> ALS_PARTICIPANT_HANDLER: Return result of Participant Create request + deactivate ALS_PARTICIPANT_ORACLE_DAO + + '********************* Create Participant Information - END ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Store results in ParticipantResultMap[TypeKey] + + end loop + + loop for keys in ParticipantResultMap -> TypeKey + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Combine ParticipantResultMap[TypeKey] results into ParticipantResult + end loop + + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match PayerFSP Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Return list of Participant information from ParticipantResult + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{requestId} + + else Validation failure and/or the ParticipantMap was not created successfully + '********************* Get PayerFSP Participant End-point Information - START ************************ + + ALS_PARTICIPANT_HANDLER -> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint\nError code: 200x, 310x, 320x + activate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO -> CENTRALSERVICE_API: Retrieve the PayerFSP Participant Callback Endpoint\nGET - /participants/{FSPIOP-Source}/endpoints\nResponse code: 200 \nError code: 200x, 310x, 320x + activate CENTRALSERVICE_API + CENTRALSERVICE_API --> ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO: List of PayerFSP Participant Callback Endpoints + deactivate CENTRALSERVICE_API + ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO --> ALS_PARTICIPANT_HANDLER: List of PayerFSP Participant Callback Endpoints + deactivate ALS_CENTRALSERVICE_ENDPOINT_CONFIG_DAO + + ALS_PARTICIPANT_HANDLER -> ALS_PARTICIPANT_HANDLER: Match Participant Callback Endpoints for\nFSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR + + '********************* Get PayerFSP Participant End-point Information - END ************************ + + ALS_PARTICIPANT_HANDLER --> ALS_API: Handle error\nError code: 200x, 310x, 320x + ALS_API ->> PAYER_FSP: Callback: PUT - /participants/{requestId}/error + end alt + + + deactivate ALS_PARTICIPANT_HANDLER +end +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.svg b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.svg new file mode 100644 index 000000000..e3883aba0 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/diagrams/sequence/seq-acct-lookup-post-participants-batch-7.1.1.svg @@ -0,0 +1,674 @@ + + + + + + + + + + + 7.1.1. Post Participant (Batch) Details + + + + Financial Service Provider + + + + Account Lookup Service + + + + Central Services + + + + ALS Oracle Service/Adapter + + + + + + + + + + Payer FSP + + + + + Payer FSP + + + + + Account Lookup + + + Service (ALS) + + + + + Account Lookup + + + Service (ALS) + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Handler + + + + + ALS Participant + + + Oracle DAO + + + + + ALS Participant + + + Oracle DAO + + + + + ALS Database + + + + + ALS Database + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Endpoint DAO + + + + + ALS CentralService + + + Participant DAO + + + + + ALS CentralService + + + Participant DAO + + + + + Central Service API + + + + + Central Service API + + + + + Oracle Service API + + + + + Oracle Service API + + + + + + + + Post Participant's FSP Details + + + + + Headers - postParticipantsHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - postParticipantsMessage: + + + { + + + "requestId": "string", + + + "partyList": [ + + + { + + + "partyIdType": "string", + + + "partyIdentifier": "string", + + + "partySubIdOrType": "string", + + + "fspId": "string" + + + } + + + ], + + + "currency": "string" + + + } + + + + 1 + + + Request to add participant's FSP details + + + POST - /participants + + + Response code: + + + 202 + + + Error code: + + + 200x, 300x, 310x, 320x + + + + + Validate request against + + + Mojaloop Interface Specification. + + + Error code: + + + 300x, 310x + + + + + 2 + + + Process create participant's FSP details + + + + + loop + + + [for Participant in ParticipantList] + + + + + 3 + + + Validate that PARTICIPANT.fspId == FSPIOP-Source + + + Error code: + + + 3100 + + + + + 4 + + + Group Participant lists into a Map (ParticipantMap) based on {TYPE} + + + + + alt + + + [Validation passed and the ParticipantMap was created successfully] + + + + + loop + + + [for keys in ParticipantMap -> TypeKey] + + + + + 5 + + + Get Oracle Routing Config based on TypeKey (and optional Currency) + + + Error code: + + + 300x, 310x + + + + + ref + + + GET Participants - + + + + Get Oracle Routing Config Sequence + + + + + + + Validate Participant's FSP + + + + + 6 + + + Request participant (PARTICIPANT.fspId) information for {TypeKey} + + + Error code: + + + 200x + + + + + 7 + + + GET - /participants/{PARTICIPANT.fspId} + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 8 + + + Return participant information + + + + + 9 + + + Return participant information + + + + + 10 + + + Validate participant + + + Error code: + + + 320x + + + + + 11 + + + Create participant's FSP details + + + POST - /participants + + + Error code: + + + 200x, 310x, 320x + + + + + 12 + + + Create participant's FSP details + + + POST - /participants + + + Response code: + + + 204 + + + Error code: + + + 200x, 310x, 320x + + + + + 13 + + + Return result of Participant Create request + + + + + 14 + + + Return result of Participant Create request + + + + + 15 + + + Store results in ParticipantResultMap[TypeKey] + + + + + loop + + + [for keys in ParticipantResultMap -> TypeKey] + + + + + 16 + + + Combine ParticipantResultMap[TypeKey] results into ParticipantResult + + + + + 17 + + + Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 18 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 19 + + + List of PayerFSP Participant Callback Endpoints + + + + + 20 + + + List of PayerFSP Participant Callback Endpoints + + + + + 21 + + + Match PayerFSP Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT + + + + + 22 + + + Return list of Participant information from ParticipantResult + + + + 23 + + + Callback: PUT - /participants/{requestId} + + + + [Validation failure and/or the ParticipantMap was not created successfully] + + + + + 24 + + + Retrieve the PayerFSP (FSPIOP-Source) Participant Callback Endpoint + + + Error code: + + + 200x, 310x, 320x + + + + + 25 + + + Retrieve the PayerFSP Participant Callback Endpoint + + + GET - /participants/{FSPIOP-Source}/endpoints + + + Response code: + + + 200 + + + Error code: + + + 200x, 310x, 320x + + + + + 26 + + + List of PayerFSP Participant Callback Endpoints + + + + + 27 + + + List of PayerFSP Participant Callback Endpoints + + + + + 28 + + + Match Participant Callback Endpoints for + + + FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR + + + + + 29 + + + Handle error + + + Error code: + + + 200x, 310x, 320x + + + + 30 + + + Callback: PUT - /participants/{requestId}/error + + diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/entities/AccountLookup-ddl-MySQLWorkbench.sql b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/entities/AccountLookup-ddl-MySQLWorkbench.sql new file mode 100644 index 000000000..e538b6351 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/entities/AccountLookup-ddl-MySQLWorkbench.sql @@ -0,0 +1,195 @@ +-- MySQL dump 10.13 Distrib 5.7.17, for macos10.12 (x86_64) +-- +-- Host: 127.0.0.1 Database: account_lookup +-- ------------------------------------------------------ +-- Server version 8.0.12 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `currency` +-- + +DROP TABLE IF EXISTS `currency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `currency` ( + `currencyId` varchar(3) NOT NULL, + `name` varchar(128) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`currencyId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `currency` +-- + +LOCK TABLES `currency` WRITE; +/*!40000 ALTER TABLE `currency` DISABLE KEYS */; +INSERT INTO `currency` VALUES ('AED','UAE dirham',1,'2019-03-28 09:07:47'),('AFA','Afghanistan afghani (obsolete)',1,'2019-03-28 09:07:47'),('AFN','Afghanistan afghani',1,'2019-03-28 09:07:47'),('ALL','Albanian lek',1,'2019-03-28 09:07:47'),('AMD','Armenian dram',1,'2019-03-28 09:07:47'),('ANG','Netherlands Antillian guilder',1,'2019-03-28 09:07:47'),('AOA','Angolan kwanza',1,'2019-03-28 09:07:47'),('AOR','Angolan kwanza reajustado',1,'2019-03-28 09:07:47'),('ARS','Argentine peso',1,'2019-03-28 09:07:47'),('AUD','Australian dollar',1,'2019-03-28 09:07:47'),('AWG','Aruban guilder',1,'2019-03-28 09:07:47'),('AZN','Azerbaijanian new manat',1,'2019-03-28 09:07:47'),('BAM','Bosnia-Herzegovina convertible mark',1,'2019-03-28 09:07:47'),('BBD','Barbados dollar',1,'2019-03-28 09:07:47'),('BDT','Bangladeshi taka',1,'2019-03-28 09:07:47'),('BGN','Bulgarian lev',1,'2019-03-28 09:07:47'),('BHD','Bahraini dinar',1,'2019-03-28 09:07:47'),('BIF','Burundi franc',1,'2019-03-28 09:07:47'),('BMD','Bermudian dollar',1,'2019-03-28 09:07:47'),('BND','Brunei dollar',1,'2019-03-28 09:07:47'),('BOB','Bolivian boliviano',1,'2019-03-28 09:07:47'),('BRL','Brazilian real',1,'2019-03-28 09:07:47'),('BSD','Bahamian dollar',1,'2019-03-28 09:07:47'),('BTN','Bhutan ngultrum',1,'2019-03-28 09:07:47'),('BWP','Botswana pula',1,'2019-03-28 09:07:47'),('BYN','Belarusian ruble',1,'2019-03-28 09:07:47'),('BZD','Belize dollar',1,'2019-03-28 09:07:47'),('CAD','Canadian dollar',1,'2019-03-28 09:07:47'),('CDF','Congolese franc',1,'2019-03-28 09:07:47'),('CHF','Swiss franc',1,'2019-03-28 09:07:47'),('CLP','Chilean peso',1,'2019-03-28 09:07:47'),('CNY','Chinese yuan renminbi',1,'2019-03-28 09:07:47'),('COP','Colombian peso',1,'2019-03-28 09:07:47'),('CRC','Costa Rican colon',1,'2019-03-28 09:07:47'),('CUC','Cuban convertible peso',1,'2019-03-28 09:07:47'),('CUP','Cuban peso',1,'2019-03-28 09:07:47'),('CVE','Cape Verde escudo',1,'2019-03-28 09:07:47'),('CZK','Czech koruna',1,'2019-03-28 09:07:47'),('DJF','Djibouti franc',1,'2019-03-28 09:07:47'),('DKK','Danish krone',1,'2019-03-28 09:07:47'),('DOP','Dominican peso',1,'2019-03-28 09:07:47'),('DZD','Algerian dinar',1,'2019-03-28 09:07:47'),('EEK','Estonian kroon',1,'2019-03-28 09:07:47'),('EGP','Egyptian pound',1,'2019-03-28 09:07:47'),('ERN','Eritrean nakfa',1,'2019-03-28 09:07:47'),('ETB','Ethiopian birr',1,'2019-03-28 09:07:47'),('EUR','EU euro',1,'2019-03-28 09:07:47'),('FJD','Fiji dollar',1,'2019-03-28 09:07:47'),('FKP','Falkland Islands pound',1,'2019-03-28 09:07:47'),('GBP','British pound',1,'2019-03-28 09:07:47'),('GEL','Georgian lari',1,'2019-03-28 09:07:47'),('GGP','Guernsey pound',1,'2019-03-28 09:07:47'),('GHS','Ghanaian new cedi',1,'2019-03-28 09:07:47'),('GIP','Gibraltar pound',1,'2019-03-28 09:07:47'),('GMD','Gambian dalasi',1,'2019-03-28 09:07:47'),('GNF','Guinean franc',1,'2019-03-28 09:07:47'),('GTQ','Guatemalan quetzal',1,'2019-03-28 09:07:47'),('GYD','Guyana dollar',1,'2019-03-28 09:07:47'),('HKD','Hong Kong SAR dollar',1,'2019-03-28 09:07:47'),('HNL','Honduran lempira',1,'2019-03-28 09:07:47'),('HRK','Croatian kuna',1,'2019-03-28 09:07:47'),('HTG','Haitian gourde',1,'2019-03-28 09:07:47'),('HUF','Hungarian forint',1,'2019-03-28 09:07:47'),('IDR','Indonesian rupiah',1,'2019-03-28 09:07:47'),('ILS','Israeli new shekel',1,'2019-03-28 09:07:47'),('IMP','Isle of Man pound',1,'2019-03-28 09:07:47'),('INR','Indian rupee',1,'2019-03-28 09:07:47'),('IQD','Iraqi dinar',1,'2019-03-28 09:07:47'),('IRR','Iranian rial',1,'2019-03-28 09:07:47'),('ISK','Icelandic krona',1,'2019-03-28 09:07:47'),('JEP','Jersey pound',1,'2019-03-28 09:07:47'),('JMD','Jamaican dollar',1,'2019-03-28 09:07:47'),('JOD','Jordanian dinar',1,'2019-03-28 09:07:47'),('JPY','Japanese yen',1,'2019-03-28 09:07:47'),('KES','Kenyan shilling',1,'2019-03-28 09:07:47'),('KGS','Kyrgyz som',1,'2019-03-28 09:07:47'),('KHR','Cambodian riel',1,'2019-03-28 09:07:47'),('KMF','Comoros franc',1,'2019-03-28 09:07:47'),('KPW','North Korean won',1,'2019-03-28 09:07:47'),('KRW','South Korean won',1,'2019-03-28 09:07:47'),('KWD','Kuwaiti dinar',1,'2019-03-28 09:07:47'),('KYD','Cayman Islands dollar',1,'2019-03-28 09:07:47'),('KZT','Kazakh tenge',1,'2019-03-28 09:07:47'),('LAK','Lao kip',1,'2019-03-28 09:07:47'),('LBP','Lebanese pound',1,'2019-03-28 09:07:47'),('LKR','Sri Lanka rupee',1,'2019-03-28 09:07:47'),('LRD','Liberian dollar',1,'2019-03-28 09:07:47'),('LSL','Lesotho loti',1,'2019-03-28 09:07:47'),('LTL','Lithuanian litas',1,'2019-03-28 09:07:47'),('LVL','Latvian lats',1,'2019-03-28 09:07:47'),('LYD','Libyan dinar',1,'2019-03-28 09:07:47'),('MAD','Moroccan dirham',1,'2019-03-28 09:07:47'),('MDL','Moldovan leu',1,'2019-03-28 09:07:47'),('MGA','Malagasy ariary',1,'2019-03-28 09:07:47'),('MKD','Macedonian denar',1,'2019-03-28 09:07:47'),('MMK','Myanmar kyat',1,'2019-03-28 09:07:47'),('MNT','Mongolian tugrik',1,'2019-03-28 09:07:47'),('MOP','Macao SAR pataca',1,'2019-03-28 09:07:47'),('MRO','Mauritanian ouguiya',1,'2019-03-28 09:07:47'),('MUR','Mauritius rupee',1,'2019-03-28 09:07:47'),('MVR','Maldivian rufiyaa',1,'2019-03-28 09:07:47'),('MWK','Malawi kwacha',1,'2019-03-28 09:07:47'),('MXN','Mexican peso',1,'2019-03-28 09:07:47'),('MYR','Malaysian ringgit',1,'2019-03-28 09:07:47'),('MZN','Mozambique new metical',1,'2019-03-28 09:07:47'),('NAD','Namibian dollar',1,'2019-03-28 09:07:47'),('NGN','Nigerian naira',1,'2019-03-28 09:07:47'),('NIO','Nicaraguan cordoba oro',1,'2019-03-28 09:07:47'),('NOK','Norwegian krone',1,'2019-03-28 09:07:47'),('NPR','Nepalese rupee',1,'2019-03-28 09:07:47'),('NZD','New Zealand dollar',1,'2019-03-28 09:07:47'),('OMR','Omani rial',1,'2019-03-28 09:07:47'),('PAB','Panamanian balboa',1,'2019-03-28 09:07:47'),('PEN','Peruvian nuevo sol',1,'2019-03-28 09:07:47'),('PGK','Papua New Guinea kina',1,'2019-03-28 09:07:47'),('PHP','Philippine peso',1,'2019-03-28 09:07:47'),('PKR','Pakistani rupee',1,'2019-03-28 09:07:47'),('PLN','Polish zloty',1,'2019-03-28 09:07:47'),('PYG','Paraguayan guarani',1,'2019-03-28 09:07:47'),('QAR','Qatari rial',1,'2019-03-28 09:07:47'),('RON','Romanian new leu',1,'2019-03-28 09:07:47'),('RSD','Serbian dinar',1,'2019-03-28 09:07:47'),('RUB','Russian ruble',1,'2019-03-28 09:07:47'),('RWF','Rwandan franc',1,'2019-03-28 09:07:47'),('SAR','Saudi riyal',1,'2019-03-28 09:07:47'),('SBD','Solomon Islands dollar',1,'2019-03-28 09:07:47'),('SCR','Seychelles rupee',1,'2019-03-28 09:07:47'),('SDG','Sudanese pound',1,'2019-03-28 09:07:47'),('SEK','Swedish krona',1,'2019-03-28 09:07:47'),('SGD','Singapore dollar',1,'2019-03-28 09:07:47'),('SHP','Saint Helena pound',1,'2019-03-28 09:07:47'),('SLL','Sierra Leone leone',1,'2019-03-28 09:07:47'),('SOS','Somali shilling',1,'2019-03-28 09:07:47'),('SPL','Seborgan luigino',1,'2019-03-28 09:07:47'),('SRD','Suriname dollar',1,'2019-03-28 09:07:47'),('STD','Sao Tome and Principe dobra',1,'2019-03-28 09:07:47'),('SVC','El Salvador colon',1,'2019-03-28 09:07:47'),('SYP','Syrian pound',1,'2019-03-28 09:07:47'),('SZL','Swaziland lilangeni',1,'2019-03-28 09:07:47'),('THB','Thai baht',1,'2019-03-28 09:07:47'),('TJS','Tajik somoni',1,'2019-03-28 09:07:47'),('TMT','Turkmen new manat',1,'2019-03-28 09:07:47'),('TND','Tunisian dinar',1,'2019-03-28 09:07:47'),('TOP','Tongan pa\'anga',1,'2019-03-28 09:07:47'),('TRY','Turkish lira',1,'2019-03-28 09:07:47'),('TTD','Trinidad and Tobago dollar',1,'2019-03-28 09:07:47'),('TVD','Tuvaluan dollar',1,'2019-03-28 09:07:47'),('TWD','Taiwan New dollar',1,'2019-03-28 09:07:47'),('TZS','Tanzanian shilling',1,'2019-03-28 09:07:47'),('UAH','Ukrainian hryvnia',1,'2019-03-28 09:07:47'),('UGX','Uganda new shilling',1,'2019-03-28 09:07:47'),('USD','US dollar',1,'2019-03-28 09:07:47'),('UYU','Uruguayan peso uruguayo',1,'2019-03-28 09:07:47'),('UZS','Uzbekistani sum',1,'2019-03-28 09:07:47'),('VEF','Venezuelan bolivar fuerte',1,'2019-03-28 09:07:47'),('VND','Vietnamese dong',1,'2019-03-28 09:07:47'),('VUV','Vanuatu vatu',1,'2019-03-28 09:07:47'),('WST','Samoan tala',1,'2019-03-28 09:07:47'),('XAF','CFA franc BEAC',1,'2019-03-28 09:07:47'),('XAG','Silver (ounce)',1,'2019-03-28 09:07:47'),('XAU','Gold (ounce)',1,'2019-03-28 09:07:47'),('XCD','East Caribbean dollar',1,'2019-03-28 09:07:47'),('XDR','IMF special drawing right',1,'2019-03-28 09:07:47'),('XFO','Gold franc',1,'2019-03-28 09:07:47'),('XFU','UIC franc',1,'2019-03-28 09:07:47'),('XOF','CFA franc BCEAO',1,'2019-03-28 09:07:47'),('XPD','Palladium (ounce)',1,'2019-03-28 09:07:47'),('XPF','CFP franc',1,'2019-03-28 09:07:47'),('XPT','Platinum (ounce)',1,'2019-03-28 09:07:47'),('YER','Yemeni rial',1,'2019-03-28 09:07:47'),('ZAR','South African rand',1,'2019-03-28 09:07:47'),('ZMK','Zambian kwacha (obsolete)',1,'2019-03-28 09:07:47'),('ZMW','Zambian kwacha',1,'2019-03-28 09:07:47'),('ZWD','Zimbabwe dollar (initial)',1,'2019-03-28 09:07:47'),('ZWL','Zimbabwe dollar (3rd denomination)',1,'2019-03-28 09:07:47'),('ZWN','Zimbabwe dollar (1st denomination)',1,'2019-03-28 09:07:47'),('ZWR','Zimbabwe dollar (2nd denomination)',1,'2019-03-28 09:07:47'); +/*!40000 ALTER TABLE `currency` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `endpointType` +-- + +DROP TABLE IF EXISTS `endpointType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `endpointType` ( + `endpointTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `type` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`endpointTypeId`), + UNIQUE KEY `endpointtype_type_unique` (`type`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `endpointType` +-- + +LOCK TABLES `endpointType` WRITE; +/*!40000 ALTER TABLE `endpointType` DISABLE KEYS */; +INSERT INTO `endpointType` VALUES (1,'URL','REST URLs',1,'2019-03-28 09:07:47'); +/*!40000 ALTER TABLE `endpointType` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `migration` +-- + +DROP TABLE IF EXISTS `migration`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `migration` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `batch` int(11) DEFAULT NULL, + `migration_time` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `migration` +-- + +LOCK TABLES `migration` WRITE; +/*!40000 ALTER TABLE `migration` DISABLE KEYS */; +INSERT INTO `migration` VALUES (1,'01_currency.js',1,'2019-03-28 11:07:46'),(2,'02_endpointType.js',1,'2019-03-28 11:07:46'),(3,'03_endpointType-indexes.js',1,'2019-03-28 11:07:46'),(4,'04_partyIdType.js',1,'2019-03-28 11:07:46'),(5,'05_partyIdType-indexes.js',1,'2019-03-28 11:07:46'),(6,'08_oracleEndpoint.js',1,'2019-03-28 11:07:47'),(7,'09_oracleEndpoint-indexes.js',1,'2019-03-28 11:07:47'); +/*!40000 ALTER TABLE `migration` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `migration_lock` +-- + +DROP TABLE IF EXISTS `migration_lock`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `migration_lock` ( + `index` int(10) unsigned NOT NULL AUTO_INCREMENT, + `is_locked` int(11) DEFAULT NULL, + PRIMARY KEY (`index`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `migration_lock` +-- + +LOCK TABLES `migration_lock` WRITE; +/*!40000 ALTER TABLE `migration_lock` DISABLE KEYS */; +INSERT INTO `migration_lock` VALUES (1,0); +/*!40000 ALTER TABLE `migration_lock` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `oracleEndpoint` +-- + +DROP TABLE IF EXISTS `oracleEndpoint`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `oracleEndpoint` ( + `oracleEndpointId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `partyIdTypeId` int(10) unsigned NOT NULL, + `endpointTypeId` int(10) unsigned NOT NULL, + `currencyId` varchar(255) DEFAULT NULL, + `value` varchar(512) NOT NULL, + `isDefault` tinyint(1) NOT NULL DEFAULT '0', + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`oracleEndpointId`), + KEY `oracleendpoint_currencyid_foreign` (`currencyId`), + KEY `oracleendpoint_partyidtypeid_index` (`partyIdTypeId`), + KEY `oracleendpoint_endpointtypeid_index` (`endpointTypeId`), + CONSTRAINT `oracleendpoint_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `oracleendpoint_endpointtypeid_foreign` FOREIGN KEY (`endpointTypeId`) REFERENCES `endpointType` (`endpointtypeid`), + CONSTRAINT `oracleendpoint_partyidtypeid_foreign` FOREIGN KEY (`partyIdTypeId`) REFERENCES `partyIdType` (`partyidtypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `oracleEndpoint` +-- + +LOCK TABLES `oracleEndpoint` WRITE; +/*!40000 ALTER TABLE `oracleEndpoint` DISABLE KEYS */; +/*!40000 ALTER TABLE `oracleEndpoint` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `partyIdType` +-- + +DROP TABLE IF EXISTS `partyIdType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `partyIdType` ( + `partyIdTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL, + `description` varchar(512) NOT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`partyIdTypeId`), + UNIQUE KEY `partyidtype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `partyIdType` +-- + +LOCK TABLES `partyIdType` WRITE; +/*!40000 ALTER TABLE `partyIdType` DISABLE KEYS */; +INSERT INTO `partyIdType` VALUES (1,'MSISDN','A MSISDN (Mobile Station International Subscriber Directory Number, that is, the phone number) is used as reference to a participant. The MSISDN identifier should be in international format according to the ITU-T E.164 standard. Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix.',1,'2019-03-28 09:07:47'),(2,'EMAIL','An email is used as reference to a participant. The format of the email should be according to the informational RFC 3696.',1,'2019-03-28 09:07:47'),(3,'PERSONAL_ID','A personal identifier is used as reference to a participant. Examples of personal identification are passport number, birth certificate number, and national registration number. The identifier number is added in the PartyIdentifier element. The personal identifier type is added in the PartySubIdOrType element.',1,'2019-03-28 09:07:47'),(4,'BUSINESS','A specific Business (for example, an organization or a company) is used as reference to a participant. The BUSINESS identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the PartySubIdOrType element should be used.',1,'2019-03-28 09:07:47'),(5,'DEVICE','A specific device (for example, a POS or ATM) ID connected to a specific business or organization is used as reference to a Party. For referencing a specific device under a specific business or organization, use the PartySubIdOrType element.',1,'2019-03-28 09:07:47'),(6,'ACCOUNT_ID','A bank account number or FSP account ID should be used as reference to a participant. The ACCOUNT_ID identifier can be in any format, as formats can greatly differ depending on country and FSP.',1,'2019-03-28 09:07:47'),(7,'IBAN','A bank account number or FSP account ID is used as reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without whitespace.',1,'2019-03-28 09:07:47'),(8,'ALIAS','An alias is used as reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias is a username in the FSP system. The ALIAS identifier can be in any format. It is also possible to use the PartySubIdOrType element for identifying an account under an Alias defined by the PartyIdentifier.',1,'2019-03-28 09:07:47'); +/*!40000 ALTER TABLE `partyIdType` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2019-03-28 11:09:54 diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/entities/AccountLookupDB-schema-DBeaver.erd b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/entities/AccountLookupDB-schema-DBeaver.erd new file mode 100644 index 000000000..ea177ae89 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/entities/AccountLookupDB-schema-DBeaver.erd @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/entities/AccountLookupService-schema.png b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/entities/AccountLookupService-schema.png new file mode 100644 index 000000000..bdca208cd Binary files /dev/null and b/website/versioned_docs/v1.0.1/technical/account-lookup-service/assets/entities/AccountLookupService-schema.png differ diff --git a/website/versioned_docs/v1.0.1/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI5.svg b/website/versioned_docs/v1.0.1/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI5.svg new file mode 100644 index 000000000..d87484a3c --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI5.svg @@ -0,0 +1,3 @@ + + +
    Mojaloop Adapter
    Mojaloop Adapter
    Central-Ledger
    Central-Ledger
    Mojaloop
    Adapter
    [Not supported by viewer]
    C 1. Transfer
    C 1. Transfer
    request_to_prepare
    request_to_prepare
    C 1.2
    [Not supported by viewer]
    C 1.3
    [Not supported by viewer]
    prepared.notification
    prepared.notification
    C 1.4
    C 1.4
    fulfiled.notification
    fulfiled.notification
    request_to_fulfil
    request_to_fulfil
    Fulfil Transfer
    Fulfil Transfer
    C 1.8
    C 1.8
    C 1.9
    [Not supported by viewer]
    C 1.10
    [Not supported by viewer]
    C 1.11
    C 1.11
    C 1.12 Fulfil Notify
    C 1.12 Fulfil Notify
    C 1.1
    C 1.1
    C 1.5
    C 1.5
    DB
    DB
    Mojaloop
    Open Source Services
    [Not supported by viewer]
    positions
    positions
    Account Lookup Service
    (Parties / Participant)
    [Not supported by viewer]
    FSP
    Backend

    (Does not natively speak Mojaloop API)



    [Not supported by viewer]
    Scheme-Adapter

    (Converts from Mojaloop API to backend FSP API)
    [Not supported by viewer]
    A 2. MSISDN
    based lookup
    A 2. MSISDN <br>based lookup
    DB
    DB
     Database
     Database
    FSP
    Backend
      

    (Natively speaks Mojaloop API)



    [Not supported by viewer]
    A
    A
    A 1. User Lookup
    A 1. User Lookup
    A 3. Receiver Details
    A 3. Receiver Details
    B
    B
    Merchant 
    Registry
    [Not supported by viewer]
    A 2. mID based
    lookup
    A 2. mID based <br>lookup
    B 1. Quote
    B 1. Quote
    Mojaloop Hub
    <font>Mojaloop Hub<br></font>
    Payer FSP
    [Not supported by viewer]
    Payee FSP
    [Not supported by viewer]
    Ledger
    Ledger<br>
    Ledger
    Ledger<br>
    C
    C
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    C 1.6
    Prepare
    Transfer
    [Not supported by viewer]
    C 1.7
    C 1.7
    C 1.11
    C 1.11
    C 1.12
    C 1.12
    Fulfil Notify
    Fulfil Notify
    C 1.13
    Fulfil Notify
    [Not supported by viewer]
    B 2. Fee /
    Commission
    [Not supported by viewer]
    A 4. Get 
    receiver 
    details
    [Not supported by viewer]
    B 1. Quote
    B 1. Quote
    D 6.
    D 6.
    Central-Settlement
    Central-Settlement
    D 5. Update Positions
    [Not supported by viewer]
    settlement.notifications
    settlement.notifications
    kafka
    kafka
    Scheme Settlement Processor
    <span>Scheme Settlement Processor</span><br>
    Hub Operator
    Hub Operator
    D 1. Create
    Settlement
    [Not supported by viewer]
    D
    D
    D 2. Query
    Settlement
    Report
    (Pull)
    [Not supported by viewer]
    D 4. Send
    Acks
    (Push)
    [Not supported by viewer]
    Settlement
    Bank
    Settlement<br>Bank<br>
    D 3. Process Settlements
    [Not supported by viewer]
    Bank
    [Not supported by viewer]
    D 7. Position Notifications Change result
    D 7. Position Notifications Change result
    D 7. Settlement Notification
    D 7. Settlement Notification
    kafka
    kafka
    GSMA
    [Not supported by viewer]
    (Schema customised by Hub Operator)
    [Not supported by viewer]
    Pathfinder
    [Not supported by viewer]
    ALS Oracle MSISDN Adapter
    [Not supported by viewer]
    ALS Oracle Merchant Service
    [Not supported by viewer]
    API
    Internal Use-Only
    API <br>Internal Use-Only
    Mojaloop API
    Specification v1.0
    Mojaloop API<br>Specification v1.0<br>
    Key
    [Not supported by viewer]
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg b/website/versioned_docs/v1.0.1/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg new file mode 100644 index 000000000..f75130984 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-PI6.svg @@ -0,0 +1,3 @@ + + +
    Mojaloop Adapter
    Mojaloop Adapter
    Central-Services
    (Ledger - API, Handlers)
    Central-Services<br>(Ledger - API, Handlers)<br>
    Mojaloop
    Adapter
    [Not supported by viewer]
    C 1. Transfer
    C 1. Transfer
    request_to_prepare
    request_to_prepare
    C 1.2
    [Not supported by viewer]
    C 1.3
    [Not supported by viewer]
    prepared.notification
    prepared.notification
    C 1.4
    C 1.4
    fulfiled.notification
    fulfiled.notification
    request_to_fulfil
    request_to_fulfil
    Fulfil Transfer
    Fulfil Transfer
    C 1.8
    C 1.8
    C 1.9
    [Not supported by viewer]
    C 1.10
    [Not supported by viewer]
    C 1.11
    C 1.11
    C 1.12 Fulfil Notify
    C 1.12 Fulfil Notify
    C 1.1
    C 1.1
    C 1.5
    C 1.5
    DB
    DB
    Mojaloop
    Open Source Services
    [Not supported by viewer]
    positions
    positions
    Account Lookup Service
    (Parties / Participant)
    [Not supported by viewer]
    FSP
    Backend

    (Does not natively speak Mojaloop API)



    [Not supported by viewer]
    Scheme-Adapter

    (Converts from Mojaloop API to backend FSP API)
    [Not supported by viewer]
    A 2. MSISDN
    based lookup
    A 2. MSISDN <br>based lookup
    DB
    DB
     Database
     Database
    FSP
    Backend
      

    (Natively speaks Mojaloop API)



    [Not supported by viewer]
    A
    A
    A 1. User Lookup
    A 1. User Lookup
    A 3. Receiver Details
    A 3. Receiver Details
    B
    B
    Merchant 
    Registry
    [Not supported by viewer]
    A 2. mID based
    lookup
    A 2. mID based <br>lookup
    B 1. Quote
    B 1. Quote
    Mojaloop Hub
    <font>Mojaloop Hub<br></font>
    Payer FSP
    [Not supported by viewer]
    Payee FSP
    [Not supported by viewer]
    Ledger
    Ledger<br>
    Ledger
    Ledger<br>
    C
    C
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    kafka
    C 1.6
    Prepare
    Transfer
    [Not supported by viewer]
    C 1.7
    C 1.7
    C 1.11
    C 1.11
    C 1.12
    C 1.12
    Fulfil Notify
    Fulfil Notify
    C 1.13
    Fulfil Notify
    [Not supported by viewer]
    B 2. Fee /
    Commission
    [Not supported by viewer]
    A 4. Get 
    receiver 
    details
    [Not supported by viewer]
    B 1. Quote
    B 1. Quote
    D 6.
    D 6.
    Central-Settlement
    Central-Settlement
    D 5. Update Positions
    [Not supported by viewer]
    settlement.notifications
    settlement.notifications
    kafka
    kafka
    Scheme Settlement Processor
    <span>Scheme Settlement Processor</span><br>
    Hub Operator
    Hub Operator
    D 1. Create
    Settlement
    [Not supported by viewer]
    D
    D
    D 2. Query
    Settlement
    Report
    (Pull)
    [Not supported by viewer]
    D 4. Send
    Acks
    (Push)
    [Not supported by viewer]
    Settlement
    Bank
    Settlement<br>Bank<br>
    D 3. Process Settlements
    [Not supported by viewer]
    Bank
    [Not supported by viewer]
    D 7. Position Notifications Change result
    D 7. Position Notifications Change result
    D 7. Settlement Notification
    D 7. Settlement Notification
    kafka
    kafka
    GSMA
    [Not supported by viewer]
    (Schema customised by Hub Operator)
    [Not supported by viewer]
    Pathfinder
    [Not supported by viewer]
    ALS Oracle MSISDN Adapter
    [Not supported by viewer]
    ALS Oracle Merchant Service
    [Not supported by viewer]
    API
    Internal Use-Only
    API <br>Internal Use-Only
    Mojaloop API
    Specification v1.0
    Mojaloop API<br>Specification v1.0<br>
    Key
    [Not supported by viewer]
    Quoting-Service
    Quoting-Service
    ALS Oracle Simulator
    [Not supported by viewer]
    A 2. *ID based
    lookup
    A 2. *ID based <br>lookup
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-simple.svg b/website/versioned_docs/v1.0.1/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-simple.svg new file mode 100644 index 000000000..a2fbbe512 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/assets/diagrams/architecture/Arch-Mojaloop-end-to-end-simple.svg @@ -0,0 +1,3 @@ + + +
    C 4. Transfer
    Fulfil Notify
    [Not supported by viewer]
    Account Lookup Services
    [Not supported by viewer]
    Pathfinder
    Pathfinder
    FSP
    Backend


    (Does not natively speak Mojaloop API)








    [Not supported by viewer]
    S
    c
    h
    e
    m
    e

    A
    d
    a
    p
    t
    e
    r

    [Not supported by viewer]
    A 2. MSISDN based lookup
    A 2. MSISDN based lookup
    FSP
    Backend
      

    (Natively speaks Mojaloop API)









    [Not supported by viewer]
    A
    A
    A 1. User
    Lookup
    A 1. User <br>Lookup
    B
    B
    Merchant 
    Registry
    [Not supported by viewer]
    A 2. mID based lookup
    A 2. mID based lookup
    Mojaloop Hub
    [Not supported by viewer]
    Payer FSP
    [Not supported by viewer]
    Payee FSP
    [Not supported by viewer]
    Ledger
    Ledger<br>
    Ledger
    Ledger<br>
    C
    C
    C 1. Transfer
        Prepare
    [Not supported by viewer]
    A 3. Receiver
    Details
    A 3. Receiver<br>Details<br>
     Fee /
    Comm
    [Not supported by viewer]
    Get Receiver
    Details
    [Not supported by viewer]
     C 2. Transfer
    Prepare
    [Not supported by viewer]
    C 5. Transfer
    Fulfil Notify
    [Not supported by viewer]
    Transfer
    Prepare
    [Not supported by viewer]
    C 3. Transfer
    Fulfil
    C 3. Transfer<br>Fulfil<br>
    Transfer
    Fulfil
    [Not supported by viewer]
    B 1. Quote
    B 1. Quote
    Central Services
    [Not supported by viewer]
    B 1. Quote
    B 1. Quote<br>
    Settlement Provider
    Settlement Provider
    Hub Operator
    Hub Operator
    D 1. Create Settlement
    D 1. Create Settlement
    D
    D
    D 2. Query Settlement Report
    (Pull)
    D 2. Query Settlement Report<br>(Pull)<br>
    D 3. Send Acknowledgements
    (Push)
    D 3. Send Acknowledgements<br>(Push)<br>
    Quoting Service
    <font style="font-size: 18px">Quoting Service</font>
    Central Services
    • Transfers
    • Settlements
    • Auditing
    • Notifications
    [Not supported by viewer]
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/assets/diagrams/architecture/central_ledger_block_diagram.png b/website/versioned_docs/v1.0.1/technical/assets/diagrams/architecture/central_ledger_block_diagram.png new file mode 100644 index 000000000..48199cf3e Binary files /dev/null and b/website/versioned_docs/v1.0.1/technical/assets/diagrams/architecture/central_ledger_block_diagram.png differ diff --git a/website/versioned_docs/v1.0.1/technical/central-event-processor/README.md b/website/versioned_docs/v1.0.1/technical/central-event-processor/README.md new file mode 100644 index 000000000..45b2203f8 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/central-event-processor/README.md @@ -0,0 +1,13 @@ +# Central Event Processor Service + +The Central Event Processor (CEP) service provides the capability to monitor for a pre-defined/configured set of business rules or patterns. + +In the current iteration, the rules are set to monitor for three criteria: + + 1. Breaching of a threshold on the Limit of Net Debit Cap (which may be set as part of on-boarding), + 2. Adjustment of the limit - Net Debit Cap, + 3. Adjust of position based on a Settlement. + +The CEP can then be integrated with a notifier service, to send out notifications or alerts. In this instance, it integrates with the email-notifier to send out alerts based on the aforementioned criteria. + +![Central Event Processor Architecture](./assets/diagrams/architecture/CEPArchTechOverview.svg) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/architecture/CEPArchTechOverview.svg b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/architecture/CEPArchTechOverview.svg new file mode 100644 index 000000000..40e9f3ae0 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/architecture/CEPArchTechOverview.svg @@ -0,0 +1,2 @@ + +


    Notifiers
    /email, sms, etc./
    [Not supported by viewer]
    ML-Adapter
    [Not supported by viewer]
    prepare 
    [Not supported by viewer]
    fulfil 
    [Not supported by viewer]
    notification 
    <b>notification </b>

    DB
    [Not supported by viewer]
    Central-Services
    Central-Services

    MangoDB
    [Not supported by viewer]
    Central Event
    Processor (CEP)

    [Not supported by viewer]
    RxJS
    RxJS
    json-rule-engine
    json-rule-engine

    Heading

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

    [Not supported by viewer]
    REST admin API
    [Not supported by viewer]
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.plantuml b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.plantuml new file mode 100644 index 000000000..d01340e1f --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.plantuml @@ -0,0 +1,94 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declate title +title 9.1.0. Event Handler Placeholder + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +control "Event Handler Placeholder" as EVENT_HANDLER + +box "Event Handler Placeholder" #LightGray + participant EVENT_HANDLER +end box + +collections "Event-Topic" as TOPIC_EVENTS + +' start flow +activate EVENT_HANDLER + +group Event Handler Placeholder + EVENT_HANDLER -> TOPIC_EVENTS: Consume Event message \n Error code: 2001 + note right of EVENT_HANDLER #yellow + Message: + { + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: INFO, + action: AUDIT, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + note right of EVENT_HANDLER #LightGray + The type would be an ENUM with values: + [INFO, DEBUG, ERROR, WARN, FATAL, TRACE] + Possible values for "action" would be + [AUDIT, EXCEPTION] + The event messages can be handled based on the values of these two variables + (when the placeholder is extended). + end note + EVENT_HANDLER -> EVENT_HANDLER: Auto-commit \n Error code: 2001 + note right of EVENT_HANDLER #lightBlue + Currently events to only be published as part of the placeholder. + This can be evolved to add relevant functionality. + end note + activate TOPIC_EVENTS + deactivate TOPIC_EVENTS +end +deactivate EVENT_HANDLER + +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.svg b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.svg new file mode 100644 index 000000000..3f48ce80a --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-event-9.1.0.svg @@ -0,0 +1,170 @@ + + + + + + + + + + + 9.1.0. Event Handler Placeholder + + + + Event Handler Placeholder + + + + + + Event Handler Placeholder + + + + + Event Handler Placeholder + + + + + + + Event-Topic + + + + + Event-Topic + + + + + + Event Handler Placeholder + + + + + 1 + + + Consume Event message + + + Error code: + + + 2001 + + + + + Message: + + + { + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: INFO, + + + action: AUDIT, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + The type would be an ENUM with values: + + + [INFO, DEBUG, ERROR, WARN, FATAL, TRACE] + + + Possible values for "action" would be + + + [AUDIT, EXCEPTION] + + + The event messages can be handled based on the values of these two variables + + + (when the placeholder is extended). + + + + + 2 + + + Auto-commit + + + Error code: + + + 2001 + + + + + Currently events to only be published as part of the placeholder. + + + This can be evolved to add relevant functionality. + + diff --git a/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.plantuml b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.plantuml new file mode 100644 index 000000000..38e5e7dd3 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.plantuml @@ -0,0 +1,111 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Henk Kodde + -------------- + ******'/ + +@startuml +' declate title +title 5.1.1. Notification Handler for Rejections + +autonumber + +' Actor Keys: + +' declare actors + +actor "DFSP1\nPayer" as DFSP1 +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Event-Topic" as TOPIC_EVENT +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_EVENT + participant TOPIC_NOTIFICATIONS +end box + +' start flow + +group DFSP Notified of Rejection + activate NOTIFY_HANDLER + NOTIFY_HANDLER -> TOPIC_NOTIFICATIONS: Consume Notification event message \n Error code: 2001 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + group Persist Event Information + NOTIFY_HANDLER -> TOPIC_EVENT: Publish event information \n Error code: 3201 + activate TOPIC_EVENT + ref over TOPIC_EVENT : Event Handler + deactivate TOPIC_EVENT + end + + alt consume a single messages + group Validate Event + NOTIFY_HANDLER <-> NOTIFY_HANDLER: Validate event - Rule: type == 'notification' && [action IN ['reject', 'timeout-received', 'timeout-reserved']] + end + NOTIFY_HANDLER -> CSAPI: Request Participant Callback details \n Error code: 3201 + ref over NOTIFY_HANDLER, CSAPI: Get Participant Callback Details + NOTIFY_HANDLER <-- CSAPI: Return Participant Callback details + note left of NOTIFY_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + payload: + }, + } + end note + NOTIFY_HANDLER --> DFSP1: Send Callback Notification \n Error code: 1000, 1001, 3002 + else Validate rule type != 'notification' / Error + note right of NOTIFY_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + NOTIFY_HANDLER -> TOPIC_EVENT: Invalid messages retrieved from the Notification Topic \n Error code: 3201 + activate TOPIC_EVENT + deactivate TOPIC_EVENT + ref over TOPIC_EVENT: Event Handler + note right of NOTIFY_HANDLER #lightblue + Log ERROR Messages + Update Event log upon ERROR notification + end note +' deactivate TOPIC_NOTIFICATIONS + end +end +@enduml \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.svg b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.svg new file mode 100644 index 000000000..6eb610b07 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-notification-reject-5.1.1.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + 5.1.1. Notification Handler for Rejections + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + DFSP Notified of Rejection + + + + + 1 + + + Consume Notification event message + + + Error code: + + + 2001 + + + + + Persist Event Information + + + + + 2 + + + Publish event information + + + Error code: + + + 3201 + + + + + ref + + + Event Handler + + + + + alt + + + [consume a single messages] + + + + + Validate Event + + + + + 3 + + + Validate event - Rule: type == 'notification' && [action IN ['reject', 'timeout-received', 'timeout-reserved']] + + + + + 4 + + + Request Participant Callback details + + + Error code: + + + 3201 + + + + + ref + + + Get Participant Callback Details + + + + + 5 + + + Return Participant Callback details + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + payload: <transferMessage> + + + }, + + + } + + + + + 6 + + + Send Callback Notification + + + Error code: + + + 1000, 1001, 3002 + + + + [Validate rule type != 'notification' / Error] + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <errorCode>, + + + "errorDescription": <ErrorMessage>, + + + } + + + } + + + + + 7 + + + Invalid messages retrieved from the Notification Topic + + + Error code: + + + 3201 + + + + + ref + + + Event Handler + + + + + Log ERROR Messages + + + Update Event log upon ERROR notification + + diff --git a/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-signature-validation.plantuml b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-signature-validation.plantuml new file mode 100644 index 000000000..03a932865 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-signature-validation.plantuml @@ -0,0 +1,35 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + * Rajiv Mothilal + -------------- + ******'/ + +@startuml +' declare title +title Signature Validation + +Alice -> Bob: Authentication Request +Bob --> Alice: Authentication Response + +Alice -> Bob: Another authentication Request +Alice <-- Bob: another authentication Response +@enduml \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-signature-validation.svg b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-signature-validation.svg new file mode 100644 index 000000000..4e80c45ca --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/central-event-processor/assets/diagrams/sequence/seq-signature-validation.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + Signature Validation + + + + + Alice + + + + Alice + + + + Bob + + + + Bob + + + + + Authentication Request + + + + + Authentication Response + + + + + Another authentication Request + + + + + another authentication Response + + diff --git a/website/versioned_docs/v1.0.1/technical/central-event-processor/event-handler-placeholder.md b/website/versioned_docs/v1.0.1/technical/central-event-processor/event-handler-placeholder.md new file mode 100644 index 000000000..38904e3d2 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/central-event-processor/event-handler-placeholder.md @@ -0,0 +1,7 @@ +# Event Handler Placeholder + +Sequence design diagram for the Event Handler process. + +## Sequence Diagram + +![seq-event-9.1.0.svg](./assets/diagrams/sequence/seq-event-9.1.0.svg) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/central-event-processor/notification-handler-for-rejections.md b/website/versioned_docs/v1.0.1/technical/central-event-processor/notification-handler-for-rejections.md new file mode 100644 index 000000000..258ef5fb7 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/central-event-processor/notification-handler-for-rejections.md @@ -0,0 +1,12 @@ +# Notification Handler for Rejections + +Sequence design diagram for the Notification Handler for Rejections process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](9.1.0-event-handler-placeholder.md) +* [Get Participant Callback Details (3.1.0)](../central-ledger/admin-operations/3.1.0-post-participant-callback-details.md) + +## Sequence Diagram + +![seq-notification-reject-5.1.1.svg](./assets/diagrams/sequence/seq-notification-reject-5.1.1.svg) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/central-event-processor/signature-validation.md b/website/versioned_docs/v1.0.1/technical/central-event-processor/signature-validation.md new file mode 100644 index 000000000..e4aabbbe7 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/central-event-processor/signature-validation.md @@ -0,0 +1,7 @@ +# Signature Validation + +Sequence design diagram for the Signature Validation process. + +## Sequence Diagram + +![seq-signature-validation.svg](./assets/diagrams/sequence/seq-signature-validation.svg) \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/event-framework/README.md b/website/versioned_docs/v1.0.1/technical/event-framework/README.md new file mode 100644 index 000000000..d1a0f5ece --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/event-framework/README.md @@ -0,0 +1,233 @@ +# Event Framework + +The purpose of the Event Framework is to provide a standard unified architecture to capture all Mojaloop events. + +_Disclaimer: This is experimental and is being implemented as a PoC. As such the design may change based on the evolution of the PoC's implementation, and any lessons learned._ + + +## 1. Requirements + +- Events will be produced by utilising a standard common library that will publish events to a sidecar component utilising a light-weight highly performant protocol (e.g. gRPC). +- Sidecar module will publish events to a singular Kafka topic that will allow for multiple handlers to consume and process the events as required. +- Kafka partitions will be determined by the event-type (e.g. log, audit, trace, errors etc). +- Each Mojaloop component will have its own tightly coupled Sidecar. +- Event messages will be produced to Kafka using the Trace-Id as the message key. This will ensure that all the messages part of the same trace (transaction) are stored in the same partition in order. + + +## 2. Architecture + +### 2.1 Overview + +![Event Framework Architecture](./assets/diagrams/architecture/architecture-event-framework.svg) + +### 2.2 Micro Service Pods + +![Pod Architecture](./assets/diagrams/architecture/architecture-event-sidecar.svg) + +### 2.3 Event Flow + +![Tracing Architecture](./assets/diagrams/architecture/architecture-event-trace.svg) + + +## 3. Event Envelope Model + +## 3.1 JSON Example + +```JSON +{ + "from": "noresponsepayeefsp", + "to": "payerfsp", + "id": "aa398930-f210-4dcd-8af0-7c769cea1660", + "content": { + "headers": { + "content-type": "application/vnd.interoperability.transfers+json;version=1.0", + "date": "2019-05-28T16:34:41.000Z", + "fspiop-source": "noresponsepayeefsp", + "fspiop-destination": "payerfsp" + }, + "payload": "data:application/vnd.interoperability.transfers+json;version=1.0;base64,ewogICJmdWxmaWxtZW50IjogIlVObEo5OGhaVFlfZHN3MGNBcXc0aV9VTjN2NHV0dDdDWkZCNHlmTGJWRkEiLAogICJjb21wbGV0ZWRUaW1lc3RhbXAiOiAiMjAxOS0wNS0yOVQyMzoxODozMi44NTZaIiwKICAidHJhbnNmZXJTdGF0ZSI6ICJDT01NSVRURUQiCn0" + }, + "type": "application/json", + "metadata": { + "event": { + "id": "3920382d-f78c-4023-adf9-0d7a4a2a3a2f", + "type": "trace", + "action": "span", + "createdAt": "2019-05-29T23:18:32.935Z", + "state": { + "status": "success", + "code": 0, + "description": "action successful" + }, + "responseTo": "1a396c07-47ab-4d68-a7a0-7a1ea36f0012" + }, + "trace": { + "service": "central-ledger-prepare-handler", + "traceId": "bbd7b2c7-3978-408e-ae2e-a13012c47739", + "parentSpanId": "4e3ce424-d611-417b-a7b3-44ba9bbc5840", + "spanId": "efeb5c22-689b-4d04-ac5a-2aa9cd0a7e87", + "startTimestamp": "2015-08-29T11:22:09.815479Z", + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + "tags": { + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + "transctionType": "transfer", + "parentEventType": "bulk-prepare", + "parentEventAction": "prepare" + } + } + } +} +``` + +## 3.2 Schema Definition + +### 3.2.1 Object Definition: EventMessage + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| id | string | Y | The id references the related message. | | +| from | string | N | If the value is not present in the destination, it means that the notification was generated by the connected node (server). | | +| to | string | Y | Mandatory for the sender and optional in the destination. The sender can ommit the value of the domain. | | +| pp | string | N | Optional for the sender, when is considered the identity of the session. Is mandatory in the destination if the identity of the originator is different of the identity of the from property. | | +| metadata | object `` | N | The sender should avoid to use this property to transport any kind of content-related information, but merely data relevant to the context of the communication. Consider to define a new content type if there's a need to include more content information into the message. | | +| type | string | Y | `MIME` declaration of the content type of the message. | | +| content | object \ | Y | The representation of the content. | | + +##### 3.2.1.1 Object Definition: MessageMetadata + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| event | object `` | Y | Event information. | | +| trace | object `` | Y | Trace information. | | + +##### 3.2.1.2 Object Definition: EventMetadata + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| id | string | Y | Generated UUIDv4 representing the event. | 3920382d-f78c-4023-adf9-0d7a4a2a3a2f | +| type | enum `` | Y | Type of event. | [`log`, `audit`, `error` `trace`] | +| action | enum `` | Y | Type of action. | [ `start`, `end` ] | +| createdAt | timestamp | Y | ISO Timestamp. | 2019-05-29T23:18:32.935Z | +| responseTo | string | N | UUIDv4 id link to the previous parent event. | 2019-05-29T23:18:32.935Z | +| state | object `` | Y | Object describing the state. | | + +##### 3.2.1.3 Object Definition: EventStateMetadata + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| status | enum `` | Y | The id references the related message. | success | +| code | number | N | The error code as per Mojaloop specification. | 2000 | +| description | string | N | Description for the status. Normally used to include an description for an error. | Generic server error to be used in order not to disclose information that may be considered private. | + +##### 3.2.1.4 Object Definition: EventTraceMetaData + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| service | string | Y | Name of service producing trace | central-ledger-prepare-handler | +| traceId | 32HEXDIGLC | Y | The end-to-end transaction identifier. | 664314d5b207d3ba722c6c0fdcd44c61 | +| spanId | 16HEXDIGLC | Y | Id for a processing leg identifier for a component or function. | 81fa25e8d66d2e88 | +| parentSpanId | 16HEXDIGLC | N | The id references the related message. | e457b5a2e4d86bd1 | +| sampled | number | N | Indicator if event message should be included in the trace `1`. If excluded it will be left the consumer to decide on sampling. | 1 | +| flags | number | N | Indicator if event message should be included in the trace flow. ( Debug `1` - this will override the sampled value ) | 0 | +| startTimestamp | datetime | N | ISO 8601 with the following format `yyyy-MM-dd'T'HH:mm:ss.SSSSSSz`. If not included the current timestamp will be taken. Represents the start timestamp of a span.| 2015-08-29T11:22:09.815479Z | +| finishTimestamp | datetime | N | ISO 8601 with the following format `yyyy-MM-dd'T'HH:mm:ss.SSSSSSz`. If not included the current timestamp will be taken. Represents the finish timestamp of a span | 2015-08-29T11:22:09.815479Z | +| tags | object `` | Y | The id references the related message. | success | + +_Note: HEXDIGLC = DIGIT / "a" / "b" / "c" / "d" / "e" / "f" ; lower case hex character. Ref: [WC3 standard for trace-context](https://www.w3.org/TR/trace-context/#field-value)._ + +##### 3.2.1.5 Object Definition: EventTraceMetaDataTags + +| Name | Type | Mandatory (Y/N) | Description | Example | +| --- | --- | --- | --- | --- | +| transactionId | string | N | Transaction Id representing either a transfer, quote, etc | 659ee338-c8f8-4c06-8aff-944e6c5cd694 | +| transactionType | string | N | The transaction type represented by the transactionId. E.g. (transfer, quote, etc) | transfer | +| parentEventType | string | N | The event-type of the parent Span. | bulk-prepare | +| parentEventAction | string | N | The event-action of the parent Span. | prepare | +| tracestate | string | N | This tag is set if EventSDK environmental variable `EVENT_SDK_TRACESTATE_HEADER_ENABLED` is `true` or if parent span context has the `tracestate` header or tag included. The tag holds updated `tracestate` header value as per the W3C trace headers specification. [More here](#411-wc3-http-headers)| `congo=t61rcWkgMzE,rojo=00f067aa0ba902b7` | +| `` | string | N | Arbitary Key-value pair for additional meta-data to be added to the trace information. | n/a | + +##### 3.2.1.6 Enum: EventStatusType + +| Enum | Description | +| --- | --- | +| success | Event was processed successfully | +| fail | Event was processed with a failure or error | + +##### 3.2.1.7 Enum: EventType + +| Enum | Description | +| --- | --- | +| log | Event representing a general log entry. | +| audit | Event to be signed and persisted into the audit store. | +| trace | Event containing trace context information to be persisted into the tracing store. | + +##### 3.2.1.8 Enum: LogEventAction + +| Enum | Description | +| --- | --- | +| info | Event representing an `info` level log entry. | +| debug | Event representing a `debug` level log entry. | +| error | Event representing an `error` level log entry. | +| verbose | Event representing a `verbose` level log entry. | +| warning | Event representing a `warning` level log entry. | +| performance | Event representing a `performance` level log entry. | + +##### 3.2.1.9 Enum: AuditEventAction + +| Enum | Description | +| --- | --- | +| default | Standard audit action. | +| start | Audit action to represent the start of a process. | +| finish | Audit action to represent the end of a process. | +| ingress | Audit action to capture ingress activity. | +| egress | Audit action to capture egress activity. | + +##### 3.2.1.10 Enum: TraceEventAction + +| Enum | Description | +| --- | --- | +| span | Event action representing a span of a trace. | + + +## 4. Tracing Design + +### 4.1 HTTP Transports + +Below find the current proposed standard HTTP Transport headers for tracing. + +Mojaloop has yet to standardise on either standard, or if it will possible support both. + +#### 4.1.1 W3C Http Headers + +Refer to the following publication for more information: https://w3c.github.io/trace-context/ + +| Header | Description | Example | +| --- | --- | --- | +| traceparent | Dash delimited string of tracing information: \-\-\-\ | 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00 | +| tracestate | Comma delimited vendor specific format captured as follows: \=\| congo=t61rcWkgMzE,rojo=00f067aa0ba902b7 | + +Note: Before this specification was written, some tracers propagated X-B3-Sampled as true or false as opposed to 1 or 0. While you shouldn't encode X-B3-Sampled as true or false, a lenient implementation may accept them. + +Note: (Event-SDK)[https://github.com/mojaloop/event-sdk] since version v9.4.1 has methods to add key value tags in the tracestate, and since version v9.5.2 the tracestate is base64 encoded. To be able to use the tracestate consistently, use matching versions across all services in a system. + +#### 4.1.2 B3 HTTP Headers + +Refer to the following publication for more information: https://github.com/apache/incubator-zipkin-b3-propagation + +| Header | Description | Example | +| --- | --- | --- | +| X-B3-TraceId | Encoded as 32 or 16 lower-hex characters. | a 128-bit TraceId header might look like: X-B3-TraceId: 463ac35c9f6413ad48485a3953bb6124. Unless propagating only the Sampling State, the X-B3-TraceId header is required. | +| X-B3-SpanId | Encoded as 16 lower-hex characters. | a SpanId header might look like: X-B3-SpanId: a2fb4a1d1a96d312. Unless propagating only the Sampling State, the X-B3-SpanId header is required. | +| X-B3-ParentSpanId | header may be present on a child span and must be absent on the root span. It is encoded as 16 lower-hex characters. | A ParentSpanId header might look like: X-B3-ParentSpanId: 0020000000000001 | +| X-B3-Sampled | An accept sampling decision is encoded as `1` and a deny as `0`. Absent means defer the decision to the receiver of this header. | A Sampled header might look like: X-B3-Sampled: 1. | +| X-B3-Flags | Debug is encoded as `1`. Debug implies an accept decision, so don't also send the X-B3-Sampled header. | | + +### 4.2 Kafka Transports + +Refer to `Event Envelope Model` section. This defines the message that will be sent through the Kafka transport. + +Alternatively the tracing context could be stored in Kafka headers which are only supports v0.11 or later. Note that this would break support for older versions of Kafka. + +### 4.3 Known limitations + +- Transfer tracing would be limited to each of the transfer legs (i.e. Prepare and Fulfil) as a result of the Mojaloop API specification not catering for tracing information. The trace information will be send as part of the callbacks by the Switch, but the FSPs will not be required to respond appropriately with a reciprocal trace headers. diff --git a/website/versioned_docs/v1.0.1/technical/event-framework/assets/diagrams/architecture/architecture-event-framework.svg b/website/versioned_docs/v1.0.1/technical/event-framework/assets/diagrams/architecture/architecture-event-framework.svg new file mode 100644 index 000000000..47c2c4acb --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/event-framework/assets/diagrams/architecture/architecture-event-framework.svg @@ -0,0 +1,3 @@ + + +
    Central-Ledger
    (API)
    Central-Ledger<br>(API)<br>
    Central-Ledger
    Handler #
    Central-Ledger<br>Handler #<br>
    Central-Ledger
    Handler #
    Central-Ledger<br>Handler #<br>
    Central-Ledger
    (Handler #)
    Central-Ledger<br>(Handler #)<br>

    <div style="text-align: left ; font-size: 8px"><br></div>
    ML-API-Adapter
    (API)
    ML-API-Adapter<br>(API)<br>
    Central-Settlements
    (API)
    Central-Settlements<br>(API)<br>
    ML-API-Adapter
    (Handler)
    ML-API-Adapter<br>(Handler)<br>
    Quoting-Service
    (API)
    Quoting-Service<br>(API)<br>
    Account-Lookup-Service
    (API)
    Account-Lookup-Service<br>(API)<br>

    <div style="text-align: left"><br></div>
    Message Types:
    - Tracing
    - Audit
    - Logs
    [Not supported by viewer]
    <div style="text-align: center"></div>
    Kafka
    (Event Stream)
    topic-events
    [Not supported by viewer]

    <div style="text-align: left ; font-size: 8px"><br></div>
    Sidecar
    Sidecar

    <div style="text-align: left ; font-size: 8px"><br></div>
    Sidecar
    Sidecar
    Sidecar
    Sidecar
    Sidecar
    Sidecar

    <div style="text-align: left ; font-size: 8px"><br></div>
    Sidecar
    Sidecar

    <div style="text-align: left ; font-size: 8px"><br></div>
    Sidecar
    Sidecar

    <div style="text-align: left ; font-size: 8px"><br></div>
    Sidecar
    Sidecar
    Sidecar
    Sidecar
    Sidecar
    Sidecar
    EFK
    (Elasticsearch, Fluentd, 
    Kibana & APM)
    [Not supported by viewer]
    Forensic-Logging
    (Future - re-factored from Side-Car into Service for Batch Audits)
    [Not supported by viewer]
    Central-KMS
    Central-KMS
    Audits
    Audits
    Keys
    Keys
    Partitioned by Trace-Id
    [Not supported by viewer]
    Event-stream-processor
    (Mediation,  Translation)
    [Not supported by viewer]
    Open-Tracing
    [Not supported by viewer]
    log, trace, audit
    [Not supported by viewer]
    log, trace, audit
    [Not supported by viewer]
    log, trace, audit
    [Not supported by viewer]
    log, trace, audit
    [Not supported by viewer]

    <div style="text-align: left ; font-size: 8px"><br></div>
    log, trace, audit
    [Not supported by viewer]
    log, trace, audit
    [Not supported by viewer]
    log, trace, audit
    [Not supported by viewer]
    Key provisioning
    [Not supported by viewer]
    Key provisioning
    [Not supported by viewer]
    Message Types:
    - Tracing
    - Audit
    - Logs
    [Not supported by viewer]
    Message Types:
    - Audits
    [Not supported by viewer]
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/event-framework/assets/diagrams/architecture/architecture-event-sidecar.svg b/website/versioned_docs/v1.0.1/technical/event-framework/assets/diagrams/architecture/architecture-event-sidecar.svg new file mode 100644 index 000000000..b274a9d3a --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/event-framework/assets/diagrams/architecture/architecture-event-sidecar.svg @@ -0,0 +1,3 @@ + + +

    <div style="text-align: left"><br></div>
    POD #2
    POD #2
    Service #2
    Service #2<br>
    POD #1
    POD #1
    <div style="text-align: center"></div>
    Kafka
    (Event Stream)
    topic-events
    [Not supported by viewer]
    Kubernetes Cluster
    [Not supported by viewer]
    Event Framework
    SideCar
    Event Framework<br>SideCar<br>
    gRPC Server
    gRPC Server
    gRPC Client
    gRPC Client
    Kafka
    Client
    [Not supported by viewer]
    Partitioned by Trace-Id
    [Not supported by viewer]
    Service #1
    Service #1<br>
    Event Framework
    SideCar
    Event Framework<br>SideCar<br>
    gRPC Server
    gRPC Server
    gRPC Client
    gRPC Client
    Kafka
    Client
    [Not supported by viewer]
    @mojaloop/
    event-sdk
    @mojaloop/<br>event-sdk
    Event Framework Sidecar included as part of each component Helm Chart
    [Not supported by viewer]
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/event-framework/assets/diagrams/architecture/architecture-event-trace.svg b/website/versioned_docs/v1.0.1/technical/event-framework/assets/diagrams/architecture/architecture-event-trace.svg new file mode 100644 index 000000000..5fd81ccfb --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/event-framework/assets/diagrams/architecture/architecture-event-trace.svg @@ -0,0 +1,3 @@ + + +
    Sidecar
    Sidecar
    Sidecar
    Sidecar
    Service
    Consumer 
    Service...
    Parent Span
    Parent Span
    Trace
    Trace
    Start
    Start
    End
    End
    Child Span
    Child Span
    Start
    Start
    End
    End
    Child Span
    Child Span
    Start
    Start
    End
    End
    Trace Context
    - traceId
    - spanId
    - parentId
    - sampled
    - flags
    - tracestate
    Trace Context...
    Service
    Producer 
    Service...
    Tags: [ transactionId: transferId, transactionType: transfer, source: payerFsp, destination: payeeFsp, tracestate: mojaloop=f32c19568004ce8b ]
    Tags: [ transactionId: transferId, transactionType: transfer, source: payerFsp, destination: payeeFsp, tracestate: mojaloop=f32c19568004ce...
    Child Span
    Child Span
    Start
    Start
    End
    End
    Message Transport
    - HTTP
    - Kafka

    Message Transport...
    Error
    Error
    Kafka
    (Event Topic)
    Kafka...
    Event Sidecar
    Event Sidecar
    Event Sidecar
    Event Sidecar
    Record Trace
    Record...
    Service A
    Service A
    Service B
    Service B
    Trace Message
    - traceId
    - spanId
    - parentId
    - sampled
    - flags
    - tags
    - tracestate
    - content / error
    Trace Message...
    Record Trace
    Record...
    Record Trace
    Record...
    Record Trace
    Record...
    Record Error
    Record...
    Audit
    Audit
    Record
    Audit
    Record...
    Log
    Log
    Record Log
    Record...
    Record
    Audit
    Record...
    Record
    Audit
    Record...
    Record
    Audit
    Record...
    Record
    Audit
    Record...
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/event-stream-processor/README.md b/website/versioned_docs/v1.0.1/technical/event-stream-processor/README.md new file mode 100644 index 000000000..645e221fc --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/event-stream-processor/README.md @@ -0,0 +1,18 @@ +# Event Stream Processor Service + +Event Stream Processor consumes event messages from the `topic-events` topic as a result of messages published by the [event-sidecar](https://github.com/mojaloop/event-sidecar) service. Refer to [Event Framework](../event-framework/README.md) for more information on the overall architecture. + +The Service delivers logs, including audits, and traces to EFK stack with enabled APM plugin. Based on the event message type, the messages are delivered to different indexes in the Elasticsearch. + +## 1. Prerequisites + +The service logs all the events to Elasticsearch instance with enabled APM plugin. Sample docker-compose of the Elastic stack is available [here](https://github.com/mojaloop/event-stream-processor/blob/master/test/util/scripts/docker-efk/docker-compose.yml). The logs and audits are created under custom index template, while the trace data is stored to the default `apm-*` index. +Please, ensure that you have created the `mojatemplate` as it is described into the [event-stream-processor](https://github.com/mojaloop/event-stream-processor#111-create-template) service documentation. + +## 2. Architecture overview + +### 2.1. Flow overview +![Event Stream Processor flow overview](./assets/diagrams/architecture/event-stream-processor-overview.svg) + +### 2.2 Trace processing flow sequence diagram +![process-flow.svg](./assets/diagrams/sequence/process-flow.svg) diff --git a/website/versioned_docs/v1.0.1/technical/event-stream-processor/assets/diagrams/architecture/event-stream-processor-overview.svg b/website/versioned_docs/v1.0.1/technical/event-stream-processor/assets/diagrams/architecture/event-stream-processor-overview.svg new file mode 100644 index 000000000..9deb189e9 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/event-stream-processor/assets/diagrams/architecture/event-stream-processor-overview.svg @@ -0,0 +1,3 @@ + + +
    topic-event
    topic-event
    Event Stream Processor
    Send to Elasticsearch mojaloop custom schema via Elasticsearch API
    [Not supported by viewer]
    Yes
    Yes
    Is it trace?
    Is it trace?
    No
    No
    Should create master span?
    Should create master span?
    exit
    exit
    No
    No
    APM Agent
    APM Agent
    Create cache for the trace
    Create cache for the trace
    Yes
    Yes
    No
    No
    Is last span?
    Is last span?
    Recreate trace
    Recreate trace
    exit
    exit
    EFK Stack (Elasticsearch, Kibana, APM)
    EFK Stack (Elasticsearch, Kibana, APM)
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/event-stream-processor/assets/diagrams/sequence/process-flow.plantuml b/website/versioned_docs/v1.0.1/technical/event-stream-processor/assets/diagrams/sequence/process-flow.plantuml new file mode 100644 index 000000000..9817a79d8 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/event-stream-processor/assets/diagrams/sequence/process-flow.plantuml @@ -0,0 +1,280 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title Event Streaming Processor flow + +autonumber + +' Actor Keys: + +' declare actors + +collections "Notification topic" as TOPIC_NOTIFICATIONS +control "Topic Observable" as TOPIC_OBSERVABLE +control "Tracing Observable" as TRACING_OBSERVABLE +control "Caching Observable" as CACHING_OBSERVABLE +control "Check For Last Span Observable" as LASTSPAN_OBSERVABLE +control "Create Trace Observable" as CREATETRACE_OBSERVABLE +control "Cache Handler" as CACHE_HANDLER +control "Send Trace Handler" as TRACE_HANDLER +control "Send Span Handler" as SPAN_SENDER +database "Cache Storage" as CACHE +boundary "APM" as APM +boundary "Elasticsearch API" as ELASTIC + +box "Central Services" #lightGray + participant TOPIC_NOTIFICATIONS +end box + +box "Event Stream Processor" #LightBlue + participant TOPIC_OBSERVABLE + participant TRACING_OBSERVABLE + participant CACHING_OBSERVABLE + participant LASTSPAN_OBSERVABLE + participant CREATETRACE_OBSERVABLE + participant TRACE_HANDLER + participant SPAN_SENDER + participant CACHE_HANDLER +end box + +box "Cache" #LightSteelBlue + participant CACHE +end box + +box "Elasticsearch" #LightYellow + participant APM + participant ELASTIC +end box + +' start flow + +group New Event Message Received + TOPIC_NOTIFICATIONS -> TOPIC_OBSERVABLE: Consume Event Message + activate TOPIC_OBSERVABLE + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + note over TOPIC_OBSERVABLE #yellow + Message: + { + "from": "payeefsp", + "to": "payerfsp", + "id": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + "content": { + "headers": { + "content-type": "applicationvnd.interoperability.transfers+json;version=1.0", + "date": "2019-05-28T16:34:41.000Z", + "fspiop-source": "payeefsp", + "fspiop-destination": "payerfsp" + }, + "payload": + }, + "type": "application/json", + "metadata": { + "event": { + "id": "3920382d-f78c-4023-adf9-0d7a4a2a3a2f", + "type": "trace", + "action": "span", + "createdAt": "2019-05-29T23:18:32.935Z", + "state": { + "status": "success", + "code": 0, + "description": "action successful" + }, + "responseTo": "1a396c07-47ab-4d68-a7a0-7a1ea36f0012" + }, + "trace": { + "service": "central-ledger-prepare-handler", + "traceId": "bbd7b2c7bbd7b2c7", + "parentSpanId": "44ba9bbc5840", + "spanId": "2aa9cd0a7e87", + "startTimestamp": "2015-08-29T11:22:09.815479Z", + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + "tags": { + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + "transctionType": "transfer", + "parentEventType": "bulk-prepare", + "parentEventAction": "prepare" + } + } + } + } + end note + TOPIC_OBSERVABLE -> ELASTIC: Send message for log purposes to custom index + TOPIC_OBSERVABLE -> TOPIC_OBSERVABLE: Verify its tracing event Message + TOPIC_OBSERVABLE -> TRACING_OBSERVABLE: Send Message to Tracing Observable + deactivate TOPIC_OBSERVABLE + activate TRACING_OBSERVABLE + group Cache Span + TRACING_OBSERVABLE -> CACHING_OBSERVABLE: Send Span Context, \nmetadata.State and Content\nfrom Message + note right of TRACING_OBSERVABLE #yellow + { + spanContext: { + service: "central-ledger-prepare-handler", + traceId: "bbd7b2c7bbd7b2c7", + parentSpanId: "44ba9bbc5840", + spanId: "2aa9cd0a7e87", + startTimestamp: "2015-08-29T11:22:09.815479Z", + finishTimestamp: "2015-08-29T11:22:09.815479Z", + tags: { + transctionId: "659ee338-c8f8-4c06-8aff-944e6c5cd694", + transctionType: "transfer", + parentEventType: "bulk-prepare", + parentEventAction: "prepare" + }, + state: metadata.state, + content + } + end note + deactivate TRACING_OBSERVABLE + activate CACHING_OBSERVABLE + CACHING_OBSERVABLE <- CACHE: Get cachedTrace by traceId + alt the span should not be cached + CACHING_OBSERVABLE -> SPAN_SENDER: currentSpan + SPAN_SENDER -> APM: store to APM + CACHING_OBSERVABLE -> CACHING_OBSERVABLE: Complete + else + CACHING_OBSERVABLE <-> CACHING_OBSERVABLE: Validate transactionType, TransactionAction and service to match Config.START_CRITERIA && !parentSpandId + alt !cachedTrace + CACHING_OBSERVABLE -> CACHING_OBSERVABLE: Create new cachedTrace + note right of CACHING_OBSERVABLE #yellow + { + spans: {}, + masterSpan: null, + lastSpan: null + } + end note + end + alt !parentSpan + CACHING_OBSERVABLE <-> CACHING_OBSERVABLE: Generate MasterSpanId + CACHING_OBSERVABLE <-> CACHING_OBSERVABLE: Make received span child of masterSpan \nmerge({ parentSpanId: MasterSpanId }, { ...spanContext }) + CACHING_OBSERVABLE <-> CACHING_OBSERVABLE: Create MasterSpanContext merge({ tags: { ...tags, masterSpan: MasterSpanId } }, \n{ ...spanContext }, \n{ spanId: MasterSpanId, service: `master-${tags.transactionType}` }) + CACHING_OBSERVABLE <-> CACHING_OBSERVABLE: Add masterSpan to cachedTrace + end + CACHING_OBSERVABLE <-> CACHE_HANDLER: Add span to cachedTrace + note right of CACHING_OBSERVABLE #yellow + { + spans: { + 2aa9cd0a7e87: { + state, + content + spanContext: { + "service": "central-ledger-prepare-handler", + "traceId": "bbd7b2c7bbd7b2c7", + "parentSpanId": MasterSpanId, + "spanId": "2aa9cd0a7e87", + "startTimestamp": "2015-08-29T11:22:09.815479Z", + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + "tags": { + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + "transctionType": "transfer", + "parentEventType": "bulk-prepare", + "parentEventAction": "prepare" + } + } + }, + MasterSpanId: { + state, + content, + MasterSpanContext + } + }, + masterSpan: MasterSpanContext, + lastSpan: null + } + end note + CACHING_OBSERVABLE -> CACHE_HANDLER: Update cachedTrace to Cache + alt cachedTrace not staled or expired + CACHE_HANDLER -> CACHE_HANDLER: unsubscribe from Scheduler + CACHE_HANDLER -> CACHE: record cachedTrace + CACHE_HANDLER <-> CACHE_HANDLER: Reschedule scheduler for handling stale traces + end + end + CACHING_OBSERVABLE -> LASTSPAN_OBSERVABLE: Send traceId to check if last span has been received\nand cached + deactivate CACHING_OBSERVABLE + activate LASTSPAN_OBSERVABLE + end + group Check for last span + LASTSPAN_OBSERVABLE <- CACHE: Get cachedTrace by traceId + LASTSPAN_OBSERVABLE -> LASTSPAN_OBSERVABLE: Sort spans by startTimestamp + loop for currentSpan of SortedSpans + alt parentSpan + LASTSPAN_OBSERVABLE -> LASTSPAN_OBSERVABLE: isError = (errorCode in parentSpan \nOR parentSpan status === failed \nOR status === failed) + LASTSPAN_OBSERVABLE -> LASTSPAN_OBSERVABLE: apply masterSpan and error tags from parent to current span in cachedTrace + alt !isLastSpan + LASTSPAN_OBSERVABLE -> CACHE_HANDLER: Update cachedTrace to Cache + alt cachedTrace not staled or expired + CACHE_HANDLER -> CACHE_HANDLER: unsubscribe from Scheduler + CACHE_HANDLER -> CACHE: record cachedTrace + CACHE_HANDLER <-> CACHE_HANDLER: Reschedule scheduler for handling stale traces + end + else + LASTSPAN_OBSERVABLE -> LASTSPAN_OBSERVABLE: Validate transactionType, TransactionAction, service and isError \nto match Config.START_CRITERIA && !parentSpandId + LASTSPAN_OBSERVABLE -> LASTSPAN_OBSERVABLE: cachedTrace.lastSpan = currentSpan.spanContext + LASTSPAN_OBSERVABLE -> CACHE_HANDLER: Update cachedTrace to Cache + alt cachedTrace not staled or expired + CACHE_HANDLER -> CACHE_HANDLER: unsubscribe from Scheduler + CACHE_HANDLER -> CACHE: record cachedTrace + CACHE_HANDLER <-> CACHE_HANDLER: Reschedule scheduler for handling stale traces + end + LASTSPAN_OBSERVABLE -> CREATETRACE_OBSERVABLE: Send traceId + deactivate LASTSPAN_OBSERVABLE + activate CREATETRACE_OBSERVABLE + end + end + end + end + group Recreate Trace from Cached Trace + CREATETRACE_OBSERVABLE <- CACHE: get cachedTrace by TraceId + alt cachedTrace.lastSpan AND cachedTrace.masterSpan + CREATETRACE_OBSERVABLE -> CREATETRACE_OBSERVABLE: currentSpan = lastSpan + CREATETRACE_OBSERVABLE -> CREATETRACE_OBSERVABLE: resultTrace = [lastSpan] + loop for i = 0; i < cachedTrace.spans.length; i++ + CREATETRACE_OBSERVABLE -> CREATETRACE_OBSERVABLE: get parentSpan of currentSpan + alt parentSpan + CREATETRACE_OBSERVABLE -> CREATETRACE_OBSERVABLE: insert parent span in resultTrace in front + else + CREATETRACE_OBSERVABLE -> CREATETRACE_OBSERVABLE: break loop + end + end + alt cachedTrace.masterSpan === currentSpan.spanId + CREATETRACE_OBSERVABLE -> CREATETRACE_OBSERVABLE: masterSpan.finishTimestamp = resultTrace[resultTrace.length - 1].finishTimestamp + CREATETRACE_OBSERVABLE -> TRACE_HANDLER: send resultTrace + deactivate CREATETRACE_OBSERVABLE + activate TRACE_HANDLER + end + end + end + group send Trace + loop trace elements + TRACE_HANDLER -> SPAN_SENDER: send each span + SPAN_SENDER -> APM: send span to APM + end + TRACE_HANDLER -> TRACE_HANDLER: unsubscribe scheduler for traceId + TRACE_HANDLER -> CACHE: drop cachedTrace + + end + end +@enduml \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/event-stream-processor/assets/diagrams/sequence/process-flow.svg b/website/versioned_docs/v1.0.1/technical/event-stream-processor/assets/diagrams/sequence/process-flow.svg new file mode 100644 index 000000000..0919b3c48 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/event-stream-processor/assets/diagrams/sequence/process-flow.svg @@ -0,0 +1,1028 @@ + + + + + + + + + + + Event Streaming Processor flow + + + + Central Services + + + + Event Stream Processor + + + + Cache + + + + Elasticsearch + + + + + + + + + + + + + + + + + + + + + + + + Notification topic + + + + + Notification topic + + + Topic Observable + + + + + Topic Observable + + + + + Tracing Observable + + + + + Tracing Observable + + + + + Caching Observable + + + + + Caching Observable + + + + + Check For Last Span Observable + + + + + Check For Last Span Observable + + + + + Create Trace Observable + + + + + Create Trace Observable + + + + + Send Trace Handler + + + + + Send Trace Handler + + + + + Send Span Handler + + + + + Send Span Handler + + + + + Cache Handler + + + + + Cache Handler + + + + + Cache Storage + + + + + Cache Storage + + + + + APM + + + + + APM + + + + + Elasticsearch API + + + + + Elasticsearch API + + + + + + + + New Event Message Received + + + + + 1 + + + Consume Event Message + + + + + Message: + + + { + + + "from": "payeefsp", + + + "to": "payerfsp", + + + "id": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + + + "content": { + + + "headers": { + + + "content-type": "applicationvnd.interoperability.transfers+json;version=1.0", + + + "date": "2019-05-28T16:34:41.000Z", + + + "fspiop-source": "payeefsp", + + + "fspiop-destination": "payerfsp" + + + }, + + + "payload": <payload> + + + }, + + + "type": "application/json", + + + "metadata": { + + + "event": { + + + "id": "3920382d-f78c-4023-adf9-0d7a4a2a3a2f", + + + "type": "trace", + + + "action": "span", + + + "createdAt": "2019-05-29T23:18:32.935Z", + + + "state": { + + + "status": "success", + + + "code": 0, + + + "description": "action successful" + + + }, + + + "responseTo": "1a396c07-47ab-4d68-a7a0-7a1ea36f0012" + + + }, + + + "trace": { + + + "service": "central-ledger-prepare-handler", + + + "traceId": "bbd7b2c7bbd7b2c7", + + + "parentSpanId": "44ba9bbc5840", + + + "spanId": "2aa9cd0a7e87", + + + "startTimestamp": "2015-08-29T11:22:09.815479Z", + + + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + + + "tags": { + + + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + + + "transctionType": "transfer", + + + "parentEventType": "bulk-prepare", + + + "parentEventAction": "prepare" + + + } + + + } + + + } + + + } + + + + + 2 + + + Send message for log purposes to custom index + + + + + 3 + + + Verify its tracing event Message + + + + + 4 + + + Send Message to Tracing Observable + + + + + Cache Span + + + + + 5 + + + Send Span Context, + + + metadata.State and Content + + + from Message + + + + + { + + + spanContext: { + + + service: "central-ledger-prepare-handler", + + + traceId: "bbd7b2c7bbd7b2c7", + + + parentSpanId: "44ba9bbc5840", + + + spanId: "2aa9cd0a7e87", + + + startTimestamp: "2015-08-29T11:22:09.815479Z", + + + finishTimestamp: "2015-08-29T11:22:09.815479Z", + + + tags: { + + + transctionId: "659ee338-c8f8-4c06-8aff-944e6c5cd694", + + + transctionType: "transfer", + + + parentEventType: "bulk-prepare", + + + parentEventAction: "prepare" + + + }, + + + state: metadata.state, + + + content + + + } + + + + + 6 + + + Get cachedTrace by traceId + + + + + alt + + + [the span should not be cached] + + + + + 7 + + + currentSpan + + + + + 8 + + + store to APM + + + + + 9 + + + Complete + + + + + + 10 + + + Validate transactionType, TransactionAction and service to match Config.START_CRITERIA && !parentSpandId + + + + + alt + + + [!cachedTrace] + + + + + 11 + + + Create new cachedTrace + + + + + { + + + spans: {}, + + + masterSpan: null, + + + lastSpan: null + + + } + + + + + alt + + + [!parentSpan] + + + + + 12 + + + Generate MasterSpanId + + + + + 13 + + + Make received span child of masterSpan + + + merge({ parentSpanId: MasterSpanId }, { ...spanContext }) + + + + + 14 + + + Create MasterSpanContext merge({ tags: { ...tags, masterSpan: MasterSpanId } }, + + + { ...spanContext }, + + + { spanId: MasterSpanId, service: `master-${tags.transactionType}` }) + + + + + 15 + + + Add masterSpan to cachedTrace + + + + + 16 + + + Add span to cachedTrace + + + + + { + + + spans: { + + + 2aa9cd0a7e87: { + + + state, + + + content + + + spanContext: { + + + "service": "central-ledger-prepare-handler", + + + "traceId": "bbd7b2c7bbd7b2c7", + + + "parentSpanId": + + + MasterSpanId + + + , + + + "spanId": "2aa9cd0a7e87", + + + "startTimestamp": "2015-08-29T11:22:09.815479Z", + + + "finishTimestamp": "2015-08-29T11:22:09.815479Z", + + + "tags": { + + + "transctionId": "659ee338-c8f8-4c06-8aff-944e6c5cd694", + + + "transctionType": "transfer", + + + "parentEventType": "bulk-prepare", + + + "parentEventAction": "prepare" + + + } + + + } + + + }, + + + MasterSpanId: + + + { + + + state, + + + content, + + + MasterSpanContext + + + } + + + }, + + + masterSpan: + + + MasterSpanContext + + + , + + + lastSpan: null + + + } + + + + + 17 + + + Update cachedTrace to Cache + + + + + alt + + + [cachedTrace not staled or expired] + + + + + 18 + + + unsubscribe from Scheduler + + + + + 19 + + + record cachedTrace + + + + + 20 + + + Reschedule scheduler for handling stale traces + + + + + 21 + + + Send traceId to check if last span has been received + + + and cached + + + + + Check for last span + + + + + 22 + + + Get cachedTrace by traceId + + + + + 23 + + + Sort spans by startTimestamp + + + + + loop + + + [for currentSpan of SortedSpans] + + + + + alt + + + [parentSpan] + + + + + 24 + + + isError = (errorCode in parentSpan + + + OR parentSpan status === failed + + + OR status === failed) + + + + + 25 + + + apply masterSpan and error tags from parent to current span in cachedTrace + + + + + alt + + + [!isLastSpan] + + + + + 26 + + + Update cachedTrace to Cache + + + + + alt + + + [cachedTrace not staled or expired] + + + + + 27 + + + unsubscribe from Scheduler + + + + + 28 + + + record cachedTrace + + + + + 29 + + + Reschedule scheduler for handling stale traces + + + + + + 30 + + + Validate transactionType, TransactionAction, service and isError + + + to match Config.START_CRITERIA && !parentSpandId + + + + + 31 + + + cachedTrace.lastSpan = currentSpan.spanContext + + + + + 32 + + + Update cachedTrace to Cache + + + + + alt + + + [cachedTrace not staled or expired] + + + + + 33 + + + unsubscribe from Scheduler + + + + + 34 + + + record cachedTrace + + + + + 35 + + + Reschedule scheduler for handling stale traces + + + + + 36 + + + Send traceId + + + + + Recreate Trace from Cached Trace + + + + + 37 + + + get cachedTrace by TraceId + + + + + alt + + + [cachedTrace.lastSpan AND cachedTrace.masterSpan] + + + + + 38 + + + currentSpan = lastSpan + + + + + 39 + + + resultTrace = [lastSpan] + + + + + loop + + + [for i = 0; i < cachedTrace.spans.length; i++] + + + + + 40 + + + get parentSpan of currentSpan + + + + + alt + + + [parentSpan] + + + + + 41 + + + insert parent span in resultTrace in front + + + + + + 42 + + + break loop + + + + + alt + + + [cachedTrace.masterSpan === currentSpan.spanId] + + + + + 43 + + + masterSpan.finishTimestamp = resultTrace[resultTrace.length - 1].finishTimestamp + + + + + 44 + + + send resultTrace + + + + + send Trace + + + + + loop + + + [trace elements] + + + + + 45 + + + send each span + + + + + 46 + + + send span to APM + + + + + 47 + + + unsubscribe scheduler for traceId + + + + + 48 + + + drop cachedTrace + + diff --git a/website/versioned_docs/v1.0.1/technical/faqs.md b/website/versioned_docs/v1.0.1/technical/faqs.md new file mode 100644 index 000000000..afb76ba68 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/faqs.md @@ -0,0 +1,158 @@ +# Frequently Asked Questions + +This document contains some of the frequently asked technical questions from the community. + +## 1. What is supported? + +Currently the Central ledger components are supported by the team. The DFSP components are outdated and thus the end-to-end environment and full setup is challenging to install. + +### 2. Can we connect directly to Pathfinder in a development environment? + +For the local and test environment, we recommend interfacing with the 'mock-pathfinder' service instead. Pathfinder is a 'paid by usage' service. + +Access the https://github.com/mojaloop/mock-pathfinder repository to download and install mock-pathfinder. Run command npm install in mock-pathfinder directory to install dependencies after this update Database_URI in mock-pathfinder/src/lib/config.js. + +### 3. Should i register DFSP via url http://central-directory/commands/register or i need to update configuration in default.json? + +You should register using the API provided, using postman or curl. Client is using LevelOne code. Needs to implement the current Mojaloop release with the current Postman scripts. + +### 4. Status of the pod pi3-kafka-0 is still on CrashLoopBackOff? + +- More background related to the question: + + When I tired to get logs of the container centralledger-handler-admin-transfer, I get the following error: + Error from server (BadRequest): container "centralledger-handler-admin-transfer" in pod "pi3-centralledger-handler-admin-transfer-6787b6dc8d-x68q9" is waiting to start: PodInitializing + And the status of the pod pi3-kafka-0 is still on CrashLoopBackOff. + I am using a vps on ubuntu 16.04 with RAM 12GB, 2vCores, 2.4GHz, Rom 50GB at OVH for the deployment. + +Increased RAM to 24 GB and CPU to 4 resolved the issues. Appears to be a timeout on Zookeeper due depletion of available resources, resulting in the services shutting down. + +### 5. Why am I getting an error when we try to create new DFSP using Admin? + +Please insure you are using the most current Postman scripts available on https://github.com/mojaloop/mock-pathfinder repository. + + +### 6. Can I spread Mojaloop components over different physical machines and VM's? + +You should be able to setup on different VM's or physical machines. The distribution pretty much depend on your requirements and would be implementation specific. We utilise Kubernetes to assist with the Container Orchestration. This enables us to schedule the deployments through the Kubernetes runtime to specific machines if required, and request specific resources if required. The helm charts in the helm repository could be used as guideline to how best allocate and group the components in your deployment. Naturally you would need to update the configurations to complement your custom implementation. + +### 7. Can we expect all the endpoints defined in the API document are implemented in Mojaloop? + +The Mojaloop Specification API for transfers and the Mojaloop Open Source Switch implementation are independent streams, though obviously the implementation is based on the Specification. Based on the use-cases prioritized for a time-frame and based on the end-points needed to support those use-cases, implementation will be done. If a few end-points are not prioritized then implementation for them may not be available. However, I think the goal is to eventually support all the end-points specified though it may take time. Thanks for the collection. We do have some of these on the ‘postman’ repo in the mojaloop GitHub org. + +### 8. Does Mojaloop store the payment initiator FSP’s quote/status info? + +At the moment, the Mojaloop Open source Switch implementation does *not* store Quotes related information. The onus is on the Payer, Payee involved in the process to store the relevant information. + +### 9. Does Mojaloop handle workflow validation? + +Not at the moment, but this may happen in the future. Regarding correlating requests that are related to a specific transfer, you may look at the ‘transaction’ end-point/resource in the Specification for more information on this. In addition to this, I can convey that some background work is ongoing regarding the specification to make this correlation more straight-forward and simpler i.e., to correlate quote and transfer requests that come under a single transaction. + + +### 10. How to register a new party in Mojaloop? + +There is no POST on /parties resource, as specified in section 6.1.1 of the API Defintion. Please refer to section: 6.2.2.3 `POST /participants//` in the API Defintion. + +” _The HTTP request `POST /participants//` (or `POST /participants///`) is used to create information on the server regarding the provided identity, defined by ``, ``, and optionally `` (for example, POST_ + _/participants/MSISDN/123456789 or POST /participants/BUSINESS/shoecompany/employee1). See Section 5.1.6.11 for more information regarding addressing of a Party._ ”. + +### 11. Does the participant represent an account of a customer in a bank? + +For more on this, please refer to this doc (Section 3..2): https://github.com/mojaloop/mojaloop-specification/blob/develop/Generic%20Transaction%20Patterns.pdf. + +” _In the API, a Participant is the same as an FSP that is participating in an Interoperability Scheme. The primary purpose of the logical API resource Participants is for FSPs to find out in which other FSP a counterparty in an interoperable financial transaction is located. There are also services defined for the FSPs to provision information to a common system._ ” + +In essence, a participant is any FSP participating in the Scheme (usually not a customer). For account lookup, a directory service such as *Pathfinder* can be used, which provides user lookup and the mapping. If such a directory service is not provided, an alternative is provided in the Specification, where the Switch hosts an Account Lookup Service (ALS) but to which the participants need to register parties. I addressed this earlier. But one thing to note here is that the Switch does not store the details, just the mapping between an ID and an FSP and then the calls to resolve the party are sent to that FSP. + +https://github.com/mojaloop/mojaloop-specification CORE RELATED (Mojaloop): + +This repo contains the specification document set of the Open API for FSP Interoperability - mojaloop/mojaloop-specification. + +### 12. How to register _trusted_ payee to a payer, to skip OTP? + +To skip the OTP, the initial request on the /transactionRequests from the Payee can be programmatically (or manually for that matter) made to be approved without the use of the /authorizations endpoint (that is need for OTP approval). Indeed the FSP needs to handle this, the Switch does not. This is discussed briefly in section 6.4 of the Specification. + +### 13. Receiving a 404 error when attempting to access or load kubernetes-dashboard.yaml file? + +From the official kubernetes github repository in the README.md, the latest link to use is "https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml". Be sure to always verify 3rd party links before implementing. Open source applications are always evolving. + +### 14. When installing nginx-ingress for load balancing & external access - Error: no available release name found? + +Please have a look at the following addressing a similar issue. To summarise - it is most likely an RBAC issue. Have a look at the documentation to set up Tiller with RBAC. https://docs.helm.sh/using_helm/#role-based-access-control goes into detail about this. The issue logged: helm/helm#3839. + +### 15. Received "ImportError: librdkafka.so.1: cannot open shared object file: No such file or directory" when running `npm start' command. + +Found a solution here https://github.com/confluentinc/confluent-kafka-python/issues/65#issuecomment-269964346 +GitHub +ImportError: librdkafka.so.1: cannot open shared object file: No such file or directory · Issue #65 · confluentinc/confluent-kafka-python +Ubuntu 14 here, pip==7.1.2, setuptools==18.3.2, virtualenv==13.1.2. First, I want to build latest stable (seems it's 0.9.2) librdkafka into /opt/librdkafka. curl https://codeload.github.com/ede... + +Here are the steps to rebuild librdkafka: + +git clone https://github.com/edenhill/librdkafka && cd librdkafka && git checkout ` + +cd librdkafka && ./configure && make && make install && ldconfig + +After that I'm able to import stuff without specifying LD_LIBRARY_PATH. +GitHub +edenhill/librdkafka +The Apache Kafka C/C++ library. Contribute to edenhill/librdkafka development by creating an account on GitHub. + +### 16. Can we use mojaloop as open-source mobile wallet software or mojaloop does interoperability only? + +We can use mojaloop for interoperability to support mobile wallet and other such money transfers. This is not a software for a DFSP (there are open source projects that cater for these such as Finserv etc). Mojaloop is for a Hub/Switch primarily and an API that needs to be implemented by a DFSP. But this is not for managing mobile wallets as such. + +### 17. Describe companies that helps to deploy & support for mojaloop? + +Mojaloop is an open source software and specification. + +### 18. Can you say something about mojaloop & security? + +The Specification is pretty standard and has good security standards. But these need to be implemented by the adopters and deployers. Along with this, the security measures need to be coupled with other Operational and Deployment based security measures. Moreover, the coming few months will focus on security perspective for the Open Source community. + +### 19. What are the benefit(s) from using mojaloop as interoperabilty platform? + +Benefits: Right now for example, an Airtel mobile money user can transfer to another Airtel mobile money user only. With this, he/she can transfer to any Financial service provider such as another mobile money provider or any other bank account or Merchant that is connected to the Hub, irrespective of their implementation. They just need to be connected to the same Switch. Also, this is designed for feature phones so everyone can use it. + +### 20. What are the main challenges that companies face using mojaloop? + +At this point, the main challenges are around expectations. Expectations of the adopters of mojaloop and what really mojaloop is. A lot of adopters have different understanding of what mojaloop is and about its capabilities. If they have a good understanding, a lot of current challenges are mitigated.. +Yes, forensic logging is a security measure as well for auditing purposes which will ensure there is audit-able log of actions and that everything that is a possible action of note is logged and rolled up, securely after encryption at a couple of levels. + +### 21. Is forensic logging/audit in mojaloop , is it related with securing the inter-operability platform? + +This also ensures all the services always run the code they’re meant to run and anything wrong/bad is stopped from even starting up. Also, for reporting and auditors, reports can have a forensic-log to follow. + +### 22. How do the financial service providers connect with mojaloop? + +There is an architecture diagram that presents a good view of the integration between the different entities. https://github.com/mojaloop/docs/blob/master/Diagrams/ArchitectureDiagrams/Arch-Flows.svg. + +### 23. Is there any open source ISO8583-OpenAPI converter/connector available? + +I don't believe a generic ISO8583 `<-> Mojaloop integration is available currently. We're working on some "traditional payment channel" to Mojaloop integrations (POS and ATM) which we hope to demo at the next convening. These would form the basis for an ISO8583 integration we might build and add to the OSS stack but bare in mind that these integrations will be very use case specific. + +### 24. How do I know the end points to setup postman for testing the deployment? + +On the Kubernetes dashboard, select the correct NAMESPACE. Go to Ingeresses. Depending on how you deployed the helm charts, look for 'moja-centralledger-service'. Click on edit, and find the tag ``. This would contain the endpoint for this service. + +### 25. Why are there no reversals allowed on a Mojaloop? + +*Irrevocability* is a core Level One Principle (edited) and not allowing reversals is essential for that. Here is the section from the API Definition addressing this: + +_*6.7.1.2 Transaction Irrevocability*_ +_The API is designed to support irrevocable financial transactions only; this means that a financial transaction cannot be changed, cancelled, or reversed after it has been created. This is to simplify and reduce costs for FSPs using the API. A large percentage of the operating costs of a typical financial system is due to reversals of transactions._ +_As soon as a Payer FSP sends a financial transaction to a Payee FSP (that is, using POST /transfers including the end-to-end financial transaction), the transaction is irrevocable from the perspective of the Payer FSP. The transaction could still be rejected in the Payee FSP, but the Payer FSP can no longer reject or change the transaction. An exception to this would be if the transfer’s expiry time is exceeded before the Payee FSP responds (see Sections 6.7.1.3 and 6.7.1.5 for more information). As soon as the financial transaction has been accepted by the Payee FSP, the transaction is irrevocable for all parties._ + +However, *Refunds* is a use case supported by the API. + +### 26. ffg. error with microk8s installation "MountVolume.SetUp failed"? + +Would appear if it is a space issue, but more the 100GiB of EBS storage was allocated. +The issue resolved itself after 45 minutes. Initial implementation of the mojaloop project can take a while to stabilize. + +### 27. Why am I getting this error when trying to create a participant: "Hub reconciliation account for the specified currency does not exist"? + +You need to create the corresponding Hub accounts (HUB_MULTILATERAL_SETTLEMENT and HUB_RECONCILIATION) for the specified currency before setting up the participants. +In this Postman collection you can find the requests to perform the operation in the "Hub Account" folder: https://github.com/mojaloop/postman/blob/master/OSS-New-Deployment-FSP-Setup.postman_collection.json + +Find also the related environments in the Postman repo: https://github.com/mojaloop/postman diff --git a/website/versioned_docs/v1.0.1/technical/fraud-services/README.md b/website/versioned_docs/v1.0.1/technical/fraud-services/README.md new file mode 100644 index 000000000..d44482e5b --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/fraud-services/README.md @@ -0,0 +1,5 @@ +# Fraud Services + +Provides an overview of the monitoring and preventative measures in consideration to prevent and discourage fraudulent activities within a Mojaloop scheme. + +Relevant artefacts available for public consumption are shared within [related-documents](./related-documents/documentation.md) section. diff --git a/website/versioned_docs/v1.0.1/technical/fraud-services/related-documents/documentation.md b/website/versioned_docs/v1.0.1/technical/fraud-services/related-documents/documentation.md new file mode 100644 index 000000000..920da7b7f --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/fraud-services/related-documents/documentation.md @@ -0,0 +1,7 @@ +# Fraud Services + +Artefacts available for public reference related to the preventative measures in preventing and discouraging fraudulent activities within the ecosystem. + +## List of current artefacts + +#### [Mojaloop Ecosystem Fraud Overview Document](https://github.com/mojaloop/documentation-artifacts/blob/master/presentations/April%202019%20PI-6_OSS_community%20session/Mojaloop-Fraud-20190410.pdf) diff --git a/website/versioned_docs/v1.0.1/technical/ml-testing-toolkit/README.md b/website/versioned_docs/v1.0.1/technical/ml-testing-toolkit/README.md new file mode 100644 index 000000000..0260e22a2 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/ml-testing-toolkit/README.md @@ -0,0 +1,16 @@ +Mojaloop Testing Toolkit +============================= + +The **Mojaloop Testing Toolkit** was designed to help Mojaloop Schemes scale effectively by easing the DFSP Onboarding process. Schemes can provide a set of rules and tests on the toolkit and DFSPs can use it for self testing (or self-certification in some cases). This ensures that DFSPs are well and truly ready with their implementations to be integrated with the Scheme and allows for a quick and smooth onboarding process for the Mojaloop Hubs, thereby increasing their scalability. + +This was initially aimed at FSPs/Participants that would like to participate in a Mojaloop scheme. However, in its current form, this tool set can potentially be used by both DFSPs and _Mojaloop Hubs_ to verify integration between the 2 entities. Intentionally built as a standard integration testing tool between a _Digital Financial Service Provider (DFSP)_ and the _Mojaloop Switch_ (Hub), to facilitate testing. + +For additional background on the Self Testing Toolkit, please see [Mojaloop Testing Toolkit](https://github.com/mojaloop/ml-testing-toolkit/blob/master/documents/Mojaloop-Testing-Toolkit.md). It would be to the particpant's benefit to familiarise themselves with the understanding of the [Architecture Diagram](https://github.com/mojaloop/ml-testing-toolkit/blob/master/documents/Mojaloop-Testing-Toolkit.md#7-architecture) that explains the various components and related flows. + +## Usage Guides + +For Web interface follow this [Usage Guide](https://github.com/mojaloop/ml-testing-toolkit/blob/master/documents/User-Guide.md) + +For Command line tool follow this [CLI User Guide](https://github.com/mojaloop/ml-testing-toolkit/blob/master/documents/User-Guide-CLI.md) + +**If you have your own DFSP implementation you can point the peer endpoint to Mojaloop Testing Toolkit on port 5000 and try to send requests from your implementation instead of using mojaloop-simulator.** diff --git a/website/versioned_docs/v1.0.1/technical/overview/README.md b/website/versioned_docs/v1.0.1/technical/overview/README.md new file mode 100644 index 000000000..373cbfa93 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/README.md @@ -0,0 +1,24 @@ +# Mojaloop Hub + +There are several components that make up the Mojaloop ecosystem. The Mojaloop Hub is the primary container and reference we use to describe the core Mojaloop components. + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture: + +![Current Mojaloop Architecture Overview](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ + +These consist of: + +* The **Mojaloop API Adapters** (**ML-API-Adapter**) provide the standard set of interfaces a DFSP can implement to connect to the system for Transfers. A DFSP that wants to connect up can adapt our example code or implement the standard interfaces into their own software. The goal is for it to be as straightforward as possible for a DFSP to connect to the interoperable network. +* The **Central Services** (**CS**) provide the set of components required to move money from one DFSP to another through the Mojaloop API Adapters. This is similar to how money moves through a central bank or clearing house in developed countries. The Central Services contains the core Central Ledger logic to move money but also will be extended to provide fraud management and enforce scheme rules. +* The **Account Lookup Service** (**ALS**) provides a mechanism to resolve FSP routing information through the Participant API or orchestrate a Party request based on an internal Participant look-up. The internal Participant look-up is handled by a number of standard Oracle adapter or services. Example Oracle adapter/service would be to look-up Participant information from Pathfinder or a Merchant Registry. These Oracle adapters or services can easily be added depending on the schema requirements. +* The **Quoting Service** (**QA**) provides Quoting is the process that determines any fees and any commission required to perform a financial transaction between two FSPs. It is always initiated by the Payer FSP to the Payee FSP, which means that the quote flows in the same way as a financial transaction. +* The **Simulator** (**SIM**) mocks several DFSP functions as follows: + * Oracle end-points for Oracle Participant CRUD operations using in-memory cache; + * Participant end-points for Oracles with support for parameterized partyIdTypes; + * Parties end-points for Payer and Payee FSPs with associated callback responses; + * Transfer end-points for Payer and Payee FSPs with associated callback responses; and + * Query APIs to verify transactions (requests, responses, callbacks, etc) to support QA testing and verification. + +On either side of the Mojaloop Hub there is sample open source code to show how a DFSP can send and receive payments and the client that an existing DFSP could host to connect to the network. diff --git a/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI11.svg b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI11.svg new file mode 100644 index 000000000..df9396cae --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI11.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    Operational Monitoring
    Quality Assurance
    Quality Assurance
    Core Components
    Core Components
    API - Security / Policy / Ingress / Egress
    API - Security / Policy / Ingress / Egress
    Continuous Integration & Delivery
    Continuous Integration & Delivery
    Container Management & Orchestration
    Container Management & Orchestration
    Supporting Components
    Supporting Components
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    Helm...
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    Kubernetes...
    Docker
    (Container Engine)
    Docker...
    Infrastructure
    (AWS, Azure, On-Prem)
    Infrastructure...
    EFK - ElasticSearch / Fluentd / Kibana
    (Log Search / Collection / Monitoring / Tracing)
    EFK - ElasticSearch / Fluentd / Kibana...
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    Promfana - Prometheus / Grafana...
    Open Tracing
    (Distributed Tracing)
    Open Tracing...
    Rancher
    (Infrastructure Management)
    Rancher...
    Mojaloop API Adapter
    (API - Transfers)
    Mojaloop API Adapter...
    Central-Services
    (API - Operational Admin)
    Central-Services...
    Central-Services
    (Handler - Prepare)
    Central-Services...
    Central-Services
    (Handler - Position)
    Central-Services...
    Central-Services
    (Handler - Fulfil)
    Central-Services...
    Central-Services
    (Handler - Get Transfers)
    Central-Services...
    Central-Services
    (Handler - Timeout)
    Central-Services...
    Central-KMS
    (Future - Key Management Store)
    Central-KMS...
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    ALS - Account-Lookup-Service...
    ALS-Oracle-Pathfinder
    (MSISDN Lookup)
    ALS-Oracle-Pathfinder...
    Central-Event-Processor
    (CEP)
    Central-Event-Processor...
    Email-Notifier
    (Handler - Email)
    Email-Notifier...
    Central-Services
    (Handler - Admin)
    Central-Services...
    Circle-CI
    (Test, Build, Deploy)
    Circle-CI...
    Docker Hub
    (Container Repository)
    Docker Hub...
    NPM Org
    (NPM Repository)
    NPM Org...
    GitBooks
    (Documetation)
    GitBooks...
    API Gateway
    (Future - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)
    API Gateway...
    Central-Services
    (Handler - Bulk Prepare)
    Central-Services...
    Central-Services
    (Handler - Bulk Fulfil)
    Central-Services...
    Central-Services
    (Handler - Bulk Process)
    Central-Services...
    Mojaloop API Adapter
    (API - Bulk Transfers)
    Mojaloop API Adapter...
    Forensic-Logging
    (Future - Auditing)
    Forensic-Logging...
    Central-Settlements
    (API - Settlement)
    Central-Settlements...
    Event-Stream-Processor
    Logs, Error, Audits, Tracing)
    Event-Stream-Processor...
    Simulators
    (API, SDK, FSP & Oracle)
    Simulators...
    On-boarding
    (Postman - Scripts)
    On-boarding...
    Functional Tests
    (Postman - Scripts)
    Functional Tests...
    Self Testing Toolkit
    (
    POC UI)
    Self Testing Toolkit...
    License, Security & Audit
    (Dependencies)
    License, Security & Audit...
    Persistence
    Persistence
    Redis
    (SDK - Cache)
    Redis...
    MongoDB
    (CEP - Data)
    MongoDB...
    MySQL
    (Percona - Data)
    MySQL...
    Kafka
    (Message - Streaming)
    Kafka...
    Transaction Request Service
    (API - Transaction)
    Transaction Request Service...
    Software Dev Kits
    Software Dev Kits
    Oracle SDK
    (Participant Store)
    Oracle SDK...
    Mojaloop SDK 
    (FSP Payer/Payee)
    Mojaloop SDK...
    Event SDK
    (Audit, Log, Trace - Client/Server)
    Event SDK...
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    Event-Sidecar...
    Mojaloop API Adapter
    (Handler - Notifications)
    Mojaloop API Adapter...
    Quoting-Service
    (API - Quotes)
    Quoting-Service...
    Finance-Portal-UI
    (API - Bulk Transfers)
    Finance-Portal-UI...
    Settlement-Management
    (Closing, Recon report, Cronjob)
    Settlement-Management...
    Schema-Adapter
    (SDK - Parties, Participants, Quotes, Transfers)
    Schema-Adapter...
    IaC (Infra as Code) Tools
    (Future - Automated
    Prov / Depl / Upgrades)
    IaC (Infra as Code) Tools...
    Third Party API Adapter
    (PoC - API - Transfers)
    Third Party API Adapter...
    Third Party API Adapter
    (PoC - Handler - Notifications)
    Third Party API Adapter...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI12.svg b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI12.svg new file mode 100644 index 000000000..763c5697e --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI12.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    Operational Monitoring
    Quality Assurance
    Quality Assurance
    Core Components
    Core Components
    API - Security / Policy / Ingress / Egress
    API - Security / Policy / Ingress / Egress
    Continuous Integration & Delivery
    Continuous Integration & Delivery
    Container Management & Orchestration
    Container Management & Orchestration
    Supporting Components
    Supporting Components
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    Helm...
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    Kubernetes...
    Docker
    (Container Engine)
    Docker...
    Infrastructure
    (AWS, Azure, On-Prem)
    Infrastructure...
    EFK - ElasticSearch / Fluentd / Kibana
    (Log Search / Collection / Monitoring / Tracing)
    EFK - ElasticSearch / Fluentd / Kibana...
    Promfana - Prometheus / Grafana
    (Metrics - Collection / Monitoring)
    Promfana - Prometheus / Grafana...
    Open Tracing
    (Distributed Tracing)
    Open Tracing...
    Rancher
    (Infrastructure Management)
    Rancher...
    Mojaloop API Adapter
    (API - Transfers)
    Mojaloop API Adapter...
    Central-Services
    (API - Operational Admin)
    Central-Services...
    Central-Services
    (Handler - Prepare)
    Central-Services...
    Central-Services
    (Handler - Position)
    Central-Services...
    Central-Services
    (Handler - Fulfil)
    Central-Services...
    Central-Services
    (Handler - Get Transfers)
    Central-Services...
    Central-Services
    (Handler - Timeout)
    Central-Services...
    Central-KMS
    (Future - Key Management Store)
    Central-KMS...
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    ALS - Account-Lookup-Service...
    ALS-Oracle-Pathfinder
    (MSISDN Lookup)
    ALS-Oracle-Pathfinder...
    Central-Event-Processor
    (CEP)
    Central-Event-Processor...
    Email-Notifier
    (Handler - Email)
    Email-Notifier...
    Central-Services
    (Handler - Admin)
    Central-Services...
    Circle-CI
    (Test, Build, Deploy)
    Circle-CI...
    Docker Hub
    (Container Repository)
    Docker Hub...
    NPM Org
    (NPM Repository)
    NPM Org...
    GitBooks
    (Documetation)
    GitBooks...
    API Gateway (IaC)
    (API - Parties, Participants, Quotes, Transfers, Bulk Transfers; OAuth; MTLS)
    API Gateway (IaC)...
    Central-Services
    (Handler - Bulk Prepare)
    Central-Services...
    Central-Services
    (Handler - Bulk Fulfil)
    Central-Services...
    Central-Services
    (Handler - Bulk Process)
    Central-Services...
    Mojaloop API Adapter
    (API - Bulk Transfers)
    Mojaloop API Adapter...
    Forensic-Logging
    (Future - Auditing)
    Forensic-Logging...
    Central-Settlements
    (API - Settlements)
    Central-Settlements...
    Event-Stream-Processor
    (Logs, Error, Audits, Tracing)
    Event-Stream-Processor...
    Simulators
    (API, SDK, FSP & Oracle)
    Simulators...
    On-boarding
    (Postman - Scripts)
    On-boarding...
    Functional Tests
    (Postman - Scripts)
    Functional Tests...
    Testing Toolkit
    (
    UI, CLI & Backend)
    Testing Toolkit...
    License, Security & Audit
    (Dependencies)
    License, Security & Audit...
    Persistence
    Persistence
    Redis
    (SDK - Cache)
    Redis...
    MongoDB
    (CEP - Data)
    MongoDB...
    MySQL
    (Percona - Data)
    MySQL...
    Kafka
    (Message - Streaming)
    Kafka...
    Transaction Request Service
    (API - Transaction)
    Transaction Request Service...
    Software Dev Kits
    Software Dev Kits
    Oracle SDK
    (Participant Store)
    Oracle SDK...
    Mojaloop SDK 
    (FSP Payer/Payee)
    Mojaloop SDK...
    Event SDK
    (Audit, Log, Trace - Client/Server)
    Event SDK...
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    Event-Sidecar...
    Mojaloop API Adapter
    (Handler - Notifications)
    Mojaloop API Adapter...
    Quoting-Service
    (API - Quotes)
    Quoting-Service...
    Finance-Portal-UI
    (API - Bulk Transfers)
    Finance-Portal-UI...
    Settlement-Management
    (Closing, Recon report, Cronjob)
    Settlement-Management...
    Schema-Adapter
    (SDK - Parties, Participants, Quotes, Transfers)
    Schema-Adapter...
    IaC (Infra as Code) Tools
    (Automated Lab/Env Setup & Configuration)
    IaC (Infra as Code) Tools...
    Third Party API Adapter
    (PoC - API - Transfers)
    Third Party API Adapter...
    Third Party API Adapter
    (PoC - Handler - Notifications)
    Third Party API Adapter...
    Central-Settlements
    (Handler - Settlement Windows)
    Central-Settlements...
    Central-Settlements
    (Handler - Transfer Settlements)
    Central-Settlements...
    Viewer does not support full SVG 1.1
    diff --git a/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg new file mode 100644 index 000000000..06680fbae --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    Operational Monitoring
    Quality Assurance
    Quality Assurance
    Core Components
    Core Components
    API - Security / Policy / Ingress / Egress
    API - Security / Policy / Ingress / Egress
    Continuous Integration & Delivery
    Continuous Integration & Delivery
    Container Management & Orchestration
    Container Management & Orchestration
    Supporting Components
    Supporting Components
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    Helm...
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    Kubernetes...
    Docker
    (Container Engine)
    Docker...
    Infrastructure
    (AWS, Azure, On-Prem)
    Infrastructure...
    EFK - ElasticSearch / Fluentd / Kibana
    (Log Search / Collection / Monitoring / Tracing)
    EFK - ElasticSearch / Fluentd / Kibana...
    Promfana - Prometheus / Grafana
    (Metrics - Collection / Monitoring)
    Promfana - Prometheus / Grafana...
    Open Tracing
    (Distributed Tracing)
    Open Tracing...
    Rancher
    (Infrastructure Management)
    Rancher...
    Mojaloop API Adapter
    (API - Transfers)
    Mojaloop API Adapter...
    Central-Services
    (API - Operational Admin)
    Central-Services...
    Central-Services
    (Handler - Prepare)
    Central-Services...
    Central-Services
    (Handler - Position)
    Central-Services...
    Central-Services
    (Handler - Fulfil)
    Central-Services...
    Central-Services
    (Handler - Get Transfers)
    Central-Services...
    Central-Services
    (Handler - Timeout)
    Central-Services...
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    ALS - Account-Lookup-Service...
    ALS-Oracle-Pathfinder
    (MSISDN Lookup)
    ALS-Oracle-Pathfinder...
    Central-Event-Processor
    (CEP)
    Central-Event-Processor...
    Email-Notifier
    (Handler - Email)
    Email-Notifier...
    Central-Services
    (Handler - Admin)
    Central-Services...
    Circle-CI
    (Test, Build, Deploy)
    Circle-CI...
    Docker Hub
    (Container Repository)
    Docker Hub...
    NPM Org
    (NPM Repository)
    NPM Org...
    GitBooks
    (Documetation)
    GitBooks...
    API Gateway (IaC)
    (API - Parties, Participants, Quotes, Transfers, Bulk Transfers; OAuth; MTLS)
    API Gateway (IaC)...
    Central-Services
    (Handler - Bulk Prepare)
    Central-Services...
    Central-Services
    (Handler - Bulk Fulfil)
    Central-Services...
    Central-Services
    (Handler - Bulk Process)
    Central-Services...
    Mojaloop API Adapter
    (API - Bulk Transfers)
    Mojaloop API Adapter...
    Central-Settlements
    (API - Settlements)
    Central-Settlements...
    Event-Stream-Processor
    (Logs, Error, Audits, Tracing)
    Event-Stream-Processor...
    Simulators
    (API, SDK, FSP & Oracle)
    Simulators...
    On-boarding
    (Postman - Scripts)
    On-boarding...
    Functional Tests
    (Postman - Scripts)
    Functional Tests...
    Testing Toolkit
    (
    UI, CLI & Backend)
    Testing Toolkit...
    License, Security & Audit
    (Dependencies)
    License, Security & Audit...
    Persistence
    Persistence
    Redis
    (SDK - Cache)
    Redis...
    MongoDB
    (CEP - Data)
    MongoDB...
    MySQL
    (Percona - Data)
    MySQL...
    Kafka
    (Message - Streaming)
    Kafka...
    Transaction Request Service
    (API - Transaction)
    Transaction Request Service...
    Software Dev Kits
    Software Dev Kits
    Oracle SDK
    (Participant Store)
    Oracle SDK...
    Mojaloop SDK 
    (FSP Payer/Payee)
    Mojaloop SDK...
    Event SDK
    (Audit, Log, Trace - Client/Server)
    Event SDK...
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    Event-Sidecar...
    Mojaloop API Adapter
    (Handler - Notifications)
    Mojaloop API Adapter...
    Quoting-Service
    (API - Quotes)
    Quoting-Service...
    Finance-Portal-UI
    (API - Bulk Transfers)
    Finance-Portal-UI...
    Settlement-Management
    (Closing, Recon report, Cronjob)
    Settlement-Management...
    Schema-Adapter
    (SDK - Parties, Participants, Quotes, Transfers)
    Schema-Adapter...
    IaC (Infra as Code) Tools
    (Automated Lab/Env Setup & Configuration)
    IaC (Infra as Code) Tools...
    Third Party API Adapter
    (PoC - API - Transfers)
    Third Party API Adapter...
    Third Party API Adapter
    (PoC - Handler - Notifications)
    Third Party API Adapter...
    Central-Settlements
    (Handler - Deferred)
    Central-Settlements...
    Central-Settlements
    (Handler - Gross)
    Central-Settlements...
    Central-Settlements
    (Handler - Rules)
    Central-Settlements...
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI3.svg b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI3.svg new file mode 100644 index 000000000..4a658b897 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI3.svg @@ -0,0 +1,3 @@ + + +
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    [Not supported by viewer]
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    [Not supported by viewer]
    Docker
    (Container Engine)
    [Not supported by viewer]
    Infrastructure
    (AWS, Azure, On-Prem)
    [Not supported by viewer]
    EFK - ElasticSearch / Fluentd / Kabana
    (Log Search / Collection / Monitoring)
    [Not supported by viewer]
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    [Not supported by viewer]
    Zipkin
    (Future - Distributed Tracing)
    [Not supported by viewer]
    Rancher
    (Infrastructure Management)
    [Not supported by viewer]
    PostgreSQL
    (Deprecated - Data)
    [Not supported by viewer]
    MongoDB
    (CEP - Data)
    [Not supported by viewer]
    MySQL
    (Percona - Data)
    [Not supported by viewer]
    Kafka
    (Message - Streaming)
    [Not supported by viewer]
    Mojaloop API Adapter
    (API - Transfers)
    [Not supported by viewer]
    Mojaloop API Adapter
    (Handler - Notifications)
    [Not supported by viewer]
    Central-Services
    (API - Operational Admin)
    [Not supported by viewer]
    Central-Services
    (Handler - Prepare)
    [Not supported by viewer]
    Central-Services
    (Handler - Position)
    [Not supported by viewer]
    Central-Services
    (Handler - Fulfil)
    [Not supported by viewer]
    Central-Services
    (Handler - Get Transfers)
    [Not supported by viewer]
    Central-Services
    (Handler - Timeout)
    [Not supported by viewer]
    Simulator
    (API - QA FSP Simulator)
    [Not supported by viewer]
    Forensic-Logging-Sidecar
    (Auditing)
    [Not supported by viewer]
    Central-KMS
    (Key Management Store)
    [Not supported by viewer]
    Central-Directory
    (Participant Lookup)
    [Not supported by viewer]
    Central-End-User-Registry
    (Custom Participant Store)
    [Not supported by viewer]
    Mock-Pathfinder
    (Mocked Pathfinder)
    [Not supported by viewer]
    Central-Event-Processor
    (CEP)
    [Not supported by viewer]
    Email-Notifier
    (Handler - Email)
    [Not supported by viewer]
    Central-Services
    (Handler - Admin)
    [Not supported by viewer]
    Central-Hub
    (Retired - Operational Web Interface)
    [Not supported by viewer]
    Interop-Switch
    (To be Retired - Transfers, Quotes, Parties, Participants)
    [Not supported by viewer]
    Circle-CI
    (Test, Build, Deploy)
    [Not supported by viewer]
    Docker Hub
    (Container Repository)
    [Not supported by viewer]
    NPM Org
    (NPM Repository)
    [Not supported by viewer]
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI5.svg b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI5.svg new file mode 100644 index 000000000..ac0b21621 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI5.svg @@ -0,0 +1,3 @@ + + +
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    [Not supported by viewer]
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    [Not supported by viewer]
    Docker
    (Container Engine)
    [Not supported by viewer]
    Infrastructure
    (AWS, Azure, On-Prem)
    [Not supported by viewer]
    EFK - ElasticSearch / Fluentd / Kabana
    (Log Search / Collection / Monitoring)
    [Not supported by viewer]
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    [Not supported by viewer]
    Zipkin
    (Future - Distributed Tracing)
    [Not supported by viewer]
    Rancher
    (Infrastructure Management)
    [Not supported by viewer]
    PostgreSQL
    (Deprecated - Data)
    [Not supported by viewer]
    MongoDB
    (CEP - Data)
    [Not supported by viewer]
    MySQL
    (Percona - Data)
    [Not supported by viewer]
    Kafka
    (Message - Streaming)
    [Not supported by viewer]
    Mojaloop API Adapter
    (API - Transfers)
    [Not supported by viewer]
    Mojaloop API Adapter
    (Handler - Notifications)
    [Not supported by viewer]
    Central-Services
    (API - Operational Admin)
    [Not supported by viewer]
    Central-Services
    (Handler - Prepare)
    [Not supported by viewer]
    Central-Services
    (Handler - Position)
    [Not supported by viewer]
    Central-Services
    (Handler - Fulfil)
    [Not supported by viewer]
    Central-Services
    (Handler - Get Transfers)
    [Not supported by viewer]
    Central-Services
    (Handler - Timeout)
    [Not supported by viewer]
    Simulator
    (API - QA FSP Simulator)
    [Not supported by viewer]
    Forensic-Logging-Sidecar
    (Auditing)
    [Not supported by viewer]
    Central-KMS
    (Key Management Store)
    [Not supported by viewer]
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    [Not supported by viewer]
    ALS-Oracle-Msisdn-Service
    (Pathfinder Lookup Adapter)
    [Not supported by viewer]
    Mock-Pathfinder
    (Mocked Pathfinder)
    [Not supported by viewer]
    Central-Event-Processor
    (CEP)
    [Not supported by viewer]
    Email-Notifier
    (Handler - Email)
    [Not supported by viewer]
    Central-Services
    (Handler - Admin)
    [Not supported by viewer]
    Moja-Hub
    (Future - Operational Web Interface)
    [Not supported by viewer]
    Interop-Switch
    (To be Retired - Transfers, Quotes, Parties, Participants)
    [Not supported by viewer]
    Circle-CI
    (Test, Build, Deploy)
    [Not supported by viewer]
    Docker Hub
    (Container Repository)
    [Not supported by viewer]
    NPM Org
    (NPM Repository)
    [Not supported by viewer]
    GitBooks
    (Documetation)
    [Not supported by viewer]
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI6.svg b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI6.svg new file mode 100644 index 000000000..9697dfc5b --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI6.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    <b>Operational Monitoring</b>
    Quality Assurance
    <b>Quality Assurance</b>
    Core
    <b>Core</b>
    API - Security / Policy / Ingress / Egress
    <b>API - Security / Policy / Ingress / Egress</b>
    Continuous Integration & Delivery
    <b>Continuous Integration & Delivery</b>
    Container Management & Orchestration
    <b>Container Management & Orchestration</b>
    Persistence
    <b>Persistence</b>
    Scaffolding
    [Not supported by viewer]
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    [Not supported by viewer]
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    [Not supported by viewer]
    Docker
    (Container Engine)
    [Not supported by viewer]
    Infrastructure
    (AWS, Azure, On-Prem)
    [Not supported by viewer]
    EFK - ElasticSearch / Fluentd / Kabana
    (Log Search / Collection / Monitoring / PoC - Tracing)
    [Not supported by viewer]
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    [Not supported by viewer]
    Open Tracing
    (POC - Distributed Tracing)
    [Not supported by viewer]
    Rancher
    (Infrastructure Management)
    [Not supported by viewer]
    PostgreSQL
    (Deprecated - Data)
    [Not supported by viewer]
    MongoDB
    (CEP - Data)
    [Not supported by viewer]
    MySQL
    (Percona - Data)
    [Not supported by viewer]
    Kafka
    (Message - Streaming)
    [Not supported by viewer]
    Mojaloop API Adapter
    (API - Transfers)
    [Not supported by viewer]
    Mojaloop API Adapter
    (Handler - Notifications)
    [Not supported by viewer]
    Central-Services
    (API - Operational Admin)
    [Not supported by viewer]
    Central-Services
    (Handler - Prepare)
    [Not supported by viewer]
    Central-Services
    (Handler - Position)
    [Not supported by viewer]
    Central-Services
    (Handler - Fulfil)
    [Not supported by viewer]
    Central-Services
    (Handler - Get Transfers)
    [Not supported by viewer]
    Central-Services
    (Handler - Timeout)
    [Not supported by viewer]
    Event-Logging-Sidecar
    (POC - Logs, Error, Audits, Tracing)
    [Not supported by viewer]
    Central-KMS
    (Key Management Store)
    [Not supported by viewer]
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    [Not supported by viewer]
    ALS-Oracle-Pathfinder-Service
    (Future - MSISDN Lookup)
    [Not supported by viewer]
    Quoting-Service
    (API - Quotes)
    [Not supported by viewer]
    Central-Event-Processor
    (CEP, POCLogs, Error, Audits, Tracing)
    [Not supported by viewer]
    Email-Notifier
    (Handler - Email)
    [Not supported by viewer]
    Central-Services
    (Handler - Admin)
    [Not supported by viewer]
    Moja-Hub
    (Future - Operational UI)
    [Not supported by viewer]
    Circle-CI
    (Test, Build, Deploy)
    [Not supported by viewer]
    Docker Hub
    (Container Repository)
    [Not supported by viewer]
    NPM Org
    (NPM Repository)
    [Not supported by viewer]
    GitBooks
    (Documetation)
    [Not supported by viewer]
    API Gateway
    (POC - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)
    <b>API Gateway<br></b>(<b><font color="#ff1b0a">POC</font></b> - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)<br>
    Central-Services
    (Handler - Bulk Prepare)
    [Not supported by viewer]
    Central-Services
    (Handler - Bulk Fulfil)
    [Not supported by viewer]
    Central-Services
    (Handler - Bulk Process)
    [Not supported by viewer]
    Mojaloop API Adapter
    (API - Bulk Transfers)
    [Not supported by viewer]
    Forensic-Logging-Sidecar
    (Deprecated - Auditing)
    [Not supported by viewer]
    Simulator
    (API - FSP Simulator /
    API - Oracle Simulator)

    [Not supported by viewer]
    Central-Settlements
    (API - Settlement)
    [Not supported by viewer]
    On-boarding
    (Postman - Scripts)
    [Not supported by viewer]
    Functional Tests
    (Postman - Scripts)
    [Not supported by viewer]
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI7.svg b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI7.svg new file mode 100644 index 000000000..2fedecbc1 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI7.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    <b>Operational Monitoring</b>
    Quality Assurance
    <b>Quality Assurance</b>
    Core Components
    <b>Core Components</b>
    API - Security / Policy / Ingress / Egress
    <b>API - Security / Policy / Ingress / Egress</b>
    Continuous Integration & Delivery
    <b>Continuous Integration & Delivery</b>
    Container Management & Orchestration
    <b>Container Management & Orchestration</b>
    Supporting Components
    <b style="line-height: 0%">Supporting Components</b>
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    [Not supported by viewer]
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    [Not supported by viewer]
    Docker
    (Container Engine)
    [Not supported by viewer]
    Infrastructure
    (AWS, Azure, On-Prem)
    [Not supported by viewer]
    EFK - ElasticSearch / Fluentd / Kabana
    (Log Search / Collection / Monitoring / PoC - Tracing)
    [Not supported by viewer]
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    [Not supported by viewer]
    Open Tracing
    (POC - Distributed Tracing)
    [Not supported by viewer]
    Rancher
    (Infrastructure Management)
    [Not supported by viewer]
    Mojaloop API Adapter
    (API - Transfers)
    [Not supported by viewer]
    Central-Services
    (API - Operational Admin)
    [Not supported by viewer]
    Central-Services
    (Handler - Prepare)
    [Not supported by viewer]
    Central-Services
    (Handler - Position)
    [Not supported by viewer]
    Central-Services
    (Handler - Fulfil)
    [Not supported by viewer]
    Central-Services
    (Handler - Get Transfers)
    [Not supported by viewer]
    Central-Services
    (Handler - Timeout)
    [Not supported by viewer]
    Central-KMS
    (Key Management Store)
    [Not supported by viewer]
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    [Not supported by viewer]
    ALS-Oracle-Pathfinder-Service
    (Future - MSISDN Lookup)
    [Not supported by viewer]
    Central-Event-Processor
    (CEP)
    [Not supported by viewer]
    Email-Notifier
    (Handler - Email)
    [Not supported by viewer]
    Central-Services
    (Handler - Admin)
    [Not supported by viewer]
    Circle-CI
    (Test, Build, Deploy)
    [Not supported by viewer]
    Docker Hub
    (Container Repository)
    [Not supported by viewer]
    NPM Org
    (NPM Repository)
    [Not supported by viewer]
    GitBooks
    (Documetation)
    [Not supported by viewer]
    API Gateway
    (POC - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)
    <b>API Gateway<br></b>(<b><font color="#ff1b0a">POC</font></b> - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)<br>
    Central-Services
    (Handler - Bulk Prepare)
    [Not supported by viewer]
    Central-Services
    (Handler - Bulk Fulfil)
    [Not supported by viewer]
    Central-Services
    (Handler - Bulk Process)
    [Not supported by viewer]
    Mojaloop API Adapter
    (API - Bulk Transfers)
    [Not supported by viewer]
    Forensic-Logging
    (Future - Auditing)
    [Not supported by viewer]
    Central-Settlements
    (API - Settlement)
    [Not supported by viewer]
    Event-Stream-Processor
    Logs, Error, Audits, Tracing)
    [Not supported by viewer]
    Simulator
    (API - FSP & Oracle Simulator)
    [Not supported by viewer]
    On-boarding
    (Postman - Scripts)
    [Not supported by viewer]
    Functional Tests
    (Postman - Scripts)
    [Not supported by viewer]
    Mojaloop-Simulator
    (SDK)
    [Not supported by viewer]
    License & Audit
    (Dependencies)
    [Not supported by viewer]
    Persistence
    <b>Persistence</b>
    PostgreSQL
    (Deprecated - Data)
    [Not supported by viewer]
    MongoDB
    (CEP - Data)
    [Not supported by viewer]
    MySQL
    (Percona - Data)
    [Not supported by viewer]
    Kafka
    (Message - Streaming)
    [Not supported by viewer]
    Transaction Request Service
    (API - Transaction)
    <b>Transaction Request Service</b><br>(API - Transaction)
    Software Dev Kits
    <b>Software Dev Kits</b>
    Oracle SDK
    (Participant Store)
    [Not supported by viewer]
    Mojaloop SDK 
    (FSP Payer/Payee)
    [Not supported by viewer]
    Event SDK
    (Audit, Log, Trace - Client/Server)
    [Not supported by viewer]
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    <b>Event-Sidecar</b><br>(Logs, Error, Audits, Tracing)
    Mojaloop API Adapter
    (Handler - Notifications)
    [Not supported by viewer]
    Quoting-Service
    (API - Quotes)
    [Not supported by viewer]
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg new file mode 100644 index 000000000..3e5b75f13 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg @@ -0,0 +1,3 @@ + + +
    Operational Monitoring
    Operational Monitoring
    Quality Assurance
    Quality Assurance
    Core Components
    Core Components
    API - Security / Policy / Ingress / Egress
    API - Security / Policy / Ingress / Egress
    Continuous Integration & Delivery
    Continuous Integration & Delivery
    Container Management & Orchestration
    Container Management & Orchestration
    Supporting Components
    Supporting Components
    Helm
    (Package Manager for K8s, Templatized Deployments and Configuration)
    Helm...
    Kubernetes
    (Abstraction layer for Infrastructure, Infrastructure as a Policy, Container Orchestration)
    Kubernetes...
    Docker
    (Container Engine)
    Docker...
    Infrastructure
    (AWS, Azure, On-Prem)
    Infrastructure...
    EFK - ElasticSearch / Fluentd / Kibana
    (Log Search / Collection / Monitoring / Tracing)
    EFK - ElasticSearch / Fluentd / Kibana...
    Promfana - Prometheus / Grafana
    (Log Search / Collection / Monitoring)
    Promfana - Prometheus / Grafana...
    Open Tracing
    (Distributed Tracing)
    Open Tracing...
    Rancher
    (Infrastructure Management)
    Rancher...
    Mojaloop API Adapter
    (API - Transfers)
    Mojaloop API Adapter...
    Central-Services
    (API - Operational Admin)
    Central-Services...
    Central-Services
    (Handler - Prepare)
    Central-Services...
    Central-Services
    (Handler - Position)
    Central-Services...
    Central-Services
    (Handler - Fulfil)
    Central-Services...
    Central-Services
    (Handler - Get Transfers)
    Central-Services...
    Central-Services
    (Handler - Timeout)
    Central-Services...
    Central-KMS
    (Future - Key Management Store)
    Central-KMS...
    ALS - Account-Lookup-Service
    (API - Parties, Participant)
    ALS - Account-Lookup-Service...
    ALS-Oracle-Pathfinder
    (MSISDN Lookup)
    ALS-Oracle-Pathfinder...
    Central-Event-Processor
    (CEP)
    Central-Event-Processor...
    Email-Notifier
    (Handler - Email)
    Email-Notifier...
    Central-Services
    (Handler - Admin)
    Central-Services...
    Circle-CI
    (Test, Build, Deploy)
    Circle-CI...
    Docker Hub
    (Container Repository)
    Docker Hub...
    NPM Org
    (NPM Repository)
    NPM Org...
    GitBooks
    (Documetation)
    GitBooks...
    API Gateway
    (Future - API - Parties, Participants, Quotes, Transfers, Bulk Transfers)
    API Gateway...
    Central-Services
    (Handler - Bulk Prepare)
    Central-Services...
    Central-Services
    (Handler - Bulk Fulfil)
    Central-Services...
    Central-Services
    (Handler - Bulk Process)
    Central-Services...
    Mojaloop API Adapter
    (API - Bulk Transfers)
    Mojaloop API Adapter...
    Forensic-Logging
    (Future - Auditing)
    Forensic-Logging...
    Central-Settlements
    (API - Settlement)
    Central-Settlements...
    Event-Stream-Processor
    Logs, Error, Audits, Tracing)
    Event-Stream-Processor...
    Simulators
    (API, SDK, FSP & Oracle)
    Simulators...
    On-boarding
    (Postman - Scripts)
    On-boarding...
    Functional Tests
    (Postman - Scripts)
    Functional Tests...
    Self Testing Toolkit
    (
    POC UI)
    Self Testing Toolkit...
    License, Security & Audit
    (Dependencies)
    License, Security & Audit...
    Persistence
    Persistence
    Redis
    (SDK - Cache)
    Redis...
    MongoDB
    (CEP - Data)
    MongoDB...
    MySQL
    (Percona - Data)
    MySQL...
    Kafka
    (Message - Streaming)
    Kafka...
    Transaction Request Service
    (API - Transaction)
    Transaction Request Service...
    Software Dev Kits
    Software Dev Kits
    Oracle SDK
    (Participant Store)
    Oracle SDK...
    Mojaloop SDK 
    (FSP Payer/Payee)
    Mojaloop SDK...
    Event SDK
    (Audit, Log, Trace - Client/Server)
    Event SDK...
    Event-Sidecar
    (Logs, Error, Audits, Tracing)
    Event-Sidecar...
    Mojaloop API Adapter
    (Handler - Notifications)
    Mojaloop API Adapter...
    Quoting-Service
    (API - Quotes)
    Quoting-Service...
    Finance-Portal-UI
    (API - Bulk Transfers)
    Finance-Portal-UI...
    Settlement-Management
    (Closing, Recon report, Cronjob)
    Settlement-Management...
    Schema-Adapter
    (SDK - Parties, Participants, Quotes, Transfers)
    Schema-Adapter...
    IaC (Infra as Code) Tools
    (Future - Automated
    Prov / Depl / Upgrades)
    IaC (Infra as Code) Tools...
    \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/overview/components-PI11.md b/website/versioned_docs/v1.0.1/technical/overview/components-PI11.md new file mode 100644 index 000000000..35b839657 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/components-PI11.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Current Components - PI11 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI11: + +![Mojaloop Architecture Overview PI11](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI11.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/website/versioned_docs/v1.0.1/technical/overview/components-PI12.md b/website/versioned_docs/v1.0.1/technical/overview/components-PI12.md new file mode 100644 index 000000000..d90d82eb9 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/components-PI12.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Current Components - PI12 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI12: + +![Mojaloop Architecture Overview PI12](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI12.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/website/versioned_docs/v1.0.1/technical/overview/components-PI14.md b/website/versioned_docs/v1.0.1/technical/overview/components-PI14.md new file mode 100644 index 000000000..d4c4e3887 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/components-PI14.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Current Components - PI14 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI14: + +![Mojaloop Architecture Overview PI14](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI14.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/website/versioned_docs/v1.0.1/technical/overview/components-PI3.md b/website/versioned_docs/v1.0.1/technical/overview/components-PI3.md new file mode 100644 index 000000000..a3cb1b686 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/components-PI3.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Legacy Components - PI3 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI3: + +![Mojaloop Architecture Overview PI5](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI3.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/website/versioned_docs/v1.0.1/technical/overview/components-PI5.md b/website/versioned_docs/v1.0.1/technical/overview/components-PI5.md new file mode 100644 index 000000000..f54ac4856 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/components-PI5.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Legacy Components - PI5 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI5: + +![Mojaloop Architecture Overview PI5](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI5.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/website/versioned_docs/v1.0.1/technical/overview/components-PI6.md b/website/versioned_docs/v1.0.1/technical/overview/components-PI6.md new file mode 100644 index 000000000..a935f7cc5 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/components-PI6.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Legacy Components - PI6 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI6: + +![Mojaloop Architecture Overview PI6](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI6.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/website/versioned_docs/v1.0.1/technical/overview/components-PI7.md b/website/versioned_docs/v1.0.1/technical/overview/components-PI7.md new file mode 100644 index 000000000..f2f59dd8a --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/components-PI7.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Legacy Components - PI7 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI7: + +![Mojaloop Architecture Overview PI7](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI7.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/website/versioned_docs/v1.0.1/technical/overview/components-PI8.md b/website/versioned_docs/v1.0.1/technical/overview/components-PI8.md new file mode 100644 index 000000000..3d18e7fac --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/overview/components-PI8.md @@ -0,0 +1,7 @@ +# Mojaloop Hub Legacy Components - PI8 + +The following component diagram shows the break-down of the Mojaloop services and its micro-service architecture for pre PI8: + +![Mojaloop Architecture Overview PI8](./assets/diagrams/architecture/Arch-Mojaloop-overview-PI8.svg) + +_Note: Colour-grading indicates the relationship between data-store, and message-streaming / adapter-interconnects. E.g. `Central-Services` utilise `MySQL` as a Data-store, and leverage on `Kafka` for Messaging_ diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/README.md b/website/versioned_docs/v1.0.1/technical/quoting-service/README.md new file mode 100644 index 000000000..95743aaae --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/README.md @@ -0,0 +1,12 @@ +--- +version: 1.1 +--- + +# Quoting Service Overview +The **Quoting Service** (**QS**) _(refer to section `5.1`) as per the [Mojaloop {{ $page.frontmatter.version }} Specification](/api) implements the quoting phase of the various use-cases. + +_Note: In addition to individual quotes, the quoting service supports bulk quotes as well._ + +## Sequence Diagram + +![seq-quotes-1.0.0.svg](./assets/diagrams/sequence/seq-quotes-1.0.0.svg) diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.plantuml b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.plantuml new file mode 100644 index 000000000..0405a9868 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.plantuml @@ -0,0 +1,92 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- +******'/ + +@startuml +Title Retrieve Bulk Quote Information +participant "Payer FSP" as PayerFSP +participant "Switch\n[Quoting Service]" as Switch +participant "Payee FSP" as PayeeFSP + +autonumber +note right of PayerFSP: Payer FSP sends request to get bulk quote details \nto Payee FSP via the Switch +PayerFSP -\ Switch: GET /bulkQuotes/{ID} +note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** +end note +Switch -> Switch: Schema validation +PayerFSP \-- Switch: 202 Accepted +Switch -> Switch: Retrieve bulk quotes endpoint for Payee FSP +alt Payee FSP quotes endpoint is found + note right of Switch: Switch forwards request to Payee FSP (pass-through mode) + Switch -\ PayeeFSP: GET /bulkQuotes/{ID} + PayeeFSP --/ Switch: 202 Accepted + PayeeFSP -> PayeeFSP: Payee FSP retireves bulk quote + alt Payee FSP successfully retieves quote + note left of PayeeFSP: Payee FSP responds to quote request + PayeeFSP -\ Switch: PUT /quotes/{ID} + note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** + end note + Switch --/ PayeeFSP: 200 Ok + alt Response is ok + Switch -> Switch: Retrieve bulk quotes endpoint for the Payer FSP + alt Bulk Quotes callback endpoint found + note left of Switch: Switch forwards bulk quote response to Payer FSP + Switch -\ PayerFSP: PUT /bulkQuotes/{ID} + PayerFSP --/ Switch: 200 Ok + else Bulk Quotes callback endpoint not found + note right of Switch: Switch returns error to Payee FSP + Switch -\ PayeeFSP: PUT /bulkQuotes/{ID}/error + PayeeFSP --/ Switch : 200 Ok + end + else Response is invalid + note right of Switch: Switch returns error to Payee FSP + Switch -\ PayeeFSP: PUT /bulkQuotes/{ID}/error + PayeeFSP --/ Switch : 200 Ok + note over Switch, PayeeFSP #ec7063: Note that under this\nscenario the Payer FSP\nmay not receive a response + end + + else bulkQuote not found + note left of PayeeFSP: Payee FSP returns error to Switch\n **Error code: 3205** + PayeeFSP -\ Switch: PUT /bulkQuotes/{ID}/error + Switch --/ PayeeFSP: 200 OK + note left of Switch: Switch returns error to Payer FSP\n **Error code: 3205** + Switch -\ PayerFSP: PUT /bulkQuotes/{ID}/error + PayerFSP --/ Switch: 200 OK + end +else Payee FSP Bulk quotes endpoint is not found + note left of Switch + Switch returns error to Payer FSP + **Error code: 3201** + end note + PayerFSP /- Switch: PUT /bulkQuotes/{ID}error + PayerFSP --/ Switch: 200 OK +end +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.svg b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.svg new file mode 100644 index 000000000..9cab870cb --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.svg @@ -0,0 +1,369 @@ + + + + + + + + + + + Retrieve Bulk Quote Information + + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + [Quoting Service] + + + + Switch + + + [Quoting Service] + + + + Payee FSP + + + + Payee FSP + + + + + Payer FSP sends request to get bulk quote details + + + to Payee FSP via the Switch + + + + + 1 + + + GET /bulkQuotes/{ID} + + + + + Validate request against + + + Mojaloop interface specification + + + Error code: 300x, 310x + + + HTTP error response code: 4xx + + + + + 2 + + + Schema validation + + + + + 3 + + + 202 Accepted + + + + + 4 + + + Retrieve bulk quotes endpoint for Payee FSP + + + + + alt + + + [Payee FSP quotes endpoint is found] + + + + + Switch forwards request to Payee FSP (pass-through mode) + + + + + 5 + + + GET /bulkQuotes/{ID} + + + + + 6 + + + 202 Accepted + + + + + 7 + + + Payee FSP retireves bulk quote + + + + + alt + + + [Payee FSP successfully retieves quote] + + + + + Payee FSP responds to quote request + + + + + 8 + + + PUT /quotes/{ID} + + + + + Validate request against + + + Mojaloop interface specification + + + Error code: 300x, 310x + + + HTTP error response code: 4xx + + + + + 9 + + + 200 Ok + + + + + alt + + + [Response is ok] + + + + + 10 + + + Retrieve bulk quotes endpoint for the Payer FSP + + + + + alt + + + [Bulk Quotes callback endpoint found] + + + + + Switch forwards bulk quote response to Payer FSP + + + + + 11 + + + PUT /bulkQuotes/{ID} + + + + + 12 + + + 200 Ok + + + + [Bulk Quotes callback endpoint not found] + + + + + Switch returns error to Payee FSP + + + + + 13 + + + PUT /bulkQuotes/{ID}/error + + + + + 14 + + + 200 Ok + + + + [Response is invalid] + + + + + Switch returns error to Payee FSP + + + + + 15 + + + PUT /bulkQuotes/{ID}/error + + + + + 16 + + + 200 Ok + + + + + Note that under this + + + scenario the Payer FSP + + + may not receive a response + + + + [bulkQuote not found] + + + + + Payee FSP returns error to Switch + + + Error code: 3205 + + + + + 17 + + + PUT /bulkQuotes/{ID}/error + + + + + 18 + + + 200 OK + + + + + Switch returns error to Payer FSP + + + Error code: 3205 + + + + + 19 + + + PUT /bulkQuotes/{ID}/error + + + + + 20 + + + 200 OK + + + + [Payee FSP Bulk quotes endpoint is not found] + + + + + Switch returns error to Payer FSP + + + Error code: 3201 + + + + + 21 + + + PUT /bulkQuotes/{ID}error + + + + + 22 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.plantuml b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.plantuml new file mode 100644 index 000000000..dfcb1918b --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.plantuml @@ -0,0 +1,86 @@ +@startuml +Title Retrieve Quote Information +participant "Payer FSP" as PayerFSP +participant "Switch\n[Quoting\nService]" as Switch +database "Central Store" as DB +participant "Payee FSP" as PayeeFSP +autonumber +note right of PayerFSP: Payer FSP sends request to get quote details \nto Payee FSP via the Switch +PayerFSP -\ Switch: GET /quotes/{ID} +note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** +end note +Switch -> Switch: Schema validation +PayerFSP \-- Switch: 202 Accepted +Switch -> Switch: Retrieve quotes endpoint for Payee FSP +alt Payee FSP quotes endpoint is found + note right of Switch: Switch forwards request to Payee FSP (pass-through mode)\n + Switch -\ PayeeFSP: GET /quotes/{ID} + PayeeFSP --/ Switch: 202 Accepted + PayeeFSP -> PayeeFSP: Payee FSP retireves quote + alt Payee FSP successfully retieves quote + note left of PayeeFSP: Payee FSP responds to quote request + PayeeFSP -\ Switch: PUT /quotes/{ID} + Switch --/ PayeeFSP: 200 Ok + Switch -> Switch: Validate response (schema, headers (**Error code: 3100**)) + alt Response is ok + alt SimpleRoutingMode is FALSE + Switch -> Switch: Validate response (duplicate response check, handle resend scenario (**Error code: 3106**)) + alt Validation passed + Switch -\ DB: Persist quote response + activate DB + hnote over DB + quoteResponse + quoteResponseDuplicateCheck + quoteResponseIlpPacket + quoteExtensions + geoCode + end hnote + Switch \-- DB: Quote response saved + deactivate DB + end + end + alt SimpleRoutingMode is TRUE + Switch -> Switch: Retrieve quotes endpoint for the Payer FSP + else SimpleRoutingMode is FALSE + Switch -> Switch: Retrieve quote party endpoint (PAYER) + end + alt Quotes callback endpoint found + note left of Switch: Switch forwards quote response to Payer FSP\n + Switch -\ PayerFSP: PUT /quotes/{ID} + PayerFSP --/ Switch: 200 Ok + else Quotes callback endpoint not found + note right of Switch: Switch returns error to Payee FSP + Switch -\ PayeeFSP: PUT /quotes/{ID}/error + PayeeFSP --/ Switch : 200 Ok + end + else Response is invalid + note right of Switch: Switch returns error to Payee FSP + Switch -\ PayeeFSP: PUT /quotes/{ID}/error + PayeeFSP --/ Switch : 200 Ok + note over Switch, PayeeFSP #ec7063: Note that under this\nscenario the Payer FSP\nmay not receive a response + end + + else Quote not found + note left of PayeeFSP: Payee FSP returns error to Switch\n **Error code: 3205** + PayeeFSP -\ Switch: PUT quotes/{ID}/error + Switch --/ PayeeFSP: 200 OK + alt SimpleRoutingMode is FALSE + Switch -> Switch: Persist error data + end + note left of Switch: Switch returns error to Payer FSP\n **Error code: 3205** + Switch -\ PayerFSP: PUT quotes/{ID}/error + PayerFSP --/ Switch: 200 OK + end +else Payee FSP quotes endpoint is not found + note left of Switch + Switch returns error to Payer FSP + **Error code: 3201** + end note + PayerFSP /- Switch: PUT quotes/{ID}error + PayerFSP --/ Switch: 200 OK +end +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.svg b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.svg new file mode 100644 index 000000000..679d20f98 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-get-quotes-1.1.0.svg @@ -0,0 +1,496 @@ + + + + + + + + + + + Retrieve Quote Information + + + + + + + + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + [Quoting + + + Service] + + + + Switch + + + [Quoting + + + Service] + + + Central Store + + + + + Central Store + + + + + + Payee FSP + + + + Payee FSP + + + + + + Payer FSP sends request to get quote details + + + to Payee FSP via the Switch + + + + + 1 + + + GET /quotes/{ID} + + + + + Validate request against + + + Mojaloop interface specification + + + Error code: 300x, 310x + + + HTTP error response code: 4xx + + + + + 2 + + + Schema validation + + + + + 3 + + + 202 Accepted + + + + + 4 + + + Retrieve quotes endpoint for Payee FSP + + + + + alt + + + [Payee FSP quotes endpoint is found] + + + + + Switch forwards request to Payee FSP (pass-through mode) + + + <Payer based Rules> + + + + + 5 + + + GET /quotes/{ID} + + + + + 6 + + + 202 Accepted + + + + + 7 + + + Payee FSP retireves quote + + + + + alt + + + [Payee FSP successfully retieves quote] + + + + + Payee FSP responds to quote request + + + + + 8 + + + PUT /quotes/{ID} + + + + + 9 + + + 200 Ok + + + + + 10 + + + Validate response (schema, headers ( + + + Error code: 3100 + + + )) + + + + + alt + + + [Response is ok] + + + + + alt + + + [SimpleRoutingMode is FALSE] + + + + + 11 + + + Validate response (duplicate response check, handle resend scenario ( + + + Error code: 3106 + + + )) + + + + + alt + + + [Validation passed] + + + + + 12 + + + Persist quote response + + + + quoteResponse + + + quoteResponseDuplicateCheck + + + quoteResponseIlpPacket + + + quoteExtensions + + + geoCode + + + + + 13 + + + Quote response saved + + + + + alt + + + [SimpleRoutingMode is TRUE] + + + + + 14 + + + Retrieve quotes endpoint for the Payer FSP + + + + [SimpleRoutingMode is FALSE] + + + + + 15 + + + Retrieve quote party endpoint (PAYER) + + + + + alt + + + [Quotes callback endpoint found] + + + + + Switch forwards quote response to Payer FSP + + + <Payee whole request Rule> + + + + + 16 + + + PUT /quotes/{ID} + + + + + 17 + + + 200 Ok + + + + [Quotes callback endpoint not found] + + + + + Switch returns error to Payee FSP + + + + + 18 + + + PUT /quotes/{ID}/error + + + + + 19 + + + 200 Ok + + + + [Response is invalid] + + + + + Switch returns error to Payee FSP + + + + + 20 + + + PUT /quotes/{ID}/error + + + + + 21 + + + 200 Ok + + + + + Note that under this + + + scenario the Payer FSP + + + may not receive a response + + + + [Quote not found] + + + + + Payee FSP returns error to Switch + + + Error code: 3205 + + + + + 22 + + + PUT quotes/{ID}/error + + + + + 23 + + + 200 OK + + + + + alt + + + [SimpleRoutingMode is FALSE] + + + + + 24 + + + Persist error data + + + + + Switch returns error to Payer FSP + + + Error code: 3205 + + + + + 25 + + + PUT quotes/{ID}/error + + + + + 26 + + + 200 OK + + + + [Payee FSP quotes endpoint is not found] + + + + + Switch returns error to Payer FSP + + + Error code: 3201 + + + + + 27 + + + PUT quotes/{ID}error + + + + + 28 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.plantuml b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.plantuml new file mode 100644 index 000000000..ca4c1d30f --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.plantuml @@ -0,0 +1,99 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- +******'/ + +@startuml +Title Request Bulk Quote Creation +participant "Payer FSP" as PayerFSP +participant "Switch\n[Quoting Service]" as Switch +participant "Payee FSP" as PayeeFSP +autonumber + +note over PayerFSP, Switch: Payer FSP sends bulk quote request\nto Payee FSP via the Switch +PayerFSP -\ Switch: POST /bulkQuotes +note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** +end note +Switch -> Switch: Schema validation +PayerFSP \-- Switch: 202 Accepted +||| +Switch -> Switch: Bulk Quote request validation (rules engine etc.) +||| +Switch -> Switch: Duplicate check +||| +alt Request is a duplicate but not a resend +||| + note left of Switch + Switch returns error back to Payer FSP + **Error code: 3106** + end note + PayerFSP /- Switch: PUT /bulkQuotes/{ID}/error + PayerFSP --/ Switch: 200 OK +||| +else Request is a duplicate and a resend + Switch -> Switch: Switch handles resend scenario +end +||| +Switch -> Switch: Use fspiop-destination header to retrieve\n bulk quotes endpoint for Payee DFSP +alt Payee bulk quotes endpoint found + note right of Switch: Switch forwards bulk quote request to Payee FSP + Switch -\ PayeeFSP: POST /bulkQuotes + Switch \-- PayeeFSP: 202 OK + + PayeeFSP -> PayeeFSP: Payee FSP calculates individual quotes\nand responds with a bulk quote result + alt Payee bulkQuotes processing successful + note over PayeeFSP, Switch: Payee FSP sends bulk quote response back to Payer FSP via the Switch + Switch /- PayeeFSP: PUT /bulkQuotes/{ID} + Switch --/ PayeeFSP: 200 OK + + Switch -> Switch: Validate bulk quote response + Switch -> Switch: Duplicate check + alt Response is duplicate but not a resend + Switch -\ PayeeFSP: PUT /bulkQuotes/{ID}/error + Switch \-- PayeeFSP: 200 OK + end + alt Response is a duplicate and a resend + Switch -> Switch: Switch handles resend scenario + end + + note left of Switch: Switch forwards quote response to Payer FSP + PayerFSP /- Switch: PUT /bulkQuotes/{ID} + PayerFSP --/ Switch: 200 OK + else Payee rejects bulk quote or encounters an error + note left of PayeeFSP: Payee FSP sends error callback to Payer FSP via the Switch + Switch /- PayeeFSP: PUT /bulkQuotes/{ID}/error + Switch --/ PayeeFSP: 200 OK + note left of Switch: Switch forwards error callback to Payer FSP + PayerFSP /- Switch: PUT /bulkQuotes/{ID}/error + PayerFSP --/ Switch: 200 OK + end +else Payee FSP quotes endpoint not found + note left of Switch: Switch sends an error callback to Payer FSP \n **Error code: 3201** + PayerFSP /- Switch: PUT /bulkQuotes/{ID}/error + PayerFSP --\ Switch: 200 OK +end + +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.svg b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.svg new file mode 100644 index 000000000..4b3363dd6 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.svg @@ -0,0 +1,387 @@ + + + + + + + + + + + Request Bulk Quote Creation + + + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + [Quoting Service] + + + + Switch + + + [Quoting Service] + + + + Payee FSP + + + + Payee FSP + + + + + Payer FSP sends bulk quote request + + + to Payee FSP via the Switch + + + + + 1 + + + POST /bulkQuotes + + + + + Validate request against + + + Mojaloop interface specification + + + Error code: 300x, 310x + + + HTTP error response code: 4xx + + + + + 2 + + + Schema validation + + + + + 3 + + + 202 Accepted + + + + + 4 + + + Bulk Quote request validation (rules engine etc.) + + + + + 5 + + + Duplicate check + + + + + alt + + + [Request is a duplicate but not a resend] + + + + + Switch returns error back to Payer FSP + + + Error code: 3106 + + + + + 6 + + + PUT /bulkQuotes/{ID}/error + + + + + 7 + + + 200 OK + + + + [Request is a duplicate and a resend] + + + + + 8 + + + Switch handles resend scenario + + + + + 9 + + + Use fspiop-destination header to retrieve + + + bulk quotes endpoint for Payee DFSP + + + + + alt + + + [Payee bulk quotes endpoint found] + + + + + Switch forwards bulk quote request to Payee FSP + + + + + 10 + + + POST /bulkQuotes + + + + + 11 + + + 202 OK + + + + + 12 + + + Payee FSP calculates individual quotes + + + and responds with a bulk quote result + + + + + alt + + + [Payee bulkQuotes processing successful] + + + + + Payee FSP sends bulk quote response back to Payer FSP via the Switch + + + + + 13 + + + PUT /bulkQuotes/{ID} + + + + + 14 + + + 200 OK + + + + + 15 + + + Validate bulk quote response + + + + + 16 + + + Duplicate check + + + + + alt + + + [Response is duplicate but not a resend] + + + + + 17 + + + PUT /bulkQuotes/{ID}/error + + + + + 18 + + + 200 OK + + + + + alt + + + [Response is a duplicate and a resend] + + + + + 19 + + + Switch handles resend scenario + + + + + Switch forwards quote response to Payer FSP + + + + + 20 + + + PUT /bulkQuotes/{ID} + + + + + 21 + + + 200 OK + + + + [Payee rejects bulk quote or encounters an error] + + + + + Payee FSP sends error callback to Payer FSP via the Switch + + + + + 22 + + + PUT /bulkQuotes/{ID}/error + + + + + 23 + + + 200 OK + + + + + Switch forwards error callback to Payer FSP + + + + + 24 + + + PUT /bulkQuotes/{ID}/error + + + + + 25 + + + 200 OK + + + + [Payee FSP quotes endpoint not found] + + + + + Switch sends an error callback to Payer FSP + + + Error code: 3201 + + + + + 26 + + + PUT /bulkQuotes/{ID}/error + + + + + 27 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.plantuml b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.plantuml new file mode 100644 index 000000000..86fb8f8b6 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.plantuml @@ -0,0 +1,117 @@ +@startuml +Title Request Quote Creation +participant "Payer FSP" as PayerFSP +participant "Switch\n[Quoting\nService]" as Switch +database "Central Store" as DB +participant "Payee FSP" as PayeeFSP +autonumber + +note over PayerFSP, Switch: Payer FSP sends request for quote \nto Payee FSP via the Switch +PayerFSP -\ Switch: POST /quotes +note right of Switch #aaa + Validate request against + Mojaloop interface specification + **Error code: 300x, 310x** + **HTTP error response code: 4xx** +end note +Switch -> Switch: Schema validation +PayerFSP \-- Switch: 202 Accepted +||| +Switch -> Switch: Quote request validation (rules engine etc.) +||| +alt SimpleRoutingMode === FALSE + Switch -> Switch: Duplicate check + ||| + alt Request is a duplicate but not a resend + ||| + note left of Switch + Switch returns error back to Payer FSP + **Error code: 3106** + end note + PayerFSP /- Switch: PUT /quotes/{ID}/error + PayerFSP --/ Switch: 200 OK + ||| + else Request is a duplicate and a resend + Switch -> Switch: Switch handles resend scenario + end + ||| + Switch -\ DB: Persist quote request + activate DB + hnote over DB + quoteDuplicateCheck + transactionReference + quote + quoteParty + quoteExtension + geoCode + end hnote + Switch \-- DB: Quote request saved + deactivate DB +end +||| +alt SimpleRoutingMode === TRUE + Switch -> Switch: Use fspiop-destination header to retrieve quotes endpoint for Payee FSP +else SimpleRoutingMode === FALSE + Switch -> Switch: Retireve Payee FSP endpoint using quote party information +end +||| +alt Payee quotes endpoint found + note right of Switch: Switch forwards quote request to Payee FSP + Switch -\ PayeeFSP: POST /quotes + Switch \-- PayeeFSP: 202 OK + + PayeeFSP -> PayeeFSP: Payee FSP presists and calculates quote + alt Payee quotes processing successful + note left of PayeeFSP: Payee FSP sends quote response back to Payer FSP via the Switch + Switch /- PayeeFSP: PUT /quotes/{ID} + Switch --/ PayeeFSP: 200 OK + + Switch -> Switch: Validate quote response + alt SimpleRoutingMode === FALSE + Switch -> Switch: Duplicate check + alt Response is duplicate but not a resend + Switch -\ PayeeFSP: PUT /quotes/{ID}/error + Switch \-- PayeeFSP: 200 OK + end + alt Response is a duplicate and a resend + Switch -> Switch: Switch handles resend scenario + end + Switch -\ DB: Persist quote response + activate DB + hnote over DB + quoteResponse + quoteDuplicateCheck + quoteResponseIlpPacket + geoCode + quoteExtension + end hnote + Switch \-- DB: Quote response saved + deactivate DB + end + note left of Switch: Switch forwards quote response to Payer FSP + PayerFSP /- Switch: PUT /quotes/{ID} + PayerFSP --/ Switch: 200 OK + else Payee rejects quotes or encounters and error + note left of PayeeFSP: Payee FSP sends error callback to Payer FSP via the Switch + Switch /- PayeeFSP: PUT /quotes/{ID}/error + Switch --/ PayeeFSP: 200 OK + alt SimpleRoutingMode === FALSE + Switch -\ DB: Store quote error + activate DB + hnote over DB + quoteError + end hnote + Switch \-- DB: Quote error saved + deactivate DB + end + note left of Switch: Switch forwards error callback to Payer FSP + PayerFSP /- Switch: PUT /quotes/{ID}/error + PayerFSP --/ Switch: 200 OK + end +else Payee FSP quotes endpoint not found + note left of Switch: Switch sends an error callback to Payer FSP \n **Error code: 3201** + PayerFSP /- Switch: PUT /quotes/{ID}/error + PayerFSP --\ Switch: 200 OK +end + +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.svg b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.svg new file mode 100644 index 000000000..6250d6e02 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-post-quotes-1.2.0.svg @@ -0,0 +1,536 @@ + + + + + + + + + + + Request Quote Creation + + + + + + + + + + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + [Quoting + + + Service] + + + + Switch + + + [Quoting + + + Service] + + + Central Store + + + + + Central Store + + + + + + Payee FSP + + + + Payee FSP + + + + + + Payer FSP sends request for quote + + + to Payee FSP via the Switch + + + + + 1 + + + POST /quotes + + + + + Validate request against + + + Mojaloop interface specification + + + Error code: 300x, 310x + + + HTTP error response code: 4xx + + + + + 2 + + + Schema validation + + + + + 3 + + + 202 Accepted + + + + + 4 + + + Quote request validation (rules engine etc.) + + + + + alt + + + [SimpleRoutingMode === FALSE] + + + + + 5 + + + Duplicate check + + + + + alt + + + [Request is a duplicate but not a resend] + + + + + Switch returns error back to Payer FSP + + + Error code: 3106 + + + + + 6 + + + PUT /quotes/{ID}/error + + + + + 7 + + + 200 OK + + + + [Request is a duplicate and a resend] + + + + + 8 + + + Switch handles resend scenario + + + + + 9 + + + Persist quote request + + + + quoteDuplicateCheck + + + transactionReference + + + quote + + + quoteParty + + + quoteExtension + + + geoCode + + + + + 10 + + + Quote request saved + + + + + alt + + + [SimpleRoutingMode === TRUE] + + + + + 11 + + + Use fspiop-destination header to retrieve quotes endpoint for Payee FSP + + + + [SimpleRoutingMode === FALSE] + + + + + 12 + + + Retireve Payee FSP endpoint using quote party information + + + + + alt + + + [Payee quotes endpoint found] + + + + + Switch forwards quote request to Payee FSP + + + + + 13 + + + POST /quotes + + + + + 14 + + + 202 OK + + + + + 15 + + + Payee FSP presists and calculates quote + + + + + alt + + + [Payee quotes processing successful] + + + + + Payee FSP sends quote response back to Payer FSP via the Switch + + + + + 16 + + + PUT /quotes/{ID} + + + + + 17 + + + 200 OK + + + + + 18 + + + Validate quote response + + + + + alt + + + [SimpleRoutingMode === FALSE] + + + + + 19 + + + Duplicate check + + + + + alt + + + [Response is duplicate but not a resend] + + + + + 20 + + + PUT /quotes/{ID}/error + + + + + 21 + + + 200 OK + + + + + alt + + + [Response is a duplicate and a resend] + + + + + 22 + + + Switch handles resend scenario + + + + + 23 + + + Persist quote response + + + + quoteResponse + + + quoteDuplicateCheck + + + quoteResponseIlpPacket + + + geoCode + + + quoteExtension + + + + + 24 + + + Quote response saved + + + + + Switch forwards quote response to Payer FSP + + + + + 25 + + + PUT /quotes/{ID} + + + + + 26 + + + 200 OK + + + + [Payee rejects quotes or encounters and error] + + + + + Payee FSP sends error callback to Payer FSP via the Switch + + + + + 27 + + + PUT /quotes/{ID}/error + + + + + 28 + + + 200 OK + + + + + alt + + + [SimpleRoutingMode === FALSE] + + + + + 29 + + + Store quote error + + + + quoteError + + + + + 30 + + + Quote error saved + + + + + Switch forwards error callback to Payer FSP + + + + + 31 + + + PUT /quotes/{ID}/error + + + + + 32 + + + 200 OK + + + + [Payee FSP quotes endpoint not found] + + + + + Switch sends an error callback to Payer FSP + + + Error code: 3201 + + + + + 33 + + + PUT /quotes/{ID}/error + + + + + 34 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml new file mode 100644 index 000000000..4f3405364 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.plantuml @@ -0,0 +1,68 @@ +@startuml +Title Quoting Service Sequences +participant "Payer DFSP" +participant "Switch\nQuoting\nService" as Switch +participant "Payee DFSP" + +autonumber +note over "Payer DFSP", Switch: Payer DFSP requests quote from Payee DFSP +"Payer DFSP" -\ Switch: POST /quotes +Switch --/ "Payer DFSP": 202 Accepted +Switch -> Switch: Validate Quote Request + +alt quote is valid + + Switch -> Switch: Persist Quote Data + note over Switch, "Payee DFSP": Switch forwards quote request to Payee DFSP\n + Switch -\ "Payee DFSP": POST /quotes + "Payee DFSP" --/ Switch: 202 Accepted + "Payee DFSP" -> "Payee DFSP": Calculate Fees/Charges + + alt Payee DFSP successfully calculates quote + + note over "Payee DFSP", Switch: Payee DFSP responds to quote request + "Payee DFSP" -\ Switch: PUT /quotes/{ID} + Switch --/ "Payee DFSP": 200 Ok + + Switch -> Switch: Validate Quote Response + + alt response is ok + + Switch -> Switch: Persist Response Data + + note over Switch, "Payer DFSP": Switch forwards quote response to Payer DFSP\n + + Switch -\ "Payer DFSP": PUT /quotes/{ID} + "Payer DFSP" --/ Switch: 200 Ok + + note over "Payer DFSP" #3498db: Payer DFSP continues\nwith transfer if quote\nis acceptable... + else response invalid + + note over Switch, "Payee DFSP": Switch returns error to Payee DFSP + + Switch -\ "Payee DFSP": PUT /quotes/{ID}/error + "Payee DFSP" --/ Switch : 200 Ok + + note over Switch, "Payee DFSP" #ec7063: Note that under this\nscenario the Payer DFSP\nmay not receive a response + + end + else Payee DFSP calculation fails or rejects the request + + note over "Payee DFSP", Switch: Payee DFSP returns error to Switch + + "Payee DFSP" -\ Switch: PUT quotes/{ID}/error + Switch --/ "Payee DFSP": 200 OK + Switch -> Switch: Persist error data + + note over "Payer DFSP", Switch: Switch returns error to Payer DFSP + + Switch -\ "Payer DFSP": PUT quotes/{ID}/error + "Payer DFSP" --/ Switch: 200 OK + + end +else quote invalid + note over "Payer DFSP", Switch: Switch returns error to Payer DFSP + Switch -\ "Payer DFSP": PUT quotes/{ID}/error + "Payer DFSP" --/ Switch: 200 OK +end +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.svg b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.svg new file mode 100644 index 000000000..b79aecb9d --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-quotes-1.0.0.svg @@ -0,0 +1,334 @@ + + + + + + + + + + + Quoting Service Sequences + + + + + + + + + Payer DFSP + + + + Payer DFSP + + + + Switch + + + Quoting + + + Service + + + + Switch + + + Quoting + + + Service + + + + Payee DFSP + + + + Payee DFSP + + + + + Payer DFSP requests quote from Payee DFSP + + + + + 1 + + + POST /quotes + + + + + 2 + + + 202 Accepted + + + + + 3 + + + Validate Quote Request + + + + + alt + + + [quote is valid] + + + + + 4 + + + Persist Quote Data + + + + + Switch forwards quote request to Payee DFSP + + + <Payer based Rules> + + + + + 5 + + + POST /quotes + + + + + 6 + + + 202 Accepted + + + + + 7 + + + Calculate Fees/Charges + + + + + alt + + + [Payee DFSP successfully calculates quote] + + + + + Payee DFSP responds to quote request + + + + + 8 + + + PUT /quotes/{ID} + + + + + 9 + + + 200 Ok + + + + + 10 + + + Validate Quote Response + + + + + alt + + + [response is ok] + + + + + 11 + + + Persist Response Data + + + + + Switch forwards quote response to Payer DFSP + + + <Payee whole request Rule> + + + + + 12 + + + PUT /quotes/{ID} + + + + + 13 + + + 200 Ok + + + + + Payer DFSP continues + + + with transfer if quote + + + is acceptable... + + + + [response invalid] + + + + + Switch returns error to Payee DFSP + + + + + 14 + + + PUT /quotes/{ID}/error + + + + + 15 + + + 200 Ok + + + + + Note that under this + + + scenario the Payer DFSP + + + may not receive a response + + + + [Payee DFSP calculation fails or rejects the request] + + + + + Payee DFSP returns error to Switch + + + + + 16 + + + PUT quotes/{ID}/error + + + + + 17 + + + 200 OK + + + + + 18 + + + Persist error data + + + + + Switch returns error to Payer DFSP + + + + + 19 + + + PUT quotes/{ID}/error + + + + + 20 + + + 200 OK + + + + [quote invalid] + + + + + Switch returns error to Payer DFSP + + + + + 21 + + + PUT quotes/{ID}/error + + + + + 22 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.plantuml b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.plantuml new file mode 100644 index 000000000..3275abff7 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.plantuml @@ -0,0 +1,67 @@ +@startuml +Title Quoting Service Sequences +participant "Payer FSP" +participant "Switch\nQuoting\nService" as Switch +participant "Payee FSP" + +autonumber +note over "Payer FSP", Switch: Payer FSP requests quote from Payee FSP +"Payer FSP" -\ Switch: POST /quotes +Switch --/ "Payer FSP": 202 Accepted +Switch -> Switch: Validate Quote Request + +alt quote is valid + + Switch -> Switch: Persist Quote Data + note over Switch, "Payee FSP": Switch forwards quote request to Payee FSP\n + Switch -\ "Payee FSP": POST /quotes + "Payee FSP" --/ Switch: 202 Accepted + "Payee FSP" -> "Payee FSP": Calculate Fees/Charges + + alt Payee FSP successfully calculates quote + + note over "Payee FSP", Switch: Payee FSP responds to quote request + "Payee FSP" -\ Switch: PUT /quotes/{ID} + Switch --/ "Payee FSP": 200 Ok + + Switch -> Switch: Validate Quote Response + + alt response is ok + Switch -> Switch: Persist Response Data + + note over Switch, "Payer FSP": Switch forwards quote response to Payer FSP\n + + Switch -\ "Payer FSP": PUT /quotes/{ID} + "Payer FSP" --/ Switch: 200 Ok + + note over "Payer FSP" #3498db: Payer FSP continues\nwith transfer if quote\nis acceptable... + else response invalid + + note over Switch, "Payee FSP": Switch returns error to Payee FSP + + Switch -\ "Payee FSP": PUT /quotes/{ID}/error + "Payee FSP" --/ Switch : 200 Ok + + note over Switch, "Payee FSP" #ec7063: Note that under this\nscenario the Payer FSP\nmay not receive a response + + end + else Payee FSP calculation fails or rejects the request + + note over "Payee FSP", Switch: Payee FSP returns error to Switch + + "Payee FSP" -\ Switch: PUT quotes/{ID}/error + Switch --/ "Payee FSP": 200 OK + Switch -> Switch: Persist error data + + note over "Payer FSP", Switch: Switch returns error to Payer FSP + + Switch -\ "Payer FSP": PUT quotes/{ID}/error + "Payer FSP" --/ Switch: 200 OK + + end +else quote invalid + note over "Payer FSP", Switch: Switch returns error to Payer FSP + Switch -\ "Payer FSP": PUT quotes/{ID}/error + "Payer FSP" --/ Switch: 200 OK +end +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.svg b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.svg new file mode 100644 index 000000000..69b7fb6d4 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/assets/diagrams/sequence/seq-quotes-overview-1.0.0.svg @@ -0,0 +1,334 @@ + + + + + + + + + + + Quoting Service Sequences + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + Quoting + + + Service + + + + Switch + + + Quoting + + + Service + + + + Payee FSP + + + + Payee FSP + + + + + Payer FSP requests quote from Payee FSP + + + + + 1 + + + POST /quotes + + + + + 2 + + + 202 Accepted + + + + + 3 + + + Validate Quote Request + + + + + alt + + + [quote is valid] + + + + + 4 + + + Persist Quote Data + + + + + Switch forwards quote request to Payee FSP + + + <Payer based Rules> + + + + + 5 + + + POST /quotes + + + + + 6 + + + 202 Accepted + + + + + 7 + + + Calculate Fees/Charges + + + + + alt + + + [Payee FSP successfully calculates quote] + + + + + Payee FSP responds to quote request + + + + + 8 + + + PUT /quotes/{ID} + + + + + 9 + + + 200 Ok + + + + + 10 + + + Validate Quote Response + + + + + alt + + + [response is ok] + + + + + 11 + + + Persist Response Data + + + + + Switch forwards quote response to Payer FSP + + + <Payee whole request Rule> + + + + + 12 + + + PUT /quotes/{ID} + + + + + 13 + + + 200 Ok + + + + + Payer FSP continues + + + with transfer if quote + + + is acceptable... + + + + [response invalid] + + + + + Switch returns error to Payee FSP + + + + + 14 + + + PUT /quotes/{ID}/error + + + + + 15 + + + 200 Ok + + + + + Note that under this + + + scenario the Payer FSP + + + may not receive a response + + + + [Payee FSP calculation fails or rejects the request] + + + + + Payee FSP returns error to Switch + + + + + 16 + + + PUT quotes/{ID}/error + + + + + 17 + + + 200 OK + + + + + 18 + + + Persist error data + + + + + Switch returns error to Payer FSP + + + + + 19 + + + PUT quotes/{ID}/error + + + + + 20 + + + 200 OK + + + + [quote invalid] + + + + + Switch returns error to Payer FSP + + + + + 21 + + + PUT quotes/{ID}/error + + + + + 22 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/qs-get-bulk-quotes.md b/website/versioned_docs/v1.0.1/technical/quoting-service/qs-get-bulk-quotes.md new file mode 100644 index 000000000..b78339ff6 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/qs-get-bulk-quotes.md @@ -0,0 +1,7 @@ +# GET Quote By ID + +Design for the retrieval of a Bulk Quote by an FSP. + +## Sequence Diagram + +![seq-get-bulk-quotes-2.1.0.svg](./assets/diagrams/sequence/seq-get-bulk-quotes-2.1.0.svg) diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/qs-get-quotes.md b/website/versioned_docs/v1.0.1/technical/quoting-service/qs-get-quotes.md new file mode 100644 index 000000000..765b5b4bf --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/qs-get-quotes.md @@ -0,0 +1,7 @@ +# GET Quote By ID + +Design for the retrieval of a Quote by an FSP. + +## Sequence Diagram + +![seq-get-quotes-1.1.0.svg](./assets/diagrams/sequence/seq-get-quotes-1.1.0.svg) diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/qs-post-bulk-quotes.md b/website/versioned_docs/v1.0.1/technical/quoting-service/qs-post-bulk-quotes.md new file mode 100644 index 000000000..28e692e68 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/qs-post-bulk-quotes.md @@ -0,0 +1,7 @@ +# POST Quote + +Design for a Bulk Quote request by an FSP. + +## Sequence Diagram + +![seq-post-bulk-quotes-2.2.0.svg](./assets/diagrams/sequence/seq-post-bulk-quotes-2.2.0.svg) diff --git a/website/versioned_docs/v1.0.1/technical/quoting-service/qs-post-quotes.md b/website/versioned_docs/v1.0.1/technical/quoting-service/qs-post-quotes.md new file mode 100644 index 000000000..b8f99fedf --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/quoting-service/qs-post-quotes.md @@ -0,0 +1,7 @@ +# POST Quote + +Design for a Quote request by an FSP. + +## Sequence Diagram + +![seq-post-quotes-1.2.0.svg](./assets/diagrams/sequence/seq-post-quotes-1.2.0.svg) diff --git a/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/README.md b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/README.md new file mode 100644 index 000000000..99127ef7c --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/README.md @@ -0,0 +1,9 @@ +# SDK Scheme Adapter +A scheme adapter is a service that interfaces between a Mojaloop API compliant switch and a DFSP backend platform that does not natively implement the Mojaloop API. + +The API between the scheme adapter and the DFSP backend is synchronous HTTP while the interface between the scheme adapter and the switch is native Mojaloop API. + +* [Usage](./usage/README.md) + * [Scheme Adapter to Scheme Adapter](./usage/scheme-adapter-to-scheme-adapter/README.md) + * [Scheme Adapter to Local K8S cluster](./usage/scheme-adapter-and-local-k8s/README.md) + * [Scheme Adapter to WSO2 API Gateway](./usage/scheme-adapter-and-wso2-api-gateway/README.md) diff --git a/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/README.md b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/README.md new file mode 100644 index 000000000..4984fc721 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/README.md @@ -0,0 +1,44 @@ +# Overview +A scheme adapter is a service that interfaces between a Mojaloop API compliant switch and a DFSP backend platform that does not natively implement the Mojaloop API. + +The API between the scheme adapter and the DFSP backend is synchronous HTTP while the interface between the scheme adapter and the switch is native Mojaloop API. + +This document provides different ways of setups that a DFSP can test using the scheme adapter. + +# Scenarios +There are number of scenarios those we tested and documented as follows. + +* [[Scheme Adapter + Mock DFSP Backend] -> [Scheme Adapter + Mojaloop Simulator]](./scheme-adapter-to-scheme-adapter/README.md) +* [[Scheme Adapter + Mock DFSP Backend] -> [Local K8S cluster]](./scheme-adapter-and-local-k8s/README.md) +* [[Scheme Adapter + Mojaloop Simulator] -> [Public hosted WSO2 enabled Mojaloop Switch]](./scheme-adapter-and-wso2-api-gateway/README.md) + +## [Scheme Adapter + Mock DFSP Backend] -> [Scheme Adapter + Mojaloop Simulator] + +The scheme adpater can be used in combination with some already implemented mock backends "Mock DFSP Backend" and "Mojaloop Simulator". The below are the links for the repositories. + +https://github.com/mojaloop/sdk-mock-dfsp-backend.git + +https://github.com/mojaloop/mojaloop-simulator.git + +The idea is to combine scheme adapter with mock DFSP backend on oneside and with mojaloop simulator on another side. Consider one side is payer dfsp and another side is payee dfsp. By following this example, you can send and recieve funds from one dfsp to another. + +Please [click here](./scheme-adapter-to-scheme-adapter/README.md) for the documentation. + +![SchemeAdapterToSchemeAdapter](./scheme-adapter-to-scheme-adapter/scheme-adapter-to-scheme-adapter-overview.png) + +## [Scheme Adapter + Mock DFSP Backend] -> [Local K8S cluster] + +Then if we want to include a switch inbetween the DFSPs, we can simulate that environment using a local K8S cluster. Please follow the onboarding documentation of local K8S cluster here (https://mojaloop.io/documentation/deployment-guide/). + +Please [click here](./scheme-adapter-and-local-k8s/README.md) for the documentation. + +![SchemeAdapterAndK8S](./scheme-adapter-and-local-k8s/scheme-adapter-and-local-k8s-overview.png) + +## [Scheme Adapter + Mojaloop Simulator] -> [Public hosted WSO2 enabled Mojaloop Switch] + +If you have access to the WSO2 Mojaloop API, you can test that by the following documentation. In the above two scenarios, we didn't use token authentication and SSL encryption capabilities of scheme adapter. We are going to use those capabilites in this section. + +Please [click here](./scheme-adapter-and-wso2-api-gateway/README.md) for the documentation. + + +![SchemeAdapterAndWSO2APIGateway](./scheme-adapter-and-wso2-api-gateway/scheme-adapter-and-wso2-api-gateway-overview.png) diff --git a/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/README.md b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/README.md new file mode 100644 index 000000000..5accc7ec1 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/README.md @@ -0,0 +1,206 @@ +# SDK Scheme Adapter and Local K8S cluster testing + +A detailed documentation for dfsps who want to test the mojaloop cluster deployment with scheme adapter and a mock backend service. + +![Overview](scheme-adapter-and-local-k8s-overview.png) + +## Prerequisite + +* A working mojaloop k8s cluster (Local / Cloud deployment) +* DFSP mock backend service +* sdk-scheme-adapter > 8.6.0 + +## Configuration & Starting services + +### Mojaloop Local K8S cluster deployment +Please follow the below link to deploy your own cluster on local system. +https://mojaloop.io/documentation/deployment-guide/ + +A Linux based operating system is recommended and at least 16GB RAM and 4 core processor is required. + +After installation please complete the `OSS-New-Deployment-FSP-Setup.postman_collection` collection available at https://github.com/mojaloop/postman + +Then make sure the oracles & endpoints are configured correctly and that the "Golden Path Collection" can be run successfully. + +### DFSP Mock Backend service & SDK Scheme adapter +The SDK scheme adapter version should be greater than 8.6.0 +The next step starts the scheme adapter from docker-compose file automatically. + +Please download the following repository +https://github.com/mojaloop/sdk-mock-dfsp-backend + +Edit the docker-compose.yml file and verify the following lines. + +``` +version: '3' +services: + redis2: + image: "redis:5.0.4-alpine" + container_name: redis2 + backend: + image: "mojaloop/sdk-mock-dfsp-backend" + env_file: ./backend.env + container_name: dfsp_mock_backend2 + ports: + - "23000:3000" + depends_on: + - scheme-adapter2 + + scheme-adapter2: + image: "mojaloop/sdk-scheme-adapter:latest" + env_file: ./scheme-adapter.env + container_name: sa_sim2 + ports: + - "4000:4000" + depends_on: + - redis2 +``` + +Edit the backend.env file and change the OUTBOUND_ENDPOINT value +``` +OUTBOUND_ENDPOINT=http://sa_sim2:4001 +``` + +Edit scheme-adapter.env and change the following lines +Please replace the endpoint values with the appropriate hostnames provided in /etc/hosts file. + +``` +DFSP_ID=safsp +CACHE_HOST=redis2 +ALS_ENDPOINT=account-lookup-service.local +QUOTES_ENDPOINT=quoting-service.local +TRANSFERS_ENDPOINT=ml-api-adapter.local +BACKEND_ENDPOINT=dfsp_mock_backend2:3000 +AUTO_ACCEPT_PARTY=true +AUTO_ACCEPT_QUOTES=true +VALIDATE_INBOUND_JWS=false +VALIDATE_INBOUND_PUT_PARTIES_JWS=false +JWS_SIGN=true +JWS_SIGN_PUT_PARTIES=true +``` + +### Name resolution configuration - Mac ONLY + +Point the following hostnames to your local machine IP by adding the below line in /etc/hosts file +``` +192.168.5.101 ml-api-adapter.local account-lookup-service.local central-ledger.local central-settlement.local account-lookup-service-admin.local quoting-service.local moja-simulator.local central-ledger central-settlement ml-api-adapter account-lookup-service account-lookup-service-admin quoting-service simulator host.docker.internal moja-account-lookup-mysql +``` + +Make sure to change 192.168.5.101 to your real external IP. + +### Name resolution configuration - Linux ONLY + +Add extra_hosts configuration to scheme-adapter2 config in the docker-compose.yml file, so that the scheme-adapter2 container can resolve dns of account-lookup-service.local, quoting-service.local and ml-api-adapter.local. For example the config could be: + +``` + scheme-adapter2: + image: "mojaloop/sdk-scheme-adapter:latest" + env_file: ./scheme-adapter.env + container_name: sa_sim2 + ports: + - "4000:4000" + depends_on: + - redis2 + extra_hosts: + - "account-lookup-service.local:172.17.0.1" + - "quoting-service.local:172.17.0.1" + - "ml-api-adapter.local:172.17.0.1" +``` + +The 172.17.0.1 is a default docker0 network interface on linux, however please make sure it's valid in your configuration and change it if needed. + +### Start + +Start the backend and scheme adapter using the following command. +``` +cd src +docker-compose up -d +``` + +## Testing + +### Configure new FSP +Download the following files: +* [Mojaloop-Local.postman_environment_modified.json](assets/postman_files/Mojaloop-Local.postman_environment_modified.json) - modified environment variables that point to your local setup +* [OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json](assets/postman_files/OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json) - steps that will setup new FSP + +The SCHEME_ADAPTER_ENDPOINT in the environment file should point to your local scheme-adapter deployment. For mac this is configured already to be http://host.docker.internal:4000. If you're running on Linux, please edit the environment file, so that SCHEME_ADAPTER_ENDPOINT points to your docker0 interface (usually 172.17.0.1 - see remarks in previous step). + +In postman, select the environment file and run the custom collection in the postman to provision a new FSP called "safsp". The endpoints for safsp will be set to the URL of the scheme adapter which is configured in environment file. + +### Add the target MSISDN to payee simulator which is running inside the K8S. Run the following commands +``` +curl -X POST \ + http://moja-simulator.local/payeefsp/parties/MSISDN/27713803912 \ + -H 'Accept: */*' \ + -H 'Accept-Encoding: gzip, deflate' \ + -H 'Cache-Control: no-cache' \ + -H 'Connection: keep-alive' \ + -H 'Content-Length: 406' \ + -H 'Content-Type: application/json' \ + -H 'Host: moja-simulator.local' \ + -H 'User-Agent: PostmanRuntime/7.20.1' \ + -H 'cache-control: no-cache' \ + -d '{ + "party": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27713803912", + "fspId": "payeefsp" + }, + "name": "Siabelo Maroka", + "personalInfo": { + "complexName": { + "firstName": "Siabelo", + "lastName": "Maroka" + }, + "dateOfBirth": "1974-01-01" + } + } +}' + +curl -X POST \ + http://account-lookup-service.local/participants/MSISDN/27713803912 \ + -H 'Accept: application/vnd.interoperability.participants+json;version=1' \ + -H 'Connection: keep-alive' \ + -H 'Content-Length: 50' \ + -H 'Content-Type: application/vnd.interoperability.participants+json;version=1.0' \ + -H 'Date: Fri, 21 Dec 2018 12:17:01 GMT' \ + -H 'FSPIOP-Source: payeefsp' \ + -H 'Host: account-lookup-service.local' \ + -H 'User-Agent: PostmanRuntime/7.11.0' \ + -H 'accept-encoding: gzip, deflate' \ + -H 'cache-control: no-cache,no-cache' \ + -d '{ + "fspId": "payeefsp", + "currency": "USD" +}' +``` + +### Try to send money +Try to send funds from "safsp" (Mock DFSP) to a MSISDN which is in "payeedfsp" (Simulator in K8S) through scheme adapter. +Run the following curl command to issue command to Mock DFSP service. +``` +curl -X POST \ + http://localhost:23000/send \ + -H 'Content-Type: application/json' \ + -d '{ + "from": { + "displayName": "John Doe", + "idType": "MSISDN", + "idValue": "123456789" + }, + "to": { + "idType": "MSISDN", + "idValue": "27713803912" + }, + "amountType": "SEND", + "currency": "USD", + "amount": "100", + "transactionType": "TRANSFER", + "note": "testpayment", + "homeTransactionId": "123ABC" +}' +``` + +You should get a response with COMPLETED currentState. diff --git a/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/Mojaloop-Local.postman_environment_modified.json b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/Mojaloop-Local.postman_environment_modified.json new file mode 100644 index 000000000..eddcac266 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/Mojaloop-Local.postman_environment_modified.json @@ -0,0 +1,1012 @@ +{ + "id": "a9937c8b-0281-4128-8b53-1f1f913ff2aa", + "name": "Mojaloop-Local", + "values": [ + { + "key": "payeefsp", + "value": "payeefsp", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "payerfsp", + "value": "payerfsp", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "transferExpiration", + "value": "2019-05-27T15:44:53.292Z", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "transactionRequestId", + "value": "25a00155-c777-4629-a6b7-61cf0d16f499", + "enabled": true + }, + { + "key": "transferDate", + "value": "Fri, 21 Dec 2018 12:17:01 GMT", + "enabled": true + }, + { + "key": "currentTimestamp", + "value": "2018-12-06T17:09:56.386Z", + "enabled": true + }, + { + "key": "quoteDate", + "value": "Fri, 21 Dec 2018 12:19:49 GMT", + "enabled": true + }, + { + "key": "quoteExpiration", + "value": "2018-11-08T21:31:00.534+01:00", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_MOJALOOP", + "value": "localhost:4000", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "BASE_MOJALOOP", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_CENTRAL_LEDGER", + "value": "http://central-ledger.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "BASE_CENTRAL_LEDGER_API", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "BASE_CENTRAL_LEDGER_ADMIN", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_ML_API", + "value": "http://ml-api-adapter.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "BASE_ML_API", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_CENTRAL_SETTLEMENT", + "value": "http://central-settlement.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "BASE_CENTRAL_SETTLEMENT", + "value": "/v1", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_TRANSFER_UUID_ON_PREPARE", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_TRANSFER_UUID_ON_QUOTE\n", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_QUOTE_UUID_ON_QUOTE", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_TIMESTAMP", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_PREPARE_DATE", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_QUOTE_DATE", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "CONFIG_GENERATE_NEW_TRANSACTION_UUID_ON_QUOTE", + "value": "true", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "transferExpiredExpiration", + "value": "2018-08-31T15:26:01.870Z", + "enabled": true + }, + { + "key": "condition", + "value": "HOr22-H3AfTDHrSkPjJtVPRdKouuMkDXTR4ejlQa8Ks", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "fulfilment", + "value": "uU0nuZNNPgilLlLX2n2r-sSE7-N6U4DukIj3rOLvzek", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_SIMULATOR", + "value": "http://moja-simulator.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "SCHEME_ADAPTER_ENDPOINT", + "value": "http://host.docker.internal:4000", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "quoteId", + "value": "ddaa67b3-5bf8-45c1-bfcf-1e8781177c37", + "enabled": true + }, + { + "key": "ilpPacket", + "value": "AQAAAAAAAADIEHByaXZhdGUucGF5ZWVmc3CCAiB7InRyYW5zYWN0aW9uSWQiOiIyZGY3NzRlMi1mMWRiLTRmZjctYTQ5NS0yZGRkMzdhZjdjMmMiLCJxdW90ZUlkIjoiMDNhNjA1NTAtNmYyZi00NTU2LThlMDQtMDcwM2UzOWI4N2ZmIiwicGF5ZWUiOnsicGFydHlJZEluZm8iOnsicGFydHlJZFR5cGUiOiJNU0lTRE4iLCJwYXJ0eUlkZW50aWZpZXIiOiIyNzcxMzgwMzkxMyIsImZzcElkIjoicGF5ZWVmc3AifSwicGVyc29uYWxJbmZvIjp7ImNvbXBsZXhOYW1lIjp7fX19LCJwYXllciI6eyJwYXJ0eUlkSW5mbyI6eyJwYXJ0eUlkVHlwZSI6Ik1TSVNETiIsInBhcnR5SWRlbnRpZmllciI6IjI3NzEzODAzOTExIiwiZnNwSWQiOiJwYXllcmZzcCJ9LCJwZXJzb25hbEluZm8iOnsiY29tcGxleE5hbWUiOnt9fX0sImFtb3VudCI6eyJjdXJyZW5jeSI6IlVTRCIsImFtb3VudCI6IjIwMCJ9LCJ0cmFuc2FjdGlvblR5cGUiOnsic2NlbmFyaW8iOiJERVBPU0lUIiwic3ViU2NlbmFyaW8iOiJERVBPU0lUIiwiaW5pdGlhdG9yIjoiUEFZRVIiLCJpbml0aWF0b3JUeXBlIjoiQ09OU1VNRVIiLCJyZWZ1bmRJbmZvIjp7fX19", + "enabled": true + }, + { + "key": "payerFspId", + "value": "3", + "enabled": true + }, + { + "key": "payerFspAccountId", + "value": "3", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "payeeFspId", + "value": "4", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "payeeFspAccountId", + "value": "5", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "openWindowID", + "value": 1, + "enabled": true + }, + { + "key": "newOpenWindowID", + "value": 2, + "enabled": true + }, + { + "key": "closedWindowID", + "value": 1, + "enabled": true + }, + { + "key": "settlementId", + "value": 1, + "enabled": true + }, + { + "key": "expectedFullName", + "value": "Siabelo Maroka", + "enabled": true + }, + { + "key": "expectedFirstName", + "value": "Siabelo", + "enabled": true + }, + { + "key": "expectedLastName", + "value": "Maroka", + "enabled": true + }, + { + "key": "expectedDOB", + "value": "3/3/1973", + "enabled": true + }, + { + "key": "pathfinderMSISDN", + "value": "27713803912", + "enabled": true + }, + { + "key": "fullName", + "value": "Siabelo Maroka", + "enabled": true + }, + { + "key": "firstName", + "value": "Siabelo", + "enabled": true + }, + { + "key": "lastName", + "value": "Maroka", + "enabled": true + }, + { + "key": "dob", + "value": "3/3/1973", + "enabled": true + }, + { + "key": "HOST_ML_API_ADAPTER", + "value": "http://ml-api-adapter.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "dateHeader", + "value": "Thu, 24 Jan 2019 10:22:12 GMT", + "enabled": true + }, + { + "key": "participant", + "value": "testfsp4", + "enabled": true + }, + { + "key": "payerfspBeforePosition", + "value": -1782, + "enabled": true + }, + { + "key": "HOST_SWITCH_TRANSFERS", + "value": "http://ml-api-adapter.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "BASE_PATH_SWITCH_TRANSFERS", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_SIMULATOR_K8S_CLUSTER", + "value": "http://moja-simulator", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "payerfspPositionBeforeTransfer", + "value": 0, + "enabled": true + }, + { + "key": "payerNDC", + "value": 1000, + "enabled": true + }, + { + "key": "payeefspPositionBeforeTransfer", + "value": 0, + "enabled": true + }, + { + "key": "blockTransferAmount", + "value": 7494, + "enabled": true + }, + { + "key": "payeeNDC", + "value": 1000, + "enabled": true + }, + { + "key": "payerfspPositionAfterTransfer", + "value": 0, + "enabled": true + }, + { + "key": "transferAmount", + "value": "99", + "enabled": true + }, + { + "key": "payeefspPositionAfterTransfer", + "value": 0, + "enabled": true + }, + { + "key": "payerfspPositionAfterTransferBeforeExpiry", + "value": 1596, + "enabled": true + }, + { + "key": "fspName", + "value": "payerfsp", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "settlementAccountId", + "value": "3", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "reportEndDate", + "value": "2018-10-31", + "enabled": true + }, + { + "key": "reportFSPID", + "value": "payerfsp", + "enabled": true + }, + { + "key": "reportStartDate", + "value": "2018-10-01", + "enabled": true + }, + { + "key": "transactionId", + "value": "97f3f215-37a0-4755-a17c-c39313aa2f98", + "enabled": true + }, + { + "key": "payerfspSettlementAccountId", + "value": 8, + "enabled": true + }, + { + "key": "payeefspSettlementAccountId", + "value": 4, + "enabled": true + }, + { + "key": "fundsInPrepareTransferId", + "value": "b79a979e-9605-4db4-a052-85bc948be414", + "enabled": true + }, + { + "key": "HUBOPERATOR_BEARER_TOKEN", + "value": "NOT_APPLICABLE", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "hub_operator", + "value": "NOT_APPLICABLE", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "payeefspNetSettlementAmount", + "value": -198, + "enabled": true + }, + { + "key": "payerfspNetSettlementAmount", + "value": 198, + "enabled": true + }, + { + "key": "fundsInPrepareAmount", + "value": 500, + "enabled": true + }, + { + "key": "payerfspSettlementAccountBalance", + "value": -4800, + "enabled": true + }, + { + "key": "hubReconAccountBalance", + "value": 4800, + "enabled": true + }, + { + "key": "payerfspAccountBalanceBeforeSettlement", + "value": 0, + "enabled": true + }, + { + "key": "payeefspAccountBalanceBeforeSettlement", + "value": 0, + "enabled": true + }, + { + "key": "fundsOutPrepareTransferId", + "value": "f60c555f-72a7-44c7-a3a8-1f4a4df4b100", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "hubReconAccountBalanceBeforeFundsIn", + "value": "", + "enabled": true + }, + { + "key": "payerfspSettlementAccountBalanceBeforeFundsIn", + "value": "", + "enabled": true + }, + { + "key": "fundsOutPrepareAmount", + "value": "", + "enabled": true + }, + { + "key": "payerfspNDCBeforePrepare", + "value": "", + "enabled": true + }, + { + "key": "payeefspNDCBeforePrepare", + "value": "", + "enabled": true + }, + { + "key": "payeefspPositionAccountId", + "value": 3, + "enabled": true + }, + { + "key": "payerfspPositionAccountId", + "value": 7, + "enabled": true + }, + { + "key": "testfsp1", + "value": "testfsp1", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp2", + "value": "testfsp2", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp1PositionAccountId", + "value": 25, + "enabled": true + }, + { + "key": "testfsp1SettlementAccountId", + "value": 26, + "enabled": true + }, + { + "key": "testfsp2PositionAccountId", + "value": 29, + "enabled": true + }, + { + "key": "testfsp2SettlementAccountId", + "value": 30, + "enabled": true + }, + { + "key": "testfsp1Id", + "value": "13", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp2Id", + "value": "14", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "hubReconAccountBalanceBeforeFundsOutPrepare", + "value": "", + "enabled": true + }, + { + "key": "payerfspSettlementAccountBalanceBeforeFundsOutPrepare", + "value": "", + "enabled": true + }, + { + "key": "fundsOutCommitAmount", + "value": "", + "enabled": true + }, + { + "key": "fundsOutCommitTransferId", + "value": "", + "enabled": true + }, + { + "key": "hubReconAccountBalanceBeforeFundsOutCommit", + "value": "", + "enabled": true + }, + { + "key": "payerfspSettlementAccountBalanceBeforeFundsOutCommit", + "value": "", + "enabled": true + }, + { + "key": "transfer_ID", + "value": "e7b43799-e69e-4578-bd26-2a4b9a22e92e", + "enabled": true + }, + { + "key": "get_transfer_ID", + "value": "7e19ae5f-7db6-4612-ab99-7538a56b4c25", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "env_prefix", + "value": "test", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "hubReconAccountBalanceBeforeFundsInReserve", + "value": "", + "enabled": true + }, + { + "key": "payerfspSettlementAccountBalanceBeforeFundsInReserve", + "value": "", + "enabled": true + }, + { + "key": "validCondition", + "value": "GRzLaTP7DJ9t4P-a_BA0WA9wzzlsugf00-Tn6kESAfM", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "validFulfillment", + "value": "UNlJ98hZTY_dsw0cAqw4i_UN3v4utt7CZFB4yfLbVFA", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "currency", + "value": "USD", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp1PositionAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp1SettleAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp2PositionAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp2SettleAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp3PositionAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp3SettleAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp4PositionAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfsp4SettleAccountBalance", + "value": "", + "enabled": true + }, + { + "key": "testfspId3", + "value": "15", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfspId4", + "value": "16", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "invalidFulfillment", + "value": "_3cco-YN5OGpRKVWV3n6x6uNpBTH9tYUdOYmHA", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "completedTimestamp", + "value": "", + "enabled": true + }, + { + "key": "payerfspPositionBeforePrepare", + "value": "", + "enabled": true + }, + { + "key": "payeefspPositionBeforePrepare", + "value": "", + "enabled": true + }, + { + "key": "payerfspPositionAfterPrepare", + "value": "", + "enabled": true + }, + { + "key": "fundsOutPrepareReserveAmount", + "value": "", + "enabled": true + }, + { + "key": "fundsOutPrepareReserveTransferId", + "value": "", + "enabled": true + }, + { + "key": "testfsp1PositionAccountBalanceBeforeTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp1SettleAccountBalanceBeforeTransfer", + "value": "", + "enabled": true + }, + { + "key": "fspiop-signature", + "value": "{\"signature\":\"iU4GBXSfY8twZMj1zXX1CTe3LDO8Zvgui53icrriBxCUF_wltQmnjgWLWI4ZUEueVeOeTbDPBZazpBWYvBYpl5WJSUoXi14nVlangcsmu2vYkQUPmHtjOW-yb2ng6_aPfwd7oHLWrWzcsjTF-S4dW7GZRPHEbY_qCOhEwmmMOnE1FWF1OLvP0dM0r4y7FlnrZNhmuVIFhk_pMbEC44rtQmMFv4pm4EVGqmIm3eyXz0GkX8q_O1kGBoyIeV_P6RRcZ0nL6YUVMhPFSLJo6CIhL2zPm54Qdl2nVzDFWn_shVyV0Cl5vpcMJxJ--O_Zcbmpv6lxqDdygTC782Ob3CNMvg\\\",\\\"protectedHeader\\\":\\\"eyJhbGciOiJSUzI1NiIsIkZTUElPUC1VUkkiOiIvdHJhbnNmZXJzIiwiRlNQSU9QLUhUVFAtTWV0aG9kIjoiUE9TVCIsIkZTUElPUC1Tb3VyY2UiOiJPTUwiLCJGU1BJT1AtRGVzdGluYXRpb24iOiJNVE5Nb2JpbGVNb25leSIsIkRhdGUiOiIifQ\"}", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp3SettlementAccountId", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp4SettlementAccountId", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp3SettlementAccountBalanceBeforeFundsIn", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp4SettlementAccountBalanceBeforeFundsIn", + "value": "", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp3", + "value": "testfsp3", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp4", + "value": "testfsp4", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "testfsp1PositionAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp1SettleAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp2PositionAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp2SettleAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp3PositionAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp3SettleAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp4PositionAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "testfsp4SettleAccountBalanceAfterTransfer", + "value": "", + "enabled": true + }, + { + "key": "hubReconAccountBalanceBeforeFundsOutAbort", + "value": "", + "enabled": true + }, + { + "key": "payerfspSettlementAccountBalanceBeforeFundsOutAbort", + "value": "", + "enabled": true + }, + { + "key": "payeefsp_fspiop_signature", + "value": "{\"signature\":\"abcJjvNrkyK2KBieDUbGfhaBUn75aDUATNF4joqA8OLs4QgSD7i6EO8BIdy6Crph3LnXnTM20Ai1Z6nt0zliS_qPPLU9_vi6qLb15FOkl64DQs9hnfoGeo2tcjZJ88gm19uLY_s27AJqC1GH1B8E2emLrwQMDMikwQcYvXoyLrL7LL3CjaLMKdzR7KTcQi1tCK4sNg0noIQLpV3eA61kess\",\"protectedHeader\":\"eyJhbGciOiJSUzI1NiIsIkZTUElPUC1Tb3VyY2UiOiJwYXllZWZzcCIsIkZTUElPUC1EZXN0aW5hdGlvbiI6InBheWVyZnNwIiwiRlNQSU9QLVVSSSI6Ii90cmFuc2ZlcnMvZDY3MGI1OTAtZjc5ZC00YWU5LThjNmUtMTVjZjZjNWMzODk5IiwiRlNQSU9QLUhUVFAtTWV0aG9kIjoiUFVUIiwiRGF0ZSI6IiJ9\"}", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_ACCOUNT_LOOKUP_SERVICE", + "value": "http://account-lookup-service.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_ACCOUNT_LOOKUP_ADMIN", + "value": "http://account-lookup-service-admin.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "HOST_QUOTING_SERVICE", + "value": "http://quoting-service.local", + "description": { + "content": "", + "type": "text/plain" + }, + "enabled": true + }, + { + "key": "payeefsp_signature", + "value": "abcJjvNrkyK2KBieDUbGfhaBUn75aDUATNF4joqA8OLs4QgSD7i6EO8BIdy6Crph3LnXnTM20Ai1Z6nt0zliS_qPPLU9_vi6qLb15FOkl64DQs9hnfoGeo2tcjZJ88gm19uLY_s27AJqC1GH1B8E2emLrwQMDMikwQcYvXoyLrL7LL3CjaLMKdzR7KTcQi1tCK4sNg0noIQLpV3eA61kess", + "type": "text", + "description": "", + "enabled": true + } + ], + "_postman_variable_scope": "environment", + "_postman_exported_at": "2019-05-30T00:29:41.827Z", + "_postman_exported_using": "Postman/6.7.4" +} diff --git a/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json new file mode 100644 index 000000000..70e2b3599 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/assets/postman_files/OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup.postman_collection.json @@ -0,0 +1,1072 @@ +{ + "info": { + "_postman_id": "52f405c0-bec3-4915-8c43-c250208623aa", + "name": "OSS-Custom-FSP-Onboaring-SchemeAdapter-Setup", + "description": "Author: Sridevi Miriyala\nPurpose: Used to add new FSP and relevant Callback Information", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "FSP Onboarding", + "item": [ + { + "name": "safsp (p2p transfers)", + "item": [ + { + "name": "Add payerfsp - TRANSFERS", + "event": [ + { + "listen": "test", + "script": { + "id": "76c222f4-969b-4081-b4d7-133ebe48f50f", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\"name\": \"safsp\",\"currency\": \"{{currency}}\"}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants" + ] + } + }, + "response": [] + }, + { + "name": "Add initial position and limits - payerfsp", + "event": [ + { + "listen": "test", + "script": { + "id": "d767079d-a9dd-401a-8d6a-5f94654c4259", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"currency\": \"{{currency}}\",\n\t\"limit\": {\n\t \"type\": \"NET_DEBIT_CAP\",\n\t \"value\": 1000000\n\t},\n\t\"initialPosition\": 0\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/initialPositionAndLimits", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "initialPositionAndLimits" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTICIPANT PUT", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTICIPANT_PUT\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/participants/{{partyIdType}}/{{partyIdentifier}}\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTICIPANT PUT Error", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/participants/{{partyIdType}}/{{partyIdentifier}}/error\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTICIPANT PUT Batch", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/participants/{{requestId}}\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTICIPANT PUT Batch Error", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/participants/{{requestId}}/error\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTIES GET", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTIES_GET\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/parties/{{partyIdType}}/{{partyIdentifier}}\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTIES PUT", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTIES_PUT\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/parties/{{partyIdType}}/{{partyIdentifier}}\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - PARTIES PUT Error", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/parties/{{partyIdType}}/{{partyIdentifier}}/error\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - QUOTES PUT", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_QUOTES\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - TRANSFER POST", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_TRANSFER_POST\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/transfers\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - TRANSFER PUT", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_TRANSFER_PUT\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/transfers/{{transferId}}\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "Add payerfsp callback - TRANSFER ERROR", + "event": [ + { + "listen": "test", + "script": { + "id": "bb928ca3-8904-4cff-94fa-9629ccf2418d", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"FSPIOP_CALLBACK_URL_TRANSFER_ERROR\",\n \"value\": \"{{SCHEME_ADAPTER_ENDPOINT}}/transfers/{{transferId}}/error\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + } + }, + "response": [] + }, + { + "name": "9. Set Endpoint-NET_DEBIT_CAP_ADJUSTMENT_EMAIL Copy", + "event": [ + { + "listen": "test", + "script": { + "id": "83984619-0430-4a4c-87ec-671bf97894de", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BEARER_TOKEN}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Cache-Control", + "value": "no-cache" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"NET_DEBIT_CAP_ADJUSTMENT_EMAIL\",\n \"value\": \"sridevi.miriyala@modusbox.com\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + }, + "description": "Generated from a curl request: \ncurl -i -X POST {{HOST_CENTRAL_LEDGER}}/participants/testfsp2/initialPositionAndLimits -H 'Cache-Control: no-cache' -H 'Content-Type: application/json' -d '{\n \\\"currency\\\": \\\"USD\\\",\n \\\"limit\\\": {\n \\\"type\\\": \\\"NET_DEBIT_CAP\\\",\n \\\"value\\\": 1000\n },\n \\\"initialPosition\\\": 0\n }'" + }, + "response": [ + { + "name": "2. Create Initial Position and Limits", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Cache-Control", + "value": "no-cache" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"currency\": \"USD\",\n \"limit\": {\n \"type\": \"NET_DEBIT_CAP\",\n \"value\": 1000\n },\n \"initialPosition\": 0\n }" + }, + "url": { + "raw": "http://{{HOST_CENTRAL_LEDGER}}/participants/testfsp/initialPositionAndLimits", + "protocol": "http", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "testfsp", + "initialPositionAndLimits" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "Text", + "header": [], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "Set Endpoint-SETTLEMENT_TRANSFER_POSITION_CHANGE_EMAIL Copy", + "event": [ + { + "listen": "test", + "script": { + "id": "16f8d261-3f2d-470b-986b-c8e23602605b", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BEARER_TOKEN}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Cache-Control", + "value": "no-cache" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"SETTLEMENT_TRANSFER_POSITION_CHANGE_EMAIL\",\n \"value\": \"sridevi.miriyala@modusbox.com\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + }, + "description": "Generated from a curl request: \ncurl -i -X POST {{HOST_CENTRAL_LEDGER}}/participants/testfsp2/initialPositionAndLimits -H 'Cache-Control: no-cache' -H 'Content-Type: application/json' -d '{\n \\\"currency\\\": \\\"USD\\\",\n \\\"limit\\\": {\n \\\"type\\\": \\\"NET_DEBIT_CAP\\\",\n \\\"value\\\": 1000\n },\n \\\"initialPosition\\\": 0\n }'" + }, + "response": [ + { + "name": "2. Create Initial Position and Limits", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Cache-Control", + "value": "no-cache" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"currency\": \"USD\",\n \"limit\": {\n \"type\": \"NET_DEBIT_CAP\",\n \"value\": 1000\n },\n \"initialPosition\": 0\n }" + }, + "url": { + "raw": "http://{{HOST_CENTRAL_LEDGER}}/participants/testfsp/initialPositionAndLimits", + "protocol": "http", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "testfsp", + "initialPositionAndLimits" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "Text", + "header": [], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "DFSP Endpoint-NET_DEBIT_CAP_THRESHOLD_BREACH_EMAIL Copy", + "event": [ + { + "listen": "test", + "script": { + "id": "67082524-b658-4f1c-90c4-af6fc24adb3e", + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BEARER_TOKEN}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Cache-Control", + "value": "no-cache" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"NET_DEBIT_CAP_THRESHOLD_BREACH_EMAIL\",\n \"value\": \"sridevi.miriyala@modusbox.com\"\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/endpoints", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "endpoints" + ] + }, + "description": "Generated from a curl request: \ncurl -i -X POST {{HOST_CENTRAL_LEDGER}}/participants/testfsp2/initialPositionAndLimits -H 'Cache-Control: no-cache' -H 'Content-Type: application/json' -d '{\n \\\"currency\\\": \\\"USD\\\",\n \\\"limit\\\": {\n \\\"type\\\": \\\"NET_DEBIT_CAP\\\",\n \\\"value\\\": 1000\n },\n \\\"initialPosition\\\": 0\n }'" + }, + "response": [ + { + "name": "2. Create Initial Position and Limits", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Cache-Control", + "value": "no-cache" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"currency\": \"USD\",\n \"limit\": {\n \"type\": \"NET_DEBIT_CAP\",\n \"value\": 1000\n },\n \"initialPosition\": 0\n }" + }, + "url": { + "raw": "http://{{HOST_CENTRAL_LEDGER}}/participants/testfsp/initialPositionAndLimits", + "protocol": "http", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "testfsp", + "initialPositionAndLimits" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "Text", + "header": [], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "Record Funds In - payerfsp ", + "event": [ + { + "listen": "test", + "script": { + "id": "802139ed-ec95-40f8-99a7-d88f0e77e49d", + "exec": [ + "pm.test(\"Status code is 202\", function () {", + " pm.response.to.have.status(202);", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "id": "461d34bc-33f6-4031-bbc4-b26489ff1953", + "exec": [ + "var uuid = require('uuid');", + "var generatedUUID = uuid.v4();", + "pm.environment.set('fundsInPrepareTransferId', generatedUUID);", + "pm.environment.set('fundsInPrepareAmount', 5000);", + "", + "", + "const payerfspGetStatusRequest = {", + " url: pm.environment.get(\"HOST_CENTRAL_LEDGER\")+pm.environment.get(\"BASE_CENTRAL_LEDGER_ADMIN\")+'/participants/'+pm.environment.get(\"payerfsp\")+'/accounts',", + " method: 'GET',", + " header: {", + " \"Authorization\":\"Bearer \"+pm.environment.get(\"HUB_OPERATOR_BEARER_TOKEN\"),", + " \"FSPIOP-Source\": pm.environment.get(\"hub_operator\"),", + " \"Content-Type\": \"application/json\"", + " }", + "};", + "pm.sendRequest(payerfspGetStatusRequest, function (err, response) {", + " console.log(response.json())", + " var jsonData = response.json()", + " for(var i in jsonData) {", + " if((jsonData[i].ledgerAccountType === 'SETTLEMENT') && (jsonData[i].currency === pm.environment.get(\"currency\"))) {", + " pm.environment.set(\"payerfspSettlementAccountId\",jsonData[i].id)", + " pm.environment.set(\"payerfspSettlementAccountBalanceBeforeFundsIn\",jsonData[i].value)", + " }", + " }", + "});", + "", + "const hubGetStatusRequest = {", + " url: pm.environment.get(\"HOST_CENTRAL_LEDGER\")+pm.environment.get(\"BASE_CENTRAL_LEDGER_ADMIN\")+'/participants/hub/accounts',", + " method: 'GET',", + " header: {", + " \"Authorization\":\"Bearer \"+pm.environment.get(\"BEARER_TOKEN\"),", + " \"FSPIOP-Source\": pm.environment.get(\"payerfsp\"),", + " \"Content-Type\": \"application/json\"", + " }", + "};", + "pm.sendRequest(hubGetStatusRequest, function (err, response) {", + " console.log(response.json())", + " var jsonData = response.json()", + " for(var i in jsonData) {", + " if((jsonData[i].ledgerAccountType === 'HUB_RECONCILIATION') && (jsonData[i].currency === pm.environment.get(\"currency\"))) {", + " pm.environment.set(\"hubReconAccountBalanceBeforeFundsIn\",jsonData[i].value)", + " }", + " }", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BEARER_TOKEN}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "FSPIOP-Source", + "value": "{{payerfsp}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"transferId\": \"{{fundsInPrepareTransferId}}\",\n \"externalReference\": \"string\",\n \"action\": \"recordFundsIn\",\n \"reason\": \"string\",\n \"amount\": {\n \"amount\":\"{{fundsInPrepareAmount}}\" ,\n \"currency\": \"{{currency}}\"\n },\n \"extensionList\": {\n \"extension\": [\n {\n \"key\": \"string\",\n \"value\": \"string\"\n }\n ]\n }\n}" + }, + "url": { + "raw": "{{HOST_CENTRAL_LEDGER}}/participants/safsp/accounts/{{payerfspSettlementAccountId}}", + "host": [ + "{{HOST_CENTRAL_LEDGER}}" + ], + "path": [ + "participants", + "safsp", + "accounts", + "{{payerfspSettlementAccountId}}" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "e5ffaeb6-241f-4b10-af63-b52b064ff44f", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "efb91eb5-c6c5-460c-89b0-a424f39dcf9a", + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": {}, + "_postman_isSubFolder": true + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "a29d64a2-7a89-4cc9-ac33-2a630283471d", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "7bcf1b8c-ce85-4b11-ac83-899cc81ce501", + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": {} + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "402cb439-04ee-4add-9a65-f4b3f9dafa58", + "type": "text/javascript", + "exec": [ + "", + "// Ensure that the following variables are not set in the environment", + "// This is a fix for the following issue: https://github.com/mojaloop/project/issues/903", + "// This will ensure that templates are not replaced in the endpoint configs:", + "pm.environment.unset('partyIdType')", + "pm.environment.unset('partyIdentifier')", + "pm.environment.unset('requestId')", + "pm.environment.unset('transferId')", + "", + "pm.globals.unset('partyIdType')", + "pm.globals.unset('partyIdentifier')", + "pm.globals.unset('requestId')", + "pm.globals.unset('transferId')" + ] + } + }, + { + "listen": "test", + "script": { + "id": "e73fb24a-c94a-4551-ac31-fb7ceb250579", + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": {} +} \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/scheme-adapter-and-local-k8s-overview.png b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/scheme-adapter-and-local-k8s-overview.png new file mode 100644 index 000000000..4d6282c3c Binary files /dev/null and b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-local-k8s/scheme-adapter-and-local-k8s-overview.png differ diff --git a/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/README.md b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/README.md new file mode 100644 index 000000000..f780e85bc --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/README.md @@ -0,0 +1,221 @@ +# SDK Scheme Adapter and WSO2 API Gateway + +This documentaion is for testing scheme adapter against a public hosted WSO2 API gateway with SSL encryption and bearer token authentication. + + +![Overview](scheme-adapter-and-wso2-api-gateway-overview.png) + +## Prerequisite + +* Accesss to WSO2 API production api with a generated token. +* sdk-scheme-adapter +* mojaloop-simulator + +## Generate access token and URL from WSO2 API + +* Login to your WSO2 store and go to applications in the menu. Create a new application and access keys if you don't have those already. +* Then go to APIs menu, you should find the following applications. Subscribe to these two APIs by selecting your application and tier from the each API main page. + * Central Ledger Admin API - We will use this endpoint for creating a new fsp and configure endpoints for that fsp. (Please contact your infra team for the proper https endpoints, they need to provision them on the hub) + * FSPIOP API - This is the main API for account lookup, quotes & transfers +* You can try some api requests in "API Console" tab by selecting the generated access token. +* Please make a note of the API URLs for both APIs and access token. + + +## Infrastructure Stuff +The following are the things your infrastructure team should take care off. +Please contact your infra team for further details. +* For getting back the responses, we need a machine with static public IP. And a domain name should be pointed to that IP. +* Generate client and server SSL certificates using MCM portal and keychain tool. This step is to establish secure communication using mutual SSL. +* Provision the endpoints pointing to your https address in WSO2 / HA Proxy. +* Establish JWS authentication +* **AWS Deployment** + * Launch an EC2 instance in AWS console + * Create an EC2 instance in AWS console and select **t2.micro** instance type. + * Select **Ubuntu 18.04** as your operating system. + * After your instance is ready, you can connect to it using ssh and the downloaded key file from AWS EC2 dashboard. + * Install docker and docker-compose in that EC2 instance + + * Open 4000 TCP port in security groups and assign elastic IP + * Add the inbound rule in security group of this EC2 instance that will expose the TCP 4000 port to public + * Use Elastic IP service to assign a static IP for this instance + + * Setup domain name for this instance + * You can use route53 in aws or any other DNS service to point a DNS name to this IP address + * This step is required because the Let's Encrypt certificate authority will not issue certificates for a bare IP address. + + +## Setting up Scheme Adapter with Mojaloop Simulator + +Please download the Mojaloop Simulator repo +``` +git clone https://github.com/mojaloop/mojaloop-simulator.git +``` +* Replace the certificates and keys in src/secrets folder with the generated certificates in the previous step. + +* Edit the file src/docker-compose.yml and change the required parameters. Please refer the following file. + + ``` + version: '3' + services: + redis: + image: "redis:5.0.4-alpine" + container_name: redis + backend: + image: "mojaloop/mojaloop-simulator-backend" + env_file: ./sim-backend.env + container_name: ml_simulator + ports: + - "3000:3000" + - "3001:3001" + - "3003:3003" + depends_on: + - scheme-adapter + + scheme-adapter: + image: "mojaloop/sdk-scheme-adapter:latest" + env_file: ./scheme-adapter.env + container_name: sa_sim2 + volumes: + - ./secrets:/src/secrets + ports: + - "3500:3000" + - "4000:4000" + depends_on: + - redis + ``` + +* Edit the file src/sim-backend.env file and change the container name of the scheme adapter in that. Please refer the following lines. + + ``` + OUTBOUND_ENDPOINT=http://src_scheme-adapter_1:4001 + DFSP_ID=extpayerfsp + ``` + +* Edit the file src/scheme-adapter.env and change the following settings + ``` + MUTUAL_TLS_ENABLED=true + CACHE_HOST=redis + DFSP_ID=extpayerfsp + BACKEND_ENDPOINT=ml_simulator:3000 + PEER_ENDPOINT= + AUTO_ACCEPT_QUOTES=true + ``` + +Then try running the following command to run the services +``` +cd src/ +docker-compose up -d +``` + +We can now access the mojaloop simulator's test api on 3003. + +## Provision a new DFSP "extpayerfsp" with proper endpoints + +We should create a new fsp named "extpayerfp" or with any other name. + +The FSP onboarding section in "OSS-New-Deployment-FSP-Setup" postman collection can be used for this. You can get the postman repo from https://github.com/mojaloop/postman. +* Duplicate the "Mojaloop-Local" environment and change the following valuesin that + * payerfsp - extpayerfsp + * HOST_ML_API_ADAPTER, HOST_ML_API, HOST_SWITCH_TRANSFERS, HOST_ACCOUNT_LOOKUP_SERVICE, HOST_QUOTING_SERVICE - Your WSO2 FSPIOP API endpoint + * HOST_CENTRAL_LEDGER - Your WSO2 Central Services Admin API endpoint + * HOST_CENTRAL_SETTLEMENT - Your WSO2 Central Settlement API endpoint (optional for our testing) + * HOST_SIMULATOR & HOST_SIMULATOR_K8S_CLUSTER - https://:4000 +* Change the URLs in payerfsp onboarding in "FSP Onboarding" section of "OSS-New-Deployment-FSP-Setup" from "payerfsp" to "extpayerfsp" +* Change the authentication as "Bearer Token" and provide the access token we created in WSO2 store for the entire "Payer FSP Onboarding" folder. +* Change the endpoint URLs to the https endpoints provided by your infra team. +* Then run the "Payer FSP Onboarding" folder in that collection with the newly created environment. + +You should get 100% pass then we can confirm that the fsp is created and endpoints are set for the fsp. + +## Provision payeefsp and register a participant against MSISDN simulator + +Generally the simulator running in the switch contains payeefsp and you should register a new participant (phone number) of your choice. + +You can refer the postman request "p2p_happy_path SEND QUOTE / Register Participant {{pathfinderMSISDN}} against MSISDN Simulator for PayeeFSP" in "Golden_Path" collection to achieve this. + +The postman request will send a POST request to /participants/MSISDN/ with the following body and required http headers. +``` +{ + "fspId": "payeefsp", + "currency": "USD" +} +``` + +## Send money + +### In one step +If you want to send the money in one step, the configuration options "AUTO_ACCEPT_QUOTES" & "AUTO_ACCEPT_PARTY" in "scheme_adapter.env" should be enabled. + +``` +curl -X POST \ + "http://localhost:3003/scenarios" \ + -H 'Content-Type: application/json' \ + -d '[ + { + "name": "scenario1", + "operation": "postTransfers", + "body": { + "from": { + "displayName": "From some person name", + "idType": "MSISDN", + "idValue": "44123456789" + }, + "to": { + "idType": "MSISDN", + "idValue": "919848123456" + }, + "amountType": "SEND", + "currency": "USD", + "amount": "100", + "transactionType": "TRANSFER", + "note": "testpayment", + "homeTransactionId": "123ABC" + } + } +]' + +``` + +### In two steps + +The following command is used to send the money in two steps (i.e Requesting the quote first, accept after review the charges and party details) + +``` +curl -X POST \ + "http://localhost:3003/scenarios" \ + -H 'Content-Type: application/json' \ + -d '[ + { + "name": "scenario1", + "operation": "postTransfers", + "body": { + "from": { + "displayName": "From some person name", + "idType": "MSISDN", + "idValue": "44123456789" + }, + "to": { + "idType": "MSISDN", + "idValue": "9848123456" + }, + "amountType": "SEND", + "currency": "USD", + "amount": "100", + "transactionType": "TRANSFER", + "note": "testpayment", + "homeTransactionId": "123ABC" + } + }, + { + "name": "scenario2", + "operation": "putTransfers", + "params": { + "transferId": "{{scenario1.result.transferId}}" + }, + "body": { + "acceptQuote": true + } + } +]' + +``` \ No newline at end of file diff --git a/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/scheme-adapter-and-wso2-api-gateway-overview.png b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/scheme-adapter-and-wso2-api-gateway-overview.png new file mode 100644 index 000000000..206d31d45 Binary files /dev/null and b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-and-wso2-api-gateway/scheme-adapter-and-wso2-api-gateway-overview.png differ diff --git a/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/README.md b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/README.md new file mode 100644 index 000000000..b34595858 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/README.md @@ -0,0 +1,180 @@ +# Scheme Adapter to Scheme Adapter testing + +A detailed documentation for dfsps who want to test the transfer of funds from a scheme adapter to another scheme adapter directly using mock backend and mojaloop simulator services. + +![Overview](scheme-adapter-to-scheme-adapter-overview.png) + +## Prerequisite + +* Mojaloop Simulator +* DFSP mock backend service +* Scheme adapter is already included in both the above docker-compose scripts + +## Configuration & Starting services + +The idea is to run two docker-compose scripts in parallel from the above two services. To avoid conflicts we need to edit the docker-compose.yml files and specify the container names. + +### Mojaloop Simulator service + +Please download the Mojaloop Simulator repo +``` +git clone https://github.com/mojaloop/mojaloop-simulator.git +``` +* Edit the file src/docker-compose.yml and add the container names for all the containers. Please refer the following lines + +``` +version: '3' +services: + redis1: + image: "redis:5.0.4-alpine" + container_name: redis1 + sim: + image: "mojaloop-simulator-backend" + build: ../ + env_file: ./sim-backend.env + container_name: ml_sim1 + ports: + - "13000:3000" + - "3001:3001" + - "3003:3003" + depends_on: + - scheme-adapter + scheme-adapter: + image: "mojaloop/sdk-scheme-adapter:latest" + env_file: ./scheme-adapter.env + container_name: sa_sim1 + ports: + - "13500:3000" + - "14000:4000" + depends_on: + - redis1 +``` + +* Edit the file src/sim-backend.env file and change the container name of the scheme adapter in that. Please refer the following lines. + +``` +OUTBOUND_ENDPOINT=http://sa_sim1:4001 +``` + +* Edit the file src/scheme-adapter.env file and change the container names of the another scheme adapter and mojaloop simulator. Please refer the following lines + +``` +DFSP_ID=payeefsp +CACHE_HOST=redis1 +PEER_ENDPOINT=sa_sim2:4000 +BACKEND_ENDPOINT=ml_sim1:3000 +AUTO_ACCEPT_PARTY=true +AUTO_ACCEPT_QUOTES=true +VALIDATE_INBOUND_JWS=false +VALIDATE_INBOUND_PUT_PARTIES_JWS=false +JWS_SIGN=true +JWS_SIGN_PUT_PARTIES=true + +``` + +Then try running the following command to run the services +``` +cd src/ +docker-compose up -d +``` + +We can now access the mojaloop simulator's test api on 3003. + +A new party should be added to the simulator using the following command. Feel free to change the details you want. +``` +curl -X POST "http://localhost:3003/repository/parties" -H "accept: */*" -H "Content-Type: application/json" -d "{\"displayName\":\"Test Payee1\",\"firstName\":\"Test\",\"middleName\":\"\",\"lastName\":\"Payee1\",\"dateOfBirth\":\"1970-01-01\",\"idType\":\"MSISDN\",\"idValue\":\"9876543210\"}" +``` + +Then try to run the following command to check the new party added. +``` +curl -X GET "http://localhost:3003/repository/parties" -H "accept: */*" +``` + +Let's move on to setup another instance of scheme adapter with DFSP mock backend. + +### DFSP Mock Backend service + +The DFSP mock backend is a minimal implementation of an example DFSP. Only basic functions are supported at the moment. + +Please download the following repository +``` +git clone https://github.com/mojaloop/sdk-mock-dfsp-backend.git +``` + +Edit the files src/docker-compose.yml, src/backend.env and src/scheme-adapter.env and add the container names for all the containers. Please refer the following files. +docker-compose.yml +``` +version: '3' +services: + redis2: + image: "redis:5.0.4-alpine" + container_name: redis2 + backend: + image: "mojaloop/sdk-mock-dfsp-backend" + env_file: ./backend.env + container_name: dfsp_mock_backend2 + ports: + - "23000:3000" + depends_on: + - scheme-adapter2 + + scheme-adapter2: + image: "mojaloop/sdk-scheme-adapter:latest" + env_file: ./scheme-adapter.env + container_name: sa_sim2 + depends_on: + - redis2 +``` +scheme-adapter.env +``` +DFSP_ID=payerfsp +CACHE_HOST=redis2 +PEER_ENDPOINT=sa_sim1:4000 +BACKEND_ENDPOINT=dfsp_mock_backend2:3000 +AUTO_ACCEPT_PARTY=true +AUTO_ACCEPT_QUOTES=true +VALIDATE_INBOUND_JWS=false +VALIDATE_INBOUND_PUT_PARTIES_JWS=false +JWS_SIGN=true +JWS_SIGN_PUT_PARTIES=true + +``` + +backend.env +``` +OUTBOUND_ENDPOINT=http://sa_sim2:4001 +``` + +Then try running the following command to run the services +``` +cd src/ +docker-compose up -d +``` + +## Try to send money +Try to send funds from "payerfsp" (Mock DFSP) to a MSISDN which is in "payeefsp" (Mojaloop Simulator) through scheme adapter. +Run the following curl command to issue command to Mock DFSP service. +``` +curl -X POST \ + http://localhost:23000/send \ + -H 'Content-Type: application/json' \ + -d '{ + "from": { + "displayName": "John Doe", + "idType": "MSISDN", + "idValue": "123456789" + }, + "to": { + "idType": "MSISDN", + "idValue": "9876543210" + }, + "amountType": "SEND", + "currency": "USD", + "amount": "100", + "transactionType": "TRANSFER", + "note": "test payment", + "homeTransactionId": "123ABC" +}' +``` + +You should get a response with COMPLETED currentState. diff --git a/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/scheme-adapter-to-scheme-adapter-overview.png b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/scheme-adapter-to-scheme-adapter-overview.png new file mode 100644 index 000000000..35702294c Binary files /dev/null and b/website/versioned_docs/v1.0.1/technical/sdk-scheme-adapter/usage/scheme-adapter-to-scheme-adapter/scheme-adapter-to-scheme-adapter-overview.png differ diff --git a/website/versioned_docs/v1.0.1/technical/transaction-requests-service/README.md b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/README.md new file mode 100644 index 000000000..b339478a9 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/README.md @@ -0,0 +1,8 @@ +# Transaction Requests Service + +## Sequence Diagram + +![trx-service-overview-spec.svg](./assets/diagrams/sequence/trx-service-overview-spec.svg) + +* The transaction-requests-service is a mojaloop core service that enables Payee initiated use cases such as "Merchant Request to Pay". +* This is a pass through service which also includes Authorizations. diff --git a/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.plantuml b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.plantuml new file mode 100644 index 000000000..0d4005e68 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.plantuml @@ -0,0 +1,64 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- + ******'/ + + +@startuml +Title Transaction Requests Service - Authorizations +participant "Payer FSP" +participant "Switch\ntransaction-requests-service" as Switch +participant "Payee FSP" + +autonumber +"Payee FSP" --\ "Payee FSP": Lookup, Transaction request,\nprocessing not shown here +note over "Payee FSP", Switch: Payee FSP generates a transaction-request to the Payer FSP +"Payer FSP" --> "Payer FSP": Do quote, generate OTP\nnotify user (not shown here) +"Payer FSP" -\ Switch: GET /authorizations/{TransactionRequestID} +Switch --/ "Payer FSP": 202 Accepted + +alt authorization request is valid + + Switch -> Switch: Validate GET /authorizations/{TransactionRequestID} (internal validation) + Switch -> Switch: Retrieve corresponding end-points for Payee FSP + note over Switch, "Payee FSP": Switch forwards GET /authorizations request to Payee FSP + Switch -\ "Payee FSP": GET /authorizations/{TransactionRequestID} + "Payee FSP" --/ Switch: 202 Accepted + "Payee FSP" -> "Payee FSP": Process authorization request\n(Payer approves/rejects transaction\nusing OTP) + + note over Switch, "Payee FSP": Payee FSP responds with PUT /authorizations//{TransactionRequestID} + "Payee FSP" -\ Switch: PUT /authorizations//{TransactionRequestID} + Switch --/ "Payee FSP": 200 Ok + + note over "Payer FSP", Switch: Switch forwards PUT /authorizations//{TransactionRequestID} to Payer FSP + Switch -> Switch: Retrieve corresponding end-points for Payer FSP + Switch -\ "Payer FSP": PUT /authorizations//{TransactionRequestID} + "Payer FSP" --/ Switch: 200 Ok + + +else authorization request is invalid + note over "Payer FSP", Switch: Switch returns error callback to Payer FSP + Switch -\ "Payer FSP": PUT /authorizations/{TransactionRequestID}/error + "Payer FSP" --/ Switch: 200 OK + "Payer FSP" --> "Payer FSP": Validate OTP sent by Payee FSP +end +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.svg b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.svg new file mode 100644 index 000000000..20f251063 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.svg @@ -0,0 +1,231 @@ + + + + + + + + + + + Transaction Requests Service - Authorizations + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + transaction-requests-service + + + + Switch + + + transaction-requests-service + + + + Payee FSP + + + + Payee FSP + + + + + 1 + + + Lookup, Transaction request, + + + processing not shown here + + + + + Payee FSP generates a transaction-request to the Payer FSP + + + + + 2 + + + Do quote, generate OTP + + + notify user (not shown here) + + + + + 3 + + + GET /authorizations/{TransactionRequestID} + + + + + 4 + + + 202 Accepted + + + + + alt + + + [authorization request is valid] + + + + + 5 + + + Validate GET /authorizations/{TransactionRequestID} (internal validation) + + + + + 6 + + + Retrieve corresponding end-points for Payee FSP + + + + + Switch forwards GET /authorizations request to Payee FSP + + + + + 7 + + + GET /authorizations/{TransactionRequestID} + + + + + 8 + + + 202 Accepted + + + + + 9 + + + Process authorization request + + + (Payer approves/rejects transaction + + + using OTP) + + + + + Payee FSP responds with PUT /authorizations//{TransactionRequestID} + + + + + 10 + + + PUT /authorizations//{TransactionRequestID} + + + + + 11 + + + 200 Ok + + + + + Switch forwards PUT /authorizations//{TransactionRequestID} to Payer FSP + + + + + 12 + + + Retrieve corresponding end-points for Payer FSP + + + + + 13 + + + PUT /authorizations//{TransactionRequestID} + + + + + 14 + + + 200 Ok + + + + [authorization request is invalid] + + + + + Switch returns error callback to Payer FSP + + + + + 15 + + + PUT /authorizations/{TransactionRequestID}/error + + + + + 16 + + + 200 OK + + + + + 17 + + + Validate OTP sent by Payee FSP + + diff --git a/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.plantuml b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.plantuml new file mode 100644 index 000000000..655cf6e07 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.plantuml @@ -0,0 +1,93 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- + ******'/ + + +@startuml +Title Transaction Requests Service - Create +participant "Payer FSP" +participant "Switch\ntransaction-requests-service" as Switch +participant "Payee FSP" + +autonumber +"Payee FSP" -\ "Payee FSP": Lookup process\n(not shown here) +note over "Payee FSP", Switch: Payee FSP generates a transaction-request to the Payer FSP +"Payee FSP" -\ Switch: POST /transactionRequests +Switch -> Switch: Validate POST /transactionRequests schema +Switch --/ "Payee FSP": 202 Accepted + +alt transaction-request is valid + + Switch -> Switch: Validate POST /transactionRequests (internal validation) + Switch -> Switch: Retrieve corresponding end-points for Payer FSP + note over Switch, "Payer FSP": Switch forwards POST /transactionRequests request to Payer FSP + Switch -\ "Payer FSP": POST /transactionRequests + "Payer FSP" --/ Switch: 202 Accepted + "Payer FSP" -> "Payer FSP": Process transaction-request + + alt Payer FSP successfully processes transaction-request + + note over "Payer FSP", Switch: Payer FSP responds to POST /transactionRequests + "Payer FSP" -\ Switch: PUT /transactionRequests/{ID} + Switch --/ "Payer FSP": 200 Ok + + Switch -> Switch: Validate PUT /transactionRequests/{ID} + + alt response is ok + + note over Switch, "Payee FSP": Switch forwards transaction-request response to Payee FSP + Switch -> Switch: Retrieve corresponding end-points for Payee FSP + + Switch -\ "Payee FSP": PUT /transactionRequests/{ID} + "Payee FSP" --/ Switch: 200 Ok + + note over "Payee FSP" #3498db: Wait for a quote, transfer by Payer FSP\nor a rejected transaction-request + else response invalid + + note over Switch, "Payer FSP": Switch returns error to Payer FSP + + Switch -\ "Payer FSP": PUT /transactionRequests/{ID}/error + "Payer FSP" --/ Switch : 200 Ok + + note over Switch, "Payer FSP" #ec7063: Note that under this\nscenario the Payee FSP\nmay not receive a response + + end + else Payer FSP calculation fails or rejects the request + + note over "Payer FSP", Switch: Payer FSP returns error to Switch + + "Payer FSP" -\ Switch: PUT /transactionRequests/{ID}/error + Switch --/ "Payer FSP": 200 OK + + note over "Payee FSP", Switch: Switch returns error to Payee FSP + + Switch -\ "Payee FSP": PUT /transactionRequests/{ID}/error + "Payee FSP" --/ Switch: 200 OK + + end +else transaction-request is invalid + note over "Payee FSP", Switch: Switch returns error to Payee FSP + Switch -\ "Payee FSP": PUT /transactionRequests/{ID}/error + "Payee FSP" --/ Switch: 200 OK +end +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.svg b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.svg new file mode 100644 index 000000000..b5a1c7313 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-1.0.0.svg @@ -0,0 +1,330 @@ + + + + + + + + + + + Transaction Requests Service - Create + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + transaction-requests-service + + + + Switch + + + transaction-requests-service + + + + Payee FSP + + + + Payee FSP + + + + + 1 + + + Lookup process + + + (not shown here) + + + + + Payee FSP generates a transaction-request to the Payer FSP + + + + + 2 + + + POST /transactionRequests + + + + + 3 + + + Validate POST /transactionRequests schema + + + + + 4 + + + 202 Accepted + + + + + alt + + + [transaction-request is valid] + + + + + 5 + + + Validate POST /transactionRequests (internal validation) + + + + + 6 + + + Retrieve corresponding end-points for Payer FSP + + + + + Switch forwards POST /transactionRequests request to Payer FSP + + + + + 7 + + + POST /transactionRequests + + + + + 8 + + + 202 Accepted + + + + + 9 + + + Process transaction-request + + + + + alt + + + [Payer FSP successfully processes transaction-request] + + + + + Payer FSP responds to POST /transactionRequests + + + + + 10 + + + PUT /transactionRequests/{ID} + + + + + 11 + + + 200 Ok + + + + + 12 + + + Validate PUT /transactionRequests/{ID} + + + + + alt + + + [response is ok] + + + + + Switch forwards transaction-request response to Payee FSP + + + + + 13 + + + Retrieve corresponding end-points for Payee FSP + + + + + 14 + + + PUT /transactionRequests/{ID} + + + + + 15 + + + 200 Ok + + + + + Wait for a quote, transfer by Payer FSP + + + or a rejected transaction-request + + + + [response invalid] + + + + + Switch returns error to Payer FSP + + + + + 16 + + + PUT /transactionRequests/{ID}/error + + + + + 17 + + + 200 Ok + + + + + Note that under this + + + scenario the Payee FSP + + + may not receive a response + + + + [Payer FSP calculation fails or rejects the request] + + + + + Payer FSP returns error to Switch + + + + + 18 + + + PUT /transactionRequests/{ID}/error + + + + + 19 + + + 200 OK + + + + + Switch returns error to Payee FSP + + + + + 20 + + + PUT /transactionRequests/{ID}/error + + + + + 21 + + + 200 OK + + + + [transaction-request is invalid] + + + + + Switch returns error to Payee FSP + + + + + 22 + + + PUT /transactionRequests/{ID}/error + + + + + 23 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.plantuml b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.plantuml new file mode 100644 index 000000000..17262a24a --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.plantuml @@ -0,0 +1,90 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- + ******'/ + + +@startuml +Title Transaction Requests Service - Query +participant "Payer FSP" +participant "Switch\ntransaction-requests-service" as Switch +participant "Payee FSP" + +autonumber +note over "Payee FSP", Switch: Payee FSP requests the status of a transaction-request at the Payer FSP.\nID here is the ID of prevoiusly created transaction-request +"Payee FSP" -\ Switch: GET /transactionRequests/{ID} +Switch -> Switch: Validate GET /transactionRequests/{ID} +Switch --/ "Payee FSP": 202 Accepted + +alt transaction-request query is valid + + Switch -> Switch: Retrieve corresponding end-points for Payer FSP + note over Switch, "Payer FSP": Switch forwards GET /transactionRequests/{ID} request to Payer FSP + Switch -\ "Payer FSP": GET /transactionRequests/{ID} + "Payer FSP" --/ Switch: 202 Accepted + "Payer FSP" -> "Payer FSP": Retrieve transaction-request + + alt Payer FSP successfully retrieves transaction-request + + note over "Payer FSP", Switch: Payer FSP responds with the\nPUT /transactionRequests/{ID} callback + "Payer FSP" -\ Switch: PUT /transactionRequests/{ID} + Switch --/ "Payer FSP": 200 Ok + + Switch -> Switch: Validate PUT /transactionRequests/{ID} + + alt response is ok + + note over Switch, "Payee FSP": Switch forwards transaction-request response to Payee FSP + Switch -> Switch: Retrieve corresponding end-points for Payee FSP + + Switch -\ "Payee FSP": PUT /transactionRequests/{ID} + "Payee FSP" --/ Switch: 200 Ok + + else response invalid + + note over Switch, "Payer FSP": Switch returns error to Payer FSP + + Switch -\ "Payer FSP": PUT /transactionRequests/{ID}/error + "Payer FSP" --/ Switch : 200 Ok + + note over Switch, "Payer FSP" #ec7063: Note that under this\nscenario the Payee FSP\nmay not receive a response + + end + else Payer FSP is unable to retrieve the transaction-request + + note over "Payer FSP", Switch: Payer FSP returns error to Switch + + "Payer FSP" -\ Switch: PUT /transactionRequests/{ID}/error + Switch --/ "Payer FSP": 200 OK + + note over "Payee FSP", Switch: Switch returns error to Payee FSP + + Switch -\ "Payee FSP": PUT /transactionRequests/{ID}/error + "Payee FSP" --/ Switch: 200 OK + + end +else transaction-request is invalid + note over "Payee FSP", Switch: Switch returns error to Payee FSP + Switch -\ "Payee FSP": PUT /transactionRequests/{ID}/error + "Payee FSP" --/ Switch: 200 OK +end +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.svg b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.svg new file mode 100644 index 000000000..bbc20538b --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.svg @@ -0,0 +1,309 @@ + + + + + + + + + + + Transaction Requests Service - Query + + + + + + + + + Payer FSP + + + + Payer FSP + + + + Switch + + + transaction-requests-service + + + + Switch + + + transaction-requests-service + + + + Payee FSP + + + + Payee FSP + + + + + Payee FSP requests the status of a transaction-request at the Payer FSP. + + + ID here is the ID of prevoiusly created transaction-request + + + + + 1 + + + GET /transactionRequests/{ID} + + + + + 2 + + + Validate GET /transactionRequests/{ID} + + + + + 3 + + + 202 Accepted + + + + + alt + + + [transaction-request query is valid] + + + + + 4 + + + Retrieve corresponding end-points for Payer FSP + + + + + Switch forwards GET /transactionRequests/{ID} request to Payer FSP + + + + + 5 + + + GET /transactionRequests/{ID} + + + + + 6 + + + 202 Accepted + + + + + 7 + + + Retrieve transaction-request + + + + + alt + + + [Payer FSP successfully retrieves transaction-request] + + + + + Payer FSP responds with the + + + PUT /transactionRequests/{ID} callback + + + + + 8 + + + PUT /transactionRequests/{ID} + + + + + 9 + + + 200 Ok + + + + + 10 + + + Validate PUT /transactionRequests/{ID} + + + + + alt + + + [response is ok] + + + + + Switch forwards transaction-request response to Payee FSP + + + + + 11 + + + Retrieve corresponding end-points for Payee FSP + + + + + 12 + + + PUT /transactionRequests/{ID} + + + + + 13 + + + 200 Ok + + + + [response invalid] + + + + + Switch returns error to Payer FSP + + + + + 14 + + + PUT /transactionRequests/{ID}/error + + + + + 15 + + + 200 Ok + + + + + Note that under this + + + scenario the Payee FSP + + + may not receive a response + + + + [Payer FSP is unable to retrieve the transaction-request] + + + + + Payer FSP returns error to Switch + + + + + 16 + + + PUT /transactionRequests/{ID}/error + + + + + 17 + + + 200 OK + + + + + Switch returns error to Payee FSP + + + + + 18 + + + PUT /transactionRequests/{ID}/error + + + + + 19 + + + 200 OK + + + + [transaction-request is invalid] + + + + + Switch returns error to Payee FSP + + + + + 20 + + + PUT /transactionRequests/{ID}/error + + + + + 21 + + + 200 OK + + diff --git a/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.plantuml b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.plantuml new file mode 100644 index 000000000..d88913d33 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.plantuml @@ -0,0 +1,138 @@ +/'***** +License +-------------- +Copyright © 2017 Bill & Melinda Gates Foundation +The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Contributors +-------------- +This is the official list of the Mojaloop project contributors for this file. +Names of the original copyright holders (individuals or organizations) +should be listed with a '*' in the first column. People who have +contributed from an organization can be listed under the organization +that actually holds the copyright for their contributions (see the +Gates Foundation organization for an example). Those individuals should have +their names indented and be marked with a '-'. Email address can be added +optionally within square brackets . +* Gates Foundation +- Name Surname + +* Henk Kodde +-------------- +******'/ + +@startuml transactionRequests + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ActorFontStyle Bold +skinparam ActorFontSize 20 +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +skinparam participant { + shadowing true +} + +hide footbox + +' declare title +' title How to use the /transactionRequests service + +' Actor Keys: +' participant - FSP(Payer/Payee) and Switch +' actor - Payee + +' declare actors +participant "Payer\nFSP" as payerfsp +participant "Optional\nSwitch" as Switch +participant "Payee\nFSP" as payeefsp +actor "<$actor>\nPayee" as Payee + +' start flow +payeefsp <- Payee: I would like to receive\nfunds from +123456789 +activate payeefsp +payeefsp <- payeefsp: Lookup +123456789\n(process not shown here) +Switch <<- payeefsp: **POST /transactionRequest/**\n(Payee information,\ntransaction details) +activate Switch +Switch -->> payeefsp: **HTTP 202** (Accepted) +payerfsp <<- Switch: **POST /transactionRequests/**\n(Payee information,\ntransaction details) +activate payerfsp +payerfsp -->> Switch: **HTTP 202** (Accepted) +payeefsp -> payeefsp: Perform optional validation +payerfsp ->> Switch: **PUT /transactionRequests/**\n(Received status) +payerfsp <<-- Switch: **HTTP 200** (OK) +deactivate payerfsp +Switch ->> payeefsp: **PUT /transactionRequests/**\n(Received status) +Switch <<-- payeefsp: **HTTP 200** (OK) +deactivate Switch +payeefsp -> payeefsp: Wait for either quote and\ntransfer, or rejected\ntransaction request by Payer +payeefsp <[hidden]- payeefsp +deactivate payeefsp +@enduml diff --git a/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.svg b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.svg new file mode 100644 index 000000000..e54569705 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/assets/diagrams/sequence/trx-service-overview-spec.svg @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + Payer + + + FSP + + + + Optional + + + Switch + + + + Payee + + + FSP + + + + Payee + + + + + + + I would like to receive + + + funds from +123456789 + + + + Lookup +123456789 + + + (process not shown here) + + + + POST /transactionRequest/ + + + (Payee information, + + + transaction details) + + + + + HTTP 202 + + + (Accepted) + + + + POST /transactionRequests/ + + + (Payee information, + + + transaction details) + + + + + HTTP 202 + + + (Accepted) + + + + Perform optional validation + + + + PUT /transactionRequests/ + + + <ID> + + + (Received status) + + + + + HTTP 200 + + + (OK) + + + + PUT /transactionRequests/ + + + <ID> + + + (Received status) + + + + + HTTP 200 + + + (OK) + + + + Wait for either quote and + + + transfer, or rejected + + + transaction request by Payer + + diff --git a/website/versioned_docs/v1.0.1/technical/transaction-requests-service/authorizations.md b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/authorizations.md new file mode 100644 index 000000000..614b5d0a5 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/authorizations.md @@ -0,0 +1,7 @@ +# Transaction Requests + +GET /authorizations/{TransactionRequestID} and PUT /authorizations/{TransactionRequestID} to support authorizations in "Merchant Request to Pay" and other Payee initiated use cases + +## Sequence Diagram + +![seq-trx-req-authorizations-3.0.0.svg](./assets/diagrams/sequence/seq-trx-req-authorizations-3.0.0.svg) diff --git a/website/versioned_docs/v1.0.1/technical/transaction-requests-service/transaction-requests-get.md b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/transaction-requests-get.md new file mode 100644 index 000000000..b99202192 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/transaction-requests-get.md @@ -0,0 +1,7 @@ +# Transaction Requests - Query + +GET /transactionRequests and PUT /transacionRequests to suppport "Merchant Request to Pay" + +## Sequence Diagram + +![seq-trx-req-service-get-2.0.0.svg](./assets/diagrams/sequence/seq-trx-req-service-get-2.0.0.svg) diff --git a/website/versioned_docs/v1.0.1/technical/transaction-requests-service/transaction-requests-post.md b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/transaction-requests-post.md new file mode 100644 index 000000000..58ea60460 --- /dev/null +++ b/website/versioned_docs/v1.0.1/technical/transaction-requests-service/transaction-requests-post.md @@ -0,0 +1,7 @@ +# Transaction Requests + +POST /transactionRequests and PUT /transacionRequests to suppport "Merchant Request to Pay" + +## Sequence Diagram + +![seq-trx-req-service-1.0.0.svg](./assets/diagrams/sequence/seq-trx-req-service-1.0.0.svg)